1/* $NetBSD: gsp_sym.c,v 1.8 2006/08/26 18:15:37 christos Exp $ */ 2/* 3 * GSP assembler - symbol table 4 * 5 * Copyright (c) 1993 Paul Mackerras. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Paul Mackerras. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34#include <sys/cdefs.h> 35#ifndef lint 36__RCSID("$NetBSD: gsp_sym.c,v 1.8 2006/08/26 18:15:37 christos Exp $"); 37#endif 38 39#include <stdio.h> 40#include <string.h> 41#include <util.h> 42#include "gsp_ass.h" 43 44#define NHASH 64 /* must be power of 2 */ 45 46symbol symbol_hash[NHASH]; 47 48void define_sym(char *, unsigned, unsigned, int); 49 50symbol 51lookup(char *id, bool makeit) 52{ 53 symbol ptr, p, *pp; 54 int h; 55 char *ip; 56 57 h = 0; 58 for( ip = id; *ip != 0; ) 59 h = (h << 1) + *ip++; 60 h &= NHASH-1; 61 for( pp = &symbol_hash[h]; (p = *pp) != NULL; pp = &p->next ) 62 if( (h = strcmp(id, p->name)) == 0 ) 63 return p; 64 else if( h < 0 ) 65 break; 66 if( !makeit ) 67 return NULL; 68 ptr = emalloc(sizeof(struct symbol) + strlen(id)); 69 ptr->ndefn = 0; 70 ptr->flags = 0; 71 ptr->value = 0; 72 ptr->lineno = NOT_YET; 73 strcpy(ptr->name, id); 74 *pp = ptr; 75 ptr->next = p; 76 ptr->nlab = NULL; 77 return ptr; 78} 79 80void 81define_sym(char *id, unsigned val, unsigned lno, int flags) 82{ 83 symbol ptr; 84 85 ptr = lookup(id, TRUE); 86 if( (ptr->flags & SET_LABEL) == 0 ){ 87 if( ptr->ndefn >= 2 ){ 88 perr("Multiply defined label %s", id); 89 if( (flags & SET_LABEL) != 0 ) 90 return; 91 } else if( pass2 && ptr->value != val ) 92 perr("Phase error on label %s (%#x -> %#x)", 93 id, ptr->value, val); 94 } 95 ptr->flags = flags; 96 ptr->ndefn += 1; 97 ptr->value = val; 98 ptr->lineno = lno; 99} 100 101void 102set_label(char *id) 103{ 104 if( id != NULL ){ 105 define_sym(id, pc, lineno, DEFINED); 106 if( pass2 ) 107 do_list_pc(); 108 } 109} 110 111void 112do_asg(char *name, expr value, int flags) 113{ 114 int32_t val; 115 unsigned lno; 116 117 if( eval_expr(value, &val, &lno) ) 118 flags |= DEFINED; 119 if( lno < lineno ) 120 lno = lineno; 121 define_sym(name, val, lno, flags); 122 if( pass2 ) 123 do_show_val(val); 124} 125 126void 127set_numeric_label(int lnum) 128{ 129 symbol bp, fp; 130 struct numlab *nl; 131 char id[32]; 132 133 /* define the backward reference symbol */ 134 sprintf(id, "%dB", lnum); 135 bp = lookup(id, TRUE); 136 bp->flags = NUMERIC_LABEL | DEFINED; 137 bp->value = pc; 138 bp->lineno = lineno; 139 140 /* look up the forward reference symbol */ 141 id[strlen(id) - 1] = 'F'; 142 fp = lookup(id, TRUE); 143 144 if( !pass2 ){ 145 /* Record a new numeric label and link it into the 146 chain. fp->nlab points to the head of the chain, 147 bp->nlab points to the tail. */ 148 new(nl); 149 nl->value = pc; 150 nl->lineno = lineno; 151 nl->next = NULL; 152 if( bp->nlab == NULL ) 153 fp->nlab = nl; 154 else 155 bp->nlab->next = nl; 156 bp->nlab = nl; 157 fp->flags = NUMERIC_LABEL; 158 } else { 159 /* Advance to the next numeric label entry in the chain 160 and update the value of the forward reference symbol. */ 161 if( pc != fp->value ) 162 perr("Phase error on numeric label %d (%#x -> %#x)", 163 lnum, fp->value, pc); 164 nl = fp->nlab; 165 nl = nl->next; 166 if( nl == NULL ){ 167 /* no more labels of this number */ 168 /* forward references are now undefined */ 169 fp->flags &= ~DEFINED; 170 fp->lineno = NOT_YET; 171 fp->value = 0; 172 } else { 173 fp->lineno = nl->lineno; 174 fp->value = nl->value; 175 fp->nlab = nl; 176 } 177 do_list_pc(); 178 } 179} 180 181/* At the beginning of pass 2, reset all of the numeric labels. 182 Backward references become undefined, forward references are defined 183 by the first instance of the label. */ 184void 185reset_numeric_labels() 186{ 187 symbol p; 188 struct numlab *nl; 189 int h; 190 191 for( h = 0; h < NHASH; ++h ) { 192 for( p = symbol_hash[h]; p != NULL; p = p->next ) { 193 if( (p->flags & NUMERIC_LABEL) != 0 ) { 194 if( (p->flags & DEFINED) != 0 ) { 195 /* a backward reference */ 196 p->flags &= ~DEFINED; 197 } else { 198 /* a forward reference */ 199 p->flags |= DEFINED; 200 nl = p->nlab; 201 p->value = nl->value; 202 p->lineno = nl->lineno; 203 } 204 } 205 } 206 } 207} 208