/* $NetBSD: ncr53cxxx.c,v 1.6 2001/04/29 11:20:44 tsutsui 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 #include #include #include #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}}, {"sdid", {0x02, -1, -1, -1}}, {"sien", {0x03, -1, -1, -1}}, {"scid", {0x04, -1, -1, -1}}, {"scntl2", { -1, 0x02, 0x02, 0x02}}, {"scntl3", { -1, 0x03, 0x03, 0x03}}, {"scid", { -1, 0x04, 0x04, 0x04}}, {"sxfer", {0x05, 0x05, 0x05, 0x05}}, {"sodl", {0x06, -1, -1, -1}}, {"socl", {0x07, -1, -1, -1}}, {"sdid", { -1, 0x06, 0x06, 0x06}}, {"gpreg", { -1, 0x07, 0x07, 0x07}}, {"sfbr", {0x08, 0x08, 0x08, 0x08}}, {"sidl", {0x09, -1, -1, -1}}, {"sbdl", {0x0a, -1, -1, -1}}, {"socl", { -1, 0x09, 0x09, 0x09}}, {"ssid", { -1, 0x0a, 0x0a, 0x0a}}, {"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}}, {"ctest0", {0x14, 0x18, 0x18, 0x18}}, {"ctest1", {0x15, 0x19, 0x19, 0x19}}, {"ctest2", {0x16, 0x1a, 0x1a, 0x1a}}, {"ctest3", {0x17, 0x1b, 0x1b, 0x1b}}, {"ctest4", {0x18, 0x21, 0x21, 0x21}}, {"ctest5", {0x19, 0x22, 0x22, 0x22}}, {"ctest6", {0x1a, 0x23, 0x23, 0x23}}, {"ctest7", {0x1b, -1, -1, -1}}, {"temp0", {0x1c, 0x1c, 0x1c, 0x1c}}, {"temp1", {0x1d, 0x1d, 0x1d, 0x1d}}, {"temp2", {0x1e, 0x1e, 0x1e, 0x1e}}, {"temp3", {0x1f, 0x1f, 0x1f, 0x1f}}, {"dfifo", {0x20, 0x20, 0x20, 0x20}}, {"istat", {0x21, 0x14, 0x14, 0x14}}, {"ctest8", {0x22, -1, -1, -1}}, {"lcrc", {0x23, -1, -1, -1}}, {"dbc0", {0x24, 0x24, 0x24, 0x24}}, {"dbc1", {0x25, 0x25, 0x25, 0x25}}, {"dbc2", {0x26, 0x26, 0x26, 0x26}}, {"dcmd", {0x27, 0x27, 0x27, 0x27}}, {"dnad0", {0x28, 0x28, 0x28, 0x28}}, {"dnad1", {0x29, 0x29, 0x29, 0x29}}, {"dnad2", {0x2a, 0x2a, 0x2a, 0x2a}}, {"dnad3", {0x2b, 0x2b, 0x2b, 0x2b}}, {"dsp0", {0x2c, 0x2c, 0x2c, 0x2c}}, {"dsp1", {0x2d, 0x2d, 0x2d, 0x2d}}, {"dsp2", {0x2e, 0x2e, 0x2e, 0x2e}}, {"dsp3", {0x2f, 0x2f, 0x2f, 0x2f}}, {"dsps0", {0x30, 0x30, 0x30, 0x30}}, {"dsps1", {0x31, 0x31, 0x31, 0x31}}, {"dsps2", {0x32, 0x32, 0x32, 0x32}}, {"dsps3", {0x33, 0x33, 0x33, 0x33}}, {"scratch0", {0x34, -1, -1, -1}}, {"scratch1", {0x35, -1, -1, -1}}, {"scratch2", {0x36, -1, -1, -1}}, {"scratch3", {0x37, -1, -1, -1}}, {"scratcha0", { -1, 0x34, 0x34, 0x34}}, {"scratcha1", { -1, 0x35, 0x35, 0x35}}, {"scratcha2", { -1, 0x36, 0x36, 0x36}}, {"scratcha3", { -1, 0x37, 0x37, 0x37}}, {"dmode", {0x38, 0x38, 0x38, 0x38}}, {"dien", {0x39, 0x39, 0x39, 0x39}}, {"dwt", {0x3a, 0x3a, -1, -1}}, {"sbr", { -1, -1, 0x3a, 0x3a}}, {"dcntl", {0x3b, 0x3b, 0x3b, 0x3b}}, {"addr0", {0x3c, 0x3c, 0x3c, 0x3c}}, {"addr1", {0x3d, 0x3d, 0x3d, 0x3d}}, {"addr2", {0x3e, 0x3e, 0x3e, 0x3e}}, {"addr3", {0x3f, 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.6 2001/04/29 11:20:44 tsutsui 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 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); }