273 lines
6.1 KiB
C
273 lines
6.1 KiB
C
/*
|
|
* 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 Operationen, die die
|
|
* Tabellen durchsuchen oder veraendern.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include "z80a.h"
|
|
#include "z80aglb.h"
|
|
|
|
/* Die folgende Funktion fuehrt die binaere Suche
|
|
* in der alphabetisch sortierten OP-Code-Tabelle
|
|
* 'opctab' aus.
|
|
*
|
|
* Input: Zeiger auf String mit dem OP-Code
|
|
*
|
|
* Output: Zeiger auf das Tabellenelement oder
|
|
* einen NULL-Pointer, wenn OP-Code
|
|
* nicht gefunden
|
|
*/
|
|
struct opc *search_op(op_name)
|
|
register char *op_name;
|
|
{
|
|
register int cond;
|
|
register struct opc *low, *high, *mid;
|
|
|
|
low = &opctab[0];
|
|
high = &opctab[no_opcodes - 1];
|
|
while (low <= high) {
|
|
mid = low + (high - low) / 2;
|
|
if ((cond = strcmp(op_name, mid->op_name)) < 0)
|
|
high = mid - 1;
|
|
else if (cond > 0)
|
|
low = mid + 1;
|
|
else
|
|
return(mid);
|
|
}
|
|
return(NULL);
|
|
}
|
|
|
|
/* Die folgende Funktion fuehrt die binaere Suche
|
|
* in der alphabetisch sortierten Operanden-Tabelle
|
|
* 'opetab' aus.
|
|
*
|
|
* Input: Zeiger auf String mit dem Operanden
|
|
*
|
|
* Output: Symbol fuer den Operanden
|
|
* NOOPERA, wenn Operand leer ist
|
|
* NOREG, wenn Operand nicht gefunden
|
|
*/
|
|
get_reg(s)
|
|
register char *s;
|
|
{
|
|
register int cond;
|
|
register struct ope *low, *high, *mid;
|
|
|
|
if (s == NULL || *s == '\0')
|
|
return(NOOPERA);
|
|
low = &opetab[0];
|
|
high = &opetab[no_operands - 1];
|
|
while (low <= high) {
|
|
mid = low + (high - low) / 2;
|
|
if ((cond = strcmp(s, mid->ope_name)) < 0)
|
|
high = mid - 1;
|
|
else if (cond > 0)
|
|
low = mid + 1;
|
|
else
|
|
return(mid->ope_sym);
|
|
}
|
|
return(NOREG);
|
|
}
|
|
|
|
/* Die folgende Funktion fuehrt die Suche in der Symboltabelle
|
|
* 'symtab' durch. Dazu wird ein HASH-Algorithmus verwendet.
|
|
*
|
|
* Input: Zeiger auf String mit dem Symbol
|
|
*
|
|
* Output: Zeiger auf das Tabellenelement oder
|
|
* einen NULL-Pointer, wenn Symbol
|
|
* nicht gefunden
|
|
*/
|
|
struct sym *get_sym(sym_name)
|
|
register char *sym_name;
|
|
{
|
|
register struct sym *np;
|
|
|
|
for (np = symtab[hash(sym_name)]; np != NULL; np = np->sym_next)
|
|
if (strcmp(sym_name, np->sym_name) == 0)
|
|
return(np);
|
|
return(NULL);
|
|
}
|
|
|
|
/* Die folgende Funktion traegt ein Symbol in die Symboltabelle
|
|
* 'symtab' ein. Ist das Symbol in der Tabelle noch nicht
|
|
* vorhanden, wird es neu angelegt, sonst wird 'sym_wert'
|
|
* in den vorhandenen Eintrag uebernommen.
|
|
* Fuer die Symboltabellen-Zugriffe wird ein HASH-Algorithmus
|
|
* verwendet.
|
|
*
|
|
* Input: sym_name Zeiger auf String mit dem Symbol
|
|
* sym_wert Wert des Symbols
|
|
*
|
|
* Output: 0 = eingetragen
|
|
* 1 = kein Speicherplatz mehr frei
|
|
*/
|
|
put_sym(sym_name, sym_wert)
|
|
char *sym_name;
|
|
int sym_wert;
|
|
{
|
|
char *strsave(), *malloc();
|
|
struct sym *get_sym();
|
|
register int hashval;
|
|
register struct sym *np;
|
|
|
|
if (!gencode)
|
|
return(0);
|
|
if ((np = get_sym(sym_name)) == NULL) {
|
|
np = (struct sym *) malloc(sizeof (struct sym));
|
|
if (np == NULL)
|
|
return(1);
|
|
if ((np->sym_name = strsave(sym_name)) == NULL)
|
|
return(1);
|
|
hashval = hash(sym_name);
|
|
np->sym_next = symtab[hashval];
|
|
symtab[hashval] = np;
|
|
}
|
|
np->sym_wert = sym_wert;
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* Diese Funktion traegt ein Label in die Symboltabelle ein.
|
|
* Vorher wird geprueft, ob dieses Symbol bereits vorhanden
|
|
* ist, was zu einer entsprechenden Fehlermeldung fuehrt.
|
|
*/
|
|
put_label()
|
|
{
|
|
struct sym *get_sym();
|
|
|
|
if (get_sym(label) == NULL) {
|
|
if (put_sym(label, pc))
|
|
fatal(F_OUTMEM, "symbols");
|
|
} else
|
|
asmerr(E_MULSYM);
|
|
}
|
|
|
|
/* Hier folget der HASH-Algorithmus selbst.
|
|
*
|
|
* Input: Zeiger auf String mit dem Namen
|
|
*
|
|
* Output: HASH-Wert
|
|
*/
|
|
hash(name)
|
|
register char *name;
|
|
{
|
|
register int hashval;
|
|
|
|
for (hashval = 0; *name;)
|
|
hashval += *name++;
|
|
return(hashval % HASHSIZE);
|
|
}
|
|
|
|
/* Diese Funktion kopiert einen String auf einen
|
|
* angeforderten Speicherplatz.
|
|
*
|
|
* Input: Zeiger auf den String
|
|
*
|
|
* Output: Zeiger auf den Speicherplatz
|
|
*/
|
|
char *strsave(s)
|
|
register char *s;
|
|
{
|
|
char *malloc(), *strcpy();
|
|
register char *p;
|
|
|
|
if ((p = malloc((unsigned) strlen(s)+1)) != NULL)
|
|
strcpy(p, s);
|
|
return(p);
|
|
}
|
|
|
|
/*
|
|
* Diese Funktion kopiert alle Eintraege aus der
|
|
* Symbol-Hashtabelle in ein dynamisch erzeugtes
|
|
* Pointer-Array
|
|
*/
|
|
copy_sym()
|
|
{
|
|
char *malloc(), *realloc();
|
|
register int i, j;
|
|
register struct sym *np;
|
|
|
|
symarray = (struct sym **) malloc(SYMINC * sizeof(struct sym *));
|
|
if (symarray == NULL)
|
|
fatal(F_OUTMEM, "sorting symbol table");
|
|
symsize = SYMINC;
|
|
for (i = 0, j = 0; i < HASHSIZE; i++) {
|
|
if (symtab[i] != NULL) {
|
|
for (np = symtab[i]; np != NULL; np = np->sym_next) {
|
|
symarray[j++] = np;
|
|
if (j == symsize) {
|
|
symarray = (struct sym **) realloc((char *) symarray, symsize * sizeof(struct sym *) + SYMINC * sizeof(struct sym *));
|
|
if (symarray == NULL)
|
|
fatal(F_OUTMEM, "sorting symbol table");
|
|
symsize += SYMINC;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return(j);
|
|
}
|
|
|
|
/*
|
|
* Symboltabelle nach Namen sortieren
|
|
*/
|
|
n_sort_sym(len)
|
|
register int len;
|
|
{
|
|
register int gap, i, j;
|
|
register struct sym *temp;
|
|
|
|
for (gap = len/2; gap > 0; gap /= 2)
|
|
for (i = gap; i < len; i++)
|
|
for (j = i-gap; j >= 0; j -= gap) {
|
|
if (strcmp(symarray[j]->sym_name, symarray[j+gap]->sym_name) <= 0)
|
|
break;
|
|
temp = symarray[j];
|
|
symarray[j] = symarray[j+gap];
|
|
symarray[j+gap] = temp;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Symboltabelle nach Adressen sortieren
|
|
*/
|
|
a_sort_sym(len)
|
|
register int len;
|
|
{
|
|
register int gap, i, j;
|
|
register struct sym *temp;
|
|
|
|
for (gap = len/2; gap > 0; gap /= 2)
|
|
for (i = gap; i < len; i++)
|
|
for (j = i-gap; j >= 0; j -= gap) {
|
|
if (numcmp(symarray[j]->sym_wert, symarray[j+gap]->sym_wert) <= 0)
|
|
break;
|
|
temp = symarray[j];
|
|
symarray[j] = symarray[j+gap];
|
|
symarray[j+gap] = temp;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Vergleicht zwei 16-Bit Werte, Ergebnis wie strcmp
|
|
*/
|
|
numcmp(n1, n2)
|
|
register int n1, n2;
|
|
{
|
|
if ((unsigned) (n1 & 0xffff) < (unsigned) (n2 & 0xffff))
|
|
return(-1);
|
|
else if ((unsigned) (n1 & 0xffff) > (unsigned) (n2 & 0xffff))
|
|
return(1);
|
|
else
|
|
return(0);
|
|
}
|