Home | History | Annotate | Line # | Download | only in gspa
      1 /*	$NetBSD: gsp_eval.c,v 1.4 2001/06/13 10:46:06 wiz Exp $	*/
      2 /*
      3  * GSP assembler - expression evaluation
      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_eval.c,v 1.4 2001/06/13 10:46:06 wiz Exp $");
     37 #endif
     38 
     39 #include <stdlib.h>
     40 #include "gsp_ass.h"
     41 #include "gsp_gram.h"
     42 
     43 int32_t eval_op(int, int32_t, int32_t);
     44 int32_t eval_subtree(expr, unsigned *);
     45 
     46 expr
     47 fold(expr x)
     48 {
     49 	int32_t l;
     50 	expr lp, rp;
     51 
     52 	switch( x->e_op ){
     53 	case SYM:
     54 	case CONST:
     55 	case '.':
     56 		return x;
     57 	}
     58 	x->e_left = lp = fold(x->e_left);
     59 	if( x->e_right != NULL )
     60 		x->e_right = rp = fold(x->e_right);
     61 	else
     62 		rp = NULL;
     63 	if( lp->e_op == CONST && (rp == NULL || rp->e_op == CONST) ){
     64 		/* operator with constant subtree(s) */
     65 		if( rp != NULL ){
     66 			l = eval_op(x->e_op, lp->e_val, rp->e_val);
     67 			free(rp);
     68 		} else
     69 			l = eval_op(x->e_op, lp->e_val, 0);
     70 		free(lp);
     71 		x->e_op = CONST;
     72 		x->e_val = l;
     73 	}
     74 	return x;
     75 }
     76 
     77 int32_t
     78 eval_op(int op, int32_t l, int32_t r)
     79 {
     80 	switch( op ){
     81 	case NEG:	l = -l;		break;
     82 	case '~':	l = ~l;		break;
     83 	case '+':	l += r;		break;
     84 	case '-':	l -= r;		break;
     85 	case '*':	l *= r;		break;
     86 	case '&':	l &= r;		break;
     87 	case '|':	l |= r;		break;
     88 	case '^':	l ^= r;		break;
     89 	case '/':
     90 		if( r == 0 )
     91 			perr("Divide by zero");
     92 		else
     93 			l /= r;
     94 		break;
     95 	case ':':
     96 		l = (l << 16) | (r & 0xFFFF);
     97 		break;
     98 	case LEFT_SHIFT:
     99 		l <<= r;
    100 		break;
    101 	case RIGHT_SHIFT:
    102 		l >>= r;
    103 		break;
    104 	}
    105 	return l;
    106 }
    107 
    108 int
    109 eval_expr(expr e, int32_t *vp, unsigned *lp)
    110 {
    111 	e = fold(e);
    112 	*vp = eval_subtree(e, lp);
    113 	return (*lp < NOT_YET);
    114 }
    115 
    116 int32_t
    117 eval_subtree(expr e, unsigned *lp)
    118 {
    119 	symbol s;
    120 	int32_t v1, v2;
    121 	unsigned l2;
    122 
    123 	switch( e->e_op ){
    124 	case SYM:
    125 		s = e->e_sym;
    126 		*lp = s->lineno;
    127 		if( (s->flags & DEFINED) != 0 )
    128 			return s->value;
    129 		perr("Undefined symbol %s", s->name);
    130 		return 0;
    131 	case CONST:
    132 		*lp = 0;
    133 		return e->e_val;
    134 	case '.':
    135 		*lp = lineno;
    136 		return pc;
    137 	default:
    138 		v1 = eval_subtree(e->e_left, lp);
    139 		if( e->e_right == NULL )
    140 			return eval_op(e->e_op, v1, 0);
    141 		v2 = eval_subtree(e->e_right, &l2);
    142 		if( l2 > *lp )
    143 			*lp = l2;
    144 		return eval_op(e->e_op, v1, v2);
    145 	}
    146 }
    147