home *** CD-ROM | disk | FTP | other *** search
- /*
- * Z80 - Assembler
- * Copyright (C) 1987-1992 by Udo Munk
- *
- * History:
- * 17-SEP-1987 Development under Digital Research CP/M 2.2
- * 28-JUN-1988 Switched to Unix System V.3
- */
-
- /*
- * Dieses Modul enthaelt alle Funktionen, die Output
- * ins List-, Object- und Fehlerfile erzeugen.
- */
-
- #include <stdio.h>
- #include "z80a.h"
- #include "z80aglb.h"
-
- static char *errmsg[] = { /* Fehlermeldungen fuer asmerr() */
- "illegal opcode", /* 0 */
- "illegal operand", /* 1 */
- "missing operand", /* 2 */
- "multiply defined symbol", /* 3 */
- "undefined symbol", /* 4 */
- "value out of range", /* 5 */
- "missing )", /* 6 */
- "missing string separator", /* 7 */
- "memory override", /* 8 */
- "missing IF", /* 9 */
- "IF nesting to deep", /* 10 */
- "missing ENDIF", /* 11 */
- "INCLUDE nesting to deep" /* 12 */
- };
-
- #define MAXHEX 32 /* maximale Anzahl Bytes/Hex-Record */
-
- static unsigned short hex_adr; /* aktuelle Adresse Hex-Record */
- static int hex_cnt; /* aktuelle Anzahl Bytes im Hex-Puffer */
-
- static unsigned char hex_buf[MAXHEX]; /* Code-Puffer fuer einen Hex-Record */
- static char hex_out[MAXHEX*2+11]; /* ASCII-Puffer fuer einen Hex-Record */
-
- /*
- * Fehlermeldungen auf den Fehlerkanal (Listfile oder stdout)
- * ausgeben und Fehlerzaehler erhoehen.
- */
- asmerr(i)
- register int i;
- {
- if (pass == 1) {
- fprintf(errfp, "Error in file: %s Line: %d\n", srcfn, c_line);
- fprintf(errfp, errmsg[i]);
- fprintf(errfp, "\n\n");
- } else
- errnum = i;
- errors++;
- }
-
- /*
- * Die Funktion beginnt eine neue Seite in der Listdatei
- */
- lst_header()
- {
- fprintf(lstfp, "\fZ80-Assembler\t\tRelease %s\t\t\t\tPage %d\n", REL, ++page);
- fprintf(lstfp, "Source file: %s\n", srcfn);
- fprintf(lstfp, "Title: %s\n", title);
- p_line = 3;
- }
-
- /*
- * Ueberschrift fuer die Quellzeilen erzeugen
- */
- lst_attl()
- {
- fprintf(lstfp, "\nLOC OBJECT CODE LINE STMT SOURCE CODE\n");
- p_line += 2;
- }
-
- /*
- * Eine Zeile in der Listdatei erzeugen,
- * wenn Option -l gegeben.
- */
- lst_line(val, opanz)
- register int val, opanz;
- {
- register int i;
-
- if (!list_flag || sd_flag == 4) {
- sd_flag = 0;
- return;
- }
- if ((p_line >= ppl) || (c_line == 1)) {
- lst_header();
- lst_attl();
- }
- switch (sd_flag) {
- case 0:
- fprintf(lstfp, "%04x ", val & 0xffff);
- break;
- case 1:
- fprintf(lstfp, "%04x ", sd_val & 0xffff);
- break;
- case 2:
- fprintf(lstfp, " ");
- break;
- case 3:
- fprintf(lstfp, "%04x ", sd_val & 0xffff);
- goto no_data;
- default:
- fatal(F_INTERN, "illegal listflag for function lst_line");
- break;
- }
- if (opanz >= 1) fprintf(lstfp, "%02x ", ops[0] & 0xff);
- else fprintf(lstfp, " ");
- if (opanz >= 2) fprintf(lstfp, "%02x ", ops[1] & 0xff);
- else fprintf(lstfp, " ");
- if (opanz >= 3) fprintf(lstfp, "%02x ", ops[2] & 0xff);
- else fprintf(lstfp, " ");
- if (opanz >= 4) fprintf(lstfp, "%02x ", ops[3] & 0xff);
- else fprintf(lstfp, " ");
- no_data:
- fprintf(lstfp, "%6d %6d %s", c_line, s_line, line);
- if (errnum) {
- fprintf(errfp, "=> %s", errmsg[errnum]);
- putc('\n', errfp);
- errnum = 0;
- p_line++;
- }
- sd_flag = 0;
- p_line++;
- if (opanz > 4 && sd_flag == 0) {
- opanz -= 4;
- i = 4;
- sd_val = val;
- while (opanz > 0) {
- if (p_line >= ppl) {
- lst_header();
- lst_attl();
- }
- s_line++;
- sd_val += 4;
- fprintf(lstfp, "%04x ", sd_val & 0xffff);
- if (opanz-- > 0) fprintf(lstfp, "%02x ", ops[i++] & 0xff);
- else fprintf(lstfp, " ");
- if (opanz-- > 0) fprintf(lstfp, "%02x ", ops[i++] & 0xff);
- else fprintf(lstfp, " ");
- if (opanz-- > 0) fprintf(lstfp, "%02x ", ops[i++] & 0xff);
- else fprintf(lstfp, " ");
- if (opanz-- > 0) fprintf(lstfp, "%02x ", ops[i++] & 0xff);
- else fprintf(lstfp, " ");
- fprintf(lstfp, "%6d %6d\n", c_line, s_line);
- p_line++;
- }
- }
- }
-
- /*
- * Symboltabelle ins Listfile in der gespeicherten
- * Reihenfolge direkt aus der Hash-Tabelle ausgeben
- */
- lst_sym()
- {
- register int i, j;
- register struct sym *np;
- char *strcpy();
-
- p_line = j = 0;
- strcpy(title,"Symboltable");
- for (i = 0; i < HASHSIZE; i++) {
- if (symtab[i] != NULL) {
- for (np = symtab[i]; np != NULL; np = np->sym_next) {
- if (p_line == 0) {
- lst_header();
- fputs("\n", lstfp);
- p_line += 1;
- }
- fprintf(lstfp, "%-8s %04x\t", np->sym_name,
- np->sym_wert & 0xffff);
- if (++j == 4) {
- fprintf(lstfp, "\n");
- if (p_line++ >= ppl)
- p_line = 0;
- j = 0;
- }
- }
- }
- }
- }
-
- /*
- * Sortierte Symboltabelle ins Listfile ausgeben
- */
- lst_sort_sym(len)
- register int len;
- {
- register int i, j;
- char *strcpy();
-
- p_line = i = j = 0;
- strcpy(title, "Symboltable");
- while (i < len) {
- if (p_line == 0) {
- lst_header();
- fputs("\n", lstfp);
- p_line += 1;
- }
- fprintf(lstfp, "%-8s %04x\t", symarray[i]->sym_name,
- symarray[i]->sym_wert & 0xffff);
- if (++j == 4) {
- fprintf(lstfp, "\n");
- if (p_line++ >= ppl)
- p_line = 0;
- j = 0;
- }
- i++;
- }
- }
-
- /*
- * Header-Record ins Objectfile ausgeben
- */
- obj_header()
- {
- switch (out_form) {
- case OUTBIN:
- break;
- case OUTMOS:
- putc(0xff, objfp);
- putc(prg_adr & 0xff, objfp);
- putc(prg_adr >> 8, objfp);
- break;
- case OUTHEX:
- hex_adr = prg_adr;
- break;
- }
- }
-
- /*
- * Ende-Record ins Objectfile ausgeben
- */
- obj_end()
- {
- switch (out_form) {
- case OUTBIN:
- break;
- case OUTMOS:
- break;
- case OUTHEX:
- flush_hex();
- fprintf(objfp, ":0000000000\n");
- break;
- }
- }
-
- /*
- * Op-Codes in ops[] ins Objectfile ausgeben
- */
- obj_writeb(opanz)
- register int opanz;
- {
- register int i;
-
- switch (out_form) {
- case OUTBIN:
- fwrite(ops, 1, opanz, objfp);
- break;
- case OUTMOS:
- fwrite(ops, 1, opanz, objfp);
- break;
- case OUTHEX:
- for (i = 0; opanz; opanz--) {
- if (hex_cnt >= MAXHEX)
- flush_hex();
- hex_buf[hex_cnt++] = ops[i++];
- }
- break;
- }
- }
-
- /*
- * <count> Bytes mit 0xff ins Objectfile ausgeben
- */
- obj_fill(count)
- register int count;
- {
- switch (out_form) {
- case OUTBIN:
- while (count--)
- putc(0xff, objfp);
- break;
- case OUTMOS:
- while (count--)
- putc(0xff, objfp);
- break;
- case OUTHEX:
- flush_hex();
- hex_adr += count;
- break;
- }
- }
-
- /*
- * Einen Hex-Record in ASCII erzeugen und ausgeben
- */
- flush_hex()
- {
- char *p;
- register int i;
-
- if (!hex_cnt)
- return;
- p = hex_out;
- *p++ = ':';
- btoh((unsigned char) hex_cnt, &p);
- btoh((unsigned char) (hex_adr >> 8), &p);
- btoh((unsigned char) (hex_adr & 0xff), &p);
- *p++ = '0';
- *p++ = '0';
- for (i = 0; i < hex_cnt; i++)
- btoh(hex_buf[i], &p);
- btoh((unsigned char) chksum(), &p);
- *p++ = '\n';
- *p = '\0';
- fwrite(hex_out, 1, strlen(hex_out), objfp);
- hex_adr += hex_cnt;
- hex_cnt = 0;
- }
-
- /*
- * Ein unsigned char in ASCII-Hex umwandeln und an Adresse,
- * auf die p zeigt, ablegen. Der Pointer p wird dann um
- * zwei erhoeht.
- */
- btoh(byte, p)
- unsigned char byte;
- register char **p;
- {
- register unsigned char c;
-
- c = byte >> 4;
- *(*p)++ = (c < 10) ? (c + '0') : (c - 10 + 'A');
- c = byte & 0xf;
- *(*p)++ = (c < 10) ? (c + '0') : (c - 10 + 'A');
- }
-
- /*
- * Pruefsumme fuer einen Intel-Hex-Record berechnen
- */
- chksum()
- {
- register int i, j, sum;
-
- sum = hex_cnt;
- sum += hex_adr >> 8;
- sum += hex_adr & 0xff;
- for (i = 0; i < hex_cnt; i++) {
- j = hex_buf[i];
- sum += j & 0xff;
- }
- return (0x100 - (sum & 0xff));
- }
-