root/drivers/scsi/aic7770.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. error
  2. Malloc
  3. Realloc
  4. Strdup
  5. define
  6. lookup
  7. patch
  8. backpatch
  9. output
  10. getl
  11. eval_operand
  12. eval_sdi
  13. eval_addr
  14. crack
  15. assemble
  16. main

   1 /*
   2  * Adaptec 274x device driver for Linux.
   3  * Copyright (c) 1994 The University of Calgary Department of Computer Science.
   4  * 
   5  * This program is free software; you can redistribute it and/or modify
   6  * it under the terms of the GNU General Public License as published by
   7  * the Free Software Foundation; either version 2 of the License, or
   8  * (at your option) any later version.
   9  * 
  10  * This program is distributed in the hope that it will be useful,
  11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13  * GNU General Public License for more details.
  14  * 
  15  * You should have received a copy of the GNU General Public License
  16  * along with this program; if not, write to the Free Software
  17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18  *
  19  *  Comments are started by `#' and continue to the end of the line; lines
  20  *  may be of the form:
  21  *
  22  *      <label>*
  23  *      <label>*  <undef-sym> = <value>
  24  *      <label>*  <opcode> <operand>*
  25  *
  26  *  A <label> is an <undef-sym> ending in a colon.  Spaces, tabs, and commas
  27  *  are token separators.
  28  */
  29 
  30 #define _POSIX_SOURCE   1
  31 #define _POSIX_C_SOURCE 2
  32 
  33 #include <ctype.h>
  34 #include <stdio.h>
  35 #include <string.h>
  36 #include <stdlib.h>
  37 #include <unistd.h>
  38 
  39 #define MEMORY          512             /* 2^9 29-bit words */
  40 #define MAXLINE         1024
  41 #define MAXTOKEN        32
  42 #define ADOTOUT         "a.out"
  43 #define NOVALUE         -1
  44 
  45 /*
  46  *  AIC-7770 register definitions
  47  */
  48 #define R_SINDEX        0x65
  49 #define R_ALLONES       0x69
  50 #define R_ALLZEROS      0x6a
  51 #define R_NONE          0x6a
  52 
  53 static
  54 char sccsid[] =
  55     "@(#)aic7770.c 1.10 94/07/22 jda";
  56 
  57 int debug;
  58 int lineno, LC;
  59 char *filename;
  60 FILE *ifp, *ofp;
  61 unsigned char M[MEMORY][4];
  62 
  63 void error(char *s)
     /* [<][>][^][v][top][bottom][index][help] */
  64 {
  65         fprintf(stderr, "%s: %s at line %d\n", filename, s, lineno);
  66         exit(EXIT_FAILURE);
  67 }
  68 
  69 void *Malloc(size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
  70 {
  71         void *p = malloc(size);
  72         if (!p)
  73                 error("out of memory");
  74         return(p);
  75 }
  76 
  77 void *Realloc(void *ptr, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
  78 {
  79         void *p = realloc(ptr, size);
  80         if (!p)
  81                 error("out of memory");
  82         return(p);
  83 }
  84 
  85 char *Strdup(char *s)
     /* [<][>][^][v][top][bottom][index][help] */
  86 {
  87         char *p = (char *)Malloc(strlen(s) + 1);
  88         strcpy(p, s);
  89         return(p);
  90 }
  91 
  92 typedef struct sym_t {
  93         struct sym_t *next;             /* MUST BE FIRST */
  94         char *name;
  95         int value;
  96         int npatch, *patch;
  97 } sym_t;
  98 
  99 sym_t *head;
 100 
 101 void define(char *name, int value)
     /* [<][>][^][v][top][bottom][index][help] */
 102 {
 103         sym_t *p, *q;
 104 
 105         for (p = head, q = (sym_t *)&head; p; p = p->next) {
 106                 if (!strcmp(p->name, name))
 107                         error("redefined symbol");
 108                 q = p;
 109         }
 110 
 111         p = q->next = (sym_t *)Malloc(sizeof(sym_t));
 112         p->next = NULL;
 113         p->name = Strdup(name);
 114         p->value = value;
 115         p->npatch = 0;
 116         p->patch = NULL;
 117 
 118         if (debug) {
 119                 fprintf(stderr, "\"%s\" ", p->name);
 120                 if (p->value != NOVALUE)
 121                         fprintf(stderr, "defined as 0x%x\n", p->value);
 122                 else
 123                         fprintf(stderr, "undefined\n");
 124         }
 125 }
 126 
 127 sym_t *lookup(char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 128 {
 129         sym_t *p;
 130 
 131         for (p = head; p; p = p->next)
 132                 if (!strcmp(p->name, name))
 133                         return(p);
 134         return(NULL);
 135 }
 136 
 137 void patch(sym_t *p, int location)
     /* [<][>][^][v][top][bottom][index][help] */
 138 {
 139         p->npatch += 1;
 140         p->patch = (int *)Realloc(p->patch, p->npatch * sizeof(int *));
 141 
 142         p->patch[p->npatch - 1] = location;
 143 }
 144 
 145 void backpatch(void)
     /* [<][>][^][v][top][bottom][index][help] */
 146 {
 147         int i;
 148         sym_t *p;
 149 
 150         for (p = head; p; p = p->next) {
 151 
 152                 if (p->value == NOVALUE) {
 153                         fprintf(stderr,
 154                                 "%s: undefined symbol \"%s\"\n",
 155                                 filename, p->name);
 156                         exit(EXIT_FAILURE);
 157                 }
 158 
 159                 if (p->npatch) {
 160                         if (debug)
 161                                 fprintf(stderr,
 162                                         "\"%s\" (0x%x) patched at",
 163                                         p->name, p->value);
 164 
 165                         for (i = 0; i < p->npatch; i++) {
 166                                 M[p->patch[i]][0] &= ~1;
 167                                 M[p->patch[i]][0] |= ((p->value >> 8) & 1);
 168                                 M[p->patch[i]][1] = p->value & 0xff;
 169 
 170                                 if (debug)
 171                                         fprintf(stderr, " 0x%x", p->patch[i]);
 172                         }
 173 
 174                         if (debug)
 175                                 fputc('\n', stderr);
 176                 }
 177         }
 178 }
 179 
 180 /*
 181  *  Output words in byte-reversed order (least significant first)
 182  *  since the sequencer RAM is loaded that way.
 183  */
 184 void output(FILE *fp)
     /* [<][>][^][v][top][bottom][index][help] */
 185 {
 186         int i;
 187 
 188         for (i = 0; i < LC; i++)
 189                 fprintf(fp, "\t0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
 190                         M[i][3],
 191                         M[i][2],
 192                         M[i][1],
 193                         M[i][0]);
 194 }
 195 
 196 char **getl(int *n)
     /* [<][>][^][v][top][bottom][index][help] */
 197 {
 198         int i;
 199         char *p;
 200         static char buf[MAXLINE];
 201         static char *a[MAXTOKEN];
 202 
 203         i = 0;
 204 
 205         while (fgets(buf, sizeof(buf), ifp)) {
 206 
 207                 lineno += 1;
 208 
 209                 if (buf[strlen(buf)-1] != '\n')
 210                         error("line too long");
 211 
 212                 p = strchr(buf, '#');
 213                 if (p)
 214                         *p = '\0';
 215 
 216                 for (p = strtok(buf, ", \t\n"); p; p = strtok(NULL, ", \t\n"))
 217                         if (i < MAXTOKEN-1)
 218                                 a[i++] = p;
 219                         else
 220                                 error("too many tokens");
 221                 if (i) {
 222                         *n = i;
 223                         return(a);
 224                 }
 225         }
 226         return(NULL);
 227 }
 228 
 229 #define A       0x8000          /* `A'ccumulator ok */
 230 #define I       0x4000          /* use as immediate value */
 231 #define SL      0x2000          /* shift left */
 232 #define SR      0x1000          /* shift right */
 233 #define RL      0x0800          /* rotate left */
 234 #define RR      0x0400          /* rotate right */
 235 #define LO      0x8000          /* lookup: ori-{jmp,jc,jnc,call} */
 236 #define LA      0x4000          /* lookup: and-{jz,jnz} */
 237 #define LX      0x2000          /* lookup: xor-{je,jne} */
 238 #define NA      -1              /* not applicable */
 239 
 240 struct {
 241         char *name;
 242         int n;                  /* number of operands, including opcode */
 243         unsigned int op;        /* immediate or L?|pos_from_0 */
 244         unsigned int dest;      /* NA, pos_from_0, or I|immediate */
 245         unsigned int src;       /* NA, pos_from_0, or I|immediate */
 246         unsigned int imm;       /* pos_from_0, A|pos_from_0, or I|immediate */
 247         unsigned int addr;      /* NA or pos_from_0 */
 248         int fmt;                /* instruction format - 1, 2, or 3 */
 249 } instr[] = {
 250 /*
 251  *              N  OP    DEST           SRC             IMM     ADDR FMT
 252  */
 253         "mov",  3, 1,    1,             2,              I|0xff, NA,  1,
 254         "mov",  4, LO|2, NA,            1,              I|0,    3,   3,
 255         "mvi",  3, 0,    1,             I|R_ALLZEROS,   A|2,    NA,  1,
 256         "mvi",  4, LO|2, NA,            I|R_ALLZEROS,   1,      3,   3,
 257         "not",  2, 2,    1,             1,              I|0xff, NA,  1,
 258         "not",  3, 2,    1,             2,              I|0xff, NA,  1,
 259         "and",  3, 1,    1,             1,              A|2,    NA,  1,
 260         "and",  4, 1,    1,             3,              A|2,    NA,  1,
 261         "or",   3, 0,    1,             1,              A|2,    NA,  1,
 262         "or",   4, 0,    1,             3,              A|2,    NA,  1,
 263         "or",   5, LO|3, NA,            1,              2,      4,   3,
 264         "xor",  3, 2,    1,             1,              A|2,    NA,  1,
 265         "xor",  4, 2,    1,             3,              A|2,    NA,  1,
 266         "nop",  1, 1,    I|R_NONE,      I|R_ALLZEROS,   I|0xff, NA,  1,
 267         "inc",  2, 3,    1,             1,              I|1,    NA,  1,
 268         "inc",  3, 3,    1,             2,              I|1,    NA,  1,
 269         "dec",  2, 3,    1,             1,              I|0xff, NA,  1,
 270         "dec",  3, 3,    1,             2,              I|0xff, NA,  1,
 271         "jmp",  2, LO|0, NA,            I|R_SINDEX,     I|0,    1,   3,
 272         "jc",   2, LO|0, NA,            I|R_SINDEX,     I|0,    1,   3,
 273         "jnc",  2, LO|0, NA,            I|R_SINDEX,     I|0,    1,   3,
 274         "call", 2, LO|0, NA,            I|R_SINDEX,     I|0,    1,   3,
 275         "test", 5, LA|3, NA,            1,              A|2,    4,   3,
 276         "cmp",  5, LX|3, NA,            1,              A|2,    4,   3,
 277         "ret",  1, 1,    I|R_NONE,      I|R_ALLZEROS,   I|0xff, NA,  1,
 278         "clc",  1, 3,    I|R_NONE,      I|R_ALLZEROS,   I|1,    NA,  1,
 279         "clc",  4, 3,    2,             I|R_ALLZEROS,   A|3,    NA,  1,
 280         "stc",  1, 3,    I|R_NONE,      I|R_ALLONES,    I|1,    NA,  1,
 281         "stc",  2, 3,    1,             I|R_ALLONES,    I|1,    NA,  1,
 282         "add",  3, 3,    1,             1,              A|2,    NA,  1,
 283         "add",  4, 3,    1,             3,              A|2,    NA,  1,
 284         "adc",  3, 4,    1,             1,              A|2,    NA,  1,
 285         "adc",  4, 4,    1,             3,              A|2,    NA,  1,
 286         "shl",  3, 5,    1,             1,              SL|2,   NA,  2,
 287         "shl",  4, 5,    1,             2,              SL|3,   NA,  2,
 288         "shr",  3, 5,    1,             1,              SR|2,   NA,  2,
 289         "shr",  4, 5,    1,             2,              SR|3,   NA,  2,
 290         "rol",  3, 5,    1,             1,              RL|2,   NA,  2,
 291         "rol",  4, 5,    1,             2,              RL|3,   NA,  2,
 292         "ror",  3, 5,    1,             1,              RR|2,   NA,  2,
 293         "ror",  4, 5,    1,             2,              RR|3,   NA,  2,
 294         /*
 295          *  Extensions (note also that mvi allows A)
 296          */
 297         "clr",  2, 1,    1,             I|R_ALLZEROS,   I|0xff, NA,  1,
 298         0
 299 };
 300 
 301 int eval_operand(char **a, int spec)
     /* [<][>][^][v][top][bottom][index][help] */
 302 {
 303         int i;
 304         unsigned int want = spec & (LO|LA|LX);
 305 
 306         static struct {
 307                 unsigned int what;
 308                 char *name;
 309                 int value;
 310         } jmptab[] = {
 311                 LO,     "jmp",          8,
 312                 LO,     "jc",           9,
 313                 LO,     "jnc",          10,
 314                 LO,     "call",         11,
 315                 LA,     "jz",           15,
 316                 LA,     "jnz",          13,
 317                 LX,     "je",           14,
 318                 LX,     "jne",          12,
 319         };
 320 
 321         spec &= ~(LO|LA|LX);
 322 
 323         for (i = 0; i < sizeof(jmptab)/sizeof(jmptab[0]); i++)
 324                 if (jmptab[i].what == want &&
 325                     !strcmp(jmptab[i].name, a[spec]))
 326                 {
 327                         return(jmptab[i].value);
 328                 }
 329 
 330         if (want)
 331                 error("invalid jump");
 332 
 333         return(spec);           /* "case 0" - no flags set */
 334 }
 335 
 336 int eval_sdi(char **a, int spec)
     /* [<][>][^][v][top][bottom][index][help] */
 337 {
 338         sym_t *p;
 339         unsigned val;
 340 
 341         if (spec == NA)
 342                 return(NA);
 343 
 344         switch (spec & (A|I|SL|SR|RL|RR)) {
 345             case SL:
 346             case SR:
 347             case RL:
 348             case RR:
 349                 if (isdigit(*a[spec &~ (SL|SR|RL|RR)]))
 350                         val = strtol(a[spec &~ (SL|SR|RL|RR)], NULL, 0);
 351                 else {
 352                         p = lookup(a[spec &~ (SL|SR|RL|RR)]);
 353                         if (!p)
 354                                 error("undefined symbol used");
 355                         val = p->value;
 356                 }
 357 
 358                 switch (spec & (SL|SR|RL|RR)) {         /* blech */
 359                     case SL:
 360                         if (val > 7)
 361                                 return(0xf0);
 362                         return(((val % 8) << 4) |
 363                                (val % 8));
 364                     case SR:
 365                         if (val > 7)
 366                                 return(0xf0);
 367                         return(((val % 8) << 4) |
 368                                (1 << 3) |
 369                                ((8 - (val % 8)) % 8));
 370                     case RL:
 371                         return(val % 8);
 372                     case RR:
 373                         return((8 - (val % 8)) % 8);
 374                 }
 375             case I:
 376                 return(spec &~ I);
 377             case A:
 378                 /*
 379                  *  An immediate field of zero selects
 380                  *  the accumulator.  Vigorously object
 381                  *  if zero is given otherwise - it's
 382                  *  most likely an error.
 383                  */
 384                 spec &= ~A;
 385                 if (!strcmp("A", a[spec]))
 386                         return(0);
 387                 if (isdigit(*a[spec]) &&
 388                     strtol(a[spec], NULL, 0) == 0)
 389                 {
 390                         error("immediate value of zero selects accumulator");
 391                 }
 392                 /* falls through */
 393             case 0:
 394                 if (isdigit(*a[spec]))
 395                         return(strtol(a[spec], NULL, 0));
 396                 p = lookup(a[spec]);
 397                 if (p)
 398                         return(p->value);
 399                 error("undefined symbol used");
 400         }
 401 
 402         return(NA);             /* shut the compiler up */
 403 }
 404 
 405 int eval_addr(char **a, int spec)
     /* [<][>][^][v][top][bottom][index][help] */
 406 {
 407         sym_t *p;
 408 
 409         if (spec == NA)
 410                 return(NA);
 411         if (isdigit(*a[spec]))
 412                 return(strtol(a[spec], NULL, 0));
 413 
 414         p = lookup(a[spec]);
 415 
 416         if (p) {
 417                 if (p->value != NOVALUE)
 418                         return(p->value);
 419                 patch(p, LC);
 420         } else {
 421                 define(a[spec], NOVALUE);
 422                 p = lookup(a[spec]);
 423                 patch(p, LC);
 424         }
 425 
 426         return(NA);             /* will be patched in later */
 427 }
 428 
 429 int crack(char **a, int n)
     /* [<][>][^][v][top][bottom][index][help] */
 430 {
 431         int i;
 432         int I_imm, I_addr;
 433         int I_op, I_dest, I_src, I_ret;
 434 
 435         /*
 436          *  Check for "ret" at the end of the line; remove
 437          *  it unless it's "ret" alone - we still want to
 438          *  look it up in the table.
 439          */
 440         I_ret = (strcmp(a[n-1], "ret") ? 0 : !0);
 441         if (I_ret && n > 1)
 442                 n -= 1;
 443 
 444         for (i = 0; instr[i].name; i++) {
 445                 /*
 446                  *  Look for match in table given constraints,
 447                  *  currently just the name and the number of
 448                  *  operands.
 449                  */
 450                 if (!strcmp(instr[i].name, *a) && instr[i].n == n)
 451                         break;
 452         }
 453         if (!instr[i].name)
 454                 error("unknown opcode or wrong number of operands");
 455 
 456         I_op    = eval_operand(a, instr[i].op);
 457         I_src   = eval_sdi(a, instr[i].src);
 458         I_imm   = eval_sdi(a, instr[i].imm);
 459         I_dest  = eval_sdi(a, instr[i].dest);
 460         I_addr  = eval_addr(a, instr[i].addr);
 461 
 462         switch (instr[i].fmt) {
 463             case 1:
 464             case 2:
 465                 M[LC][0] = (I_op << 1) | I_ret;
 466                 M[LC][1] = I_dest;
 467                 M[LC][2] = I_src;
 468                 M[LC][3] = I_imm;
 469                 break;
 470             case 3:
 471                 if (I_ret)
 472                         error("illegal use of \"ret\"");
 473                 M[LC][0] = (I_op << 1) | ((I_addr >> 8) & 1);
 474                 M[LC][1] = I_addr & 0xff;
 475                 M[LC][2] = I_src;
 476                 M[LC][3] = I_imm;
 477                 break;
 478         }
 479 
 480         return(1);              /* no two-byte instructions yet */
 481 }
 482 
 483 #undef SL
 484 #undef SR
 485 #undef RL
 486 #undef RR
 487 #undef LX
 488 #undef LA
 489 #undef LO
 490 #undef I
 491 #undef A
 492 
 493 void assemble(void)
     /* [<][>][^][v][top][bottom][index][help] */
 494 {
 495         int n;
 496         char **a;
 497         sym_t *p;
 498 
 499         while ((a = getl(&n))) {
 500 
 501                 while (a[0][strlen(*a)-1] == ':') {
 502                         a[0][strlen(*a)-1] = '\0';
 503                         p = lookup(*a);
 504                         if (p)
 505                                 p->value = LC;
 506                         else
 507                                 define(*a, LC);
 508                         a += 1;
 509                         n -= 1;
 510                 }
 511 
 512                 if (!n)                 /* line was all labels */
 513                         continue;
 514 
 515                 if (n == 3 && !strcmp("VERSION", *a))
 516                         fprintf(ofp, "#define %s \"%s\"\n", a[1], a[2]);
 517                 else {
 518                         if (n == 3 && !strcmp("=", a[1]))
 519                                 define(*a, strtol(a[2], NULL, 0));
 520                         else
 521                                 LC += crack(a, n);
 522                 }
 523         }
 524 
 525         backpatch();
 526         output(ofp);
 527 
 528         if (debug)
 529                 output(stderr);
 530 }
 531 
 532 int main(int argc, char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 533 {
 534         int c;
 535 
 536         while ((c = getopt(argc, argv, "dho:")) != EOF) {
 537                 switch (c) {
 538                     case 'd':
 539                         debug = !0;
 540                         break;
 541                     case 'o':
 542                         ofp = fopen(optarg, "w");
 543                         if (!ofp) {
 544                                 perror(optarg);
 545                                 exit(EXIT_FAILURE);
 546                         }
 547                         break;
 548                     case 'h':
 549                         printf("usage: %s [-d] [-ooutput] input\n", *argv);
 550                         exit(EXIT_SUCCESS);
 551                     case NULL:
 552                         /*
 553                          *  An impossible option to shut the compiler
 554                          *  up about sccsid[].
 555                          */
 556                         exit((int)sccsid);
 557                     default:
 558                         exit(EXIT_FAILURE);
 559                 }
 560         }
 561 
 562         if (argc - optind != 1) {
 563                 fprintf(stderr, "%s: must have one input file\n", *argv);
 564                 exit(EXIT_FAILURE);
 565         }
 566         filename = argv[optind];
 567 
 568         ifp = fopen(filename, "r");
 569         if (!ifp) {
 570                 perror(filename);
 571                 exit(EXIT_FAILURE);
 572         }
 573 
 574         if (!ofp) {
 575                 ofp = fopen(ADOTOUT, "w");
 576                 if (!ofp) {
 577                         perror(ADOTOUT);
 578                         exit(EXIT_FAILURE);
 579                 }
 580         }
 581 
 582         assemble();
 583         exit(EXIT_SUCCESS);
 584 }

/* [<][>][^][v][top][bottom][index][help] */