home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Guide / c-cplusplus-interactive-guide.iso / c_ref / csource4 / 276_01 / a684.c < prev    next >
C/C++ Source or Header  |  1989-10-03  |  13KB  |  496 lines

  1. /*
  2.     HEADER:        CUG276;
  3.     TITLE:        6804 Cross-Assembler (Portable);
  4.     FILENAME:    A684.C;
  5.     VERSION:    0.1;
  6.     DATE:        08/27/1988;
  7.  
  8.     DESCRIPTION:    "This program lets you use your computer to assemble
  9.             code for the Motorola 6804 family microprocessors.
  10.             The program is written in portable C rather than BDS
  11.             C.  All    assembler features are supported except
  12.             relocation linkage, and macros.";
  13.  
  14.     KEYWORDS:    Software Development, Assemblers, Cross-Assemblers,
  15.             Motorola, MC6804;
  16.  
  17.     SYSTEM:        CP/M-80, CP/M-86, HP-UX, MSDOS, PCDOS, QNIX;
  18.     COMPILERS:    Aztec C86, Aztec CII, CI-C86, Eco-C, Eco-C88, HP-UX,
  19.             Lattice C, Microsoft C,    QNIX C;
  20.  
  21.     WARNINGS:    "This program should compile on any full-featured C
  22.             compiler.  Subset compilers such as Toolworks C and
  23.             BDS C will present substantial difficulties."
  24.  
  25.     AUTHORS:    William C. Colley III;
  26. */
  27.  
  28. /*
  29.               6804 Cross-Assembler in Portable C
  30.  
  31.         Copyright (c) 1985, 1988 William C. Colley, III
  32.  
  33. Revision History:
  34.  
  35. Ver    Date        Description
  36.  
  37. 0.0    MAR 1988    Adapted from version 0.2 of the portable 6805 cross-
  38.             assembler which was adapted from version 3.2 of the
  39.             portable 6801 cross-assembler.  WCC3.
  40.  
  41. 0.1    AUG 1988    Fixed a bug in the command line parser that puts it
  42.             into a VERY long loop if the user types a command line
  43.             like "A684 FILE.ASM -L".  WCC3 per Alex Cameron.
  44.  
  45. This file contains the main program and line assembly routines for the
  46. assembler.  The main program parses the command line, feeds the source lines
  47. to the line assembly routine, and sends the results to the listing and object
  48. file output routines.  It also coordinates the activities of everything.  The
  49. line assembly routines uses the expression analyzer and the lexical analyzer
  50. to parse the source line and convert it into the object bytes that it
  51. represents.
  52. */
  53.  
  54. /*  Get global goodies:  */
  55.  
  56. #include "a684.h"
  57.  
  58. /*  Define global mailboxes for all modules:                */
  59.  
  60. char errcode, line[MAXLINE + 1], title[MAXLINE];
  61. int pass = 0;
  62. int eject, filesp, forwd, listhex;
  63. unsigned  address, bytes, errors, listleft, obj[MAXLINE], pagelen, pc;
  64. FILE *filestk[FILES], *source;
  65. TOKEN token;
  66.  
  67. /*  Mainline routine.  This routine parses the command line, sets up    */
  68. /*  the assembler at the beginning of each pass, feeds the source text    */
  69. /*  to the line assembler, feeds the result to the listing and hex file    */
  70. /*  drivers, and cleans everything up at the end of the run.        */
  71.  
  72. static int done, ifsp, off;
  73.  
  74. void main(argc,argv)
  75. int argc;
  76. char **argv;
  77. {
  78.     SCRATCH unsigned *o;
  79.     int newline();
  80.     void asm_line();
  81.     void lclose(), lopen(), lputs();
  82.     void hclose(), hopen(), hputc();
  83.     void error(), fatal_error(), warning();
  84.  
  85.     printf("6804 Cross-Assembler (Portable) Ver 0.1\n");
  86.     printf("Copyright (c) 1985, 1988 William C. Colley, III\n\n");
  87.  
  88.     while (--argc > 0) {
  89.     if (**++argv == '-') {
  90.         switch (toupper(*++*argv)) {
  91.         case 'L':   if (!*++*argv) {
  92.                 if (!--argc) { warning(NOLST);  break; }
  93.                 else ++argv;
  94.                 }
  95.                 lopen(*argv);
  96.                 break;
  97.  
  98.         case 'O':   if (!*++*argv) {
  99.                 if (!--argc) { warning(NOHEX);  break; }
  100.                 else ++argv;
  101.                 }
  102.                 hopen(*argv);
  103.                 break;
  104.  
  105.         default:    warning(BADOPT);
  106.         }
  107.     }
  108.     else if (filestk[0]) warning(TWOASM);
  109.     else if (!(filestk[0] = fopen(*argv,"r"))) fatal_error(ASMOPEN);
  110.     }
  111.     if (!filestk[0]) fatal_error(NOASM);
  112.  
  113.     while (++pass < 3) {
  114.     fseek(source = filestk[0],0L,0);  done = off = FALSE;
  115.     errors = filesp = ifsp = pagelen = pc = 0;  title[0] = '\0';
  116.     while (!done) {
  117.         errcode = ' ';
  118.         if (newline()) {
  119.         error('*');
  120.         strcpy(line,"\tEND\n");
  121.         done = eject = TRUE;  listhex = FALSE;
  122.         bytes = 0;
  123.         }
  124.         else asm_line();
  125.         pc = word(pc + bytes);
  126.         if (pass == 2) {
  127.         lputs();
  128.         for (o = obj; bytes--; hputc(*o++));
  129.         }
  130.     }
  131.     }
  132.  
  133.     fclose(filestk[0]);  lclose();  hclose();
  134.  
  135.     if (errors) printf("%d Error(s)\n",errors);
  136.     else printf("No Errors\n");
  137.  
  138.     exit(errors);
  139. }
  140.  
  141. /*  Line assembly routine.  This routine gets expressions and tokens    */
  142. /*  from the source file using the expression evaluator and lexical    */
  143. /*  analyzer, respectively.  It fills a buffer with the machine code    */
  144. /*  bytes and returns nothing.                        */
  145.  
  146. static char label[MAXLINE];
  147. static int ifstack[IFDEPTH] = { ON };
  148.  
  149. static OPCODE *opcod;
  150.  
  151. void asm_line()
  152. {
  153.     SCRATCH int i;
  154.     int isalph(), popc();
  155.     OPCODE *find_code(), *find_operator();
  156.     void do_label(), flush(), normal_op(), pseudo_op();
  157.     void error(), pops(), pushc(), trash();
  158.  
  159.     address = pc;  bytes = 0;  eject = forwd = listhex = FALSE;
  160.     for (i = 0; i < BIGINST; obj[i++] = NOP);
  161.  
  162.     label[0] = '\0';
  163.     if ((i = popc()) != ' ' && i != '\n') {
  164.     if (isalph(i)) {
  165.         pushc(i);  pops(label);
  166.         if (find_operator(label)) { label[0] = '\0';  error('L'); }
  167.     }
  168.     else {
  169.         error('L');
  170.         while ((i = popc()) != ' ' && i != '\n');
  171.     }
  172.     }
  173.  
  174.     trash(); opcod = NULL;
  175.     if ((i = popc()) != '\n') {
  176.     if (!isalph(i)) error('S');
  177.     else {
  178.         pushc(i);  pops(token.sval);
  179.         if (!(opcod = find_code(token.sval))) error('O');
  180.     }
  181.     if (!opcod) { listhex = TRUE;  bytes = BIGINST; }
  182.     }
  183.  
  184.     if (opcod && opcod -> attr & ISIF) { if (label[0]) error('L'); }
  185.     else if (off) { listhex = FALSE;  flush();  return; }
  186.  
  187.     if (!opcod) { do_label();  flush(); }
  188.     else {
  189.     listhex = TRUE;
  190.     if (opcod -> attr & PSEUDO) pseudo_op();
  191.     else normal_op();
  192.     while ((i = popc()) != '\n') if (i != ' ') error('T');
  193.     }
  194.     source = filestk[filesp];
  195.     return;
  196. }
  197.  
  198. static void flush()
  199. {
  200.     while (popc() != '\n');
  201. }
  202.  
  203. static void do_label()
  204. {
  205.     SCRATCH SYMBOL *l;
  206.     SYMBOL *find_symbol(), *new_symbol();
  207.     void error();
  208.  
  209.     if (label[0]) {
  210.     listhex = TRUE;
  211.     if (pass == 1) {
  212.         if (!((l = new_symbol(label)) -> attr)) {
  213.         l -> attr = FORWD + VAL;
  214.         l -> valu = pc;
  215.         }
  216.     }
  217.     else {
  218.         if (l = find_symbol(label)) {
  219.         l -> attr = VAL;
  220.         if (l -> valu != pc) error('M');
  221.         }
  222.         else error('P');
  223.     }
  224.     }
  225. }
  226.  
  227. #define    NONUM        0
  228. #define    NEEDBYTE    1
  229. #define    HAVENUM        2
  230.  
  231. static void normal_op()
  232. {
  233.     SCRATCH unsigned attrib, *op, o;
  234.     unsigned expr();
  235.     TOKEN *lex();
  236.     void do_label(), error(), unlex();
  237.  
  238.     do_label();  attrib = opcod -> attr;  op = obj;
  239.     *op++ = opcod -> valu;
  240.     switch (attrib & OPCODE2) {
  241.     case AREG:    *op++ = 0xff;  break;
  242.  
  243.     case XREG:    *op++ = 0x80;  break;
  244.  
  245.     case YREG:    *op++ = 0x81;
  246.  
  247.     case NULL:    break;
  248.     }
  249.     if (attrib & ZERO) *op++ = 0x00;
  250.     switch (attrib & TYPE) {
  251.     case ARITHOP:    switch (lex() -> attr & TYPE) {
  252.                 case IMM:    if (attrib & IMMEDOK) {
  253.                         obj[0] += 0x08;
  254.                         if ((o = expr()) <= 0xff ||
  255.                         o >= 0xff80) *op++ = low(o);
  256.                         else { error('V');  *op++ = 0; }
  257.                     }
  258.                     else { error('A');  *op++ = 0; }
  259.                     break;
  260.  
  261.                 case REG:    if (token.valu == 'Y') obj[0] += 0x10;
  262.                     break;
  263.  
  264.                 default:    unlex();  obj[0] += 0x18;
  265.                     if ((o = expr()) <= 0xff) {
  266.                         if (attrib & SHORTOK && !forwd &&
  267.                         o >= 0x80 && o <= 0x83) {
  268.                         switch (obj[0]) {
  269.                             case 0xf8:  obj[0] = 0xac;
  270.                                 break;
  271.  
  272.                             case 0xf9:    obj[0] = 0xbc;
  273.                                 break;
  274.  
  275.                             case 0xfe:  obj[0] = 0xa8;
  276.                                 break;
  277.  
  278.                             case 0xff:    obj[0] = 0xb8;
  279.                                 break;
  280.                         }
  281.                         obj[0] += o - 0x80;
  282.                         }
  283.                         else *op++ = o;
  284.                     }
  285.                     else { error('V');  *op++ = 0; }
  286.                     break;
  287.             }
  288.             break;
  289.  
  290.     case BITJMP:    if ((o = expr()) <= 7) obj[0] |= o;
  291.             else error('V');
  292.             if ((o = expr()) <= 0xff) *op++ = o;
  293.             else { error('V');  *op++ = 0; }
  294.             if ((o = expr() - (pc + 3)) <= 0x7f || o >= 0xff80)
  295.                 *op++ = low(o);
  296.             else { error('B');  *op++ = 0xfd; }
  297.             break;
  298.  
  299.     case BITOP:    if ((o = expr()) <= 7) obj[0] |= o;
  300.             else error('V');
  301.             if ((o = expr()) <= 0xff) *op++ = o;
  302.             else { error('V');  *op++ = 0; }
  303.             break;
  304.  
  305.     case LONGJMP:    if ((o = expr()) <= 0xfff) {
  306.                 obj[0] |= high(o);  *op++ = low(o);
  307.             }
  308.             else { error('V');  *op++ = 0; }
  309.             break;
  310.  
  311.     case FLAGJMP:    if ((o = expr() - (pc +