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}
|