Home | History | Annotate | Line # | Download | only in gspa
      1 /*	$NetBSD: gsp_sym.c,v 1.9 2009/04/15 08:26:35 lukem 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.9 2009/04/15 08:26:35 lukem 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 
     46 symbol symbol_hash[NHASH];
     47 
     48 void define_sym(char *, unsigned, unsigned, int);
     49 
     50 symbol
     51 lookup(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 
     80 void
     81 define_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 
    101 void
    102 set_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 
    111 void
    112 do_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 
    126 void
    127 set_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. */
    184 void
    185 reset_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