Deleted Added
full compact
aicasm.c (22975) aicasm.c (23925)
1/*+M*************************************************************************
2 * Adaptec AIC7770/AIC7870 sequencer code assembler.
1/*
2 * Aic7xxx SCSI host adapter firmware asssembler
3 *
3 *
4 * Copyright (c) 1994 John Aycock
5 * The University of Calgary Department of Computer Science.
6 * All rights reserved.
4 * Copyright (c) 1997 Justin T. Gibbs.
5 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions, and the following disclaimer.
11 * notice immediately at the beginning of the file, without modification,
12 * this list of conditions, and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of Calgary
19 * Department of Computer Science and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
36 * Comments are started by `#' and continue to the end of the line; lines
37 * may be of the form:
38 * <label>*
39 * <label>* <undef-sym> = <value>
40 * <label>* <opcode> <operand>*
41 *
42 * A <label> is an <undef-sym> ending in a colon. Spaces, tabs, and commas
43 * are token separators.
44 *
45 *-M*************************************************************************/
46static char id[] = "$Id$";
47#include <ctype.h>
31 * $Id$
32 */
33#include <sys/types.h>
34#include <sys/mman.h>
35
48#include <stdio.h>
36#include <stdio.h>
49#include <string.h>
50#include <stdlib.h>
37#include <stdlib.h>
38#include <string.h>
39#include <sysexits.h>
51#include <unistd.h>
40#include <unistd.h>
52#include <fcntl.h>
53
41
54#define MEMORY 448
55#define MAXLINE 1024
56#define MAXTOKEN 32
57#define ADOTOUT "a.out"
58#define NOVALUE -1
42#include "aic7xxx_asm.h"
43#include "symbol.h"
44#include "sequencer.h"
59
45
60/*
61 * AIC-7770/AIC-7870 register definitions
62 */
63#define R_SINDEX 0x65
64#define R_ALLONES 0x69
65#define R_ALLZEROS 0x6a
66#define R_NONE 0x6a
46static void usage __P((void));
47static void back_patch __P((void));
48static void output_code __P((FILE *ofile));
49static void output_listing __P((FILE *listfile, char *ifilename));
67
50
68int debug;
69int lineno, LC;
70char *filename;
71unsigned char M[MEMORY][4];
51struct path_list search_path;
52int includes_search_curdir;
53char *appname;
54FILE *ofile;
55char *ofilename;
72
56
73void
74error(char *s)
75{
76 fprintf(stderr, "%s: %s at line %d\n", filename, s, lineno);
77 exit(EXIT_FAILURE);
78}
57static STAILQ_HEAD(,instruction) seq_program;
58static STAILQ_HEAD(, patch) patch_list;
59symlist_t patch_options;
79
60
80void *
81Malloc(size_t size)
82{
83 void *p = malloc(size);
84 if (!p)
85 error("out of memory");
86 return(p);
87}
61#if DEBUG
62extern int yy_flex_debug;
63extern int yydebug;
64#endif
65extern FILE *yyin;
66extern int yyparse __P((void));
88
67
89void *
90Realloc(void *ptr, size_t size)
68int
69main(argc, argv)
70 int argc;
71 char *argv[];
91{
72{
92 void *p = realloc(ptr, size);
93 if (!p)
94 error("out of memory");
95 return(p);
96}
73 extern char *optarg;
74 extern int optind;
75 int ch;
76 int retval;
77 char *inputfilename;
78 char *regfilename;
79 FILE *regfile;
80 char *listfilename;
81 FILE *listfile;
97
82
98char *
99Strdup(char *s)
100{
101 char *p = (char *)Malloc(strlen(s) + 1);
102 strcpy(p, s);
103 return(p);
104}
83 SLIST_INIT(&search_path);
84 STAILQ_INIT(&seq_program);
85 STAILQ_INIT(&patch_list);
86 SLIST_INIT(&patch_options);
87 includes_search_curdir = 1;
88 appname = *argv;
89 regfile = NULL;
90 listfile = NULL;
91#if DEBUG
92 yy_flex_debug = 0;
93#endif
94 while ((ch = getopt(argc, argv, "d:l:n:o:r:I:")) != EOF) {
95 switch(ch) {
96 case 'd':
97#if DEBUG
98 if (strcmp(optarg, "s") == 0)
99 yy_flex_debug = 1;
100 else if (strcmp(optarg, "p") == 0)
101 yydebug = 1;
102#else
103 stop("-d: Assembler not built with debugging "
104 "information", EX_SOFTWARE);
105#endif
106 break;
107 case 'l':
108 /* Create a program listing */
109 if ((listfile = fopen(optarg, "w")) == NULL) {
110 perror(optarg);
111 stop(NULL, EX_CANTCREAT);
112 }
113 listfilename = optarg;
114 break;
115 case 'n':
116 /* Don't complain about the -nostdinc directrive */
117 if (strcmp(optarg, "ostdinc")) {
118 fprintf(stderr, "%s: Unknown option -%c%s\n",
119 appname, ch, optarg);
120 usage();
121 /* NOTREACHED */
122 }
123 break;
124 case 'o':
125 if ((ofile = fopen(optarg, "w")) == NULL) {
126 perror(optarg);
127 stop(NULL, EX_CANTCREAT);
128 }
129 ofilename = optarg;
130 break;
131 case 'r':
132 if ((regfile = fopen(optarg, "w")) == NULL) {
133 perror(optarg);
134 stop(NULL, EX_CANTCREAT);
135 }
136 regfilename = optarg;
137 break;
138 case 'I':
139 {
140 path_entry_t include_dir;
105
141
106typedef struct sym_t {
107 struct sym_t *next; /* MUST BE FIRST */
108 char *name;
109 int value;
110 int npatch;
111 int *patch;
112} sym_t;
142 if (strcmp(optarg, "-") == 0) {
143 if (includes_search_curdir == 0) {
144 fprintf(stderr, "%s: Warning - '-I-' "
145 "specified multiple "
146 "times\n", appname);
147 }
148 includes_search_curdir = 0;
149 for (include_dir = search_path.slh_first;
150 include_dir != NULL;
151 include_dir = include_dir->links.sle_next)
152 /*
153 * All entries before a '-I-' only
154 * apply to includes specified with
155 * quotes instead of "<>".
156 */
157 include_dir->quoted_includes_only = 1;
158 } else {
159 include_dir =
160 (path_entry_t)malloc(sizeof(*include_dir));
161 if (include_dir == NULL) {
162 perror(optarg);
163 stop(NULL, EX_OSERR);
164 }
165 include_dir->directory = strdup(optarg);
166 if (include_dir->directory == NULL) {
167 perror(optarg);
168 stop(NULL, EX_OSERR);
169 }
170 include_dir->quoted_includes_only = 0;
171 SLIST_INSERT_HEAD(&search_path, include_dir,
172 links);
173 }
174 break;
175 }
176 case '?':
177 default:
178 usage();
179 /* NOTREACHED */
180 }
181 }
182 argc -= optind;
183 argv += optind;
113
184
114sym_t *head;
115
116void
117define(char *name, int value)
118{
119 sym_t *p, *q;
120
121 for (p = head, q = (sym_t *)&head; p; p = p->next) {
122 if (!strcmp(p->name, name))
123 error("redefined symbol");
124 q = p;
185 if (argc != 1) {
186 fprintf(stderr, "%s: No input file specifiled\n", appname);
187 usage();
188 /* NOTREACHED */
125 }
126
189 }
190
127 p = q->next = (sym_t *)Malloc(sizeof(sym_t));
128 p->next = NULL;
129 p->name = Strdup(name);
130 p->value = value;
131 p->npatch = 0;
132 p->patch = NULL;
133
134 if (debug) {
135 fprintf(stderr, "\"%s\" ", p->name);
136 if (p->value != NOVALUE)
137 fprintf(stderr, "defined as 0x%x\n", p->value);
138 else
139 fprintf(stderr, "undefined\n");
191 symtable_open();
192 inputfilename = *argv;
193 include_file(*argv, SOURCE_FILE);
194 retval = yyparse();
195 if (retval == 0) {
196 back_patch();
197 if (ofile != NULL)
198 output_code(ofile);
199 if (regfile != NULL)
200 symtable_dump(regfile);
201 if (listfile != NULL)
202 output_listing(listfile, inputfilename);
140 }
203 }
141}
142
204
143sym_t *
144lookup(char *name)
145{
146 sym_t *p;
147
148 for (p = head; p; p = p->next)
149 if (!strcmp(p->name, name))
150 return(p);
151 return(NULL);
205 stop(NULL, 0);
206 /* NOTREACHED */
207 return (0);
152}
153
208}
209
154void
155patch(sym_t *p, int location)
210static void
211usage()
156{
212{
157 p->npatch += 1;
158 p->patch = (int *)Realloc(p->patch, p->npatch * sizeof(int *));
159
213
160 p->patch[p->npatch - 1] = location;
214 (void)fprintf(stderr, "usage: %s [-I directory] [-o output_file] "
215 "input_file\n", appname);
216 exit(EX_USAGE);
161}
162
217}
218
163void backpatch(void)
219static void
220back_patch()
164{
221{
165 int i;
166 sym_t *p;
222 struct instruction *cur_instr;
167
223
168 for (p = head; p; p = p->next) {
224 for(cur_instr = seq_program.stqh_first;
225 cur_instr != NULL;
226 cur_instr = cur_instr->links.stqe_next) {
227 if (cur_instr->patch_label != NULL) {
228 struct ins_format3 *f3_instr;
229 u_int address;
169
230
170 if (p->value == NOVALUE) {
171 fprintf(stderr,
172 "%s: undefined symbol \"%s\"\n",
173 filename, p->name);
174 exit(EXIT_FAILURE);
175 }
231 if (cur_instr->patch_label->type != LABEL) {
232 char buf[255];
176
233
177 if (p->npatch) {
178 if (debug)
179 fprintf(stderr,
180 "\"%s\" (0x%x) patched at",
181 p->name, p->value);
182
183 for (i = 0; i < p->npatch; i++) {
184 M[p->patch[i]][0] &= ~1;
185 M[p->patch[i]][0] |= ((p->value >> 8) & 1);
186 M[p->patch[i]][1] = p->value & 0xff;
187
188 if (debug)
189 fprintf(stderr, " 0x%x", p->patch[i]);
234 snprintf(buf, sizeof(buf),
235 "Undefined label %s",
236 cur_instr->patch_label->name);
237 stop(buf, EX_DATAERR);
238 /* NOTREACHED */
190 }
239 }
191
192 if (debug)
193 fputc('\n', stderr);
240 f3_instr = &cur_instr->format.format3;
241 address = ((f3_instr->opcode_addr & ADDR_HIGH_BIT) << 8)
242 | f3_instr->address;
243 address += cur_instr->patch_label->info.linfo->address;
244 f3_instr->opcode_addr &= ~ADDR_HIGH_BIT;
245 f3_instr->opcode_addr |= (address >> 8) & ADDR_HIGH_BIT;
246 f3_instr->address = address & 0xFF;
194 }
195 }
196}
197
247 }
248 }
249}
250
198/*
199 * Output words in byte-reversed order (least significant first)
200 * since the sequencer RAM is loaded that way.
201 */
202void
203output(FILE *fp)
251static void
252output_code(ofile)
253 FILE *ofile;
204{
254{
205 int i;
255 struct instruction *cur_instr;
256 patch_t *cur_patch;
257 symbol_node_t *cur_node;
258 int instrcount;
206
259
207 for (i = 0; i < LC; i++)
208 fprintf(fp, "\t0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
209 M[i][3],
210 M[i][2],
211 M[i][1],
212 M[i][0]);
213 printf("%d out of %d instructions used.\n", LC, MEMORY);
214}
260 instrcount = 0;
261 fprintf(ofile,
262"/*
263 * DO NOT EDIT - This file is automatically generated.
264 */\n");
215
265
216char **
217getl(int *n)
218{
219 int i;
220 char *p, *quote;
221 static char buf[MAXLINE];
222 static char *a[MAXTOKEN];
223
224 i = 0;
225
226 while (fgets(buf, sizeof(buf), stdin)) {
227
228 lineno += 1;
229
230 if (buf[strlen(buf)-1] != '\n')
231 error("line too long");
232
233 p = strchr(buf, '#');
234 if (p)
235 *p = '\0';
236 p = buf;
237rescan:
238 quote = strchr(p, '\"');
239 if (quote)
240 *quote = '\0';
241 for (p = strtok(p, ", \t\n"); p; p = strtok(NULL, ", \t\n"))
242 if (i < MAXTOKEN-1)
243 a[i++] = p;
244 else
245 error("too many tokens");
246 if (quote) {
247 quote++;
248 p = strchr(quote, '\"');
249 if (!p)
250 error("unterminated string constant");
251 else if (i < MAXTOKEN-1) {
252 a[i++] = quote;
253 *p = '\0';
254 p++;
255 }
256 else
257 error("too many tokens");
258 goto rescan;
259 }
260 if (i) {
261 *n = i;
262 return(a);
263 }
266 fprintf(ofile, "static u_int8_t seqprog[] = {\n");
267 for(cur_instr = seq_program.stqh_first;
268 cur_instr != NULL;
269 cur_instr = cur_instr->links.stqe_next) {
270 fprintf(ofile, "\t0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
271 cur_instr->format.bytes[0],
272 cur_instr->format.bytes[1],
273 cur_instr->format.bytes[2],
274 cur_instr->format.bytes[3]);
275 instrcount++;
264 }
276 }
265 return(NULL);
266}
277 fprintf(ofile, "};\n");
267
278
268#define A 0x8000 /* `A'ccumulator ok */
269#define I 0x4000 /* use as immediate value */
270#define SL 0x2000 /* shift left */
271#define SR 0x1000 /* shift right */
272#define RL 0x0800 /* rotate left */
273#define RR 0x0400 /* rotate right */
274#define LO 0x8000 /* lookup: ori-{jmp,jc,jnc,call} */
275#define LA 0x4000 /* lookup: and-{jz,jnz} */
276#define LX 0x2000 /* lookup: xor-{je,jne} */
277#define NA -1 /* not applicable */
278
279struct {
280 char *name;
281 int n; /* number of operands, including opcode */
282 unsigned int op; /* immediate or L?|pos_from_0 */
283 unsigned int dest; /* NA, pos_from_0, or I|immediate */
284 unsigned int src; /* NA, pos_from_0, or I|immediate */
285 unsigned int imm; /* pos_from_0, A|pos_from_0, or I|immediate */
286 unsigned int addr; /* NA or pos_from_0 */
287 int fmt; /* instruction format - 1, 2, or 3 */
288} instr[] = {
289/*
290 * N OP DEST SRC IMM ADDR FMT
291 */
292 { "mov", 3, 1, 1, 2, I|0xff, NA, 1 },
293 { "mov", 4, LO|2, NA, 1, I|0, 3, 3 },
294 { "mvi", 3, 0, 1, I|R_ALLZEROS, A|2, NA, 1 },
295 { "mvi", 4, LO|2, NA, I|R_ALLZEROS, 1, 3, 3 },
296 { "not", 2, 2, 1, 1, I|0xff, NA, 1 },
297 { "and", 3, 1, 1, 1, A|2, NA, 1 },
298 { "and", 4, 1, 1, 3, A|2, NA, 1 },
299 { "or", 3, 0, 1, 1, A|2, NA, 1 },
300 { "or", 4, 0, 1, 3, A|2, NA, 1 },
301 { "or", 5, LO|3, NA, 1, 2, 4, 3 },
302 { "xor", 3, 2, 1, 1, A|2, NA, 1 },
303 { "xor", 4, 2, 1, 3, A|2, NA, 1 },
304 { "nop", 1, 1, I|R_NONE, I|R_ALLZEROS, I|0xff, NA, 1 },
305 { "inc", 2, 3, 1, 1, I|1, NA, 1 },
306 { "inc", 3, 3, 1, 2, I|1, NA, 1 },
307 { "dec", 2, 3, 1, 1, I|0xff, NA, 1 },
308 { "dec", 3, 3, 1, 2, I|0xff, NA, 1 },
309 { "jmp", 2, LO|0, NA, I|R_SINDEX, I|0, 1, 3 },
310 { "jc", 2, LO|0, NA, I|R_SINDEX, I|0, 1, 3 },
311 { "jnc", 2, LO|0, NA, I|R_SINDEX, I|0, 1, 3 },
312 { "call", 2, LO|0, NA, I|R_SINDEX, I|0, 1, 3 },
313 { "test", 5, LA|3, NA, 1, A|2, 4, 3 },
314 { "cmp", 5, LX|3, NA, 1, A|2, 4, 3 },
315 { "ret", 1, 1, I|R_NONE, I|R_ALLZEROS, I|0xff, NA, 1 },
316 { "ret", 1, 1, I|R_NONE, I|R_ALLZEROS, I|0xff, NA, 1 },
317 { "clc", 1, 3, I|R_NONE, I|R_ALLZEROS, I|1, NA, 1 },
318 { "clc", 4, 3, 2, I|R_ALLZEROS, A|3, NA, 1 },
319 { "stc", 2, 3, 1, I|R_ALLONES, I|1, NA, 1 },
320 { "add", 3, 3, 1, 1, A|2, NA, 1 },
321 { "add", 4, 3, 1, 3, A|2, NA, 1 },
322 { "adc", 3, 4, 1, 1, A|2, NA, 1 },
323 { "adc", 4, 4, 1, 3, A|2, NA, 1 },
324 { "shl", 3, 5, 1, 1, SL|2, NA, 2 },
325 { "shl", 4, 5, 1, 2, SL|3, NA, 2 },
326 { "shr", 3, 5, 1, 1, SR|2, NA, 2 },
327 { "shr", 4, 5, 1, 2, SR|3, NA, 2 },
328 { "rol", 3, 5, 1, 1, RL|2, NA, 2 },
329 { "rol", 4, 5, 1, 2, RL|3, NA, 2 },
330 { "ror", 3, 5, 1, 1, RR|2, NA, 2 },
331 { "ror", 4, 5, 1, 2, RR|3, NA, 2 },
332 /*
279 /*
333 * Extensions (note also that mvi allows A)
280 * Output the patch list, option definitions first.
334 */
281 */
335 { "clr", 2, 1, 1, I|R_ALLZEROS, I|0xff, NA, 1 },
336 { 0, 0, 0, 0, 0, 0, 0, 0 }
337};
338
339int
340eval_operand(char **a, int spec)
341{
342 int i;
343 unsigned int want = spec & (LO|LA|LX);
344
345 static struct {
346 unsigned int what;
347 char *name;
348 int value;
349 } jmptab[] = {
350 { LO, "jmp", 8 },
351 { LO, "jc", 9 },
352 { LO, "jnc", 10 },
353 { LO, "call", 11 },
354 { LA, "jz", 15 },
355 { LA, "jnz", 13 },
356 { LX, "je", 14 },
357 { LX, "jne", 12 },
358 };
359
360 spec &= ~(LO|LA|LX);
361
362 for (i = 0; i < sizeof(jmptab)/sizeof(jmptab[0]); i++)
363 if (jmptab[i].what == want &&
364 !strcmp(jmptab[i].name, a[spec]))
365 {
366 return(jmptab[i].value);
367 }
368
369 if (want)
370 error("invalid jump");
371
372 return(spec); /* "case 0" - no flags set */
373}
374
375int
376eval_sdi(char **a, int spec)
377{
378 sym_t *p;
379 unsigned val;
380
381 if (spec == NA)
382 return(NA);
383
384 switch (spec & (A|I|SL|SR|RL|RR)) {
385 case SL:
386 case SR:
387 case RL:
388 case RR:
389 if (isdigit(*a[spec &~ (SL|SR|RL|RR)]))
390 val = strtol(a[spec &~ (SL|SR|RL|RR)], NULL, 0);
391 else {
392 p = lookup(a[spec &~ (SL|SR|RL|RR)]);
393 if (!p)
394 error("undefined symbol used");
395 val = p->value;
396 }
397
398 switch (spec & (SL|SR|RL|RR)) { /* blech */
399 case SL:
400 if (val > 7)
401 return(0xf0);
402 return(((val % 8) << 4) |
403 (val % 8));
404 case SR:
405 if (val > 7)
406 return(0xf0);
407 return(((val % 8) << 4) |
408 (1 << 3) |
409 ((8 - (val % 8)) % 8));
410 case RL:
411 return(val % 8);
412 case RR:
413 return((8 - (val % 8)) % 8);
414 }
415 case I:
416 return(spec &~ I);
417 case A:
418 /*
419 * An immediate field of zero selects
420 * the accumulator. Vigorously object
421 * if zero is given otherwise - it's
422 * most likely an error.
423 */
424 spec &= ~A;
425 if (!strcmp("A", a[spec]))
426 return(0);
427 if (isdigit(*a[spec]) &&
428 strtol(a[spec], NULL, 0) == 0)
429 {
430 error("immediate value of zero selects accumulator");
431 }
432 /* falls through */
433 case 0:
434 if (isdigit(*a[spec]))
435 return(strtol(a[spec], NULL, 0));
436 p = lookup(a[spec]);
437 if (p)
438 return(p->value);
439 error("undefined symbol used");
282 for(cur_node = patch_options.slh_first;
283 cur_node != NULL;
284 cur_node = cur_node->links.sle_next) {
285 fprintf(ofile, "#define\t%-16s\t0x%x\n", cur_node->symbol->name,
286 cur_node->symbol->info.condinfo->value);
440 }
287 }
288 symlist_free(&patch_options);
441
289
442 return(NA); /* shut the compiler up */
443}
290 fprintf(ofile,
291"struct patch {
292 int options;
293 int negative;
294 int begin;
295 int end;
296} patches[] = {\n");
444
297
445int
446eval_addr(char **a, int spec)
447{
448 sym_t *p;
298 for(cur_patch = patch_list.stqh_first;
299 cur_patch != NULL;
300 cur_patch = cur_patch->links.stqe_next)
449
301
450 if (spec == NA)
451 return(NA);
452 if (isdigit(*a[spec]))
453 return(strtol(a[spec], NULL, 0));
302 fprintf(ofile, "\t{ 0x%08x, %d, 0x%03x, 0x%03x },\n",
303 cur_patch->options, cur_patch->negative, cur_patch->begin,
304 cur_patch->end);
454
305
455 p = lookup(a[spec]);
456
457 if (p) {
458 if (p->value != NOVALUE)
459 return(p->value);
460 patch(p, LC);
461 } else {
462 define(a[spec], NOVALUE);
463 p = lookup(a[spec]);
464 patch(p, LC);
465 }
466
467 return(NA); /* will be patched in later */
306 fprintf(ofile, "\t{ 0x%08x, %d, 0x%03x, 0x%03x }\n};\n",
307 0, 0, 0, 0);
308
309 fprintf(stderr, "%s: %d instructions used\n", appname, instrcount);
468}
469
310}
311
470int
471crack(char **a, int n)
312void
313output_listing(listfile, ifilename)
314 FILE *listfile;
315 char *ifilename;
472{
316{
473 int i;
474 int I_imm, I_addr;
475 int I_op, I_dest, I_src, I_ret;
317 FILE *ifile;
318 int line;
319 struct instruction *cur_instr;
320 int instrcount;
321 char buf[1024];
476
322
477 /*
478 * Check for "ret" at the end of the line; remove
479 * it unless it's "ret" alone - we still want to
480 * look it up in the table.
481 */
482 I_ret = (strcmp(a[n-1], "ret") ? 0 : !0);
483 if (I_ret && n > 1)
484 n -= 1;
485
486 for (i = 0; instr[i].name; i++) {
487 /*
488 * Look for match in table given constraints,
489 * currently just the name and the number of
490 * operands.
491 */
492 if (!strcmp(instr[i].name, *a) && instr[i].n == n)
493 break;
323 instrcount = 0;
324 line = 1;
325 if ((ifile = fopen(ifilename, "r")) == NULL) {
326 perror(ifilename);
327 stop(NULL, EX_DATAERR);
494 }
328 }
495 if (!instr[i].name)
496 error("unknown opcode or wrong number of operands");
497
498 I_op = eval_operand(a, instr[i].op);
499 I_src = eval_sdi(a, instr[i].src);
500 I_imm = eval_sdi(a, instr[i].imm);
501 I_dest = eval_sdi(a, instr[i].dest);
502 I_addr = eval_addr(a, instr[i].addr);
503
504 if( LC >= MEMORY )
505 error("Memory exhausted!\n");
506
507 switch (instr[i].fmt) {
508 case 1:
509 case 2:
510 M[LC][0] = (I_op << 1) | I_ret;
511 M[LC][1] = I_dest;
512 M[LC][2] = I_src;
513 M[LC][3] = I_imm;
514 break;
515 case 3:
516 if (I_ret)
517 error("illegal use of \"ret\"");
518 M[LC][0] = (I_op << 1) | ((I_addr >> 8) & 1);
519 M[LC][1] = I_addr & 0xff;
520 M[LC][2] = I_src;
521 M[LC][3] = I_imm;
522 break;
329 for(cur_instr = seq_program.stqh_first;
330 cur_instr != NULL;
331 cur_instr = cur_instr->links.stqe_next) {
332 while (line < cur_instr->srcline) {
333 fgets(buf, sizeof(buf), ifile);
334 fprintf(listfile, "\t\t%s", buf);
335 line++;
336 }
337 fprintf(listfile, "%03x %02x%02x%02x%02x", instrcount,
338 cur_instr->format.bytes[0],
339 cur_instr->format.bytes[1],
340 cur_instr->format.bytes[2],
341 cur_instr->format.bytes[3]);
342 fgets(buf, sizeof(buf), ifile);
343 fprintf(listfile, "%s", buf);
344 line++;
345 instrcount++;
523 }
346 }
524
525 return (1); /* no two-byte instructions yet */
347 fclose(ifile);
526}
527
348}
349
528#undef SL
529#undef SR
530#undef RL
531#undef RR
532#undef LX
533#undef LA
534#undef LO
535#undef I
536#undef A
537
350/*
351 * Print out error information if appropriate, and clean up before
352 * terminating the program.
353 */
538void
354void
539assemble(FILE *ofile)
355stop(string, err_code)
356 const char *string;
357 int err_code;
540{
358{
541 int n;
542 char **a;
543 sym_t *p;
544
545 while ((a = getl(&n))) {
546
547 while (a[0][strlen(*a)-1] == ':') {
548 a[0][strlen(*a)-1] = '\0';
549 p = lookup(*a);
550 if (p)
551 p->value = LC;
552 else
553 define(*a, LC);
554 a += 1;
555 n -= 1;
359 if (string != NULL) {
360 fprintf(stderr, "%s: ", appname);
361 if (yyfilename != NULL) {
362 fprintf(stderr, "Stopped at file %s, line %d - ",
363 yyfilename, yylineno);
556 }
364 }
365 fprintf(stderr, "%s\n", string);
366 }
557
367
558 if (!n) /* line was all labels */
559 continue;
560
561 if (n == 3 && !strcmp("VERSION", *a))
562 fprintf(ofile, "#define %s \"%s\"\n", a[1], a[2]);
563 else {
564 if (n == 3 && !strcmp("=", a[1]))
565 define(*a, strtol(a[2], NULL, 0));
566 else
567 LC += crack(a, n);
368 if (ofile != NULL) {
369 fclose(ofile);
370 if (err_code != 0) {
371 fprintf(stderr, "%s: Removing %s due to error\n",
372 appname, ofilename);
373 unlink(ofilename);
568 }
569 }
570
374 }
375 }
376
571 backpatch();
572 output(ofile);
377 symtable_close();
573
378
574 if (debug)
575 output(stderr);
379 exit(err_code);
576}
577
380}
381
578int
579main(int argc, char **argv)
382struct instruction *
383seq_alloc()
580{
384{
581 int c;
582 int pid;
583 int ifile;
584 FILE *ofile;
585 int fd[2];
385 struct instruction *new_instr;
586
386
587 ofile = NULL;
588 while ((c = getopt(argc, argv, "dho:vD:")) != EOF) {
589 switch (c) {
590 case 'd':
591 debug = !0;
592 break;
593 case 'D':
594 {
595 char *p;
596 if ((p = strchr(optarg, '=')) != NULL) {
597 *p = '\0';
598 define(optarg, strtol(p + 1, NULL, 0));
599 }
600 else
601 define(optarg, 1);
602 break;
603 }
604 case 'o':
605
606 if ((ofile = fopen(optarg, "w")) == NULL) {
607 perror(optarg);
608 exit(EXIT_FAILURE);
609 }
610 break;
611 case 'h':
612 printf("usage: %s [-d] [-Dname] [-ooutput] input\n",
613 *argv);
614 exit(EXIT_SUCCESS);
615 break;
616 case 'v':
617 printf("%s\n", id);
618 exit(EXIT_SUCCESS);
619 break;
620 default:
621 exit(EXIT_FAILURE);
622 break;
623 }
624 }
387 new_instr = (struct instruction *)malloc(sizeof(struct instruction));
388 if (new_instr == NULL)
389 stop("Unable to malloc instruction object", EX_SOFTWARE);
390 memset(new_instr, 0, sizeof(*new_instr));
391 STAILQ_INSERT_TAIL(&seq_program, new_instr, links);
392 new_instr->srcline = yylineno;
393 return new_instr;
394}
625
395
626 if (argc - optind != 1) {
627 fprintf(stderr, "%s: must have one input file\n", *argv);
628 exit(EXIT_FAILURE);
629 }
630 filename = argv[optind];
396patch_t *
397patch_alloc()
398{
399 patch_t *new_patch;
631
400
632
633 if ((ifile = open(filename, O_RDONLY)) < 0) {
634 perror(filename);
635 exit(EXIT_FAILURE);
636 }
637
638 if (!ofile) {
639 if ((ofile = fopen(ADOTOUT, "w")) == NULL) {
640 perror(ADOTOUT);
641 exit(EXIT_FAILURE);
642 }
643 }
644
645 if (pipe(fd) < 0) {
646 perror("pipe failed");
647 exit(1);
648 }
649
650 if ((pid = fork()) < 0 ) {
651 perror("fork failed");
652 exit(1);
653 }
654 else if (pid > 0) { /* Parent */
655 close(fd[1]); /* Close write end */
656 if (fd[0] != STDIN_FILENO) {
657 if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) {
658 perror("dup2 error on stdin");
659 exit(EXIT_FAILURE);
660 }
661 close(fd[0]);
662 }
663 assemble(ofile);
664 exit(EXIT_SUCCESS);
665 }
666 else { /* Child */
667 close(fd[0]); /* Close Read end */
668 if (fd[1] != STDOUT_FILENO) {
669 if (dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
670 perror("dup2 error on stdout");
671 exit(EXIT_FAILURE);
672 }
673 close(fd[1]);
674 }
675 if (ifile != STDIN_FILENO) {
676 if (dup2(ifile, STDIN_FILENO) != STDIN_FILENO) {
677 perror("dup2 error on stdin");
678 exit(EXIT_FAILURE);
679 }
680 close(ifile);
681 }
682 execl("/usr/bin/cpp", "/usr/bin/cpp", "-P", "-", "-", NULL);
683 }
684 return(EXIT_SUCCESS);
401 new_patch = (patch_t *)malloc(sizeof(patch_t));
402 if (new_patch == NULL)
403 stop("Unable to malloc patch object", EX_SOFTWARE);
404 memset(new_patch, 0, sizeof(*new_patch));
405 STAILQ_INSERT_TAIL(&patch_list, new_patch, links);
406 return new_patch;
685}
407}