home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / emulator / unix / z80pack / z80asm / z80aout.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-09  |  7.3 KB  |  362 lines

  1. /*
  2.  *      Z80 - Assembler
  3.  *      Copyright (C) 1987-1992 by Udo Munk
  4.  *
  5.  *    History:
  6.  *    17-SEP-1987 Development under Digital Research CP/M 2.2
  7.  *      28-JUN-1988 Switched to Unix System V.3
  8.  */
  9.  
  10. /*
  11.  *      Dieses Modul enthaelt alle Funktionen, die Output
  12.  *      ins List-, Object- und Fehlerfile erzeugen.
  13.  */
  14.  
  15. #include <stdio.h>
  16. #include "z80a.h"
  17. #include "z80aglb.h"
  18.  
  19. static char *errmsg[] = {               /* Fehlermeldungen fuer asmerr() */
  20.     "illegal opcode",               /* 0 */
  21.     "illegal operand",              /* 1 */
  22.     "missing operand",              /* 2 */
  23.     "multiply defined symbol",      /* 3 */
  24.     "undefined symbol",             /* 4 */
  25.     "value out of range",           /* 5 */
  26.     "missing )",                    /* 6 */
  27.     "missing string separator",     /* 7 */
  28.     "memory override",              /* 8 */
  29.     "missing IF",                   /* 9 */
  30.     "IF nesting to deep",           /* 10 */
  31.     "missing ENDIF",                /* 11 */
  32.     "INCLUDE nesting to deep"       /* 12 */
  33. };
  34.  
  35. #define MAXHEX  32                      /* maximale Anzahl Bytes/Hex-Record */
  36.  
  37. static unsigned short hex_adr;          /* aktuelle Adresse Hex-Record */
  38. static int hex_cnt;                     /* aktuelle Anzahl Bytes im Hex-Puffer */
  39.  
  40. static unsigned char hex_buf[MAXHEX];   /* Code-Puffer fuer einen Hex-Record */
  41. static char hex_out[MAXHEX*2+11];       /* ASCII-Puffer fuer einen Hex-Record */
  42.  
  43. /*
  44.  *    Fehlermeldungen auf den Fehlerkanal (Listfile oder stdout)
  45.  *    ausgeben und Fehlerzaehler erhoehen.
  46.  */
  47. asmerr(i)
  48. register int i;
  49. {
  50.     if (pass == 1) {
  51.         fprintf(errfp, "Error in file: %s  Line: %d\n", srcfn, c_line);
  52.         fprintf(errfp, errmsg[i]);
  53.         fprintf(errfp, "\n\n");
  54.     } else
  55.         errnum = i;
  56.     errors++;
  57. }
  58.  
  59. /*
  60.  *      Die Funktion beginnt eine neue Seite in der Listdatei
  61.  */
  62. lst_header()
  63. {
  64.     fprintf(lstfp, "\fZ80-Assembler\t\tRelease %s\t\t\t\tPage %d\n", REL, ++page);
  65.     fprintf(lstfp, "Source file: %s\n", srcfn);
  66.     fprintf(lstfp, "Title:       %s\n", title);
  67.     p_line = 3;
  68. }
  69.  
  70. /*
  71.  *      Ueberschrift fuer die Quellzeilen erzeugen
  72.  */
  73. lst_attl()
  74. {
  75.     fprintf(lstfp, "\nLOC   OBJECT CODE   LINE   STMT SOURCE CODE\n");
  76.     p_line += 2;
  77. }
  78.  
  79. /*
  80.  *      Eine Zeile in der Listdatei erzeugen,
  81.  *      wenn Option -l gegeben.
  82.  */
  83. lst_line(val, opanz)
  84. register int val, opanz;
  85. {
  86.     register int i;
  87.  
  88.     if (!list_flag || sd_flag == 4) {
  89.         sd_flag = 0;
  90.         return;
  91.     }
  92.     if ((p_line >= ppl) || (c_line == 1)) {
  93.         lst_header();
  94.         lst_attl();
  95.     }
  96.     switch (sd_flag) {
  97.     case 0:
  98.         fprintf(lstfp, "%04x  ", val & 0xffff);
  99.         break;
  100.     case 1:
  101.         fprintf(lstfp, "%04x  ", sd_val & 0xffff);
  102.         break;
  103.     case 2:
  104.         fprintf(lstfp, "      ");
  105.         break;
  106.     case 3:
  107.         fprintf(lstfp, "%04x              ", sd_val & 0xffff);
  108.         goto no_data;
  109.     default:
  110.         fatal(F_INTERN, "illegal listflag for function lst_line");
  111.         break;
  112.     }
  113.     if (opanz >= 1) fprintf(lstfp, "%02x ", ops[0] & 0xff);
  114.         else fprintf(lstfp, "   ");
  115.     if (opanz >= 2) fprintf(lstfp, "%02x ", ops[1] & 0xff);
  116.         else fprintf(lstfp, "   ");
  117.     if (opanz >= 3) fprintf(lstfp, "%02x ", ops[2] & 0xff);
  118.         else fprintf(lstfp, "   ");
  119.     if (opanz >= 4) fprintf(lstfp, "%02x ", ops[3] & 0xff);
  120.         else fprintf(lstfp, "   ");
  121.     no_data:
  122.     fprintf(lstfp, "%6d %6d %s", c_line, s_line, line);
  123.     if (errnum) {
  124.         fprintf(errfp, "=> %s", errmsg[errnum]);
  125.         putc('\n', errfp);
  126.         errnum = 0;
  127.         p_line++;
  128.     }
  129.     sd_flag = 0;
  130.     p_line++;
  131.     if (opanz > 4 && sd_flag == 0) {
  132.         opanz -= 4;
  133.         i = 4;
  134.         sd_val = val;
  135.         while (opanz > 0) {
  136.             if (p_line >= ppl) {
  137.                 lst_header();
  138.                 lst_attl();
  139.             }
  140.             s_line++;
  141.             sd_val += 4;
  142.             fprintf(lstfp, "%04x  ", sd_val & 0xffff);
  143.             if (opanz-- > 0) fprintf(lstfp, "%02x ", ops[i++] & 0xff);
  144.                 else fprintf(lstfp, "   ");
  145.             if (opanz-- > 0) fprintf(lstfp, "%02x ", ops[i++] & 0xff);
  146.                 else fprintf(lstfp, "   ");
  147.             if (opanz-- > 0) fprintf(lstfp, "%02x ", ops[i++] & 0xff);
  148.                 else fprintf(lstfp, "   ");
  149.             if (opanz-- > 0) fprintf(lstfp, "%02x ", ops[i++] & 0xff);
  150.                 else fprintf(lstfp, "   ");
  151.             fprintf(lstfp, "%6d %6d\n", c_line, s_line);
  152.             p_line++;
  153.         }
  154.     }
  155. }
  156.  
  157. /*
  158.  *    Symboltabelle ins Listfile in der gespeicherten
  159.  *      Reihenfolge direkt aus der Hash-Tabelle ausgeben
  160.  */
  161. lst_sym()
  162. {
  163.     register int i, j;
  164.     register struct sym *np;
  165.     char *strcpy();
  166.  
  167.     p_line = j = 0;
  168.     strcpy(title,"Symboltable");
  169.     for (i = 0; i < HASHSIZE; i++) {
  170.         if (symtab[i] != NULL) {
  171.             for (np = symtab[i]; np != NULL; np = np->sym_next) {
  172.                 if (p_line == 0) {
  173.                     lst_header();
  174.                     fputs("\n", lstfp);
  175.                     p_line += 1;
  176.                 }
  177.                 fprintf(lstfp, "%-8s %04x\t", np->sym_name,
  178.                     np->sym_wert & 0xffff);
  179.                 if (++j == 4) {
  180.                     fprintf(lstfp, "\n");
  181.                     if (p_line++ >= ppl)
  182.                         p_line = 0;
  183.                     j = 0;
  184.                 }
  185.             }
  186.         }
  187.     }
  188. }
  189.  
  190. /*
  191.  *      Sortierte Symboltabelle ins Listfile ausgeben
  192.  */
  193. lst_sort_sym(len)
  194. register int len;
  195. {
  196.     register int i, j;
  197.     char *strcpy();
  198.  
  199.     p_line = i = j = 0;
  200.     strcpy(title, "Symboltable");
  201.     while (i < len) {
  202.         if (p_line == 0) {
  203.             lst_header();
  204.             fputs("\n", lstfp);
  205.             p_line += 1;
  206.         }
  207.         fprintf(lstfp, "%-8s %04x\t", symarray[i]->sym_name,
  208.             symarray[i]->sym_wert & 0xffff);
  209.         if (++j == 4) {
  210.             fprintf(lstfp, "\n");
  211.             if (p_line++ >= ppl)
  212.                 p_line = 0;
  213.             j = 0;
  214.         }
  215.     i++;
  216.     }
  217. }
  218.  
  219. /*
  220.  *      Header-Record ins Objectfile ausgeben
  221.  */
  222. obj_header()
  223. {
  224.     switch (out_form) {
  225.     case OUTBIN:
  226.         break;
  227.     case OUTMOS:
  228.         putc(0xff, objfp);
  229.         putc(prg_adr & 0xff, objfp);
  230.         putc(prg_adr >> 8, objfp);
  231.         break;
  232.     case OUTHEX:
  233.         hex_adr = prg_adr;
  234.         break;
  235.     }
  236. }
  237.  
  238. /*
  239.  *      Ende-Record ins Objectfile ausgeben
  240.  */
  241. obj_end()
  242. {
  243.     switch (out_form) {
  244.     case OUTBIN:
  245.         break;
  246.     case OUTMOS:
  247.         break;
  248.     case OUTHEX:
  249.         flush_hex();
  250.         fprintf(objfp, ":0000000000\n");
  251.         break;
  252.     }
  253. }
  254.  
  255. /*
  256.  *      Op-Codes in ops[] ins Objectfile ausgeben
  257.  */
  258. obj_writeb(opanz)
  259. register int opanz;
  260. {
  261.     register int i;
  262.  
  263.     switch (out_form) {
  264.     case OUTBIN:
  265.         fwrite(ops, 1, opanz, objfp);
  266.         break;
  267.     case OUTMOS:
  268.         fwrite(ops, 1, opanz, objfp);
  269.         break;
  270.     case OUTHEX:
  271.         for (i = 0; opanz; opanz--) {
  272.             if (hex_cnt >= MAXHEX)
  273.                 flush_hex();
  274.             hex_buf[hex_cnt++] = ops[i++];
  275.         }
  276.         break;
  277.     }
  278. }
  279.  
  280. /*
  281.  *      <count> Bytes mit 0xff ins Objectfile ausgeben
  282.  */
  283. obj_fill(count)
  284. register int count;
  285. {
  286.     switch (out_form) {
  287.     case OUTBIN:
  288.         while (count--)
  289.             putc(0xff, objfp);
  290.         break;
  291.     case OUTMOS:
  292.         while (count--)
  293.             putc(0xff, objfp);
  294.         break;
  295.     case OUTHEX:
  296.         flush_hex();
  297.         hex_adr += count;
  298.         break;
  299.     }
  300. }
  301.  
  302. /*
  303.  *      Einen Hex-Record in ASCII erzeugen und ausgeben
  304.  */
  305. flush_hex()
  306. {
  307.     char *p;
  308.     register int i;
  309.  
  310.     if (!hex_cnt)
  311.         return;
  312.     p = hex_out;
  313.     *p++ = ':';
  314.     btoh((unsigned char) hex_cnt, &p);
  315.     btoh((unsigned char) (hex_adr >> 8), &p);
  316.     btoh((unsigned char) (hex_adr & 0xff), &p);
  317.     *p++ = '0';
  318.     *p++ = '0';
  319.     for (i = 0; i < hex_cnt; i++)
  320.         btoh(hex_buf[i], &p);
  321.     btoh((unsigned char) chksum(), &p);
  322.     *p++ = '\n';
  323.     *p = '\0';
  324.     fwrite(hex_out, 1, strlen(hex_out), objfp);
  325.     hex_adr += hex_cnt;
  326.     hex_cnt = 0;
  327. }
  328.  
  329. /*
  330.  *      Ein unsigned char in ASCII-Hex umwandeln und an Adresse,
  331.  *      auf die p zeigt, ablegen. Der Pointer p wird dann um
  332.  *      zwei erhoeht.
  333.  */
  334. btoh(byte, p)
  335. unsigned char byte;
  336. register char **p;
  337. {
  338.     register unsigned char c;
  339.  
  340.     c = byte >> 4;
  341.     *(*p)++ = (c < 10) ? (c + '0') : (c - 10 + 'A');
  342.     c = byte & 0xf;
  343.     *(*p)++ = (c < 10) ? (c + '0') : (c - 10 + 'A');
  344. }
  345.  
  346. /*
  347.  *      Pruefsumme fuer einen Intel-Hex-Record berechnen
  348.  */
  349. chksum()
  350. {
  351.     register int i, j, sum;
  352.  
  353.     sum = hex_cnt;
  354.     sum += hex_adr >> 8;
  355.     sum += hex_adr & 0xff;
  356.     for (i = 0; i < hex_cnt; i++) {
  357.         j = hex_buf[i];
  358.         sum += j & 0xff;
  359.     }
  360.     return (0x100 - (sum & 0xff));
  361. }
  362.