summaryrefslogtreecommitdiffstats
path: root/sys/dev/aic7xxx/aicasm/aicasm.c
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>1997-03-16 07:08:19 +0000
committergibbs <gibbs@FreeBSD.org>1997-03-16 07:08:19 +0000
commit40f591dab80f67b297f37fdf5bf68dd8d39f5d7a (patch)
treef2f699238be99083f0eb61cc7f4079f6da10af44 /sys/dev/aic7xxx/aicasm/aicasm.c
parentcfc29bf38bfef7204161e3ee2916a8babb6637bb (diff)
downloadFreeBSD-src-40f591dab80f67b297f37fdf5bf68dd8d39f5d7a.zip
FreeBSD-src-40f591dab80f67b297f37fdf5bf68dd8d39f5d7a.tar.gz
Makefile gram.y scan.l sequencer.h symbol.c symbol.h aic7xxx_asm.c:
New sequencer assembler for the aic7xxx adapters. This assembler performs some amount of register type checking, allows bit manipulation of symbolic constants, and generates "patch tables" for conditionalized downloading of portions of the program. This makes it easier to take full advantage of the different features of the aic7xxx cards without imposing run time penalies or being bound to the small memory footprints of the low end cards for features like target mode. aic7xxx.reg: New, assembler parsed, register definitions fo the aic7xxx cards. This was done primarily in anticipation of 7810 support which will have a different register layout, but should be able to use the same assembler. The kernel aic7xxx driver consumes a generated file in the compile directory to get the definitions of the register locations. aic7xxx.seq: Convert to the slighly different syntax of the new assembler. Conditionalize SCB_PAGING, ultra, and twin features which shaves quite a bit of space once the program is downloaded. Add code to leave the selection hardware enabled during reconnects that win bus arbitration. This ensures that we will rearbitrate as soon as the bus goes free instead of delaying for a bit. When we expect the bus to go free, perform all of the cleanup associated with that event "up front" and enter a loop awaiting bus free. If we see a REQ first, complain, but attempt to continue. This will hopefully address, or at least help diagnose, the "target didn't send identify" messages that have been reported. Spelling corrections obtained from NetBSD.
Diffstat (limited to 'sys/dev/aic7xxx/aicasm/aicasm.c')
-rw-r--r--sys/dev/aic7xxx/aicasm/aicasm.c946
1 files changed, 334 insertions, 612 deletions
diff --git a/sys/dev/aic7xxx/aicasm/aicasm.c b/sys/dev/aic7xxx/aicasm/aicasm.c
index d3e09f6..efed828 100644
--- a/sys/dev/aic7xxx/aicasm/aicasm.c
+++ b/sys/dev/aic7xxx/aicasm/aicasm.c
@@ -1,31 +1,26 @@
-/*+M*************************************************************************
- * Adaptec AIC7770/AIC7870 sequencer code assembler.
+/*
+ * Aic7xxx SCSI host adapter firmware asssembler
*
- * Copyright (c) 1994 John Aycock
- * The University of Calgary Department of Computer Science.
- * All rights reserved.
+ * Copyright (c) 1997 Justin T. Gibbs.
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions, and the following disclaimer.
+ * notice immediately at the beginning of the file, without modification,
+ * this list of conditions, and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of Calgary
- * Department of Computer Science and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
@@ -33,653 +28,380 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * Comments are started by `#' and continue to the end of the line; lines
- * may be of the form:
- * <label>*
- * <label>* <undef-sym> = <value>
- * <label>* <opcode> <operand>*
- *
- * A <label> is an <undef-sym> ending in a colon. Spaces, tabs, and commas
- * are token separators.
- *
- *-M*************************************************************************/
-static char id[] = "$Id$";
-#include <ctype.h>
+ * $Id$
+ */
+#include <sys/types.h>
+#include <sys/mman.h>
+
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
#include <unistd.h>
-#include <fcntl.h>
-#define MEMORY 448
-#define MAXLINE 1024
-#define MAXTOKEN 32
-#define ADOTOUT "a.out"
-#define NOVALUE -1
-
-/*
- * AIC-7770/AIC-7870 register definitions
- */
-#define R_SINDEX 0x65
-#define R_ALLONES 0x69
-#define R_ALLZEROS 0x6a
-#define R_NONE 0x6a
+#include "aic7xxx_asm.h"
+#include "symbol.h"
+#include "sequencer.h"
-int debug;
-int lineno, LC;
-char *filename;
-unsigned char M[MEMORY][4];
+static void usage __P((void));
+static void back_patch __P((void));
+static void output_code __P((FILE *ofile));
+static void output_listing __P((FILE *listfile, char *ifilename));
-void
-error(char *s)
-{
- fprintf(stderr, "%s: %s at line %d\n", filename, s, lineno);
- exit(EXIT_FAILURE);
-}
+struct path_list search_path;
+int includes_search_curdir;
+char *appname;
+FILE *ofile;
+char *ofilename;
-void *
-Malloc(size_t size)
-{
- void *p = malloc(size);
- if (!p)
- error("out of memory");
- return(p);
-}
+static STAILQ_HEAD(,instruction) seq_program;
+static STAILQ_HEAD(, patch) patch_list;
+symlist_t patch_options;
-void *
-Realloc(void *ptr, size_t size)
-{
- void *p = realloc(ptr, size);
- if (!p)
- error("out of memory");
- return(p);
-}
+#if DEBUG
+extern int yy_flex_debug;
+extern int yydebug;
+#endif
+extern FILE *yyin;
+extern int yyparse __P((void));
-char *
-Strdup(char *s)
-{
- char *p = (char *)Malloc(strlen(s) + 1);
- strcpy(p, s);
- return(p);
-}
-
-typedef struct sym_t {
- struct sym_t *next; /* MUST BE FIRST */
- char *name;
- int value;
- int npatch;
- int *patch;
-} sym_t;
-
-sym_t *head;
-
-void
-define(char *name, int value)
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
{
- sym_t *p, *q;
-
- for (p = head, q = (sym_t *)&head; p; p = p->next) {
- if (!strcmp(p->name, name))
- error("redefined symbol");
- q = p;
+ extern char *optarg;
+ extern int optind;
+ int ch;
+ int retval;
+ char *inputfilename;
+ char *regfilename;
+ FILE *regfile;
+ char *listfilename;
+ FILE *listfile;
+
+ SLIST_INIT(&search_path);
+ STAILQ_INIT(&seq_program);
+ STAILQ_INIT(&patch_list);
+ SLIST_INIT(&patch_options);
+ includes_search_curdir = 1;
+ appname = *argv;
+ regfile = NULL;
+ listfile = NULL;
+#if DEBUG
+ yy_flex_debug = 0;
+#endif
+ while ((ch = getopt(argc, argv, "d:l:n:o:r:I:")) != EOF) {
+ switch(ch) {
+ case 'd':
+#if DEBUG
+ if (strcmp(optarg, "s") == 0)
+ yy_flex_debug = 1;
+ else if (strcmp(optarg, "p") == 0)
+ yydebug = 1;
+#else
+ stop("-d: Assembler not built with debugging "
+ "information", EX_SOFTWARE);
+#endif
+ break;
+ case 'l':
+ /* Create a program listing */
+ if ((listfile = fopen(optarg, "w")) == NULL) {
+ perror(optarg);
+ stop(NULL, EX_CANTCREAT);
+ }
+ listfilename = optarg;
+ break;
+ case 'n':
+ /* Don't complain about the -nostdinc directrive */
+ if (strcmp(optarg, "ostdinc")) {
+ fprintf(stderr, "%s: Unknown option -%c%s\n",
+ appname, ch, optarg);
+ usage();
+ /* NOTREACHED */
+ }
+ break;
+ case 'o':
+ if ((ofile = fopen(optarg, "w")) == NULL) {
+ perror(optarg);
+ stop(NULL, EX_CANTCREAT);
+ }
+ ofilename = optarg;
+ break;
+ case 'r':
+ if ((regfile = fopen(optarg, "w")) == NULL) {
+ perror(optarg);
+ stop(NULL, EX_CANTCREAT);
+ }
+ regfilename = optarg;
+ break;
+ case 'I':
+ {
+ path_entry_t include_dir;
+
+ if (strcmp(optarg, "-") == 0) {
+ if (includes_search_curdir == 0) {
+ fprintf(stderr, "%s: Warning - '-I-' "
+ "specified multiple "
+ "times\n", appname);
+ }
+ includes_search_curdir = 0;
+ for (include_dir = search_path.slh_first;
+ include_dir != NULL;
+ include_dir = include_dir->links.sle_next)
+ /*
+ * All entries before a '-I-' only
+ * apply to includes specified with
+ * quotes instead of "<>".
+ */
+ include_dir->quoted_includes_only = 1;
+ } else {
+ include_dir =
+ (path_entry_t)malloc(sizeof(*include_dir));
+ if (include_dir == NULL) {
+ perror(optarg);
+ stop(NULL, EX_OSERR);
+ }
+ include_dir->directory = strdup(optarg);
+ if (include_dir->directory == NULL) {
+ perror(optarg);
+ stop(NULL, EX_OSERR);
+ }
+ include_dir->quoted_includes_only = 0;
+ SLIST_INSERT_HEAD(&search_path, include_dir,
+ links);
+ }
+ break;
+ }
+ case '?':
+ default:
+ usage();
+ /* NOTREACHED */
+ }
}
+ argc -= optind;
+ argv += optind;
- p = q->next = (sym_t *)Malloc(sizeof(sym_t));
- p->next = NULL;
- p->name = Strdup(name);
- p->value = value;
- p->npatch = 0;
- p->patch = NULL;
-
- if (debug) {
- fprintf(stderr, "\"%s\" ", p->name);
- if (p->value != NOVALUE)
- fprintf(stderr, "defined as 0x%x\n", p->value);
- else
- fprintf(stderr, "undefined\n");
+ if (argc != 1) {
+ fprintf(stderr, "%s: No input file specifiled\n", appname);
+ usage();
+ /* NOTREACHED */
}
-}
-sym_t *
-lookup(char *name)
-{
- sym_t *p;
+ symtable_open();
+ inputfilename = *argv;
+ include_file(*argv, SOURCE_FILE);
+ retval = yyparse();
+ if (retval == 0) {
+ back_patch();
+ if (ofile != NULL)
+ output_code(ofile);
+ if (regfile != NULL)
+ symtable_dump(regfile);
+ if (listfile != NULL)
+ output_listing(listfile, inputfilename);
+ }
- for (p = head; p; p = p->next)
- if (!strcmp(p->name, name))
- return(p);
- return(NULL);
+ stop(NULL, 0);
+ /* NOTREACHED */
+ return (0);
}
-void
-patch(sym_t *p, int location)
+static void
+usage()
{
- p->npatch += 1;
- p->patch = (int *)Realloc(p->patch, p->npatch * sizeof(int *));
- p->patch[p->npatch - 1] = location;
+ (void)fprintf(stderr, "usage: %s [-I directory] [-o output_file] "
+ "input_file\n", appname);
+ exit(EX_USAGE);
}
-void backpatch(void)
+static void
+back_patch()
{
- int i;
- sym_t *p;
-
- for (p = head; p; p = p->next) {
-
- if (p->value == NOVALUE) {
- fprintf(stderr,
- "%s: undefined symbol \"%s\"\n",
- filename, p->name);
- exit(EXIT_FAILURE);
- }
-
- if (p->npatch) {
- if (debug)
- fprintf(stderr,
- "\"%s\" (0x%x) patched at",
- p->name, p->value);
-
- for (i = 0; i < p->npatch; i++) {
- M[p->patch[i]][0] &= ~1;
- M[p->patch[i]][0] |= ((p->value >> 8) & 1);
- M[p->patch[i]][1] = p->value & 0xff;
-
- if (debug)
- fprintf(stderr, " 0x%x", p->patch[i]);
+ struct instruction *cur_instr;
+
+ for(cur_instr = seq_program.stqh_first;
+ cur_instr != NULL;
+ cur_instr = cur_instr->links.stqe_next) {
+ if (cur_instr->patch_label != NULL) {
+ struct ins_format3 *f3_instr;
+ u_int address;
+
+ if (cur_instr->patch_label->type != LABEL) {
+ char buf[255];
+
+ snprintf(buf, sizeof(buf),
+ "Undefined label %s",
+ cur_instr->patch_label->name);
+ stop(buf, EX_DATAERR);
+ /* NOTREACHED */
}
-
- if (debug)
- fputc('\n', stderr);
+ f3_instr = &cur_instr->format.format3;
+ address = ((f3_instr->opcode_addr & ADDR_HIGH_BIT) << 8)
+ | f3_instr->address;
+ address += cur_instr->patch_label->info.linfo->address;
+ f3_instr->opcode_addr &= ~ADDR_HIGH_BIT;
+ f3_instr->opcode_addr |= (address >> 8) & ADDR_HIGH_BIT;
+ f3_instr->address = address & 0xFF;
}
}
}
-/*
- * Output words in byte-reversed order (least significant first)
- * since the sequencer RAM is loaded that way.
- */
-void
-output(FILE *fp)
-{
- int i;
-
- for (i = 0; i < LC; i++)
- fprintf(fp, "\t0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
- M[i][3],
- M[i][2],
- M[i][1],
- M[i][0]);
- printf("%d out of %d instructions used.\n", LC, MEMORY);
-}
-
-char **
-getl(int *n)
+static void
+output_code(ofile)
+ FILE *ofile;
{
- int i;
- char *p, *quote;
- static char buf[MAXLINE];
- static char *a[MAXTOKEN];
-
- i = 0;
-
- while (fgets(buf, sizeof(buf), stdin)) {
-
- lineno += 1;
-
- if (buf[strlen(buf)-1] != '\n')
- error("line too long");
-
- p = strchr(buf, '#');
- if (p)
- *p = '\0';
- p = buf;
-rescan:
- quote = strchr(p, '\"');
- if (quote)
- *quote = '\0';
- for (p = strtok(p, ", \t\n"); p; p = strtok(NULL, ", \t\n"))
- if (i < MAXTOKEN-1)
- a[i++] = p;
- else
- error("too many tokens");
- if (quote) {
- quote++;
- p = strchr(quote, '\"');
- if (!p)
- error("unterminated string constant");
- else if (i < MAXTOKEN-1) {
- a[i++] = quote;
- *p = '\0';
- p++;
- }
- else
- error("too many tokens");
- goto rescan;
- }
- if (i) {
- *n = i;
- return(a);
- }
+ struct instruction *cur_instr;
+ patch_t *cur_patch;
+ symbol_node_t *cur_node;
+ int instrcount;
+
+ instrcount = 0;
+ fprintf(ofile,
+"/*
+ * DO NOT EDIT - This file is automatically generated.
+ */\n");
+
+ fprintf(ofile, "static u_int8_t seqprog[] = {\n");
+ for(cur_instr = seq_program.stqh_first;
+ cur_instr != NULL;
+ cur_instr = cur_instr->links.stqe_next) {
+ fprintf(ofile, "\t0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
+ cur_instr->format.bytes[0],
+ cur_instr->format.bytes[1],
+ cur_instr->format.bytes[2],
+ cur_instr->format.bytes[3]);
+ instrcount++;
}
- return(NULL);
-}
+ fprintf(ofile, "};\n");
-#define A 0x8000 /* `A'ccumulator ok */
-#define I 0x4000 /* use as immediate value */
-#define SL 0x2000 /* shift left */
-#define SR 0x1000 /* shift right */
-#define RL 0x0800 /* rotate left */
-#define RR 0x0400 /* rotate right */
-#define LO 0x8000 /* lookup: ori-{jmp,jc,jnc,call} */
-#define LA 0x4000 /* lookup: and-{jz,jnz} */
-#define LX 0x2000 /* lookup: xor-{je,jne} */
-#define NA -1 /* not applicable */
-
-struct {
- char *name;
- int n; /* number of operands, including opcode */
- unsigned int op; /* immediate or L?|pos_from_0 */
- unsigned int dest; /* NA, pos_from_0, or I|immediate */
- unsigned int src; /* NA, pos_from_0, or I|immediate */
- unsigned int imm; /* pos_from_0, A|pos_from_0, or I|immediate */
- unsigned int addr; /* NA or pos_from_0 */
- int fmt; /* instruction format - 1, 2, or 3 */
-} instr[] = {
-/*
- * N OP DEST SRC IMM ADDR FMT
- */
- { "mov", 3, 1, 1, 2, I|0xff, NA, 1 },
- { "mov", 4, LO|2, NA, 1, I|0, 3, 3 },
- { "mvi", 3, 0, 1, I|R_ALLZEROS, A|2, NA, 1 },
- { "mvi", 4, LO|2, NA, I|R_ALLZEROS, 1, 3, 3 },
- { "not", 2, 2, 1, 1, I|0xff, NA, 1 },
- { "and", 3, 1, 1, 1, A|2, NA, 1 },
- { "and", 4, 1, 1, 3, A|2, NA, 1 },
- { "or", 3, 0, 1, 1, A|2, NA, 1 },
- { "or", 4, 0, 1, 3, A|2, NA, 1 },
- { "or", 5, LO|3, NA, 1, 2, 4, 3 },
- { "xor", 3, 2, 1, 1, A|2, NA, 1 },
- { "xor", 4, 2, 1, 3, A|2, NA, 1 },
- { "nop", 1, 1, I|R_NONE, I|R_ALLZEROS, I|0xff, NA, 1 },
- { "inc", 2, 3, 1, 1, I|1, NA, 1 },
- { "inc", 3, 3, 1, 2, I|1, NA, 1 },
- { "dec", 2, 3, 1, 1, I|0xff, NA, 1 },
- { "dec", 3, 3, 1, 2, I|0xff, NA, 1 },
- { "jmp", 2, LO|0, NA, I|R_SINDEX, I|0, 1, 3 },
- { "jc", 2, LO|0, NA, I|R_SINDEX, I|0, 1, 3 },
- { "jnc", 2, LO|0, NA, I|R_SINDEX, I|0, 1, 3 },
- { "call", 2, LO|0, NA, I|R_SINDEX, I|0, 1, 3 },
- { "test", 5, LA|3, NA, 1, A|2, 4, 3 },
- { "cmp", 5, LX|3, NA, 1, A|2, 4, 3 },
- { "ret", 1, 1, I|R_NONE, I|R_ALLZEROS, I|0xff, NA, 1 },
- { "ret", 1, 1, I|R_NONE, I|R_ALLZEROS, I|0xff, NA, 1 },
- { "clc", 1, 3, I|R_NONE, I|R_ALLZEROS, I|1, NA, 1 },
- { "clc", 4, 3, 2, I|R_ALLZEROS, A|3, NA, 1 },
- { "stc", 2, 3, 1, I|R_ALLONES, I|1, NA, 1 },
- { "add", 3, 3, 1, 1, A|2, NA, 1 },
- { "add", 4, 3, 1, 3, A|2, NA, 1 },
- { "adc", 3, 4, 1, 1, A|2, NA, 1 },
- { "adc", 4, 4, 1, 3, A|2, NA, 1 },
- { "shl", 3, 5, 1, 1, SL|2, NA, 2 },
- { "shl", 4, 5, 1, 2, SL|3, NA, 2 },
- { "shr", 3, 5, 1, 1, SR|2, NA, 2 },
- { "shr", 4, 5, 1, 2, SR|3, NA, 2 },
- { "rol", 3, 5, 1, 1, RL|2, NA, 2 },
- { "rol", 4, 5, 1, 2, RL|3, NA, 2 },
- { "ror", 3, 5, 1, 1, RR|2, NA, 2 },
- { "ror", 4, 5, 1, 2, RR|3, NA, 2 },
/*
- * Extensions (note also that mvi allows A)
+ * Output the patch list, option definitions first.
*/
- { "clr", 2, 1, 1, I|R_ALLZEROS, I|0xff, NA, 1 },
- { 0, 0, 0, 0, 0, 0, 0, 0 }
-};
-
-int
-eval_operand(char **a, int spec)
-{
- int i;
- unsigned int want = spec & (LO|LA|LX);
-
- static struct {
- unsigned int what;
- char *name;
- int value;
- } jmptab[] = {
- { LO, "jmp", 8 },
- { LO, "jc", 9 },
- { LO, "jnc", 10 },
- { LO, "call", 11 },
- { LA, "jz", 15 },
- { LA, "jnz", 13 },
- { LX, "je", 14 },
- { LX, "jne", 12 },
- };
-
- spec &= ~(LO|LA|LX);
-
- for (i = 0; i < sizeof(jmptab)/sizeof(jmptab[0]); i++)
- if (jmptab[i].what == want &&
- !strcmp(jmptab[i].name, a[spec]))
- {
- return(jmptab[i].value);
- }
-
- if (want)
- error("invalid jump");
-
- return(spec); /* "case 0" - no flags set */
-}
-
-int
-eval_sdi(char **a, int spec)
-{
- sym_t *p;
- unsigned val;
-
- if (spec == NA)
- return(NA);
-
- switch (spec & (A|I|SL|SR|RL|RR)) {
- case SL:
- case SR:
- case RL:
- case RR:
- if (isdigit(*a[spec &~ (SL|SR|RL|RR)]))
- val = strtol(a[spec &~ (SL|SR|RL|RR)], NULL, 0);
- else {
- p = lookup(a[spec &~ (SL|SR|RL|RR)]);
- if (!p)
- error("undefined symbol used");
- val = p->value;
- }
-
- switch (spec & (SL|SR|RL|RR)) { /* blech */
- case SL:
- if (val > 7)
- return(0xf0);
- return(((val % 8) << 4) |
- (val % 8));
- case SR:
- if (val > 7)
- return(0xf0);
- return(((val % 8) << 4) |
- (1 << 3) |
- ((8 - (val % 8)) % 8));
- case RL:
- return(val % 8);
- case RR:
- return((8 - (val % 8)) % 8);
- }
- case I:
- return(spec &~ I);
- case A:
- /*
- * An immediate field of zero selects
- * the accumulator. Vigorously object
- * if zero is given otherwise - it's
- * most likely an error.
- */
- spec &= ~A;
- if (!strcmp("A", a[spec]))
- return(0);
- if (isdigit(*a[spec]) &&
- strtol(a[spec], NULL, 0) == 0)
- {
- error("immediate value of zero selects accumulator");
- }
- /* falls through */
- case 0:
- if (isdigit(*a[spec]))
- return(strtol(a[spec], NULL, 0));
- p = lookup(a[spec]);
- if (p)
- return(p->value);
- error("undefined symbol used");
+ for(cur_node = patch_options.slh_first;
+ cur_node != NULL;
+ cur_node = cur_node->links.sle_next) {
+ fprintf(ofile, "#define\t%-16s\t0x%x\n", cur_node->symbol->name,
+ cur_node->symbol->info.condinfo->value);
}
-
- return(NA); /* shut the compiler up */
-}
-
-int
-eval_addr(char **a, int spec)
-{
- sym_t *p;
-
- if (spec == NA)
- return(NA);
- if (isdigit(*a[spec]))
- return(strtol(a[spec], NULL, 0));
-
- p = lookup(a[spec]);
-
- if (p) {
- if (p->value != NOVALUE)
- return(p->value);
- patch(p, LC);
- } else {
- define(a[spec], NOVALUE);
- p = lookup(a[spec]);
- patch(p, LC);
- }
-
- return(NA); /* will be patched in later */
+ symlist_free(&patch_options);
+
+ fprintf(ofile,
+"struct patch {
+ int options;
+ int negative;
+ int begin;
+ int end;
+} patches[] = {\n");
+
+ for(cur_patch = patch_list.stqh_first;
+ cur_patch != NULL;
+ cur_patch = cur_patch->links.stqe_next)
+
+ fprintf(ofile, "\t{ 0x%08x, %d, 0x%03x, 0x%03x },\n",
+ cur_patch->options, cur_patch->negative, cur_patch->begin,
+ cur_patch->end);
+
+ fprintf(ofile, "\t{ 0x%08x, %d, 0x%03x, 0x%03x }\n};\n",
+ 0, 0, 0, 0);
+
+ fprintf(stderr, "%s: %d instructions used\n", appname, instrcount);
}
-int
-crack(char **a, int n)
+void
+output_listing(listfile, ifilename)
+ FILE *listfile;
+ char *ifilename;
{
- int i;
- int I_imm, I_addr;
- int I_op, I_dest, I_src, I_ret;
-
- /*
- * Check for "ret" at the end of the line; remove
- * it unless it's "ret" alone - we still want to
- * look it up in the table.
- */
- I_ret = (strcmp(a[n-1], "ret") ? 0 : !0);
- if (I_ret && n > 1)
- n -= 1;
-
- for (i = 0; instr[i].name; i++) {
- /*
- * Look for match in table given constraints,
- * currently just the name and the number of
- * operands.
- */
- if (!strcmp(instr[i].name, *a) && instr[i].n == n)
- break;
+ FILE *ifile;
+ int line;
+ struct instruction *cur_instr;
+ int instrcount;
+ char buf[1024];
+
+ instrcount = 0;
+ line = 1;
+ if ((ifile = fopen(ifilename, "r")) == NULL) {
+ perror(ifilename);
+ stop(NULL, EX_DATAERR);
}
- if (!instr[i].name)
- error("unknown opcode or wrong number of operands");
-
- I_op = eval_operand(a, instr[i].op);
- I_src = eval_sdi(a, instr[i].src);
- I_imm = eval_sdi(a, instr[i].imm);
- I_dest = eval_sdi(a, instr[i].dest);
- I_addr = eval_addr(a, instr[i].addr);
-
- if( LC >= MEMORY )
- error("Memory exhausted!\n");
-
- switch (instr[i].fmt) {
- case 1:
- case 2:
- M[LC][0] = (I_op << 1) | I_ret;
- M[LC][1] = I_dest;
- M[LC][2] = I_src;
- M[LC][3] = I_imm;
- break;
- case 3:
- if (I_ret)
- error("illegal use of \"ret\"");
- M[LC][0] = (I_op << 1) | ((I_addr >> 8) & 1);
- M[LC][1] = I_addr & 0xff;
- M[LC][2] = I_src;
- M[LC][3] = I_imm;
- break;
+ for(cur_instr = seq_program.stqh_first;
+ cur_instr != NULL;
+ cur_instr = cur_instr->links.stqe_next) {
+ while (line < cur_instr->srcline) {
+ fgets(buf, sizeof(buf), ifile);
+ fprintf(listfile, "\t\t%s", buf);
+ line++;
+ }
+ fprintf(listfile, "%03x %02x%02x%02x%02x", instrcount,
+ cur_instr->format.bytes[0],
+ cur_instr->format.bytes[1],
+ cur_instr->format.bytes[2],
+ cur_instr->format.bytes[3]);
+ fgets(buf, sizeof(buf), ifile);
+ fprintf(listfile, "%s", buf);
+ line++;
+ instrcount++;
}
-
- return (1); /* no two-byte instructions yet */
+ fclose(ifile);
}
-#undef SL
-#undef SR
-#undef RL
-#undef RR
-#undef LX
-#undef LA
-#undef LO
-#undef I
-#undef A
-
+/*
+ * Print out error information if appropriate, and clean up before
+ * terminating the program.
+ */
void
-assemble(FILE *ofile)
+stop(string, err_code)
+ const char *string;
+ int err_code;
{
- int n;
- char **a;
- sym_t *p;
-
- while ((a = getl(&n))) {
-
- while (a[0][strlen(*a)-1] == ':') {
- a[0][strlen(*a)-1] = '\0';
- p = lookup(*a);
- if (p)
- p->value = LC;
- else
- define(*a, LC);
- a += 1;
- n -= 1;
+ if (string != NULL) {
+ fprintf(stderr, "%s: ", appname);
+ if (yyfilename != NULL) {
+ fprintf(stderr, "Stopped at file %s, line %d - ",
+ yyfilename, yylineno);
}
+ fprintf(stderr, "%s\n", string);
+ }
- if (!n) /* line was all labels */
- continue;
-
- if (n == 3 && !strcmp("VERSION", *a))
- fprintf(ofile, "#define %s \"%s\"\n", a[1], a[2]);
- else {
- if (n == 3 && !strcmp("=", a[1]))
- define(*a, strtol(a[2], NULL, 0));
- else
- LC += crack(a, n);
+ if (ofile != NULL) {
+ fclose(ofile);
+ if (err_code != 0) {
+ fprintf(stderr, "%s: Removing %s due to error\n",
+ appname, ofilename);
+ unlink(ofilename);
}
}
- backpatch();
- output(ofile);
+ symtable_close();
- if (debug)
- output(stderr);
+ exit(err_code);
}
-int
-main(int argc, char **argv)
+struct instruction *
+seq_alloc()
{
- int c;
- int pid;
- int ifile;
- FILE *ofile;
- int fd[2];
-
- ofile = NULL;
- while ((c = getopt(argc, argv, "dho:vD:")) != EOF) {
- switch (c) {
- case 'd':
- debug = !0;
- break;
- case 'D':
- {
- char *p;
- if ((p = strchr(optarg, '=')) != NULL) {
- *p = '\0';
- define(optarg, strtol(p + 1, NULL, 0));
- }
- else
- define(optarg, 1);
- break;
- }
- case 'o':
-
- if ((ofile = fopen(optarg, "w")) == NULL) {
- perror(optarg);
- exit(EXIT_FAILURE);
- }
- break;
- case 'h':
- printf("usage: %s [-d] [-Dname] [-ooutput] input\n",
- *argv);
- exit(EXIT_SUCCESS);
- break;
- case 'v':
- printf("%s\n", id);
- exit(EXIT_SUCCESS);
- break;
- default:
- exit(EXIT_FAILURE);
- break;
- }
- }
-
- if (argc - optind != 1) {
- fprintf(stderr, "%s: must have one input file\n", *argv);
- exit(EXIT_FAILURE);
- }
- filename = argv[optind];
-
-
- if ((ifile = open(filename, O_RDONLY)) < 0) {
- perror(filename);
- exit(EXIT_FAILURE);
- }
-
- if (!ofile) {
- if ((ofile = fopen(ADOTOUT, "w")) == NULL) {
- perror(ADOTOUT);
- exit(EXIT_FAILURE);
- }
- }
-
- if (pipe(fd) < 0) {
- perror("pipe failed");
- exit(1);
- }
+ struct instruction *new_instr;
+
+ new_instr = (struct instruction *)malloc(sizeof(struct instruction));
+ if (new_instr == NULL)
+ stop("Unable to malloc instruction object", EX_SOFTWARE);
+ memset(new_instr, 0, sizeof(*new_instr));
+ STAILQ_INSERT_TAIL(&seq_program, new_instr, links);
+ new_instr->srcline = yylineno;
+ return new_instr;
+}
- if ((pid = fork()) < 0 ) {
- perror("fork failed");
- exit(1);
- }
- else if (pid > 0) { /* Parent */
- close(fd[1]); /* Close write end */
- if (fd[0] != STDIN_FILENO) {
- if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) {
- perror("dup2 error on stdin");
- exit(EXIT_FAILURE);
- }
- close(fd[0]);
- }
- assemble(ofile);
- exit(EXIT_SUCCESS);
- }
- else { /* Child */
- close(fd[0]); /* Close Read end */
- if (fd[1] != STDOUT_FILENO) {
- if (dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
- perror("dup2 error on stdout");
- exit(EXIT_FAILURE);
- }
- close(fd[1]);
- }
- if (ifile != STDIN_FILENO) {
- if (dup2(ifile, STDIN_FILENO) != STDIN_FILENO) {
- perror("dup2 error on stdin");
- exit(EXIT_FAILURE);
- }
- close(ifile);
- }
- execl("/usr/bin/cpp", "/usr/bin/cpp", "-P", "-", "-", NULL);
- }
- return(EXIT_SUCCESS);
+patch_t *
+patch_alloc()
+{
+ patch_t *new_patch;
+
+ new_patch = (patch_t *)malloc(sizeof(patch_t));
+ if (new_patch == NULL)
+ stop("Unable to malloc patch object", EX_SOFTWARE);
+ memset(new_patch, 0, sizeof(*new_patch));
+ STAILQ_INSERT_TAIL(&patch_list, new_patch, links);
+ return new_patch;
}
OpenPOWER on IntegriCloud