/* * SYMBOLS.C * * (c)Copyright 1988, Matthew Dillon, All Rights Reserved. */ #include "asm.h" uword hash1 ARGS((ubyte *, short)); static SYMBOL org; static SYMBOL special; static SYMBOL specchk; void setspecial(value, flags) int value, flags; { special.value = value; special.flags = flags; } SYMBOL * findsymbol(str, len) ubyte *str; int len; { register uword h1; register SYMBOL *sym; ubyte buf[128]; static SYMBOL org; if (str[0] == '.') { if (len == 1) { if (Csegment->flags & SF_RORG) { org.flags = Csegment->rflags & SYM_UNKNOWN; org.value = Csegment->rorg; } else { org.flags = Csegment->flags & SYM_UNKNOWN; org.value = Csegment->org; } return(&org); } if (len == 2 && str[1] == '.') return(&special); if (len == 3 && str[1] == '.' && str[2] == '.') { specchk.flags = 0; specchk.value = CheckSum; return(&specchk); } { register INCFILE *inc; BMov(str+1, buf, --len); sprintf(buf + len, ".%ld", Localindex); len += strlen(buf+len); for (inc = Incfile->next; inc; inc = inc->next) { sprintf(buf+len,".%ld", inc->lineno); len += strlen(buf+len); } str = buf; } } h1 = hash1(str, (short)len); for (sym = SHash[h1]; sym; sym = sym->next) { if (sym->namelen == len && BCmp(sym->name, str, len) == 0) break; } return(sym); } SYMBOL * createsymbol(str, len) ubyte *str; int len; { register SYMBOL *sym; register uword h1; ubyte buf[128]; if (str[0] == '.') { register INCFILE *inc; BMov(str+1, buf, --len); sprintf(buf + len, ".%ld", Localindex); len += strlen(buf+len); for (inc = Incfile->next; inc; inc = inc->next) { sprintf(buf+len,".%ld", inc->lineno); len += strlen(buf+len); } str = buf; } sym = (SYMBOL *)allocsymbol(); sym->name = permalloc(len+1); BMov(str, sym->name, len); /* permalloc zero's the array for us */ sym->namelen = len; h1 = hash1(str, (short)len); sym->next = SHash[h1]; sym->flags= SYM_UNKNOWN; SHash[h1] = sym; return(sym); } static uword hash1(str, len) register ubyte *str; register short len; { register uword result = 0; while (len--) result = (result << 2) ^ *str++; return((uword)(result & SHASHAND)); } /* * Label Support Routines */ void programlabel() { register uword len; register SYMBOL *sym; register SEGMENT *cseg = Csegment; register ubyte *str; ubyte rorg = cseg->flags & SF_RORG; ubyte cflags = (rorg) ? cseg->rflags : cseg->flags; ulong pc = (rorg) ? cseg->rorg : cseg->org; Plab = cseg->org; Pflags = cseg->flags; str = Av[0]; if (*str == 0) return; len = strlen(str); if (str[len-1] == ':') --len; /* * Redo: unknown and referenced * referenced and origin not known * known and phase error (origin known) */ if (sym = findsymbol(str, len)) { if ((sym->flags & (SYM_UNKNOWN|SYM_REF)) == (SYM_UNKNOWN|SYM_REF)) { ++Redo; Redo_why |= 1 << 13; if (Xdebug) printf("redo 13: '%s' %04x %04x\n", sym->name, sym->flags, cflags); } else if ((cflags & SYM_UNKNOWN) && (sym->flags & SYM_REF)) { ++Redo; Redo_why |= 1 << 13; } else if (!(cflags & SYM_UNKNOWN) && !(sym->flags & SYM_UNKNOWN)) { if (pc != sym->value) { printf("mismatch %10s %s pc: %s\n", sym->name, sftos(sym->value, sym->flags), sftos(pc, cflags & 7)); asmerr(17,0); ++Redo; Redo_why |= 1 << 14; } } } else { sym = createsymbol(str, len); } sym->value = pc; sym->flags = (sym->flags & ~SYM_UNKNOWN) | (cflags & SYM_UNKNOWN); } SYMBOL *SymAlloc; SYMBOL * allocsymbol() { SYMBOL *sym; if (SymAlloc) { sym = SymAlloc; SymAlloc = SymAlloc->next; BZero(sym, sizeof(SYMBOL)); } else { sym = (SYMBOL *)permalloc(sizeof(SYMBOL)); } return(sym); } void freesymbol(sym) SYMBOL *sym; { sym->next = SymAlloc; SymAlloc = sym; } void freesymbollist(sym) SYMBOL *sym; { register SYMBOL *next; while (sym) { next = sym->next; sym->next = SymAlloc; if (sym->flags & SYM_STRING) free(sym->string); SymAlloc = sym; sym = next; } }