1992413f4SGarrett D'Amore /*
2992413f4SGarrett D'Amore * CDDL HEADER START
3992413f4SGarrett D'Amore *
4992413f4SGarrett D'Amore * The contents of this file are subject to the terms of the
5992413f4SGarrett D'Amore * Common Development and Distribution License (the "License").
6992413f4SGarrett D'Amore * You may not use this file except in compliance with the License.
7992413f4SGarrett D'Amore *
8992413f4SGarrett D'Amore * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9992413f4SGarrett D'Amore * or http://www.opensolaris.org/os/licensing.
10992413f4SGarrett D'Amore * See the License for the specific language governing permissions
11992413f4SGarrett D'Amore * and limitations under the License.
12992413f4SGarrett D'Amore *
13992413f4SGarrett D'Amore * When distributing Covered Code, include this CDDL HEADER in each
14992413f4SGarrett D'Amore * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15992413f4SGarrett D'Amore * If applicable, add the following below this CDDL HEADER, with the
16992413f4SGarrett D'Amore * fields enclosed by brackets "[]" replaced with your own identifying
17992413f4SGarrett D'Amore * information: Portions Copyright [yyyy] [name of copyright owner]
18992413f4SGarrett D'Amore *
19992413f4SGarrett D'Amore * CDDL HEADER END
20992413f4SGarrett D'Amore */
21992413f4SGarrett D'Amore
22992413f4SGarrett D'Amore /*
2323a1cceaSRoger A. Faulkner * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24992413f4SGarrett D'Amore */
25992413f4SGarrett D'Amore
26992413f4SGarrett D'Amore /*
27992413f4SGarrett D'Amore * Assembler for Emu10k1
28992413f4SGarrett D'Amore */
29992413f4SGarrett D'Amore /*
30992413f4SGarrett D'Amore * Copyright (C) 4Front Technologies 1996-2008.
31992413f4SGarrett D'Amore */
32992413f4SGarrett D'Amore
33992413f4SGarrett D'Amore #include <stdio.h>
34992413f4SGarrett D'Amore #include <stdlib.h>
35992413f4SGarrett D'Amore #include <unistd.h>
36992413f4SGarrett D'Amore #include <fcntl.h>
37992413f4SGarrett D'Amore #include <string.h>
38992413f4SGarrett D'Amore #include <stdarg.h>
39992413f4SGarrett D'Amore #include <ctype.h>
40992413f4SGarrett D'Amore #include <sys/param.h>
41992413f4SGarrett D'Amore
42992413f4SGarrett D'Amore #define MAX_GPR 256
43992413f4SGarrett D'Amore #define MAX_GPR_PARMS 60
44992413f4SGarrett D'Amore #define MAX_CONST_PARMS 128
45992413f4SGarrett D'Amore #define GPR_NAME_SIZE 32
46992413f4SGarrett D'Amore
47992413f4SGarrett D'Amore typedef struct {
48992413f4SGarrett D'Amore char name[GPR_NAME_SIZE];
49992413f4SGarrett D'Amore unsigned int num;
50992413f4SGarrett D'Amore int type;
51992413f4SGarrett D'Amore int def;
52992413f4SGarrett D'Amore } gpr_t;
53992413f4SGarrett D'Amore
54992413f4SGarrett D'Amore typedef struct {
55992413f4SGarrett D'Amore unsigned int gpr;
56992413f4SGarrett D'Amore unsigned int value;
57992413f4SGarrett D'Amore } const_t;
58992413f4SGarrett D'Amore
59992413f4SGarrett D'Amore typedef struct {
60992413f4SGarrett D'Amore unsigned int ngpr;
61992413f4SGarrett D'Amore
62992413f4SGarrett D'Amore gpr_t gpr[MAX_GPR_PARMS];
63992413f4SGarrett D'Amore } gpr_info;
64992413f4SGarrett D'Amore
65992413f4SGarrett D'Amore typedef struct {
66992413f4SGarrett D'Amore unsigned int nconst;
67992413f4SGarrett D'Amore
68992413f4SGarrett D'Amore const_t consts[MAX_CONST_PARMS];
69992413f4SGarrett D'Amore } const_info;
70992413f4SGarrett D'Amore
71992413f4SGarrett D'Amore typedef struct {
72992413f4SGarrett D'Amore unsigned int code[1024];
73992413f4SGarrett D'Amore gpr_info parms;
74992413f4SGarrett D'Amore const_info consts;
75992413f4SGarrett D'Amore int ninit;
76992413f4SGarrett D'Amore struct {
77992413f4SGarrett D'Amore uint32_t gpr;
78992413f4SGarrett D'Amore uint32_t value;
79992413f4SGarrett D'Amore char name[GPR_NAME_SIZE];
80992413f4SGarrett D'Amore } init[MAX_GPR];
81992413f4SGarrett D'Amore } emu10k1_file;
82992413f4SGarrett D'Amore
83992413f4SGarrett D'Amore #define MAX_NAME 64
84992413f4SGarrett D'Amore #define MAX_SYMBOLS 1024
85992413f4SGarrett D'Amore
86992413f4SGarrett D'Amore static int parms_only = 0;
87992413f4SGarrett D'Amore static int is_audigy = 0;
88992413f4SGarrett D'Amore static int verbose = 0;
89992413f4SGarrett D'Amore
90992413f4SGarrett D'Amore static int gpr_base = 0x100;
91992413f4SGarrett D'Amore static int input_base = 0x10;
92992413f4SGarrett D'Amore static int output_base = 0x20;
93992413f4SGarrett D'Amore
94992413f4SGarrett D'Amore static char *progname;
95992413f4SGarrett D'Amore
96992413f4SGarrett D'Amore typedef struct {
97992413f4SGarrett D'Amore char name[MAX_NAME];
98992413f4SGarrett D'Amore int type;
99992413f4SGarrett D'Amore #define SY_DUMMY 0
100992413f4SGarrett D'Amore #define SY_GPR 1
101992413f4SGarrett D'Amore #define SY_INPUT 2
102992413f4SGarrett D'Amore #define SY_OUTPUT 3
103992413f4SGarrett D'Amore #define SY_CONST 4
104992413f4SGarrett D'Amore #define SY_FX 5
105992413f4SGarrett D'Amore #define SY_ACCUM 6
106992413f4SGarrett D'Amore #define SY_PARM 7
107992413f4SGarrett D'Amore int arg;
108992413f4SGarrett D'Amore } sym_t;
109992413f4SGarrett D'Amore
110992413f4SGarrett D'Amore typedef struct {
111992413f4SGarrett D'Amore char *name;
112992413f4SGarrett D'Amore int opcode;
113992413f4SGarrett D'Amore } instruction_t;
114992413f4SGarrett D'Amore
115992413f4SGarrett D'Amore static char remarks[2048] = "";
116992413f4SGarrett D'Amore static char *banner =
117992413f4SGarrett D'Amore "/*\n"
118992413f4SGarrett D'Amore " * Note: This file was automatically generated by %s\n"
119992413f4SGarrett D'Amore " * on %s.\n"
120992413f4SGarrett D'Amore " */\n";
121992413f4SGarrett D'Amore
122992413f4SGarrett D'Amore /*
123992413f4SGarrett D'Amore * Instructions. Each instruction takes 4 arguments, R, A, X, and Y.
124992413f4SGarrett D'Amore */
125992413f4SGarrett D'Amore static instruction_t instructions[] = {
126992413f4SGarrett D'Amore { "MACS", 0x0}, /* R = A + (X * Y >> 31); saturation */
127992413f4SGarrett D'Amore { "MACS1", 0x1}, /* R = A + (-X * Y >> 31); saturation */
128992413f4SGarrett D'Amore { "MACW", 0x2}, /* R = A + (X * Y >> 31); wraparound */
129992413f4SGarrett D'Amore { "MACW1", 0x3}, /* R = A + (-X * Y >> 31); wraparound */
130992413f4SGarrett D'Amore { "MACINTS", 0x4}, /* R = A + (X * Y); saturation */
131992413f4SGarrett D'Amore { "MACINTW", 0x5}, /* R = A + (X * Y); wraparound */
132992413f4SGarrett D'Amore { "SUM", 0x6}, /* R = A + X + Y; saturation */
133992413f4SGarrett D'Amore { "ACC3", 0x6}, /* R = A + X + Y; saturation */
134992413f4SGarrett D'Amore { "MACMV", 0x7}, /* R = A, acc += X * Y >> 31 */
135992413f4SGarrett D'Amore { "ANDXOR", 0x8}, /* R = (A & X) ^ Y */
136992413f4SGarrett D'Amore { "TSTNEG", 0x9}, /* R = (A >= Y) ? X : ~X */
137992413f4SGarrett D'Amore { "LIMIT", 0xa}, /* R = (A >= Y) ? X : Y */
138992413f4SGarrett D'Amore { "LIMIT1", 0xb}, /* R = (A < Y) ? X : Y */
139992413f4SGarrett D'Amore { "LOG", 0xc}, /* R = ... (log?) */
140992413f4SGarrett D'Amore { "EXP", 0xd}, /* R = ... (exp?) */
141992413f4SGarrett D'Amore { "INTERP", 0xe}, /* R = A + (X * (Y - A) >> 31) */
142992413f4SGarrett D'Amore { "SKIP", 0xf}, /* R, CCR, CC_TEST, COUNT */
143992413f4SGarrett D'Amore { NULL, 0}
144992413f4SGarrett D'Amore };
145992413f4SGarrett D'Amore
146992413f4SGarrett D'Amore #define CHECK_COUNT(tokens, cnt, mincnt, maxcnt) \
147992413f4SGarrett D'Amore if (cnt < mincnt) { \
148992413f4SGarrett D'Amore error("Too few parameters for '%s' (have %d, min %d)", \
149992413f4SGarrett D'Amore tokens[0], cnt - 1, mincnt - 1); \
150992413f4SGarrett D'Amore return; \
151992413f4SGarrett D'Amore } \
152992413f4SGarrett D'Amore if (cnt > maxcnt) { \
153992413f4SGarrett D'Amore error("Too many parameters for '%s' (have %d, max %d)", \
154992413f4SGarrett D'Amore tokens[0], cnt - 1, maxcnt - 1); \
155992413f4SGarrett D'Amore return; \
156992413f4SGarrett D'Amore }
157992413f4SGarrett D'Amore
158992413f4SGarrett D'Amore static sym_t symtab[MAX_SYMBOLS];
159992413f4SGarrett D'Amore static int nsyms = 0;
160992413f4SGarrett D'Amore
161992413f4SGarrett D'Amore static int lineno = 0, errors = 0;
162992413f4SGarrett D'Amore static emu10k1_file fle;
163992413f4SGarrett D'Amore static int pc;
164992413f4SGarrett D'Amore
165992413f4SGarrett D'Amore static int ngpr = 0;
166992413f4SGarrett D'Amore static char *infile;
167992413f4SGarrett D'Amore
168992413f4SGarrett D'Amore static int
getaline(FILE * input,char ** tokens)16923a1cceaSRoger A. Faulkner getaline(FILE *input, char **tokens)
170992413f4SGarrett D'Amore {
171992413f4SGarrett D'Amore char *s, *ls;
172992413f4SGarrett D'Amore static char *stmt = NULL, *lasts = NULL;
173992413f4SGarrett D'Amore static char line[4096];
174992413f4SGarrett D'Amore int cnt, tokcnt;
175992413f4SGarrett D'Amore
176992413f4SGarrett D'Amore for (;;) {
177992413f4SGarrett D'Amore
178992413f4SGarrett D'Amore if (stmt == NULL) {
179992413f4SGarrett D'Amore if (fgets(line, sizeof (line), input) == NULL)
180992413f4SGarrett D'Amore return (-1);
181992413f4SGarrett D'Amore lineno++;
182992413f4SGarrett D'Amore
183992413f4SGarrett D'Amore /*
184992413f4SGarrett D'Amore * Special handling for .' comments. We use
185992413f4SGarrett D'Amore * .' as a keyword to ensure that entire
186992413f4SGarrett D'Amore * comment makes it through the C preprocessor
187992413f4SGarrett D'Amore * unmolested. We also need to make sure *we*
188992413f4SGarrett D'Amore * don't molest it either. The comment will
189992413f4SGarrett D'Amore * be exported to any resulting header,
190992413f4SGarrett D'Amore * allowing us to pass through copyright and
191992413f4SGarrett D'Amore * other information from the source file to
192992413f4SGarrett D'Amore * the resulting header.
193992413f4SGarrett D'Amore */
194992413f4SGarrett D'Amore s = line;
195992413f4SGarrett D'Amore s += strspn(s, " \t");
196992413f4SGarrett D'Amore if ((strncmp(s, ".'", 2) == 0) &&
197992413f4SGarrett D'Amore (strchr(" \t\n", s[2]) != NULL)) {
198992413f4SGarrett D'Amore /* chop off trailing new line */
199992413f4SGarrett D'Amore (void) strtok(line, "\n");
200992413f4SGarrett D'Amore tokens[0] = s;
201992413f4SGarrett D'Amore s += 2;
202992413f4SGarrett D'Amore s += strspn(s, " \t");
203992413f4SGarrett D'Amore if ((s[0] == '\'') &&
204992413f4SGarrett D'Amore (s[strlen(s) - 1] == '\'')) {
205992413f4SGarrett D'Amore s[strlen(s) - 1] = 0;
206992413f4SGarrett D'Amore s++;
207992413f4SGarrett D'Amore }
208992413f4SGarrett D'Amore tokens[1] = s;
209992413f4SGarrett D'Amore tokens[0][2] = 0;
210992413f4SGarrett D'Amore tokens[2] = NULL;
211992413f4SGarrett D'Amore stmt = NULL;
212992413f4SGarrett D'Amore return (strlen(tokens[1]) ? 2 : 1);
213992413f4SGarrett D'Amore }
214992413f4SGarrett D'Amore
215992413f4SGarrett D'Amore /* strip off any C++ style comments that CPP missed */
216992413f4SGarrett D'Amore if ((s = strstr(line, "//")) != NULL) {
217bb2183e0SRichard PALO *s = '\0';
218992413f4SGarrett D'Amore }
219992413f4SGarrett D'Amore stmt = strtok_r(line, ";\n", &lasts);
220992413f4SGarrett D'Amore } else {
221992413f4SGarrett D'Amore stmt = strtok_r(NULL, ";\n", &lasts);
222992413f4SGarrett D'Amore }
223992413f4SGarrett D'Amore
224992413f4SGarrett D'Amore if (stmt != NULL) {
225992413f4SGarrett D'Amore break;
226992413f4SGarrett D'Amore }
227992413f4SGarrett D'Amore }
228992413f4SGarrett D'Amore
229992413f4SGarrett D'Amore /*
230992413f4SGarrett D'Amore * Ok, we have a statement, lets tokenize it. For
231992413f4SGarrett D'Amore * simplicities sake we convert "OPCODE(arg1, arg2)" into
232992413f4SGarrett D'Amore * "OPCODE arg1 arg2". This means that commas and parens are
233992413f4SGarrett D'Amore * treated as whitespace. This can lead to some really messed
234992413f4SGarrett D'Amore * up syntaxes that get assembled properly (such as nested
235992413f4SGarrett D'Amore * calls, empty arguments, etc.) Hopefully people don't abuse
236992413f4SGarrett D'Amore * this.
237992413f4SGarrett D'Amore */
238992413f4SGarrett D'Amore ls = NULL;
239992413f4SGarrett D'Amore s = strtok_r(stmt, " \t\n(),", &ls);
240992413f4SGarrett D'Amore cnt = 0;
241992413f4SGarrett D'Amore tokcnt = 0;
242992413f4SGarrett D'Amore while (cnt < 10) {
243992413f4SGarrett D'Amore tokens[cnt++] = s;
244992413f4SGarrett D'Amore if (s != NULL) {
245992413f4SGarrett D'Amore tokcnt++;
246992413f4SGarrett D'Amore s = strtok_r(NULL, " \t\n(),", &ls);
247992413f4SGarrett D'Amore }
248992413f4SGarrett D'Amore }
249992413f4SGarrett D'Amore return (tokcnt);
250992413f4SGarrett D'Amore }
251992413f4SGarrett D'Amore
252992413f4SGarrett D'Amore static void
error(char * msg,...)253992413f4SGarrett D'Amore error(char *msg, ...)
254992413f4SGarrett D'Amore {
255992413f4SGarrett D'Amore va_list va;
256992413f4SGarrett D'Amore char msgbuf[1024];
257992413f4SGarrett D'Amore
258992413f4SGarrett D'Amore va_start(va, msg);
259992413f4SGarrett D'Amore (void) vsnprintf(msgbuf, sizeof (msgbuf), msg, va);
260992413f4SGarrett D'Amore va_end(va);
261992413f4SGarrett D'Amore
262992413f4SGarrett D'Amore (void) fprintf(stderr, "Error: %s on line %d of %s\n", msgbuf, lineno,
263992413f4SGarrett D'Amore infile);
264992413f4SGarrett D'Amore errors++;
265992413f4SGarrett D'Amore }
266992413f4SGarrett D'Amore
267992413f4SGarrett D'Amore static sym_t *
find_symbol(char * name)268992413f4SGarrett D'Amore find_symbol(char *name)
269992413f4SGarrett D'Amore {
270992413f4SGarrett D'Amore int i;
271992413f4SGarrett D'Amore
272992413f4SGarrett D'Amore for (i = 0; i < nsyms; i++)
273992413f4SGarrett D'Amore if (strcmp(symtab[i].name, name) == 0) {
274992413f4SGarrett D'Amore return (&symtab[i]);
275992413f4SGarrett D'Amore }
276992413f4SGarrett D'Amore
277992413f4SGarrett D'Amore return (NULL);
278992413f4SGarrett D'Amore }
279992413f4SGarrett D'Amore
280992413f4SGarrett D'Amore static void
add_symbol(char * name,int type,int arg)281992413f4SGarrett D'Amore add_symbol(char *name, int type, int arg)
282992413f4SGarrett D'Amore {
283992413f4SGarrett D'Amore sym_t *sym;
284992413f4SGarrett D'Amore
285992413f4SGarrett D'Amore if (nsyms >= MAX_SYMBOLS) {
286992413f4SGarrett D'Amore error("Symbol table full");
287992413f4SGarrett D'Amore exit(-1);
288992413f4SGarrett D'Amore }
289992413f4SGarrett D'Amore
290992413f4SGarrett D'Amore if (find_symbol(name) != NULL) {
291992413f4SGarrett D'Amore error("Dublicate symbol '%s'", name);
292992413f4SGarrett D'Amore return;
293992413f4SGarrett D'Amore }
294992413f4SGarrett D'Amore
295992413f4SGarrett D'Amore if (strlen(name) >= MAX_NAME) {
296992413f4SGarrett D'Amore error("Symbol name '%s' too long", name);
297992413f4SGarrett D'Amore exit(-1);
298992413f4SGarrett D'Amore }
299992413f4SGarrett D'Amore
300992413f4SGarrett D'Amore sym = &symtab[nsyms++];
301992413f4SGarrett D'Amore
302992413f4SGarrett D'Amore (void) strcpy(sym->name, name);
303992413f4SGarrett D'Amore sym->type = type;
304992413f4SGarrett D'Amore sym->arg = arg;
305992413f4SGarrett D'Amore }
306992413f4SGarrett D'Amore
307992413f4SGarrett D'Amore static void
add_init(uint32_t gpr,uint32_t val,const char * name)308992413f4SGarrett D'Amore add_init(uint32_t gpr, uint32_t val, const char *name)
309992413f4SGarrett D'Amore {
310992413f4SGarrett D'Amore int n;
311992413f4SGarrett D'Amore
312992413f4SGarrett D'Amore n = fle.ninit;
313992413f4SGarrett D'Amore if (n >= MAX_GPR) {
314992413f4SGarrett D'Amore error("Too many GPRs");
315992413f4SGarrett D'Amore return;
316992413f4SGarrett D'Amore }
317992413f4SGarrett D'Amore fle.init[n].gpr = gpr;
318992413f4SGarrett D'Amore fle.init[n].value = val;
319992413f4SGarrett D'Amore if (name)
320992413f4SGarrett D'Amore (void) strlcpy(fle.init[n].name, name,
321992413f4SGarrett D'Amore sizeof (fle.init[n].name));
322992413f4SGarrett D'Amore fle.ninit++;
323992413f4SGarrett D'Amore }
324992413f4SGarrett D'Amore
325992413f4SGarrett D'Amore static void
compile_gpr(char ** tokens,int cnt)326992413f4SGarrett D'Amore compile_gpr(char **tokens, int cnt)
327992413f4SGarrett D'Amore {
328992413f4SGarrett D'Amore CHECK_COUNT(tokens, cnt, 2, 2);
329992413f4SGarrett D'Amore
330992413f4SGarrett D'Amore if (ngpr >= MAX_GPR)
331992413f4SGarrett D'Amore error("Too many GPR variables");
332992413f4SGarrett D'Amore
333992413f4SGarrett D'Amore add_symbol(tokens[1], SY_GPR, gpr_base + ngpr++);
334992413f4SGarrett D'Amore }
335992413f4SGarrett D'Amore
336992413f4SGarrett D'Amore static void
compile_rem(char ** tokens,int cnt)337992413f4SGarrett D'Amore compile_rem(char **tokens, int cnt)
338992413f4SGarrett D'Amore {
339992413f4SGarrett D'Amore int i;
340992413f4SGarrett D'Amore
341992413f4SGarrett D'Amore (void) strlcat(remarks, " *", sizeof (remarks));
342992413f4SGarrett D'Amore for (i = 1; i < cnt; i++) {
343992413f4SGarrett D'Amore (void) strlcat(remarks, " ", sizeof (remarks));
344992413f4SGarrett D'Amore (void) strlcat(remarks, tokens[i], sizeof (remarks));
345992413f4SGarrett D'Amore }
346992413f4SGarrett D'Amore (void) strlcat(remarks, "\n", sizeof (remarks));
347992413f4SGarrett D'Amore }
348992413f4SGarrett D'Amore
349992413f4SGarrett D'Amore static void
declare_const(unsigned int gpr,char * value)350992413f4SGarrett D'Amore declare_const(unsigned int gpr, char *value)
351992413f4SGarrett D'Amore {
352992413f4SGarrett D'Amore int n, intv;
353992413f4SGarrett D'Amore float v;
354992413f4SGarrett D'Amore
355992413f4SGarrett D'Amore n = fle.consts.nconst;
356992413f4SGarrett D'Amore
357992413f4SGarrett D'Amore if (n >= MAX_CONST_PARMS) {
358992413f4SGarrett D'Amore error("Too many constant parameters");
359992413f4SGarrett D'Amore return;
360992413f4SGarrett D'Amore }
361992413f4SGarrett D'Amore
362992413f4SGarrett D'Amore if (*value == 'I') {
363992413f4SGarrett D'Amore if (sscanf(&value[1], "%g", &v) != 1) {
364992413f4SGarrett D'Amore error("Bad floating point value (%s)", value);
365992413f4SGarrett D'Amore return;
366992413f4SGarrett D'Amore }
367992413f4SGarrett D'Amore intv = (int)v;
368992413f4SGarrett D'Amore } else if (*value == '0' && value[1] == 'x') {
369992413f4SGarrett D'Amore if (sscanf(&value[2], "%x", (unsigned *)&intv) != 1) {
370992413f4SGarrett D'Amore error("Bad hexadecimal value (%s)", value);
371992413f4SGarrett D'Amore return;
372992413f4SGarrett D'Amore }
373992413f4SGarrett D'Amore } else {
374992413f4SGarrett D'Amore if (sscanf(value, "%g", &v) != 1) {
375992413f4SGarrett D'Amore error("Bad floating point value (%s)", value);
376992413f4SGarrett D'Amore return;
377992413f4SGarrett D'Amore }
378992413f4SGarrett D'Amore intv = (int)(v * 0x7fffffff);
379992413f4SGarrett D'Amore }
380992413f4SGarrett D'Amore
381992413f4SGarrett D'Amore fle.consts.consts[n].gpr = gpr;
382992413f4SGarrett D'Amore fle.consts.consts[n].value = intv;
383992413f4SGarrett D'Amore fle.consts.nconst = n + 1;
384992413f4SGarrett D'Amore
385992413f4SGarrett D'Amore add_init(gpr, intv, NULL);
386992413f4SGarrett D'Amore }
387992413f4SGarrett D'Amore
388992413f4SGarrett D'Amore static void
compile_const(char ** tokens,int cnt)389992413f4SGarrett D'Amore compile_const(char **tokens, int cnt)
390992413f4SGarrett D'Amore {
391992413f4SGarrett D'Amore CHECK_COUNT(tokens, cnt, 2, 3);
392992413f4SGarrett D'Amore char *name = tokens[1];
393992413f4SGarrett D'Amore char *value = tokens[2] ? tokens[2] : tokens[1];
394992413f4SGarrett D'Amore
395992413f4SGarrett D'Amore if (ngpr >= MAX_GPR)
396992413f4SGarrett D'Amore error("Too many GPR variables");
397992413f4SGarrett D'Amore
398992413f4SGarrett D'Amore declare_const(ngpr, value);
399992413f4SGarrett D'Amore
400992413f4SGarrett D'Amore add_symbol(name, SY_GPR, gpr_base + ngpr++);
401992413f4SGarrett D'Amore }
402992413f4SGarrett D'Amore
403992413f4SGarrett D'Amore static void
compile_bool(char ** tokens,int cnt)404992413f4SGarrett D'Amore compile_bool(char **tokens, int cnt)
405992413f4SGarrett D'Amore {
406992413f4SGarrett D'Amore char *parm, *def;
407992413f4SGarrett D'Amore int n, num;
408992413f4SGarrett D'Amore
409992413f4SGarrett D'Amore CHECK_COUNT(tokens, cnt, 3, 3);
410992413f4SGarrett D'Amore
411992413f4SGarrett D'Amore parm = tokens[1];
412992413f4SGarrett D'Amore def = tokens[2];
413992413f4SGarrett D'Amore
414992413f4SGarrett D'Amore n = fle.parms.ngpr;
415992413f4SGarrett D'Amore if (n >= MAX_GPR_PARMS) {
416992413f4SGarrett D'Amore error("Too many GPR parameters");
417992413f4SGarrett D'Amore return;
418992413f4SGarrett D'Amore }
419992413f4SGarrett D'Amore
420992413f4SGarrett D'Amore if (sscanf(def, "%d", &num) != 1) {
421992413f4SGarrett D'Amore error("Bad integer value near '%s'", def);
422992413f4SGarrett D'Amore return;
423992413f4SGarrett D'Amore }
424992413f4SGarrett D'Amore
425992413f4SGarrett D'Amore (void) strcpy(fle.parms.gpr[n].name, parm);
426992413f4SGarrett D'Amore fle.parms.gpr[n].num = ngpr;
427992413f4SGarrett D'Amore fle.parms.gpr[n].def = num;
428992413f4SGarrett D'Amore fle.parms.ngpr = n + 1;
429992413f4SGarrett D'Amore
430992413f4SGarrett D'Amore add_init(ngpr, num, parm);
431992413f4SGarrett D'Amore
432992413f4SGarrett D'Amore add_symbol(parm, SY_PARM, gpr_base + ngpr++);
433992413f4SGarrett D'Amore }
434992413f4SGarrett D'Amore
435992413f4SGarrett D'Amore static void
compile_mono(char ** tokens,int cnt)436992413f4SGarrett D'Amore compile_mono(char **tokens, int cnt)
437992413f4SGarrett D'Amore {
438992413f4SGarrett D'Amore char *parm, *def;
439992413f4SGarrett D'Amore int n, num;
440992413f4SGarrett D'Amore
441992413f4SGarrett D'Amore CHECK_COUNT(tokens, cnt, 3, 3);
442992413f4SGarrett D'Amore
443992413f4SGarrett D'Amore parm = tokens[1];
444992413f4SGarrett D'Amore def = tokens[2];
445992413f4SGarrett D'Amore
446992413f4SGarrett D'Amore n = fle.parms.ngpr;
447992413f4SGarrett D'Amore if (n >= MAX_GPR_PARMS) {
448992413f4SGarrett D'Amore error("Too many GPR parameters");
449992413f4SGarrett D'Amore return;
450992413f4SGarrett D'Amore }
451992413f4SGarrett D'Amore
452992413f4SGarrett D'Amore if (sscanf(def, "%d", &num) != 1) {
453992413f4SGarrett D'Amore error("Bad integer value near '%s'", def);
454992413f4SGarrett D'Amore return;
455992413f4SGarrett D'Amore }
456992413f4SGarrett D'Amore
457992413f4SGarrett D'Amore (void) strcpy(fle.parms.gpr[n].name, parm);
458992413f4SGarrett D'Amore fle.parms.gpr[n].num = ngpr;
459992413f4SGarrett D'Amore fle.parms.gpr[n].def = num;
460992413f4SGarrett D'Amore fle.parms.ngpr = n + 1;
461992413f4SGarrett D'Amore
462992413f4SGarrett D'Amore add_init(ngpr, num, parm);
463992413f4SGarrett D'Amore
464992413f4SGarrett D'Amore add_symbol(parm, SY_PARM, gpr_base + ngpr++);
465992413f4SGarrett D'Amore }
466992413f4SGarrett D'Amore
467992413f4SGarrett D'Amore static void
compile_stereo(char ** tokens,int cnt)468992413f4SGarrett D'Amore compile_stereo(char **tokens, int cnt)
469992413f4SGarrett D'Amore {
470992413f4SGarrett D'Amore char *parm, *def;
471992413f4SGarrett D'Amore int n, num;
472992413f4SGarrett D'Amore char tmp[128];
473992413f4SGarrett D'Amore
474992413f4SGarrett D'Amore CHECK_COUNT(tokens, cnt, 3, 3);
475992413f4SGarrett D'Amore
476992413f4SGarrett D'Amore parm = tokens[1];
477992413f4SGarrett D'Amore def = tokens[2];
478992413f4SGarrett D'Amore
479992413f4SGarrett D'Amore n = fle.parms.ngpr;
480992413f4SGarrett D'Amore if (n >= MAX_GPR_PARMS) {
481992413f4SGarrett D'Amore error("Too many GPR parameters");
482992413f4SGarrett D'Amore return;
483992413f4SGarrett D'Amore }
484992413f4SGarrett D'Amore
485992413f4SGarrett D'Amore if (sscanf(def, "%d", &num) != 1) {
486992413f4SGarrett D'Amore error("Bad integer value near '%s'", def);
487992413f4SGarrett D'Amore return;
488992413f4SGarrett D'Amore }
489992413f4SGarrett D'Amore
490992413f4SGarrett D'Amore (void) strcpy(fle.parms.gpr[n].name, parm);
491992413f4SGarrett D'Amore fle.parms.gpr[n].num = ngpr;
492992413f4SGarrett D'Amore fle.parms.gpr[n].def = num | (num << 8);
493992413f4SGarrett D'Amore fle.parms.ngpr = n + 1;
494992413f4SGarrett D'Amore
495992413f4SGarrett D'Amore add_init(ngpr, num, parm);
496992413f4SGarrett D'Amore add_init(ngpr + 1, num, NULL);
497992413f4SGarrett D'Amore
498992413f4SGarrett D'Amore (void) sprintf(tmp, "%s_L", parm);
499992413f4SGarrett D'Amore add_symbol(tmp, SY_PARM, gpr_base + ngpr++);
500992413f4SGarrett D'Amore (void) sprintf(tmp, "%s_R", parm);
501992413f4SGarrett D'Amore add_symbol(tmp, SY_PARM, gpr_base + ngpr++);
502992413f4SGarrett D'Amore }
503992413f4SGarrett D'Amore
504992413f4SGarrett D'Amore static void
compile_input(char ** tokens,int cnt)505992413f4SGarrett D'Amore compile_input(char **tokens, int cnt)
506992413f4SGarrett D'Amore {
507992413f4SGarrett D'Amore int num;
508992413f4SGarrett D'Amore
509992413f4SGarrett D'Amore CHECK_COUNT(tokens, cnt, 3, 3);
510992413f4SGarrett D'Amore
511992413f4SGarrett D'Amore if (sscanf(tokens[2], "%d", &num) != 1) {
512992413f4SGarrett D'Amore error("Bad integer value near '%s'", tokens[2]);
513992413f4SGarrett D'Amore return;
514992413f4SGarrett D'Amore }
515992413f4SGarrett D'Amore
516992413f4SGarrett D'Amore add_symbol(tokens[1], SY_INPUT, input_base + num);
517992413f4SGarrett D'Amore }
518992413f4SGarrett D'Amore
519992413f4SGarrett D'Amore static void
compile_send(char ** tokens,int cnt)520992413f4SGarrett D'Amore compile_send(char **tokens, int cnt)
521992413f4SGarrett D'Amore {
522992413f4SGarrett D'Amore int num;
523992413f4SGarrett D'Amore
524992413f4SGarrett D'Amore CHECK_COUNT(tokens, cnt, 3, 3);
525992413f4SGarrett D'Amore
526992413f4SGarrett D'Amore if (sscanf(tokens[2], "%d", &num) != 1) {
527992413f4SGarrett D'Amore error("Bad integer near '%s'", tokens[2]);
528992413f4SGarrett D'Amore return;
529992413f4SGarrett D'Amore }
530992413f4SGarrett D'Amore
531992413f4SGarrett D'Amore add_symbol(tokens[1], SY_FX, num);
532992413f4SGarrett D'Amore }
533992413f4SGarrett D'Amore
534992413f4SGarrett D'Amore static void
compile_output(char ** tokens,int cnt)535992413f4SGarrett D'Amore compile_output(char **tokens, int cnt)
536992413f4SGarrett D'Amore {
537992413f4SGarrett D'Amore int num;
538992413f4SGarrett D'Amore
539992413f4SGarrett D'Amore CHECK_COUNT(tokens, cnt, 3, 3);
540992413f4SGarrett D'Amore
541992413f4SGarrett D'Amore if (sscanf(tokens[2], "%d", &num) != 1) {
542992413f4SGarrett D'Amore error("Bad integer value near '%s'", tokens[2]);
543992413f4SGarrett D'Amore return;
544992413f4SGarrett D'Amore }
545992413f4SGarrett D'Amore
546992413f4SGarrett D'Amore add_symbol(tokens[1], SY_OUTPUT, output_base + num);
547992413f4SGarrett D'Amore }
548992413f4SGarrett D'Amore
549992413f4SGarrett D'Amore static void
compile_directive(char ** tokens,int cnt)550992413f4SGarrett D'Amore compile_directive(char **tokens, int cnt)
551992413f4SGarrett D'Amore {
552992413f4SGarrett D'Amore if (strcmp(tokens[0], ".gpr") == 0) {
553992413f4SGarrett D'Amore compile_gpr(tokens, cnt);
554992413f4SGarrett D'Amore return;
555992413f4SGarrett D'Amore }
556992413f4SGarrett D'Amore
557992413f4SGarrett D'Amore if (strcmp(tokens[0], ".const") == 0) {
558992413f4SGarrett D'Amore compile_const(tokens, cnt);
559992413f4SGarrett D'Amore return;
560992413f4SGarrett D'Amore }
561992413f4SGarrett D'Amore
562992413f4SGarrett D'Amore if (strcmp(tokens[0], ".stereo") == 0) {
563992413f4SGarrett D'Amore compile_stereo(tokens, cnt);
564992413f4SGarrett D'Amore return;
565992413f4SGarrett D'Amore }
566992413f4SGarrett D'Amore
567992413f4SGarrett D'Amore if (strcmp(tokens[0], ".mono") == 0) {
568992413f4SGarrett D'Amore compile_mono(tokens, cnt);
569992413f4SGarrett D'Amore return;
570992413f4SGarrett D'Amore }
571992413f4SGarrett D'Amore
572992413f4SGarrett D'Amore if (strcmp(tokens[0], ".bool") == 0) {
573992413f4SGarrett D'Amore compile_bool(tokens, cnt);
574992413f4SGarrett D'Amore return;
575992413f4SGarrett D'Amore }
576992413f4SGarrett D'Amore
577992413f4SGarrett D'Amore if (strcmp(tokens[0], ".input") == 0) {
578992413f4SGarrett D'Amore compile_input(tokens, cnt);
579992413f4SGarrett D'Amore return;
580992413f4SGarrett D'Amore }
581992413f4SGarrett D'Amore
582992413f4SGarrett D'Amore if (strcmp(tokens[0], ".send") == 0) {
583992413f4SGarrett D'Amore compile_send(tokens, cnt);
584992413f4SGarrett D'Amore return;
585992413f4SGarrett D'Amore }
586992413f4SGarrett D'Amore
587992413f4SGarrett D'Amore if (strcmp(tokens[0], ".output") == 0) {
588992413f4SGarrett D'Amore compile_output(tokens, cnt);
589992413f4SGarrett D'Amore return;
590992413f4SGarrett D'Amore }
591992413f4SGarrett D'Amore
592992413f4SGarrett D'Amore if (strcmp(tokens[0], ".rem") == 0) {
593992413f4SGarrett D'Amore compile_rem(tokens, cnt);
594992413f4SGarrett D'Amore return;
595992413f4SGarrett D'Amore }
596992413f4SGarrett D'Amore if (strcmp(tokens[0], ".'") == 0) {
597992413f4SGarrett D'Amore compile_rem(tokens, cnt);
598992413f4SGarrett D'Amore return;
599992413f4SGarrett D'Amore }
600992413f4SGarrett D'Amore
601992413f4SGarrett D'Amore error("Unknown directive '%s'", tokens[0]);
602992413f4SGarrett D'Amore }
603992413f4SGarrett D'Amore
604992413f4SGarrett D'Amore static void
compile_asm(char ** tokens,int cnt)605992413f4SGarrett D'Amore compile_asm(char **tokens, int cnt)
606992413f4SGarrett D'Amore {
607992413f4SGarrett D'Amore sym_t *symbols[4];
608992413f4SGarrett D'Amore #define EMIT(o, r, a, x, y) \
609992413f4SGarrett D'Amore fle.code[pc*2] = ((x) << 10) | (y); \
610992413f4SGarrett D'Amore fle.code[pc*2+1] = ((o) << 20) | ((r) << 10) | a; pc++
611992413f4SGarrett D'Amore #define EMIT_AUDIGY(o, r, a, x, y) \
612992413f4SGarrett D'Amore fle.code[pc*2] = ((x) << 12) | (y); \
613992413f4SGarrett D'Amore fle.code[pc*2+1] = ((o) << 24) | ((r) << 12) | a; pc++
614992413f4SGarrett D'Amore
615*7f11fd00SRichard Lowe int i, nerr = 0;
616992413f4SGarrett D'Amore int ninputs = 0;
617992413f4SGarrett D'Amore
618992413f4SGarrett D'Amore CHECK_COUNT(tokens, cnt, 5, 5);
619992413f4SGarrett D'Amore
620992413f4SGarrett D'Amore for (i = 0; i < 4; i++) {
621992413f4SGarrett D'Amore if ((symbols[i] = find_symbol(tokens[i+1])) == NULL) {
622992413f4SGarrett D'Amore (void) fprintf(stderr, "%s\n", tokens[i+1]);
623992413f4SGarrett D'Amore nerr++;
624992413f4SGarrett D'Amore error("Undefined symbol '%s'", tokens[i + 1]);
625992413f4SGarrett D'Amore continue;
626992413f4SGarrett D'Amore }
627992413f4SGarrett D'Amore
628992413f4SGarrett D'Amore if (symbols[i]->type == SY_INPUT)
629992413f4SGarrett D'Amore ninputs++;
630992413f4SGarrett D'Amore
631992413f4SGarrett D'Amore if (symbols[i]->type == SY_ACCUM && i != 1)
632992413f4SGarrett D'Amore error("Bad usage of 'accum' operand.");
633992413f4SGarrett D'Amore }
634992413f4SGarrett D'Amore
635992413f4SGarrett D'Amore if (nerr > 0)
636992413f4SGarrett D'Amore return;
637992413f4SGarrett D'Amore
638992413f4SGarrett D'Amore if (ninputs > 1) {
639992413f4SGarrett D'Amore error("Attempt to access more than one input "
640992413f4SGarrett D'Amore "GPRs by the same instruction");
641992413f4SGarrett D'Amore }
642992413f4SGarrett D'Amore
643992413f4SGarrett D'Amore for (i = 0; instructions[i].name != NULL; i++)
644992413f4SGarrett D'Amore if (strcasecmp(tokens[0], instructions[i].name) == 0) {
645992413f4SGarrett D'Amore
646992413f4SGarrett D'Amore if (is_audigy) {
647992413f4SGarrett D'Amore EMIT_AUDIGY(instructions[i].opcode,
648992413f4SGarrett D'Amore symbols[0]->arg,
649992413f4SGarrett D'Amore symbols[1]->arg,
650992413f4SGarrett D'Amore symbols[2]->arg,
651992413f4SGarrett D'Amore symbols[3]->arg);
652992413f4SGarrett D'Amore } else {
653992413f4SGarrett D'Amore EMIT(instructions[i].opcode,
654992413f4SGarrett D'Amore symbols[0]->arg,
655992413f4SGarrett D'Amore symbols[1]->arg,
656992413f4SGarrett D'Amore symbols[2]->arg,
657992413f4SGarrett D'Amore symbols[3]->arg);
658992413f4SGarrett D'Amore }
659992413f4SGarrett D'Amore
660992413f4SGarrett D'Amore return;
661992413f4SGarrett D'Amore }
662992413f4SGarrett D'Amore
663992413f4SGarrett D'Amore error("Unrecognized instruction '%s'", tokens[0]);
664992413f4SGarrett D'Amore }
665992413f4SGarrett D'Amore
666992413f4SGarrett D'Amore static void
init_compiler(void)667992413f4SGarrett D'Amore init_compiler(void)
668992413f4SGarrett D'Amore {
669992413f4SGarrett D'Amore char tmp[100];
670992413f4SGarrett D'Amore int i;
671992413f4SGarrett D'Amore
672992413f4SGarrett D'Amore (void) memset(&fle, 0, sizeof (fle));
673992413f4SGarrett D'Amore /*
674992413f4SGarrett D'Amore * Initialize few predefined GPR parameter registers. These
675992413f4SGarrett D'Amore * definitions have to be in sync with the GPR_* macros in
676992413f4SGarrett D'Amore * <sblive.h>.
677992413f4SGarrett D'Amore */
678992413f4SGarrett D'Amore
679992413f4SGarrett D'Amore /*
680992413f4SGarrett D'Amore * Make sure we start at gpr id 2 for now; 0 and 1 may be used
681992413f4SGarrett D'Amore * differently.
682992413f4SGarrett D'Amore */
683992413f4SGarrett D'Amore add_symbol("NULL", SY_DUMMY, gpr_base + ngpr++);
684992413f4SGarrett D'Amore add_symbol("NULL_", SY_DUMMY, gpr_base + ngpr++);
685992413f4SGarrett D'Amore
686992413f4SGarrett D'Amore pc = 0;
687992413f4SGarrett D'Amore
688992413f4SGarrett D'Amore if (is_audigy) {
689992413f4SGarrett D'Amore /* Initialize the code array with NOPs (AUDIGY) */
690992413f4SGarrett D'Amore for (i = 0; i < 512; i++) {
691992413f4SGarrett D'Amore fle.code[i * 2 + 0] = (0xc0 << 12) | 0xc0;
692992413f4SGarrett D'Amore fle.code[i * 2 + 1] =
693992413f4SGarrett D'Amore (0x06 << 24) | (0xc0 << 12) | 0xc0;
694992413f4SGarrett D'Amore }
695992413f4SGarrett D'Amore
696992413f4SGarrett D'Amore for (i = 0; i < 32; i++) {
697992413f4SGarrett D'Amore (void) sprintf(tmp, "fx%d", i);
698992413f4SGarrett D'Amore add_symbol(tmp, SY_FX, i);
699992413f4SGarrett D'Amore }
700992413f4SGarrett D'Amore } else {
701992413f4SGarrett D'Amore /* Initialize the code array with NOPs (LIVE) */
702992413f4SGarrett D'Amore for (i = 0; i < 512; i++) {
703992413f4SGarrett D'Amore fle.code[i * 2 + 0] = 0x10040;
704992413f4SGarrett D'Amore fle.code[i * 2 + 1] = 0x610040;
705992413f4SGarrett D'Amore }
706992413f4SGarrett D'Amore
707992413f4SGarrett D'Amore for (i = 0; i < 16; i++) {
708992413f4SGarrett D'Amore (void) sprintf(tmp, "fx%d", i);
709992413f4SGarrett D'Amore add_symbol(tmp, SY_FX, i);
710992413f4SGarrett D'Amore }
711992413f4SGarrett D'Amore }
712992413f4SGarrett D'Amore
713992413f4SGarrett D'Amore /*
714992413f4SGarrett D'Amore * Constants
715992413f4SGarrett D'Amore */
716992413f4SGarrett D'Amore
717992413f4SGarrett D'Amore if (is_audigy) {
718992413f4SGarrett D'Amore /* Audigy symbols */
719992413f4SGarrett D'Amore add_symbol("0", SY_CONST, 0x0c0);
720992413f4SGarrett D'Amore add_symbol("1", SY_CONST, 0x0c1);
721992413f4SGarrett D'Amore add_symbol("2", SY_CONST, 0x0c2);
722992413f4SGarrett D'Amore add_symbol("3", SY_CONST, 0x0c3);
723992413f4SGarrett D'Amore add_symbol("4", SY_CONST, 0x0c4);
724992413f4SGarrett D'Amore add_symbol("8", SY_CONST, 0x0c5);
725992413f4SGarrett D'Amore add_symbol("16", SY_CONST, 0x0c6);
726992413f4SGarrett D'Amore add_symbol("32", SY_CONST, 0x0c7);
727992413f4SGarrett D'Amore add_symbol("256", SY_CONST, 0x0c8);
728992413f4SGarrett D'Amore add_symbol("65536", SY_CONST, 0x0c9);
729992413f4SGarrett D'Amore
730992413f4SGarrett D'Amore add_symbol("2048", SY_CONST, 0x0ca);
731992413f4SGarrett D'Amore add_symbol("0x800", SY_CONST, 0x0ca);
732992413f4SGarrett D'Amore
733992413f4SGarrett D'Amore add_symbol("2^28", SY_CONST, 0x0cb);
734992413f4SGarrett D'Amore add_symbol("0x10000000", SY_CONST, 0x0cb);
735992413f4SGarrett D'Amore
736992413f4SGarrett D'Amore add_symbol("2^29", SY_CONST, 0x0cc);
737992413f4SGarrett D'Amore add_symbol("0x20000000", SY_CONST, 0x0cc);
738992413f4SGarrett D'Amore
739992413f4SGarrett D'Amore add_symbol("2^30", SY_CONST, 0x0cd);
740992413f4SGarrett D'Amore add_symbol("0x40000000", SY_CONST, 0x0cd);
741992413f4SGarrett D'Amore
742992413f4SGarrett D'Amore add_symbol("2^31", SY_CONST, 0x0ce);
743992413f4SGarrett D'Amore add_symbol("0x80000000", SY_CONST, 0x0ce);
744992413f4SGarrett D'Amore
745992413f4SGarrett D'Amore add_symbol("0x7fffffff", SY_CONST, 0x0cf);
746992413f4SGarrett D'Amore
747992413f4SGarrett D'Amore add_symbol("0xffffffff", SY_CONST, 0x0d0);
748992413f4SGarrett D'Amore add_symbol("-1", SY_CONST, 0x0d0);
749992413f4SGarrett D'Amore
750992413f4SGarrett D'Amore add_symbol("0xfffffffe", SY_CONST, 0x0d1);
751992413f4SGarrett D'Amore add_symbol("-2", SY_CONST, 0x0d1);
752992413f4SGarrett D'Amore
753992413f4SGarrett D'Amore add_symbol("0xc0000000", SY_CONST, 0x0d2);
754992413f4SGarrett D'Amore
755992413f4SGarrett D'Amore add_symbol("0x4f1bbcdc", SY_CONST, 0x0d3);
756992413f4SGarrett D'Amore
757992413f4SGarrett D'Amore add_symbol("0x5a7ef9db", SY_CONST, 0x0d4);
758992413f4SGarrett D'Amore
759992413f4SGarrett D'Amore add_symbol("0x100000", SY_CONST, 0x0d5);
760992413f4SGarrett D'Amore add_symbol("accum", SY_ACCUM, 0x0d6);
761992413f4SGarrett D'Amore add_symbol("CCR", SY_CONST, 0x0d7);
762992413f4SGarrett D'Amore
763992413f4SGarrett D'Amore add_symbol("noise_L", SY_CONST, 0x0d8);
764992413f4SGarrett D'Amore add_symbol("noise_R", SY_CONST, 0x0d9);
765992413f4SGarrett D'Amore add_symbol("IRQREQ", SY_CONST, 0x0da);
766992413f4SGarrett D'Amore } else {
767992413f4SGarrett D'Amore /* SB Live symbols */
768992413f4SGarrett D'Amore add_symbol("0", SY_CONST, 0x040);
769992413f4SGarrett D'Amore add_symbol("1", SY_CONST, 0x041);
770992413f4SGarrett D'Amore add_symbol("2", SY_CONST, 0x042);
771992413f4SGarrett D'Amore add_symbol("3", SY_CONST, 0x043);
772992413f4SGarrett D'Amore add_symbol("4", SY_CONST, 0x044);
773992413f4SGarrett D'Amore add_symbol("8", SY_CONST, 0x045);
774992413f4SGarrett D'Amore add_symbol("16", SY_CONST, 0x046);
775992413f4SGarrett D'Amore add_symbol("32", SY_CONST, 0x047);
776992413f4SGarrett D'Amore add_symbol("256", SY_CONST, 0x048);
777992413f4SGarrett D'Amore add_symbol("65536", SY_CONST, 0x049);
778992413f4SGarrett D'Amore
779992413f4SGarrett D'Amore add_symbol("2^23", SY_CONST, 0x04a);
780992413f4SGarrett D'Amore add_symbol("0x80000", SY_CONST, 0x04a);
781992413f4SGarrett D'Amore
782992413f4SGarrett D'Amore add_symbol("2^28", SY_CONST, 0x04b);
783992413f4SGarrett D'Amore add_symbol("0x10000000", SY_CONST, 0x04b);
784992413f4SGarrett D'Amore
785992413f4SGarrett D'Amore add_symbol("2^29", SY_CONST, 0x04c);
786992413f4SGarrett D'Amore add_symbol("0x20000000", SY_CONST, 0x04c);
787992413f4SGarrett D'Amore
788992413f4SGarrett D'Amore add_symbol("2^30", SY_CONST, 0x04d);
789992413f4SGarrett D'Amore add_symbol("0x40000000", SY_CONST, 0x04d);
790992413f4SGarrett D'Amore
791992413f4SGarrett D'Amore add_symbol("2^31", SY_CONST, 0x04e);
792992413f4SGarrett D'Amore add_symbol("0x80000000", SY_CONST, 0x04e);
793992413f4SGarrett D'Amore
794992413f4SGarrett D'Amore add_symbol("0x7fffffff", SY_CONST, 0x04f);
795992413f4SGarrett D'Amore
796992413f4SGarrett D'Amore add_symbol("0xffffffff", SY_CONST, 0x050);
797992413f4SGarrett D'Amore add_symbol("-1", SY_CONST, 0x050);
798992413f4SGarrett D'Amore
799992413f4SGarrett D'Amore add_symbol("0xfffffffe", SY_CONST, 0x051);
800992413f4SGarrett D'Amore add_symbol("-2", SY_CONST, 0x051);
801992413f4SGarrett D'Amore
802992413f4SGarrett D'Amore add_symbol("accum", SY_ACCUM, 0x056);
803992413f4SGarrett D'Amore add_symbol("CCR", SY_CONST, 0x057);
804992413f4SGarrett D'Amore
805992413f4SGarrett D'Amore add_symbol("noise_L", SY_CONST, 0x058);
806992413f4SGarrett D'Amore add_symbol("noise_R", SY_CONST, 0x059);
807992413f4SGarrett D'Amore add_symbol("IRQREQ", SY_CONST, 0x05a);
808992413f4SGarrett D'Amore }
809992413f4SGarrett D'Amore }
810992413f4SGarrett D'Amore
811992413f4SGarrett D'Amore static void
produce_map(char * name)812992413f4SGarrett D'Amore produce_map(char *name)
813992413f4SGarrett D'Amore {
814992413f4SGarrett D'Amore int i;
815992413f4SGarrett D'Amore FILE *f;
816992413f4SGarrett D'Amore
817992413f4SGarrett D'Amore if ((f = fopen(name, "w")) == NULL) {
818992413f4SGarrett D'Amore perror(name);
819992413f4SGarrett D'Amore return;
820992413f4SGarrett D'Amore }
821992413f4SGarrett D'Amore
822992413f4SGarrett D'Amore (void) fprintf(f, "%d\n", pc);
823992413f4SGarrett D'Amore
824992413f4SGarrett D'Amore for (i = 0; i < nsyms; i++) {
825992413f4SGarrett D'Amore (void) fprintf(f, "%04x %x %s\n",
826992413f4SGarrett D'Amore symtab[i].arg, symtab[i].type, symtab[i].name);
827992413f4SGarrett D'Amore }
828992413f4SGarrett D'Amore
829992413f4SGarrett D'Amore (void) fclose(f);
830992413f4SGarrett D'Amore if (verbose) {
831992413f4SGarrett D'Amore (void) fprintf(stderr,
832992413f4SGarrett D'Amore "No errors detected - Map written to %s\n", name);
833992413f4SGarrett D'Amore }
834992413f4SGarrett D'Amore }
835992413f4SGarrett D'Amore
836992413f4SGarrett D'Amore static void
produce_output(char * fname)837992413f4SGarrett D'Amore produce_output(char *fname)
838992413f4SGarrett D'Amore {
839992413f4SGarrett D'Amore int fd;
840992413f4SGarrett D'Amore
841992413f4SGarrett D'Amore if ((fd = creat(fname, 0644)) == -1) {
842992413f4SGarrett D'Amore perror(fname);
843992413f4SGarrett D'Amore exit(-1);
844992413f4SGarrett D'Amore }
845992413f4SGarrett D'Amore
846992413f4SGarrett D'Amore if (write(fd, &fle, sizeof (fle)) != sizeof (fle)) {
847992413f4SGarrett D'Amore perror(fname);
848992413f4SGarrett D'Amore exit(-1);
849992413f4SGarrett D'Amore }
850992413f4SGarrett D'Amore
851992413f4SGarrett D'Amore if (verbose) {
852992413f4SGarrett D'Amore (void) fprintf(stderr,
853992413f4SGarrett D'Amore "No errors detected - Binary written to %s\n",
854992413f4SGarrett D'Amore fname);
855992413f4SGarrett D'Amore }
856992413f4SGarrett D'Amore
857992413f4SGarrett D'Amore (void) close(fd);
858992413f4SGarrett D'Amore }
859992413f4SGarrett D'Amore
860992413f4SGarrett D'Amore static void
produce_header(char * fname,char * prefix)861992413f4SGarrett D'Amore produce_header(char *fname, char *prefix)
862992413f4SGarrett D'Amore {
863992413f4SGarrett D'Amore FILE *f;
864992413f4SGarrett D'Amore char *s;
865992413f4SGarrett D'Amore char sname[MAXPATHLEN + 1];
866992413f4SGarrett D'Amore char dname[MAXPATHLEN + 1];
867992413f4SGarrett D'Amore int i;
868992413f4SGarrett D'Amore clock_t now;
869992413f4SGarrett D'Amore char when[128];
870992413f4SGarrett D'Amore
871992413f4SGarrett D'Amore /* get basename */
872992413f4SGarrett D'Amore if (prefix == NULL) {
873992413f4SGarrett D'Amore s = strrchr(fname, '/');
874992413f4SGarrett D'Amore s = (s == NULL) ? fname : s + 1;
875992413f4SGarrett D'Amore } else {
876992413f4SGarrett D'Amore s = prefix;
877992413f4SGarrett D'Amore }
878992413f4SGarrett D'Amore (void) strlcpy(sname, s, sizeof (sname));
879992413f4SGarrett D'Amore
880992413f4SGarrett D'Amore /* strip off any extension */
881992413f4SGarrett D'Amore s = strchr(sname, '.');
882992413f4SGarrett D'Amore if (s != NULL) {
883992413f4SGarrett D'Amore *s = 0;
884992413f4SGarrett D'Amore }
885992413f4SGarrett D'Amore if ((f = fopen(fname, "w")) == NULL) {
886992413f4SGarrett D'Amore perror(fname);
887992413f4SGarrett D'Amore return;
888992413f4SGarrett D'Amore }
889992413f4SGarrett D'Amore
890992413f4SGarrett D'Amore if (remarks[0] != 0) {
891992413f4SGarrett D'Amore (void) fprintf(f, "/*\n%s */\n", remarks);
892992413f4SGarrett D'Amore }
893992413f4SGarrett D'Amore now = time(NULL);
894992413f4SGarrett D'Amore strftime(when, sizeof (when), "%c", localtime(&now));
895992413f4SGarrett D'Amore (void) fprintf(f, banner, progname, when);
896992413f4SGarrett D'Amore
897992413f4SGarrett D'Amore (void) strlcpy(dname, prefix ? prefix : sname, sizeof (dname));
898992413f4SGarrett D'Amore for (i = 0; dname[i]; i++) {
899992413f4SGarrett D'Amore dname[i] = toupper(dname[i]);
900992413f4SGarrett D'Amore if (!isalnum(dname[i])) {
901992413f4SGarrett D'Amore dname[i] = '_';
902992413f4SGarrett D'Amore }
903992413f4SGarrett D'Amore }
904992413f4SGarrett D'Amore
905992413f4SGarrett D'Amore for (i = 0; i < fle.parms.ngpr; i++) {
906992413f4SGarrett D'Amore (void) fprintf(f, "#define\t%s_%s\t\t%d\n",
907992413f4SGarrett D'Amore dname, fle.parms.gpr[i].name, fle.parms.gpr[i].num);
908992413f4SGarrett D'Amore }
909992413f4SGarrett D'Amore
910992413f4SGarrett D'Amore (void) fprintf(f, "\n");
911992413f4SGarrett D'Amore
912992413f4SGarrett D'Amore if (parms_only)
913992413f4SGarrett D'Amore goto done;
914992413f4SGarrett D'Amore
915992413f4SGarrett D'Amore (void) fprintf(f, "uint32_t %s_code[] = {\n", sname);
916992413f4SGarrett D'Amore
917992413f4SGarrett D'Amore for (i = 0; i < pc * 2; i++) {
918992413f4SGarrett D'Amore if (i == 0) {
919992413f4SGarrett D'Amore (void) fprintf(f, "\t0x%08xU", fle.code[i]);
920992413f4SGarrett D'Amore } else if ((i % 4) == 0) {
921992413f4SGarrett D'Amore (void) fprintf(f, ",\n\t0x%08xU", fle.code[i]);
922992413f4SGarrett D'Amore } else {
923992413f4SGarrett D'Amore (void) fprintf(f, ", 0x%08xU", fle.code[i]);
924992413f4SGarrett D'Amore }
925992413f4SGarrett D'Amore }
926992413f4SGarrett D'Amore (void) fprintf(f, "\n};\n");
927992413f4SGarrett D'Amore
928992413f4SGarrett D'Amore (void) fprintf(f, "uint32_t %s_ninit = %d;\n", sname, fle.ninit);
929992413f4SGarrett D'Amore (void) fprintf(f, "uint32_t %s_init[] = {\n", sname);
930992413f4SGarrett D'Amore
931992413f4SGarrett D'Amore for (i = 0; i < fle.ninit; i++) {
932992413f4SGarrett D'Amore if (fle.init[i].name[0]) {
933992413f4SGarrett D'Amore (void) fprintf(f, "\t%u, 0x%x%s,\t/* %s */\n",
934992413f4SGarrett D'Amore fle.init[i].gpr, fle.init[i].value,
935992413f4SGarrett D'Amore fle.init[i].value >= 0x80000000U ? "U" : "",
936992413f4SGarrett D'Amore fle.init[i].name);
937992413f4SGarrett D'Amore } else {
938992413f4SGarrett D'Amore (void) fprintf(f, "\t%u, 0x%x%s,\n",
939992413f4SGarrett D'Amore fle.init[i].gpr, fle.init[i].value,
940992413f4SGarrett D'Amore fle.init[i].value >= 0x80000000U ? "U" : "");
941992413f4SGarrett D'Amore }
942992413f4SGarrett D'Amore }
943992413f4SGarrett D'Amore (void) fprintf(f, "};\n");
944992413f4SGarrett D'Amore
945992413f4SGarrett D'Amore done:
946992413f4SGarrett D'Amore (void) fclose(f);
947992413f4SGarrett D'Amore if (verbose) {
948992413f4SGarrett D'Amore (void) fprintf(stderr,
949992413f4SGarrett D'Amore "No errors detected - Header written to %s\n",
950992413f4SGarrett D'Amore fname);
951992413f4SGarrett D'Amore }
952992413f4SGarrett D'Amore }
953992413f4SGarrett D'Amore
954992413f4SGarrett D'Amore int
main(int argc,char * argv[])955992413f4SGarrett D'Amore main(int argc, char *argv[])
956992413f4SGarrett D'Amore {
957*7f11fd00SRichard Lowe char *outfile;
958992413f4SGarrett D'Amore int i;
959992413f4SGarrett D'Amore FILE *input;
960992413f4SGarrett D'Amore char *tokens[10];
961992413f4SGarrett D'Amore int tokcnt;
962992413f4SGarrett D'Amore char *mapfile = NULL;
963992413f4SGarrett D'Amore char *header = NULL;
964992413f4SGarrett D'Amore char *prefix = NULL;
965992413f4SGarrett D'Amore
966992413f4SGarrett D'Amore outfile = NULL;
967992413f4SGarrett D'Amore infile = NULL;
968992413f4SGarrett D'Amore input = NULL;
969992413f4SGarrett D'Amore progname = argv[0];
970992413f4SGarrett D'Amore
971992413f4SGarrett D'Amore while ((i = getopt(argc, argv, "m:h:o:i:P:021v")) != EOF) {
972992413f4SGarrett D'Amore switch (i) {
973992413f4SGarrett D'Amore case 'o':
974992413f4SGarrett D'Amore outfile = optarg;
975992413f4SGarrett D'Amore break;
976992413f4SGarrett D'Amore case 'i':
977992413f4SGarrett D'Amore infile = strdup(optarg);
978992413f4SGarrett D'Amore break;
979992413f4SGarrett D'Amore case 'm':
980992413f4SGarrett D'Amore mapfile = optarg;
981992413f4SGarrett D'Amore break;
982992413f4SGarrett D'Amore case 'P':
983992413f4SGarrett D'Amore prefix = optarg;
984992413f4SGarrett D'Amore break;
985992413f4SGarrett D'Amore case 'h':
986992413f4SGarrett D'Amore header = optarg;
987992413f4SGarrett D'Amore break;
988992413f4SGarrett D'Amore case '0':
989992413f4SGarrett D'Amore parms_only = 1;
990992413f4SGarrett D'Amore break;
991992413f4SGarrett D'Amore case '2':
992992413f4SGarrett D'Amore is_audigy = 1;
993992413f4SGarrett D'Amore break;
994992413f4SGarrett D'Amore case '1':
995992413f4SGarrett D'Amore is_audigy = 0;
996992413f4SGarrett D'Amore break;
997992413f4SGarrett D'Amore case 'v':
998992413f4SGarrett D'Amore verbose++;
999992413f4SGarrett D'Amore break;
1000992413f4SGarrett D'Amore default:
1001992413f4SGarrett D'Amore (void) fprintf(stderr,
1002992413f4SGarrett D'Amore "usage: %s [-m <map>] [-h <header>] "
1003992413f4SGarrett D'Amore "[-o <binary>] [-i <source>] [-2|-1]",
1004992413f4SGarrett D'Amore progname);
1005992413f4SGarrett D'Amore exit(-1);
1006992413f4SGarrett D'Amore break;
1007992413f4SGarrett D'Amore }
1008992413f4SGarrett D'Amore }
1009992413f4SGarrett D'Amore
1010992413f4SGarrett D'Amore if ((outfile == NULL) && (mapfile == NULL) && (header == NULL)) {
1011992413f4SGarrett D'Amore outfile = "dsp.bin";
1012992413f4SGarrett D'Amore }
1013992413f4SGarrett D'Amore
1014992413f4SGarrett D'Amore if (infile) {
1015992413f4SGarrett D'Amore input = fopen(infile, "r");
1016992413f4SGarrett D'Amore if (input == NULL) {
1017992413f4SGarrett D'Amore perror(infile);
1018992413f4SGarrett D'Amore exit(-1);
1019992413f4SGarrett D'Amore }
1020992413f4SGarrett D'Amore } else {
1021992413f4SGarrett D'Amore infile = strdup("<stdin>");
1022992413f4SGarrett D'Amore input = stdin;
1023992413f4SGarrett D'Amore }
1024992413f4SGarrett D'Amore
1025992413f4SGarrett D'Amore if (is_audigy) {
1026992413f4SGarrett D'Amore gpr_base = 0x400;
1027992413f4SGarrett D'Amore input_base = 0x40;
1028992413f4SGarrett D'Amore output_base = 0x60;
1029992413f4SGarrett D'Amore if (verbose)
1030992413f4SGarrett D'Amore (void) fprintf(stderr, "Compiling for SB Audigy\n");
1031992413f4SGarrett D'Amore } else {
1032992413f4SGarrett D'Amore if (verbose)
1033992413f4SGarrett D'Amore (void) fprintf(stderr, "Compiling for SB Live\n");
1034992413f4SGarrett D'Amore }
1035992413f4SGarrett D'Amore
1036992413f4SGarrett D'Amore init_compiler();
1037992413f4SGarrett D'Amore
103823a1cceaSRoger A. Faulkner while ((tokcnt = getaline(input, tokens)) != -1) {
1039992413f4SGarrett D'Amore /* skip empty lines */
1040992413f4SGarrett D'Amore if (tokcnt == 0) {
1041992413f4SGarrett D'Amore continue;
1042992413f4SGarrett D'Amore }
1043992413f4SGarrett D'Amore
1044992413f4SGarrett D'Amore if (strcmp(tokens[0], "#") == 0) {
1045992413f4SGarrett D'Amore int num;
1046992413f4SGarrett D'Amore if ((tokcnt >= 3) &&
1047992413f4SGarrett D'Amore (sscanf(tokens[1], "%d", &num) == 1)) {
1048992413f4SGarrett D'Amore lineno = num;
1049992413f4SGarrett D'Amore free(infile);
1050992413f4SGarrett D'Amore infile = strdup(tokens[2]);
1051992413f4SGarrett D'Amore /* we don't want to count the # directive */
1052992413f4SGarrett D'Amore lineno--;
1053992413f4SGarrett D'Amore }
1054992413f4SGarrett D'Amore
1055992413f4SGarrett D'Amore /* unknown # directive? muddle on... */
1056992413f4SGarrett D'Amore continue;
1057992413f4SGarrett D'Amore }
1058992413f4SGarrett D'Amore if (*tokens[0] == '.') {
1059992413f4SGarrett D'Amore compile_directive(tokens, tokcnt);
1060992413f4SGarrett D'Amore } else {
1061992413f4SGarrett D'Amore compile_asm(tokens, tokcnt);
1062992413f4SGarrett D'Amore }
1063992413f4SGarrett D'Amore }
1064992413f4SGarrett D'Amore
1065992413f4SGarrett D'Amore if (lineno < 1) {
1066992413f4SGarrett D'Amore error("Empty input");
1067992413f4SGarrett D'Amore }
1068992413f4SGarrett D'Amore
1069992413f4SGarrett D'Amore if (errors == 0) {
1070992413f4SGarrett D'Amore if (verbose) {
1071992413f4SGarrett D'Amore (void) fprintf(stderr,
1072992413f4SGarrett D'Amore "%d instructions out of 512 assembled\n", pc);
1073992413f4SGarrett D'Amore }
1074992413f4SGarrett D'Amore
1075992413f4SGarrett D'Amore if (outfile)
1076992413f4SGarrett D'Amore produce_output(outfile);
1077992413f4SGarrett D'Amore if (mapfile)
1078992413f4SGarrett D'Amore produce_map(mapfile);
1079992413f4SGarrett D'Amore if (header)
1080992413f4SGarrett D'Amore produce_header(header, prefix);
1081992413f4SGarrett D'Amore }
1082992413f4SGarrett D'Amore
1083992413f4SGarrett D'Amore if (errors > 0) {
1084992413f4SGarrett D'Amore (void) fprintf(stderr, "%d errors - compile failed\n", errors);
1085992413f4SGarrett D'Amore exit(-1);
1086992413f4SGarrett D'Amore }
1087992413f4SGarrett D'Amore
1088992413f4SGarrett D'Amore return (0);
1089992413f4SGarrett D'Amore }
1090