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