/* * 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 #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); }