/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ /* * Assembler for Emu10k1 */ /* * Copyright (C) 4Front Technologies 1996-2008. */ #include #include #include #include #include #include #include #include #define MAX_GPR 256 #define MAX_GPR_PARMS 60 #define MAX_CONST_PARMS 128 #define GPR_NAME_SIZE 32 typedef struct { char name[GPR_NAME_SIZE]; unsigned int num; int type; int def; } gpr_t; typedef struct { unsigned int gpr; unsigned int value; } const_t; typedef struct { unsigned int ngpr; gpr_t gpr[MAX_GPR_PARMS]; } gpr_info; typedef struct { unsigned int nconst; const_t consts[MAX_CONST_PARMS]; } const_info; typedef struct { unsigned int code[1024]; gpr_info parms; const_info consts; int ninit; struct { uint32_t gpr; uint32_t value; char name[GPR_NAME_SIZE]; } init[MAX_GPR]; } emu10k1_file; #define MAX_NAME 64 #define MAX_SYMBOLS 1024 static int parms_only = 0; static int is_audigy = 0; static int verbose = 0; static int gpr_base = 0x100; static int input_base = 0x10; static int output_base = 0x20; static char *progname; typedef struct { char name[MAX_NAME]; int type; #define SY_DUMMY 0 #define SY_GPR 1 #define SY_INPUT 2 #define SY_OUTPUT 3 #define SY_CONST 4 #define SY_FX 5 #define SY_ACCUM 6 #define SY_PARM 7 int arg; } sym_t; typedef struct { char *name; int opcode; } instruction_t; static char remarks[2048] = ""; static char *banner = "/*\n" " * Note: This file was automatically generated by %s\n" " * on %s.\n" " */\n"; /* * Instructions. Each instruction takes 4 arguments, R, A, X, and Y. */ static instruction_t instructions[] = { { "MACS", 0x0}, /* R = A + (X * Y >> 31); saturation */ { "MACS1", 0x1}, /* R = A + (-X * Y >> 31); saturation */ { "MACW", 0x2}, /* R = A + (X * Y >> 31); wraparound */ { "MACW1", 0x3}, /* R = A + (-X * Y >> 31); wraparound */ { "MACINTS", 0x4}, /* R = A + (X * Y); saturation */ { "MACINTW", 0x5}, /* R = A + (X * Y); wraparound */ { "SUM", 0x6}, /* R = A + X + Y; saturation */ { "ACC3", 0x6}, /* R = A + X + Y; saturation */ { "MACMV", 0x7}, /* R = A, acc += X * Y >> 31 */ { "ANDXOR", 0x8}, /* R = (A & X) ^ Y */ { "TSTNEG", 0x9}, /* R = (A >= Y) ? X : ~X */ { "LIMIT", 0xa}, /* R = (A >= Y) ? X : Y */ { "LIMIT1", 0xb}, /* R = (A < Y) ? X : Y */ { "LOG", 0xc}, /* R = ... (log?) */ { "EXP", 0xd}, /* R = ... (exp?) */ { "INTERP", 0xe}, /* R = A + (X * (Y - A) >> 31) */ { "SKIP", 0xf}, /* R, CCR, CC_TEST, COUNT */ { NULL, 0} }; #define CHECK_COUNT(tokens, cnt, mincnt, maxcnt) \ if (cnt < mincnt) { \ error("Too few parameters for '%s' (have %d, min %d)", \ tokens[0], cnt - 1, mincnt - 1); \ return; \ } \ if (cnt > maxcnt) { \ error("Too many parameters for '%s' (have %d, max %d)", \ tokens[0], cnt - 1, maxcnt - 1); \ return; \ } static sym_t symtab[MAX_SYMBOLS]; static int nsyms = 0; static int lineno = 0, errors = 0; static emu10k1_file fle; static int pc; static int ngpr = 0; static char *infile; static int getaline(FILE *input, char **tokens) { char *s, *ls; static char *stmt = NULL, *lasts = NULL; static char line[4096]; int cnt, tokcnt; for (;;) { if (stmt == NULL) { if (fgets(line, sizeof (line), input) == NULL) return (-1); lineno++; /* * Special handling for .' comments. We use * .' as a keyword to ensure that entire * comment makes it through the C preprocessor * unmolested. We also need to make sure *we* * don't molest it either. The comment will * be exported to any resulting header, * allowing us to pass through copyright and * other information from the source file to * the resulting header. */ s = line; s += strspn(s, " \t"); if ((strncmp(s, ".'", 2) == 0) && (strchr(" \t\n", s[2]) != NULL)) { /* chop off trailing new line */ (void) strtok(line, "\n"); tokens[0] = s; s += 2; s += strspn(s, " \t"); if ((s[0] == '\'') && (s[strlen(s) - 1] == '\'')) { s[strlen(s) - 1] = 0; s++; } tokens[1] = s; tokens[0][2] = 0; tokens[2] = NULL; stmt = NULL; return (strlen(tokens[1]) ? 2 : 1); } /* strip off any C++ style comments that CPP missed */ if ((s = strstr(line, "//")) != NULL) { *s = '\0'; } stmt = strtok_r(line, ";\n", &lasts); } else { stmt = strtok_r(NULL, ";\n", &lasts); } if (stmt != NULL) { break; } } /* * Ok, we have a statement, lets tokenize it. For * simplicities sake we convert "OPCODE(arg1, arg2)" into * "OPCODE arg1 arg2". This means that commas and parens are * treated as whitespace. This can lead to some really messed * up syntaxes that get assembled properly (such as nested * calls, empty arguments, etc.) Hopefully people don't abuse * this. */ ls = NULL; s = strtok_r(stmt, " \t\n(),", &ls); cnt = 0; tokcnt = 0; while (cnt < 10) { tokens[cnt++] = s; if (s != NULL) { tokcnt++; s = strtok_r(NULL, " \t\n(),", &ls); } } return (tokcnt); } static void error(char *msg, ...) { va_list va; char msgbuf[1024]; va_start(va, msg); (void) vsnprintf(msgbuf, sizeof (msgbuf), msg, va); va_end(va); (void) fprintf(stderr, "Error: %s on line %d of %s\n", msgbuf, lineno, infile); errors++; } static sym_t * find_symbol(char *name) { int i; for (i = 0; i < nsyms; i++) if (strcmp(symtab[i].name, name) == 0) { return (&symtab[i]); } return (NULL); } static void add_symbol(char *name, int type, int arg) { sym_t *sym; if (nsyms >= MAX_SYMBOLS) { error("Symbol table full"); exit(-1); } if (find_symbol(name) != NULL) { error("Dublicate symbol '%s'", name); return; } if (strlen(name) >= MAX_NAME) { error("Symbol name '%s' too long", name); exit(-1); } sym = &symtab[nsyms++]; (void) strcpy(sym->name, name); sym->type = type; sym->arg = arg; } static void add_init(uint32_t gpr, uint32_t val, const char *name) { int n; n = fle.ninit; if (n >= MAX_GPR) { error("Too many GPRs"); return; } fle.init[n].gpr = gpr; fle.init[n].value = val; if (name) (void) strlcpy(fle.init[n].name, name, sizeof (fle.init[n].name)); fle.ninit++; } static void compile_gpr(char **tokens, int cnt) { CHECK_COUNT(tokens, cnt, 2, 2); if (ngpr >= MAX_GPR) error("Too many GPR variables"); add_symbol(tokens[1], SY_GPR, gpr_base + ngpr++); } static void compile_rem(char **tokens, int cnt) { int i; (void) strlcat(remarks, " *", sizeof (remarks)); for (i = 1; i < cnt; i++) { (void) strlcat(remarks, " ", sizeof (remarks)); (void) strlcat(remarks, tokens[i], sizeof (remarks)); } (void) strlcat(remarks, "\n", sizeof (remarks)); } static void declare_const(unsigned int gpr, char *value) { int n, intv; float v; n = fle.consts.nconst; if (n >= MAX_CONST_PARMS) { error("Too many constant parameters"); return; } if (*value == 'I') { if (sscanf(&value[1], "%g", &v) != 1) { error("Bad floating point value (%s)", value); return; } intv = (int)v; } else if (*value == '0' && value[1] == 'x') { if (sscanf(&value[2], "%x", (unsigned *)&intv) != 1) { error("Bad hexadecimal value (%s)", value); return; } } else { if (sscanf(value, "%g", &v) != 1) { error("Bad floating point value (%s)", value); return; } intv = (int)(v * 0x7fffffff); } fle.consts.consts[n].gpr = gpr; fle.consts.consts[n].value = intv; fle.consts.nconst = n + 1; add_init(gpr, intv, NULL); } static void compile_const(char **tokens, int cnt) { CHECK_COUNT(tokens, cnt, 2, 3); char *name = tokens[1]; char *value = tokens[2] ? tokens[2] : tokens[1]; if (ngpr >= MAX_GPR) error("Too many GPR variables"); declare_const(ngpr, value); add_symbol(name, SY_GPR, gpr_base + ngpr++); } static void compile_bool(char **tokens, int cnt) { char *parm, *def; int n, num; CHECK_COUNT(tokens, cnt, 3, 3); parm = tokens[1]; def = tokens[2]; n = fle.parms.ngpr; if (n >= MAX_GPR_PARMS) { error("Too many GPR parameters"); return; } if (sscanf(def, "%d", &num) != 1) { error("Bad integer value near '%s'", def); return; } (void) strcpy(fle.parms.gpr[n].name, parm); fle.parms.gpr[n].num = ngpr; fle.parms.gpr[n].def = num; fle.parms.ngpr = n + 1; add_init(ngpr, num, parm); add_symbol(parm, SY_PARM, gpr_base + ngpr++); } static void compile_mono(char **tokens, int cnt) { char *parm, *def; int n, num; CHECK_COUNT(tokens, cnt, 3, 3); parm = tokens[1]; def = tokens[2]; n = fle.parms.ngpr; if (n >= MAX_GPR_PARMS) { error("Too many GPR parameters"); return; } if (sscanf(def, "%d", &num) != 1) { error("Bad integer value near '%s'", def); return; } (void) strcpy(fle.parms.gpr[n].name, parm); fle.parms.gpr[n].num = ngpr; fle.parms.gpr[n].def = num; fle.parms.ngpr = n + 1; add_init(ngpr, num, parm); add_symbol(parm, SY_PARM, gpr_base + ngpr++); } static void compile_stereo(char **tokens, int cnt) { char *parm, *def; int n, num; char tmp[128]; CHECK_COUNT(tokens, cnt, 3, 3); parm = tokens[1]; def = tokens[2]; n = fle.parms.ngpr; if (n >= MAX_GPR_PARMS) { error("Too many GPR parameters"); return; } if (sscanf(def, "%d", &num) != 1) { error("Bad integer value near '%s'", def); return; } (void) strcpy(fle.parms.gpr[n].name, parm); fle.parms.gpr[n].num = ngpr; fle.parms.gpr[n].def = num | (num << 8); fle.parms.ngpr = n + 1; add_init(ngpr, num, parm); add_init(ngpr + 1, num, NULL); (void) sprintf(tmp, "%s_L", parm); add_symbol(tmp, SY_PARM, gpr_base + ngpr++); (void) sprintf(tmp, "%s_R", parm); add_symbol(tmp, SY_PARM, gpr_base + ngpr++); } static void compile_input(char **tokens, int cnt) { int num; CHECK_COUNT(tokens, cnt, 3, 3); if (sscanf(tokens[2], "%d", &num) != 1) { error("Bad integer value near '%s'", tokens[2]); return; } add_symbol(tokens[1], SY_INPUT, input_base + num); } static void compile_send(char **tokens, int cnt) { int num; CHECK_COUNT(tokens, cnt, 3, 3); if (sscanf(tokens[2], "%d", &num) != 1) { error("Bad integer near '%s'", tokens[2]); return; } add_symbol(tokens[1], SY_FX, num); } static void compile_output(char **tokens, int cnt) { int num; CHECK_COUNT(tokens, cnt, 3, 3); if (sscanf(tokens[2], "%d", &num) != 1) { error("Bad integer value near '%s'", tokens[2]); return; } add_symbol(tokens[1], SY_OUTPUT, output_base + num); } static void compile_directive(char **tokens, int cnt) { if (strcmp(tokens[0], ".gpr") == 0) { compile_gpr(tokens, cnt); return; } if (strcmp(tokens[0], ".const") == 0) { compile_const(tokens, cnt); return; } if (strcmp(tokens[0], ".stereo") == 0) { compile_stereo(tokens, cnt); return; } if (strcmp(tokens[0], ".mono") == 0) { compile_mono(tokens, cnt); return; } if (strcmp(tokens[0], ".bool") == 0) { compile_bool(tokens, cnt); return; } if (strcmp(tokens[0], ".input") == 0) { compile_input(tokens, cnt); return; } if (strcmp(tokens[0], ".send") == 0) { compile_send(tokens, cnt); return; } if (strcmp(tokens[0], ".output") == 0) { compile_output(tokens, cnt); return; } if (strcmp(tokens[0], ".rem") == 0) { compile_rem(tokens, cnt); return; } if (strcmp(tokens[0], ".'") == 0) { compile_rem(tokens, cnt); return; } error("Unknown directive '%s'", tokens[0]); } static void compile_asm(char **tokens, int cnt) { sym_t *symbols[4]; #define EMIT(o, r, a, x, y) \ fle.code[pc*2] = ((x) << 10) | (y); \ fle.code[pc*2+1] = ((o) << 20) | ((r) << 10) | a; pc++ #define EMIT_AUDIGY(o, r, a, x, y) \ fle.code[pc*2] = ((x) << 12) | (y); \ fle.code[pc*2+1] = ((o) << 24) | ((r) << 12) | a; pc++ int i, nerr = 0; int ninputs = 0; CHECK_COUNT(tokens, cnt, 5, 5); for (i = 0; i < 4; i++) { if ((symbols[i] = find_symbol(tokens[i+1])) == NULL) { (void) fprintf(stderr, "%s\n", tokens[i+1]); nerr++; error("Undefined symbol '%s'", tokens[i + 1]); continue; } if (symbols[i]->type == SY_INPUT) ninputs++; if (symbols[i]->type == SY_ACCUM && i != 1) error("Bad usage of 'accum' operand."); } if (nerr > 0) return; if (ninputs > 1) { error("Attempt to access more than one input " "GPRs by the same instruction"); } for (i = 0; instructions[i].name != NULL; i++) if (strcasecmp(tokens[0], instructions[i].name) == 0) { if (is_audigy) { EMIT_AUDIGY(instructions[i].opcode, symbols[0]->arg, symbols[1]->arg, symbols[2]->arg, symbols[3]->arg); } else { EMIT(instructions[i].opcode, symbols[0]->arg, symbols[1]->arg, symbols[2]->arg, symbols[3]->arg); } return; } error("Unrecognized instruction '%s'", tokens[0]); } static void init_compiler(void) { char tmp[100]; int i; (void) memset(&fle, 0, sizeof (fle)); /* * Initialize few predefined GPR parameter registers. These * definitions have to be in sync with the GPR_* macros in * . */ /* * Make sure we start at gpr id 2 for now; 0 and 1 may be used * differently. */ add_symbol("NULL", SY_DUMMY, gpr_base + ngpr++); add_symbol("NULL_", SY_DUMMY, gpr_base + ngpr++); pc = 0; if (is_audigy) { /* Initialize the code array with NOPs (AUDIGY) */ for (i = 0; i < 512; i++) { fle.code[i * 2 + 0] = (0xc0 << 12) | 0xc0; fle.code[i * 2 + 1] = (0x06 << 24) | (0xc0 << 12) | 0xc0; } for (i = 0; i < 32; i++) { (void) sprintf(tmp, "fx%d", i); add_symbol(tmp, SY_FX, i); } } else { /* Initialize the code array with NOPs (LIVE) */ for (i = 0; i < 512; i++) { fle.code[i * 2 + 0] = 0x10040; fle.code[i * 2 + 1] = 0x610040; } for (i = 0; i < 16; i++) { (void) sprintf(tmp, "fx%d", i); add_symbol(tmp, SY_FX, i); } } /* * Constants */ if (is_audigy) { /* Audigy symbols */ add_symbol("0", SY_CONST, 0x0c0); add_symbol("1", SY_CONST, 0x0c1); add_symbol("2", SY_CONST, 0x0c2); add_symbol("3", SY_CONST, 0x0c3); add_symbol("4", SY_CONST, 0x0c4); add_symbol("8", SY_CONST, 0x0c5); add_symbol("16", SY_CONST, 0x0c6); add_symbol("32", SY_CONST, 0x0c7); add_symbol("256", SY_CONST, 0x0c8); add_symbol("65536", SY_CONST, 0x0c9); add_symbol("2048", SY_CONST, 0x0ca); add_symbol("0x800", SY_CONST, 0x0ca); add_symbol("2^28", SY_CONST, 0x0cb); add_symbol("0x10000000", SY_CONST, 0x0cb); add_symbol("2^29", SY_CONST, 0x0cc); add_symbol("0x20000000", SY_CONST, 0x0cc); add_symbol("2^30", SY_CONST, 0x0cd); add_symbol("0x40000000", SY_CONST, 0x0cd); add_symbol("2^31", SY_CONST, 0x0ce); add_symbol("0x80000000", SY_CONST, 0x0ce); add_symbol("0x7fffffff", SY_CONST, 0x0cf); add_symbol("0xffffffff", SY_CONST, 0x0d0); add_symbol("-1", SY_CONST, 0x0d0); add_symbol("0xfffffffe", SY_CONST, 0x0d1); add_symbol("-2", SY_CONST, 0x0d1); add_symbol("0xc0000000", SY_CONST, 0x0d2); add_symbol("0x4f1bbcdc", SY_CONST, 0x0d3); add_symbol("0x5a7ef9db", SY_CONST, 0x0d4); add_symbol("0x100000", SY_CONST, 0x0d5); add_symbol("accum", SY_ACCUM, 0x0d6); add_symbol("CCR", SY_CONST, 0x0d7); add_symbol("noise_L", SY_CONST, 0x0d8); add_symbol("noise_R", SY_CONST, 0x0d9); add_symbol("IRQREQ", SY_CONST, 0x0da); } else { /* SB Live symbols */ add_symbol("0", SY_CONST, 0x040); add_symbol("1", SY_CONST, 0x041); add_symbol("2", SY_CONST, 0x042); add_symbol("3", SY_CONST, 0x043); add_symbol("4", SY_CONST, 0x044); add_symbol("8", SY_CONST, 0x045); add_symbol("16", SY_CONST, 0x046); add_symbol("32", SY_CONST, 0x047); add_symbol("256", SY_CONST, 0x048); add_symbol("65536", SY_CONST, 0x049); add_symbol("2^23", SY_CONST, 0x04a); add_symbol("0x80000", SY_CONST, 0x04a); add_symbol("2^28", SY_CONST, 0x04b); add_symbol("0x10000000", SY_CONST, 0x04b); add_symbol("2^29", SY_CONST, 0x04c); add_symbol("0x20000000", SY_CONST, 0x04c); add_symbol("2^30", SY_CONST, 0x04d); add_symbol("0x40000000", SY_CONST, 0x04d); add_symbol("2^31", SY_CONST, 0x04e); add_symbol("0x80000000", SY_CONST, 0x04e); add_symbol("0x7fffffff", SY_CONST, 0x04f); add_symbol("0xffffffff", SY_CONST, 0x050); add_symbol("-1", SY_CONST, 0x050); add_symbol("0xfffffffe", SY_CONST, 0x051); add_symbol("-2", SY_CONST, 0x051); add_symbol("accum", SY_ACCUM, 0x056); add_symbol("CCR", SY_CONST, 0x057); add_symbol("noise_L", SY_CONST, 0x058); add_symbol("noise_R", SY_CONST, 0x059); add_symbol("IRQREQ", SY_CONST, 0x05a); } } static void produce_map(char *name) { int i; FILE *f; if ((f = fopen(name, "w")) == NULL) { perror(name); return; } (void) fprintf(f, "%d\n", pc); for (i = 0; i < nsyms; i++) { (void) fprintf(f, "%04x %x %s\n", symtab[i].arg, symtab[i].type, symtab[i].name); } (void) fclose(f); if (verbose) { (void) fprintf(stderr, "No errors detected - Map written to %s\n", name); } } static void produce_output(char *fname) { int fd; if ((fd = creat(fname, 0644)) == -1) { perror(fname); exit(-1); } if (write(fd, &fle, sizeof (fle)) != sizeof (fle)) { perror(fname); exit(-1); } if (verbose) { (void) fprintf(stderr, "No errors detected - Binary written to %s\n", fname); } (void) close(fd); } static void produce_header(char *fname, char *prefix) { FILE *f; char *s; char sname[MAXPATHLEN + 1]; char dname[MAXPATHLEN + 1]; int i; clock_t now; char when[128]; /* get basename */ if (prefix == NULL) { s = strrchr(fname, '/'); s = (s == NULL) ? fname : s + 1; } else { s = prefix; } (void) strlcpy(sname, s, sizeof (sname)); /* strip off any extension */ s = strchr(sname, '.'); if (s != NULL) { *s = 0; } if ((f = fopen(fname, "w")) == NULL) { perror(fname); return; } if (remarks[0] != 0) { (void) fprintf(f, "/*\n%s */\n", remarks); } now = time(NULL); strftime(when, sizeof (when), "%c", localtime(&now)); (void) fprintf(f, banner, progname, when); (void) strlcpy(dname, prefix ? prefix : sname, sizeof (dname)); for (i = 0; dname[i]; i++) { dname[i] = toupper(dname[i]); if (!isalnum(dname[i])) { dname[i] = '_'; } } for (i = 0; i < fle.parms.ngpr; i++) { (void) fprintf(f, "#define\t%s_%s\t\t%d\n", dname, fle.parms.gpr[i].name, fle.parms.gpr[i].num); } (void) fprintf(f, "\n"); if (parms_only) goto done; (void) fprintf(f, "uint32_t %s_code[] = {\n", sname); for (i = 0; i < pc * 2; i++) { if (i == 0) { (void) fprintf(f, "\t0x%08xU", fle.code[i]); } else if ((i % 4) == 0) { (void) fprintf(f, ",\n\t0x%08xU", fle.code[i]); } else { (void) fprintf(f, ", 0x%08xU", fle.code[i]); } } (void) fprintf(f, "\n};\n"); (void) fprintf(f, "uint32_t %s_ninit = %d;\n", sname, fle.ninit); (void) fprintf(f, "uint32_t %s_init[] = {\n", sname); for (i = 0; i < fle.ninit; i++) { if (fle.init[i].name[0]) { (void) fprintf(f, "\t%u, 0x%x%s,\t/* %s */\n", fle.init[i].gpr, fle.init[i].value, fle.init[i].value >= 0x80000000U ? "U" : "", fle.init[i].name); } else { (void) fprintf(f, "\t%u, 0x%x%s,\n", fle.init[i].gpr, fle.init[i].value, fle.init[i].value >= 0x80000000U ? "U" : ""); } } (void) fprintf(f, "};\n"); done: (void) fclose(f); if (verbose) { (void) fprintf(stderr, "No errors detected - Header written to %s\n", fname); } } int main(int argc, char *argv[]) { char *outfile; int i; FILE *input; char *tokens[10]; int tokcnt; char *mapfile = NULL; char *header = NULL; char *prefix = NULL; outfile = NULL; infile = NULL; input = NULL; progname = argv[0]; while ((i = getopt(argc, argv, "m:h:o:i:P:021v")) != EOF) { switch (i) { case 'o': outfile = optarg; break; case 'i': infile = strdup(optarg); break; case 'm': mapfile = optarg; break; case 'P': prefix = optarg; break; case 'h': header = optarg; break; case '0': parms_only = 1; break; case '2': is_audigy = 1; break; case '1': is_audigy = 0; break; case 'v': verbose++; break; default: (void) fprintf(stderr, "usage: %s [-m ] [-h
] " "[-o ] [-i ] [-2|-1]", progname); exit(-1); break; } } if ((outfile == NULL) && (mapfile == NULL) && (header == NULL)) { outfile = "dsp.bin"; } if (infile) { input = fopen(infile, "r"); if (input == NULL) { perror(infile); exit(-1); } } else { infile = strdup(""); input = stdin; } if (is_audigy) { gpr_base = 0x400; input_base = 0x40; output_base = 0x60; if (verbose) (void) fprintf(stderr, "Compiling for SB Audigy\n"); } else { if (verbose) (void) fprintf(stderr, "Compiling for SB Live\n"); } init_compiler(); while ((tokcnt = getaline(input, tokens)) != -1) { /* skip empty lines */ if (tokcnt == 0) { continue; } if (strcmp(tokens[0], "#") == 0) { int num; if ((tokcnt >= 3) && (sscanf(tokens[1], "%d", &num) == 1)) { lineno = num; free(infile); infile = strdup(tokens[2]); /* we don't want to count the # directive */ lineno--; } /* unknown # directive? muddle on... */ continue; } if (*tokens[0] == '.') { compile_directive(tokens, tokcnt); } else { compile_asm(tokens, tokcnt); } } if (lineno < 1) { error("Empty input"); } if (errors == 0) { if (verbose) { (void) fprintf(stderr, "%d instructions out of 512 assembled\n", pc); } if (outfile) produce_output(outfile); if (mapfile) produce_map(mapfile); if (header) produce_header(header, prefix); } if (errors > 0) { (void) fprintf(stderr, "%d errors - compile failed\n", errors); exit(-1); } return (0); }