summaryrefslogtreecommitdiff
path: root/sys/dev/microcode/siop/ncr53cxxx.c
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2001-02-15 04:08:00 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2001-02-15 04:08:00 +0000
commitc8b00c03932cfab5b77c51e6c4ff391005c70c9f (patch)
treecb1c31da4698f05d544e931f937a1e04b08cfefc /sys/dev/microcode/siop/ncr53cxxx.c
parent2b570e5d0d483fb51056d7dc3c9677f761dbf802 (diff)
Import siop, a replacement for the ncr SCSI driver, from NetBSD.
Written for NetBSD by Manuel Bouyer. Tested with various cards on i386 and alpha. Outstanding issue: doesn't work with PowerPC yet.
Diffstat (limited to 'sys/dev/microcode/siop/ncr53cxxx.c')
-rw-r--r--sys/dev/microcode/siop/ncr53cxxx.c1395
1 files changed, 1395 insertions, 0 deletions
diff --git a/sys/dev/microcode/siop/ncr53cxxx.c b/sys/dev/microcode/siop/ncr53cxxx.c
new file mode 100644
index 00000000000..b736a00cd44
--- /dev/null
+++ b/sys/dev/microcode/siop/ncr53cxxx.c
@@ -0,0 +1,1395 @@
+/* $OpenBSD: ncr53cxxx.c,v 1.1 2001/02/15 04:07:59 krw Exp $ */
+/* $NetBSD: ncr53cxxx.c,v 1.5 2000/10/23 14:51:51 bouyer Exp $ */
+
+/*
+ * Copyright (c) 1995,1999 Michael L. Hitch
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Michael L. Hitch.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * 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.
+ */
+
+/* ncr53cxxx.c - SCSI SCRIPTS Assembler */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef AMIGA
+#define strcmpi strcasecmp
+#endif
+
+#define MAXTOKENS 16
+#define MAXINST 1024
+#define MAXSYMBOLS 128
+
+struct {
+ int type;
+ char *name;
+} tokens[MAXTOKENS];
+int ntokens;
+int tokenix;
+
+void f_proc (void);
+void f_pass (void);
+void f_list (void); /* ENTRY, EXTERNAL label list */
+void f_define (void); /* ABSOLUTE, RELATIVE label list */
+void f_move (void);
+void f_jump (void);
+void f_call (void);
+void f_return (void);
+void f_int (void);
+void f_select (void);
+void f_reselect (void);
+void f_wait (void);
+void f_disconnect (void);
+void f_set (void);
+void f_clear (void);
+void f_load (void);
+void f_store (void);
+void f_nop (void);
+void f_arch (void);
+
+struct {
+ char *name;
+ void (*func)(void);
+} directives[] = {
+ {"PROC", f_proc},
+ {"PASS", f_pass},
+ {"ENTRY", f_list},
+ {"ABSOLUTE", f_define},
+ {"EXTERN", f_list},
+ {"EXTERNAL", f_list},
+ {"RELATIVE", f_define},
+ {"MOVE", f_move},
+ {"JUMP", f_jump},
+ {"CALL", f_call},
+ {"RETURN", f_return},
+ {"INT", f_int},
+ {"SELECT", f_select},
+ {"RESELECT", f_reselect},
+ {"WAIT", f_wait},
+ {"DISCONNECT", f_disconnect},
+ {"SET", f_set},
+ {"CLEAR", f_clear},
+ {"LOAD", f_load},
+ {"STORE", f_store},
+ {"NOP", f_nop},
+ {"ARCH", f_arch},
+ {NULL, NULL}};
+
+u_int32_t script[MAXINST];
+int dsps;
+char *script_name = "SCRIPT";
+u_int32_t inst0, inst1, inst2;
+unsigned int ninsts;
+unsigned int npatches;
+
+struct patchlist {
+ struct patchlist *next;
+ unsigned offset;
+};
+
+#define S_LABEL 0x0000
+#define S_ABSOLUTE 0x0001
+#define S_RELATIVE 0x0002
+#define S_EXTERNAL 0x0003
+#define F_DEFINED 0x0001
+#define F_ENTRY 0x0002
+struct {
+ short type;
+ short flags;
+ u_int32_t value;
+ struct patchlist *patchlist;
+ char *name;
+} symbols[MAXSYMBOLS];
+int nsymbols;
+
+char *stypes[] = {"Label", "Absolute", "Relative", "External"};
+
+char *phases[] = {
+ "data_out", "data_in", "cmd", "status",
+ "res4", "res5", "msg_out", "msg_in"
+};
+
+struct ncrregs {
+ char *name;
+ int addr[4];
+};
+#define ARCH710 1
+#define ARCH720 2
+#define ARCH810 3
+#define ARCH825 4
+
+struct ncrregs regs[] = {
+ {"scntl0", {0x00, 0x00, 0x00, 0x00}},
+ {"scntl1", {0x01, 0x01, 0x01, 0x01}},
+ {"scntl2", {-1, 0x02, 0x02, 0x02}},
+ {"scntl3", {-1, 0x03, 0x03, 0x03}},
+ {"scid", {-1, 0x04, 0x04, 0x04}},
+ {"sdid", {0x02, -1, -1, -1}},
+ {"sien", {0x03, -1, -1, -1}},
+ {"scid", {0x04, -1, -1, -1}},
+ {"sxfer", {0x05, 0x05, 0x05, 0x05}},
+ {"sdid", {-1, 0x06, 0x06, 0x06}},
+ {"gpreg", {-1, 0x07, 0x07, 0x07}},
+ {"sodl", {0x06, -1, -1, -1}},
+ {"socl", {0x07, -1, -1, -1}},
+ {"sfbr", {0x08, 0x08, 0x08, 0x08}},
+ {"socl", {-1, 0x09, 0x09, 0x09}},
+ {"ssid", {-1, 0x0a, 0x0a, 0x0a}},
+ {"sidl", {0x09, -1, -1, -1}},
+ {"sbdl", {0x0a, -1, -1, -1}},
+ {"sbcl", {0x0b, 0x0b, 0x0b, 0x0b}},
+ {"dstat", {0x0c, 0x0c, 0x0c, 0x0c}},
+ {"sstat0", {0x0d, 0x0d, 0x0d, 0x0d}},
+ {"sstat1", {0x0e, 0x0e, 0x0e, 0x0e}},
+ {"sstat2", {0x0f, 0x0f, 0x0f, 0x0f}},
+ {"dsa0", {0x10, 0x10, 0x10, 0x10}},
+ {"dsa1", {0x11, 0x11, 0x11, 0x11}},
+ {"dsa2", {0x12, 0x12, 0x12, 0x12}},
+ {"dsa3", {0x13, 0x13, 0x13, 0x13}},
+ {"istat", {-1, 0x14, 0x14, 0x14}},
+ {"ctest0", {0x14, 0x18, 0x18, 0x18}},
+ {"ctest1", {0x15, 0x19, 0x19, 0x19}},
+ {"ctest2", {0x16, 0x1a, 0x1a, 0x1a}},
+ {"ctest3", {0x17, 0x1b, 0x1b, 0x1b}},
+ {"temp0", {-1, 0x1c, 0x1c, 0x1c}},
+ {"temp1", {-1, 0x1d, 0x1d, 0x1d}},
+ {"temp2", {-1, 0x1e, 0x1e, 0x1e}},
+ {"temp3", {-1, 0x1f, 0x1f, 0x1f}},
+ {"dfifo", {-1, 0x20, 0x20, 0x20}},
+ {"ctest4", {0x18, 0x21, 0x21, 0x21}},
+ {"ctest5", {0x19, 0x22, 0x22, 0x22}},
+ {"ctest6", {0x20, 0x23, 0x23, 0x23}},
+ {"ctest7", {0x21, -1, -1, -1}},
+ {"temp0", {0x22, -1, -1, -1}},
+ {"temp1", {0x23, -1, -1, -1}},
+ {"temp2", {0x24, -1, -1, -1}},
+ {"temp3", {0x25, -1, -1, -1}},
+ {"dfifo", {0x26, -1, -1, -1}},
+ {"istat", {0x27, -1, -1, -1}},
+ {"ctest8", {0x28, -1, -1, -1}},
+ {"lcrc", {0x29, -1, -1, -1}},
+ {"dbc0", {0x2a, 0x24, 0x24, 0x24}},
+ {"dbc1", {0x2b, 0x25, 0x25, 0x25}},
+ {"dbc2", {0x2c, 0x26, 0x26, 0x26}},
+ {"dcmd", {0x2d, 0x27, 0x27, 0x27}},
+ {"dnad0", {0x2e, 0x28, 0x28, 0x28}},
+ {"dnad1", {0x2f, 0x29, 0x29, 0x29}},
+ {"dnad2", {0x30, 0x2a, 0x2a, 0x2a}},
+ {"dnad3", {0x31, 0x2b, 0x2b, 0x2b}},
+ {"dsp0", {0x32, 0x2c, 0x2c, 0x2c}},
+ {"dsp1", {0x33, 0x2d, 0x2d, 0x2d}},
+ {"dsp2", {0x34, 0x2e, 0x2e, 0x2e}},
+ {"dsp3", {0x35, 0x2f, 0x2f, 0x2f}},
+ {"dsps0", {0x36, 0x30, 0x30, 0x30}},
+ {"dsps1", {0x37, 0x31, 0x31, 0x31}},
+ {"dsps2", {0x38, 0x32, 0x32, 0x32}},
+ {"dsps3", {0x39, 0x33, 0x33, 0x33}},
+ {"scratch0", {0x40, -1, -1, -1}},
+ {"scratch1", {0x41, -1, -1, -1}},
+ {"scratch2", {0x42, -1, -1, -1}},
+ {"scratch3", {0x43, -1, -1, -1}},
+ {"scratcha0", { -1, 0x34, 0x34, 0x34}},
+ {"scratcha1", { -1, 0x35, 0x35, 0x35}},
+ {"scratcha2", { -1, 0x36, 0x36, 0x36}},
+ {"scratcha3", { -1, 0x37, 0x37, 0x37}},
+ {"dmode", {0x44, 0x38, 0x38, 0x38}},
+ {"dien", {0x45, 0x39, 0x39, 0x39}},
+ {"dwt", {0x46, 0x3a, -1, -1}},
+ {"sbr", { -1, -1, 0x3a, 0x3a}},
+ {"dcntl", {0x47, 0x3b, 0x3b, 0x3b}},
+ {"addr0", {0x48, 0x3c, 0x3c, 0x3c}},
+ {"addr1", {0x49, 0x3d, 0x3d, 0x3d}},
+ {"addr2", {0x4A, 0x3e, 0x3e, 0x3e}},
+ {"addr3", {0x4B, 0x3f, 0x3f, 0x3f}},
+ {"sien0", { -1, 0x40, 0x40, 0x40}},
+ {"sien1", { -1, 0x41, 0x41, 0x41}},
+ {"sist0", { -1, 0x42, 0x42, 0x42}},
+ {"sist1", { -1, 0x43, 0x43, 0x43}},
+ {"slpar", { -1, 0x44, 0x44, 0x44}},
+ {"swide", { -1, 0x45, -1, 0x45}},
+ {"macntl", { -1, 0x46, 0x46, 0x46}},
+ {"gpcntl", { -1, 0x47, 0x47, 0x47}},
+ {"stime0", { -1, 0x48, 0x48, 0x48}},
+ {"stime1", { -1, 0x49, 0x49, 0x49}},
+ {"respid0", { -1, 0x4a, 0x4a, 0x4a}},
+ {"respid1", { -1, 0x4b, -1, 0x4b}},
+ {"stest0", { -1, 0x4c, 0x4c, 0x4c}},
+ {"stest1", { -1, 0x4d, 0x4d, 0x4d}},
+ {"stest2", { -1, 0x4e, 0x4e, 0x4e}},
+ {"stest3", { -1, 0x4f, 0x4f, 0x4f}},
+ {"sidl0", { -1, 0x50, 0x50, 0x50}},
+ {"sidl1", { -1, 0x51, -1, 0x51}},
+ {"sodl0", { -1, 0x54, 0x54, 0x54}},
+ {"sodl1", { -1, 0x55, -1, 0x55}},
+ {"sbdl0", { -1, 0x58, 0x58, 0x58}},
+ {"sbdl1", { -1, 0x59, -1, 0x59}},
+ {"scratchb0", { -1, 0x5c, 0x5c, 0x5c}},
+ {"scratchb1", { -1, 0x5d, 0x5d, 0x5d}},
+ {"scratchb2", { -1, 0x5e, 0x5e, 0x5e}},
+ {"scratchb3", { -1, 0x5f, 0x5f, 0x5f}},
+ {"scratchc0", { -1, -1, -1, 0x60}},
+ {"scratchc1", { -1, -1, -1, 0x61}},
+ {"scratchc2", { -1, -1, -1, 0x62}},
+ {"scratchc3", { -1, -1, -1, 0x63}},
+ {"scratchd0", { -1, -1, -1, 0x64}},
+ {"scratchd1", { -1, -1, -1, 0x65}},
+ {"scratchd2", { -1, -1, -1, 0x5e}},
+ {"scratchd3", { -1, -1, -1, 0x67}},
+ {"scratche0", { -1, -1, -1, 0x68}},
+ {"scratche1", { -1, -1, -1, 0x69}},
+ {"scratche2", { -1, -1, -1, 0x6a}},
+ {"scratche3", { -1, -1, -1, 0x6b}},
+ {"scratchf0", { -1, -1, -1, 0x6c}},
+ {"scratchf1", { -1, -1, -1, 0x6d}},
+ {"scratchf2", { -1, -1, -1, 0x6e}},
+ {"scratchf3", { -1, -1, -1, 0x6f}},
+ {"scratchg0", { -1, -1, -1, 0x70}},
+ {"scratchg1", { -1, -1, -1, 0x71}},
+ {"scratchg2", { -1, -1, -1, 0x72}},
+ {"scratchg3", { -1, -1, -1, 0x73}},
+ {"scratchh0", { -1, -1, -1, 0x74}},
+ {"scratchh1", { -1, -1, -1, 0x75}},
+ {"scratchh2", { -1, -1, -1, 0x7e}},
+ {"scratchh3", { -1, -1, -1, 0x77}},
+ {"scratchi0", { -1, -1, -1, 0x78}},
+ {"scratchi1", { -1, -1, -1, 0x79}},
+ {"scratchi2", { -1, -1, -1, 0x7a}},
+ {"scratchi3", { -1, -1, -1, 0x7b}},
+ {"scratchj0", { -1, -1, -1, 0x7c}},
+ {"scratchj1", { -1, -1, -1, 0x7d}},
+ {"scratchj2", { -1, -1, -1, 0x7e}},
+ {"scratchj3", { -1, -1, -1, 0x7f}},
+};
+
+int lineno;
+int err_listed;
+int arch;
+int partial_flag;
+
+char inbuf[128];
+
+char *sourcefile;
+char *outputfile;
+char *listfile;
+char *errorfile;
+
+FILE *infp;
+FILE *outfp;
+FILE *listfp;
+FILE *errfp;
+
+void setarch(char *);
+void parse (void);
+void process (void);
+void emit_symbols (void);
+void list_symbols (void);
+void errout (char *);
+void define_symbol (char *, u_int32_t, short, short);
+void close_script (void);
+void new_script (char *);
+void store_inst (void);
+int expression (int *);
+int evaluate (int);
+int number (char *);
+int lookup (char *);
+int reserved (char *, int);
+int CheckPhase (int);
+int CheckRegister (int);
+void transfer (int, int);
+void select_reselect (int);
+void set_clear (u_int32_t);
+void block_move (void);
+void register_write (void);
+void memory_to_memory (void);
+void loadstore (int);
+void error_line(void);
+char *makefn(char *, char *);
+void usage(void);
+
+int
+main (int argc, char *argv[])
+{
+ int i;
+
+ if (argc < 2 || argv[1][0] == '-')
+ usage();
+ sourcefile = argv[1];
+ infp = fopen (sourcefile, "r");
+ if (infp == NULL) {
+ perror ("open source");
+ fprintf (stderr, "scc: error opening source file %s\n", argv[1]);
+ exit (1);
+ }
+ /*
+ * process options
+ * -l [listfile]
+ * -o [outputfile]
+ * -p [outputfile]
+ * -z [debugfile]
+ * -e [errorfile]
+ * -a arch
+ * -v
+ * -u
+ */
+ for (i = 2; i < argc; ++i) {
+ if (argv[i][0] != '-')
+ usage();
+ switch (argv[i][1]) {
+ case 'o':
+ case 'p':
+ partial_flag = argv[i][1] == 'p';
+ if (i + 1 >= argc || argv[i + 1][0] == '-')
+ outputfile = makefn (sourcefile, "out");
+ else {
+ outputfile = argv[i + 1];
+ ++i;
+ }
+ break;
+ case 'l':
+ if (i + 1 >= argc || argv[i + 1][0] == '-')
+ listfile = makefn (sourcefile, "lis");
+ else {
+ listfile = argv[i + 1];
+ ++i;
+ }
+ break;
+ case 'e':
+ if (i + 1 >= argc || argv[i + 1][0] == '-')
+ errorfile = makefn (sourcefile, "err");
+ else {
+ errorfile = argv[i + 1];
+ ++i;
+ }
+ break;
+ case 'a':
+ if (i + 1 == argc)
+ usage();
+ setarch(argv[i +1]);
+ if (arch == 0) {
+ fprintf(stderr,"%s: bad arch '%s'\n",
+ argv[0], argv[i +1]);
+ exit(1);
+ }
+ ++i;
+ break;
+ default:
+ fprintf (stderr, "scc: unrecognized option '%c'\n",
+ argv[i][1]);
+ usage();
+ }
+ }
+ if (outputfile)
+ outfp = fopen (outputfile, "w");
+ if (listfile)
+ listfp = fopen (listfile, "w");
+ if (errorfile)
+ errfp = fopen (errorfile, "w");
+ else
+ errfp = stderr;
+
+ if (outfp) {
+ time_t cur_time;
+
+ fprintf(outfp, "/*\t$NetBSD: ncr53cxxx.c,v 1.5 2000/10/23 14:51:51 bouyer Exp $\t*/\n");
+ fprintf(outfp, "/*\n");
+ fprintf(outfp, " *\tDO NOT EDIT - this file is automatically generated.\n");
+ time(&cur_time);
+ fprintf(outfp, " *\tcreated from %s on %s", sourcefile, ctime(&cur_time));
+ fprintf(outfp, " */\n");
+ }
+
+ while (fgets (inbuf, sizeof (inbuf), infp)) {
+ ++lineno;
+ if (listfp)
+ fprintf (listfp, "%3d: %s", lineno, inbuf);
+ err_listed = 0;
+ parse ();
+ if (ntokens) {
+#ifdef DUMP_TOKENS
+ int i;
+
+ fprintf (listfp, " %d tokens\n", ntokens);
+ for (i = 0; i < ntokens; ++i) {
+ fprintf (listfp, " %d: ", i);
+ if (tokens[i].type)
+ fprintf (listfp,"'%c'\n", tokens[i].type);
+ else
+ fprintf (listfp, "%s\n", tokens[i].name);
+ }
+#endif
+ if (ntokens >= 2 && tokens[0].type == 0 &&
+ tokens[1].type == ':') {
+ define_symbol (tokens[0].name, dsps, S_LABEL, F_DEFINED);
+ tokenix += 2;
+ }
+ if (tokenix < ntokens)
+ process ();
+ }
+
+ }
+ close_script ();
+ emit_symbols ();
+ if (outfp && !partial_flag) {
+ fprintf (outfp, "\nu_int32_t INSTRUCTIONS = 0x%08x;\n", ninsts);
+ fprintf (outfp, "u_int32_t PATCHES = 0x%08x;\n", npatches);
+ }
+ list_symbols ();
+ exit(0);
+}
+
+void setarch(char *val)
+{
+ switch (atoi(val)) {
+ case 710:
+ arch = ARCH710;
+ break;
+ case 720:
+ arch = ARCH720;
+ break;
+ case 810:
+ arch = ARCH810;
+ break;
+ case 825:
+ arch = ARCH825;
+ break;
+ default:
+ arch = 0;
+ }
+}
+
+void emit_symbols ()
+{
+ int i;
+ struct patchlist *p;
+
+ if (nsymbols == 0 || outfp == NULL)
+ return;
+
+ for (i = 0; i < nsymbols; ++i) {
+ char *code;
+ if ((symbols[i].flags & F_DEFINED) == 0 &&
+ symbols[i].type != S_EXTERNAL) {
+ fprintf(stderr, "warning: symbol %s undefined\n",
+ symbols[i].name);
+ }
+ if (symbols[i].type == S_ABSOLUTE)
+ code = "A_";
+ else if (symbols[i].type == S_RELATIVE)
+ code = "R_";
+ else if (symbols[i].type == S_EXTERNAL)
+ code = "E_";
+ else if (symbols[i].flags & F_ENTRY)
+ code = "Ent_";
+ else
+ continue;
+ fprintf (outfp, "#define\t%s%s\t0x%08x\n", code, symbols[i].name,
+ symbols[i].value);
+ if (symbols[i].flags & F_ENTRY || symbols[i].patchlist == NULL)
+ continue;
+ fprintf (outfp, "u_int32_t %s%s_Used[] = {\n", code, symbols[i].name);
+#if 1
+ p = symbols[i].patchlist;
+ while (p) {
+ fprintf (outfp, "\t0x%08x,\n", p->offset / 4);
+ p = p->next;
+ }
+#endif
+ fprintf (outfp, "};\n\n");
+ }
+ /* patches ? */
+}
+
+void list_symbols ()
+{
+ int i;
+
+ if (nsymbols == 0 || listfp == NULL)
+ return;
+ fprintf (listfp, "\n\nValue Type Symbol\n");
+ for (i = 0; i < nsymbols; ++i) {
+ fprintf (listfp, "%08x: %-8s %s\n", symbols[i].value,
+ stypes[symbols[i].type], symbols[i].name);
+ }
+}
+
+void errout (char *text)
+{
+ error_line();
+ fprintf (errfp, "*** %s ***\n", text);
+}
+
+void parse ()
+{
+ char *p = inbuf;
+ char c;
+ char string[64];
+ char *s;
+
+ ntokens = tokenix = 0;
+ while (1) {
+ while ((c = *p++) && c != '\n' && (c <= ' ' || c == '\t'))
+ ;
+ if (c == '\n' || c == 0 || c == ';')
+ break;
+ if (ntokens >= MAXTOKENS) {
+ errout ("Token table full");
+ break;
+ }
+ if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
+ (c >= 'A' && c <= 'Z') || c == '$' || c == '_') {
+ s = string;
+ *s++ = c;
+ while (((c = *p) >= '0' && c <= '9') ||
+ (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
+ c == '_' || c == '$') {
+ *s++ = *p++;
+ }
+ *s = 0;
+ tokens[ntokens].name = malloc (strlen (string) + 1);
+ strcpy (tokens[ntokens].name, string);
+ tokens[ntokens].type = 0;
+ }
+ else {
+ tokens[ntokens].type = c;
+ }
+ ++ntokens;
+ }
+ return;
+}
+
+void process ()
+{
+ int i;
+
+ if (tokens[tokenix].type) {
+ error_line();
+ fprintf (errfp, "Error: expected directive, found '%c'\n",
+ tokens[tokenix].type);
+ return;
+ }
+ for (i = 0; directives[i].name; ++i) {
+ if (strcmpi (directives[i].name, tokens[tokenix].name) == 0)
+ break;
+ }
+ if (directives[i].name == NULL) {
+ error_line();
+ fprintf (errfp, "Error: expected directive, found \"%s\"\n",
+ tokens[tokenix].name);
+ return;
+ }
+ if (directives[i].func == NULL) {
+ error_line();
+ fprintf (errfp, "No function for directive \"%s\"\n", tokens[tokenix].name);
+ } else {
+#if 0
+ fprintf (listfp, "Processing directive \"%s\"\n", directives[i].name);
+#endif
+ ++tokenix;
+ (*directives[i].func) ();
+ }
+}
+
+void define_symbol (char *name, u_int32_t value, short type, short flags)
+{
+ int i;
+ struct patchlist *p;
+
+ for (i = 0; i < nsymbols; ++i) {
+ if (symbols[i].type == type && strcmp (symbols[i].name, name) == 0) {
+ if (symbols[i].flags & F_DEFINED) {
+ error_line();
+ fprintf (errfp, "*** Symbol \"%s\" multiply defined\n",
+ name);
+ } else {
+ symbols[i].flags |= flags;
+ symbols[i].value = value;
+ p = symbols[i].patchlist;
+ while (p) {
+ if (p->offset > dsps)
+ errout ("Whoops\007");
+ else
+ script[p->offset / 4] = dsps - p->offset - 4;
+ p = p->next;
+ }
+ }
+ return;
+ }
+ }
+ if (nsymbols >= MAXSYMBOLS) {
+ errout ("Symbol table full");
+ return;
+ }
+ symbols[nsymbols].type = type;
+ symbols[nsymbols].flags = flags;
+ symbols[nsymbols].value = value;
+ symbols[nsymbols].patchlist = NULL;
+ symbols[nsymbols].name = malloc (strlen (name) + 1);
+ strcpy (symbols[nsymbols].name, name);
+ ++nsymbols;
+}
+
+void close_script ()
+{
+ int i;
+
+ if (dsps == 0)
+ return;
+ if (outfp) {
+ fprintf (outfp, "const u_int32_t %s[] = {\n", script_name);
+ for (i = 0; i < dsps / 4; i += 2) {
+ fprintf (outfp, "\t0x%08x, 0x%08x", script[i],
+ script[i + 1]);
+ /* check for memory move instruction */
+ if ((script[i] & 0xe0000000) == 0xc0000000)
+ fprintf (outfp, ", 0x%08x,", script[i + 2]);
+ else
+ if ((i + 2) <= dsps / 4) fprintf (outfp, ",\t\t");
+ fprintf (outfp, "\t/* %03x - %3d */\n", i * 4, i * 4);
+ if ((script[i] & 0xe0000000) == 0xc0000000)
+ ++i;
+ }
+ fprintf (outfp, "};\n\n");
+ }
+ dsps = 0;
+}
+
+void new_script (char *name)
+{
+ close_script ();
+ script_name = malloc (strlen (name) + 1);
+ strcpy (script_name, name);
+}
+
+int reserved (char *string, int t)
+{
+ if (tokens[t].type == 0 && strcmpi (tokens[t].name, string) == 0)
+ return (1);
+ return (0);
+}
+
+int CheckPhase (int t)
+{
+ int i;
+
+ for (i = 0; i < 8; ++i) {
+ if (reserved (phases[i], t)) {
+ inst0 |= i << 24;
+ return (1);
+ }
+ }
+ return (0);
+}
+
+int CheckRegister (int t)
+{
+ int i;
+
+ if (arch <= 0) {
+ errout("'ARCH' statement missing");
+ return -1;
+ }
+ for (i = 0; i < (sizeof(regs) / sizeof(regs[0])); i++) {
+ if (regs[i].addr[arch - 1] >= 0 && reserved(regs[i].name, t))
+ return regs[i].addr[arch-1];
+ }
+ return (-1);
+}
+
+int expression (int *t)
+{
+ int value;
+ int i = *t;
+
+ value = evaluate (i++);
+ while (i < ntokens) {
+ if (tokens[i].type == '+')
+ value += evaluate (i + 1);
+ else if (tokens[i].type == '-')
+ value -= evaluate (i + 1);
+ else
+ errout ("Unknown identifier");
+ i += 2;
+ }
+ *t = i;
+ return (value);
+}
+
+int evaluate (t)
+{
+ int value;
+ char *name;
+
+ if (tokens[t].type) {
+ errout ("Expected an identifier");
+ return (0);
+ }
+ name = tokens[t].name;
+ if (*name >= '0' && *name <= '9')
+ value = number (name);
+ else
+ value = lookup (name);
+ return (value);
+}
+
+int number (char *s)
+{
+ int value;
+ int n;
+ int radix;
+
+ radix = 10;
+ if (*s == '0') {
+ ++s;
+ radix = 8;
+ switch (*s) {
+ case 'x':
+ case 'X':
+ radix = 16;
+ break;
+ case 'b':
+ case 'B':
+ radix = 2;
+ }
+ if (radix != 8)
+ ++s;
+ }
+ value = 0;
+ while (*s) {
+ n = *s++;
+ if (n >= '0' && n <= '9')
+ n -= '0';
+ else if (n >= 'a' && n <= 'f')
+ n -= 'a' - 10;
+ else if (n >= 'A' && n <= 'F')
+ n -= 'A' - 10;
+ else {
+ error_line();
+ fprintf (errfp, "*** Expected digit\n");
+ n = 0;
+ }
+ if (n >= radix)
+ errout ("Expected digit");
+ else
+ value = value * radix + n;
+ }
+ return (value);
+}
+
+int lookup (char *name)
+{
+ int i;
+ struct patchlist *p;
+
+ for (i = 0; i < nsymbols; ++i) {
+ if (strcmp (name, symbols[i].name) == 0) {
+ if ((symbols[i].flags & F_DEFINED) == 0) {
+ p = (struct patchlist *) &symbols[i].patchlist;
+ while (p->next)
+ p = p->next;
+ p->next = (struct patchlist *) malloc (sizeof (struct patchlist));
+ p = p->next;
+ p->next = NULL;
+ p->offset = dsps + 4;
+ }
+ return ((int) symbols[i].value);
+ }
+ }
+ if (nsymbols >= MAXSYMBOLS) {
+ errout ("Symbol table full");
+ return (0);
+ }
+ symbols[nsymbols].type = S_LABEL; /* assume forward reference */
+ symbols[nsymbols].flags = 0;
+ symbols[nsymbols].value = 0;
+ p = (struct patchlist *) malloc (sizeof (struct patchlist));
+ symbols[nsymbols].patchlist = p;
+ p->next = NULL;
+ p->offset = dsps + 4;
+ symbols[nsymbols].name = malloc (strlen (name) + 1);
+ strcpy (symbols[nsymbols].name, name);
+ ++nsymbols;
+ return (0);
+}
+
+void f_arch (void)
+{
+ int i, archsave;
+
+ i = tokenix;
+
+ archsave = arch;
+ setarch(tokens[i].name);
+ if( arch == 0) {
+ errout("Unrecognized ARCH");
+ arch = archsave;
+ }
+}
+
+void f_proc (void)
+{
+ if (tokens[tokenix].type != 0 || tokens[tokenix + 1].type != ':')
+ errout ("Invalid PROC statement");
+ else
+ new_script (tokens[tokenix].name);
+}
+
+void f_pass (void)
+{
+ errout ("PASS option not implemented");
+}
+
+/*
+ * f_list: process list of symbols for the ENTRY and EXTERNAL directive
+ */
+
+void f_list (void)
+{
+ int i;
+ short type;
+ short flags;
+
+ type = strcmpi (tokens[tokenix-1].name, "ENTRY") ? S_EXTERNAL : S_LABEL;
+ flags = type == S_LABEL ? F_ENTRY : 0;
+ for (i = tokenix; i < ntokens; ++i) {
+ if (tokens[i].type != 0) {
+ errout ("Expected an identifier");
+ return;
+ }
+ define_symbol (tokens[i].name, 0, type, flags);
+ if (i + 1 < ntokens) {
+ if (tokens[++i].type == ',')
+ continue;
+ errout ("Expected a separator");
+ return;
+ }
+ }
+}
+
+/*
+ * f_define: process list of definitions for ABSOLUTE and RELATIVE directive
+ */
+
+void f_define (void)
+{
+ int i;
+ char *name;
+ u_int32_t value;
+ int type;
+
+ type = strcmpi (tokens[tokenix-1].name, "ABSOLUTE") ? S_RELATIVE : S_ABSOLUTE;
+ i = tokenix;
+ while (i < ntokens) {
+ if (tokens[i].type) {
+ errout ("Expected an identifier");
+ return;
+ }
+ if (tokens[i + 1].type != '=') {
+ errout ("Expected a separator");
+ return;
+ }
+ name = tokens[i].name;
+ i += 2;
+ value = expression (&i);
+ define_symbol (name, value, type, F_DEFINED);
+ }
+}
+
+void store_inst ()
+{
+ int i = dsps / 4;
+ int l = 8;
+
+ if ((inst0 & 0xe0000000) == 0xc0000000)
+ l = 12; /* Memory to memory move is 12 bytes */
+ if ((dsps + l) / 4 > MAXINST) {
+ errout ("Instruction table overflow");
+ return;
+ }
+ script[i++] = inst0;
+ script[i++] = inst1;
+ if (l == 12)
+ script[i++] = inst2;
+ if (listfp) {
+ fprintf (listfp, "\t%04x: %08x %08x", dsps, inst0, inst1);
+ if (l == 12)
+ fprintf (listfp, " %08x", inst2);
+ fprintf (listfp, "\n");
+ }
+ dsps += l;
+ inst0 = inst1 = inst2 = 0;
+ ++ninsts;
+}
+
+void f_move (void)
+{
+ if (reserved ("memory", tokenix))
+ memory_to_memory ();
+ else if (reserved ("from", tokenix) || tokens[tokenix+1].type == ',')
+ block_move ();
+ else
+ register_write ();
+ store_inst ();
+}
+
+void f_jump (void)
+{
+ transfer (0x80000000, 0);
+}
+
+void f_call (void)
+{
+ transfer (0x88000000, 0);
+}
+
+void f_return (void)
+{
+ transfer (0x90000000, 1);
+}
+
+void f_int (void)
+{
+ transfer (0x98000000, 2);
+}
+
+void f_select (void)
+{
+ int t = tokenix;
+
+ if (reserved ("atn", t)) {
+ inst0 = 0x01000000;
+ ++t;
+ }
+ select_reselect (t);
+}
+
+void f_reselect (void)
+{
+ select_reselect (tokenix);
+}
+
+void f_wait (void)
+{
+ int i = tokenix;
+
+ inst1 = 0;
+ if (reserved ("disconnect", i)) {
+ inst0 = 0x48000000;
+ }
+ else {
+ if (reserved ("reselect", i))
+ inst0 = 0x50000000;
+ else if (reserved ("select", i))
+ inst0 = 0x50000000;
+ else
+ errout ("Expected SELECT or RESELECT");
+ ++i;
+ if (reserved ("rel", i)) {
+ i += 2;
+ inst1 = evaluate (i) - dsps - 8;
+ inst0 |= 0x04000000;
+ }
+ else
+ inst1 = evaluate (i);
+ }
+ store_inst ();
+}
+
+void f_disconnect (void)
+{
+ inst0 = 0x48000000;
+ store_inst ();
+}
+
+void f_set (void)
+{
+ set_clear (0x58000000);
+}
+
+void f_clear (void)
+{
+ set_clear (0x60000000);
+}
+
+void f_load (void)
+{
+ inst0 = 0xe1000000;
+ if (arch < ARCH810) {
+ errout ("Wrong arch for load/store");
+ return;
+ }
+ loadstore(tokenix);
+}
+
+void f_store (void)
+{
+ int i;
+ inst0 = 0xe0000000;
+ if (arch < ARCH810) {
+ errout ("Wrong arch for load/store");
+ return;
+ }
+ i = tokenix;
+ if (reserved("noflush", i)) {
+ inst0 |= 0x2000000;
+ i++;
+ }
+ loadstore(i);
+}
+
+void f_nop (void)
+{
+ inst0 = 0x10000000;
+ inst1 = 0x00000000;
+ store_inst ();
+}
+
+void loadstore(int i)
+{
+ int reg, size;
+
+ reg = CheckRegister(i);
+ if (reg < 0)
+ errout ("Expected register");
+ else
+ inst0 |= reg << 16;
+ if (reg == 8)
+ errout ("Register can't be SFBR");
+ i++;
+ if (tokens[i].type == ',')
+ i++;
+ else
+ errout ("expected ','");
+ size = evaluate(i);
+ if (i < 1 || i > 4)
+ errout("wrong size");
+ if ((reg & 0x3) + size > 4)
+ errout("size too big for register");
+ inst0 |= size;
+ i++;
+ if (tokens[i].type == ',')
+ i++;
+ else
+ errout ("expected ','");
+ if (reserved("from", i) || reserved("dsarel", i)) {
+ i++;
+ inst0 |= 0x10000000;
+ }
+ inst1 = evaluate(i);
+ store_inst ();
+}
+
+void transfer (int word0, int type)
+{
+ int i;
+
+ i = tokenix;
+ inst0 = word0;
+ if (type == 0 && reserved ("rel", i)) {
+ inst1 = evaluate (i + 2) - dsps - 8;
+ i += 4;
+ inst0 |= 0x00800000;
+ }
+ else if (type != 1) {
+ inst1 = evaluate (i);
+ ++i;
+ }
+ if (i >= ntokens) {
+ inst0 |= 0x00080000;
+ store_inst ();
+ return;
+ }
+ if (tokens[i].type != ',')
+ errout ("Expected a separator, ',' assumed");
+ else
+ ++i;
+ if (reserved("when", i))
+ inst0 |= 0x00010000;
+ else if (reserved ("if", i) == 0) {
+ errout ("Expected a reserved word");
+ store_inst ();
+ return;
+ }
+ i++;
+ if (reserved("false", i)) {
+ store_inst ();
+ return;
+ }
+ if (reserved ("not", i))
+ ++i;
+ else
+ inst0 |= 0x00080000;
+ if (reserved ("atn", i)) {
+ inst0 |= 0x00020000;
+ ++i;
+ } else if (CheckPhase (i)) {
+ inst0 |= 0x00020000;
+ ++i;
+ }
+ if (i < ntokens && tokens[i].type != ',') {
+ if (inst0 & 0x00020000) {
+ if (inst0 & 0x00080000 && reserved ("and", i)) {
+ ++i;
+ }
+ else if ((inst0 & 0x00080000) == 0 && reserved ("or", i)) {
+ ++i;
+ }
+ else
+ errout ("Expected a reserved word");
+ }
+ inst0 |= 0x00040000 + (evaluate (i++) & 0xff);
+ }
+ if (i < ntokens) {
+ if (tokens[i].type == ',')
+ ++i;
+ else
+ errout ("Expected a separator, ',' assumed");
+ if (reserved ("and", i) && reserved ("mask", i + 1))
+ inst0 |= ((evaluate (i + 2) & 0xff) << 8);
+ else
+ errout ("Expected , AND MASK");
+ }
+ store_inst ();
+}
+
+void select_reselect (int t)
+{
+ inst0 |= 0x40000000; /* ATN may be set from SELECT */
+ if (reserved ("from", t)) {
+ ++t;
+ inst0 |= 0x02000000 | evaluate (t++);
+ }
+ else
+ inst0 |= (evaluate (t++) & 0xff) << 16;
+ if (tokens[t++].type == ',') {
+ if (reserved ("rel", t)) {
+ inst0 |= 0x04000000;
+ inst1 = evaluate (t + 2) - dsps - 8;
+ }
+ else
+ inst1 = evaluate (t);
+ }
+ else
+ errout ("Expected separator");
+ store_inst ();
+}
+
+void set_clear (u_int32_t code)
+{
+ int i = tokenix;
+ short need_and = 0;
+
+ inst0 = code;
+ while (i < ntokens) {
+ if (need_and) {
+ if (reserved ("and", i))
+ ++i;
+ else
+ errout ("Expected AND");
+ }
+ if (reserved ("atn", i)) {
+ inst0 |= 0x0008;
+ ++i;
+ }
+ else if (reserved ("ack", i)) {
+ inst0 |= 0x0040;
+ ++i;
+ }
+ else if (reserved ("target", i)) {
+ inst0 |= 0x0200;
+ ++i;
+ }
+ else
+ errout ("Expected ATN, ACK, or TARGET");
+ need_and = 1;
+ }
+ store_inst ();
+}
+
+void block_move ()
+{
+ if (reserved ("from", tokenix)) {
+ inst1 = evaluate (tokenix+1);
+ inst0 |= 0x10000000 | inst1; /*** ??? to match Zeus script */
+ tokenix += 2;
+ }
+ else {
+ inst0 |= evaluate (tokenix++); /* count */
+ tokenix++; /* skip ',' */
+ if (reserved ("ptr", tokenix)) {
+ ++ tokenix;
+ inst0 |= 0x20000000;
+ }
+ inst1 = evaluate (tokenix++); /* address */
+ }
+ if (tokens[tokenix].type != ',')
+ errout ("Expected separator");
+ if (reserved ("when", tokenix + 1)) {
+ inst0 |= 0x08000000;
+ CheckPhase (tokenix + 2);
+ }
+ else if (reserved ("with", tokenix + 1)) {
+ CheckPhase (tokenix + 2);
+ }
+ else
+ errout ("Expected WITH or WHEN");
+}
+
+void register_write ()
+{
+ /*
+ * MOVE reg/data8 TO reg register write
+ * MOVE reg <op> data8 TO reg register write
+ * MOVE reg + data8 TO reg WITH CARRY register write
+ */
+ int op;
+ int reg;
+ int data;
+
+ if (reserved ("to", tokenix+1))
+ op = 0;
+ else if (tokens[tokenix+1].type == '|')
+ op = 2;
+ else if (tokens[tokenix+1].type == '&')
+ op = 4;
+ else if (tokens[tokenix+1].type == '+')
+ op = 6;
+ else if (tokens[tokenix+1].type == '-')
+ op = 8;
+ else
+ errout ("Unknown register operator");
+ if (op && reserved ("to", tokenix+3) == 0)
+ errout ("Register command expected TO");
+ reg = CheckRegister (tokenix);
+ if (reg < 0) { /* Not register, must be data */
+ data = evaluate (tokenix);
+ if (op)
+ errout ("Register operator not move");
+ reg = CheckRegister (tokenix+2);
+ if (reg < 0)
+ errout ("Expected register");
+ inst0 = 0x78000000 | (data << 8) | reg << 16;
+#if 0
+fprintf (listfp, "Move data to register: %02x %d\n", data, reg);
+#endif
+ }
+ else if (op) { /* A register read/write operator */
+ data = evaluate (tokenix+2);
+ if (tokenix+5 < ntokens) {
+ if (!reserved("with", tokenix+5) ||
+ !reserved("carry", tokenix+6)) {
+ errout("Expected 'WITH CARRY'");
+ } else if (op != 6) {
+ errout("'WITH CARRY' only valide with '+'");
+ }
+ op = 7;
+ }
+ if (op == 8) {
+ data = -data;
+ op = 6;
+ }
+ inst0 = (data & 0xff) << 8;
+ data = CheckRegister (tokenix+4);
+ if (data < 0)
+ errout ("Expected register");
+ if (reg != data && reg != 8 && data != 8)
+ errout ("One register MUST be SBFR");
+ if (reg == data) { /* A register read/modify/write */
+#if 0
+fprintf (listfp, "Read/modify register: %02x %d %d\n", inst0 >> 8, op, reg);
+#endif
+ inst0 |= 0x78000000 | (op << 24) | (reg << 16);
+ }
+ else { /* A move to/from SFBR */
+ if (reg == 8) { /* MOVE SFBR <> TO reg */
+#if 0
+fprintf (listfp, "Move SFBR to register: %02x %d %d\n", inst0 >> 8, op, data);
+#endif
+ inst0 |= 0x68000000 | (op << 24) | (data << 16);
+ }
+ else {
+#if 0
+fprintf (listfp, "Move register to SFBR: %02x %d %d\n", inst0 >> 8, op, reg);
+#endif
+ inst0 |= 0x70000000 | (op << 24) | (reg << 16);
+ }
+ }
+ }
+ else { /* register to register */
+ data = CheckRegister (tokenix+2);
+ if (reg == 8) /* move SFBR to reg */
+ inst0 = 0x6a000000 | (data << 16);
+ else if (data == 8) /* move reg to SFBR */
+ inst0 = 0x72000000 | (reg << 16);
+ else
+ errout ("One register must be SFBR");
+ }
+}
+
+void memory_to_memory ()
+{
+ inst0 = 0xc0000000 + evaluate (tokenix+1);
+ inst1 = evaluate (tokenix+3);
+ /*
+ * need to hack dsps, otherwise patch offset will be wrong for
+ * second pointer
+ */
+ dsps += 4;
+ inst2 = evaluate (tokenix+5);
+ dsps -= 4;
+}
+
+void error_line()
+{
+ if (errfp != listfp && errfp && err_listed == 0) {
+ fprintf (errfp, "%3d: %s", lineno, inbuf);
+ err_listed = 1;
+ }
+}
+
+char * makefn (base, sub)
+ char *base;
+ char *sub;
+{
+ char *fn;
+
+ fn = malloc (strlen (base) + strlen (sub) + 2);
+ strcpy (fn, base);
+ base = strrchr(fn, '.');
+ if (base)
+ *base = 0;
+ strcat (fn, ".");
+ strcat (fn, sub);
+ return (fn);
+}
+
+void usage()
+{
+ fprintf (stderr, "usage: scc sourcfile [options]\n");
+ exit(1);
+}