xref: /netbsd-src/usr.sbin/gspa/gspa/gsp_eval.c (revision c03a48d64f1f277966fc883875c4d5f1170aa562)
1*c03a48d6Swiz /*	$NetBSD: gsp_eval.c,v 1.4 2001/06/13 10:46:06 wiz Exp $	*/
24a04381dSchopps /*
34a04381dSchopps  * GSP assembler - expression evaluation
44a04381dSchopps  *
54a04381dSchopps  * Copyright (c) 1993 Paul Mackerras.
64a04381dSchopps  * All rights reserved.
74a04381dSchopps  *
84a04381dSchopps  * Redistribution and use in source and binary forms, with or without
94a04381dSchopps  * modification, are permitted provided that the following conditions
104a04381dSchopps  * are met:
114a04381dSchopps  * 1. Redistributions of source code must retain the above copyright
124a04381dSchopps  *    notice, this list of conditions and the following disclaimer.
134a04381dSchopps  * 2. Redistributions in binary form must reproduce the above copyright
144a04381dSchopps  *    notice, this list of conditions and the following disclaimer in the
154a04381dSchopps  *    documentation and/or other materials provided with the distribution.
164a04381dSchopps  * 3. All advertising materials mentioning features or use of this software
174a04381dSchopps  *    must display the following acknowledgement:
184a04381dSchopps  *      This product includes software developed by Paul Mackerras.
194a04381dSchopps  * 4. The name of the author may not be used to endorse or promote products
20*c03a48d6Swiz  *    derived from this software without specific prior written permission
214a04381dSchopps  *
224a04381dSchopps  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
234a04381dSchopps  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
244a04381dSchopps  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
254a04381dSchopps  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
264a04381dSchopps  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
274a04381dSchopps  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
284a04381dSchopps  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
294a04381dSchopps  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
304a04381dSchopps  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
314a04381dSchopps  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
324a04381dSchopps  */
3303b56f7fSlukem 
3403b56f7fSlukem #include <sys/cdefs.h>
3503b56f7fSlukem #ifndef lint
36*c03a48d6Swiz __RCSID("$NetBSD: gsp_eval.c,v 1.4 2001/06/13 10:46:06 wiz Exp $");
3703b56f7fSlukem #endif
3803b56f7fSlukem 
3903b56f7fSlukem #include <stdlib.h>
404a04381dSchopps #include "gsp_ass.h"
4148206355Stv #include "gsp_gram.h"
424a04381dSchopps 
434a04381dSchopps int32_t eval_op(int, int32_t, int32_t);
444a04381dSchopps int32_t eval_subtree(expr, unsigned *);
454a04381dSchopps 
464a04381dSchopps expr
fold(expr x)4703b56f7fSlukem fold(expr x)
484a04381dSchopps {
4903b56f7fSlukem 	int32_t l;
5003b56f7fSlukem 	expr lp, rp;
514a04381dSchopps 
524a04381dSchopps 	switch( x->e_op ){
534a04381dSchopps 	case SYM:
544a04381dSchopps 	case CONST:
554a04381dSchopps 	case '.':
564a04381dSchopps 		return x;
574a04381dSchopps 	}
584a04381dSchopps 	x->e_left = lp = fold(x->e_left);
594a04381dSchopps 	if( x->e_right != NULL )
604a04381dSchopps 		x->e_right = rp = fold(x->e_right);
614a04381dSchopps 	else
624a04381dSchopps 		rp = NULL;
634a04381dSchopps 	if( lp->e_op == CONST && (rp == NULL || rp->e_op == CONST) ){
644a04381dSchopps 		/* operator with constant subtree(s) */
654a04381dSchopps 		if( rp != NULL ){
664a04381dSchopps 			l = eval_op(x->e_op, lp->e_val, rp->e_val);
674a04381dSchopps 			free(rp);
684a04381dSchopps 		} else
694a04381dSchopps 			l = eval_op(x->e_op, lp->e_val, 0);
704a04381dSchopps 		free(lp);
714a04381dSchopps 		x->e_op = CONST;
724a04381dSchopps 		x->e_val = l;
734a04381dSchopps 	}
744a04381dSchopps 	return x;
754a04381dSchopps }
764a04381dSchopps 
774a04381dSchopps int32_t
eval_op(int op,int32_t l,int32_t r)7803b56f7fSlukem eval_op(int op, int32_t l, int32_t r)
794a04381dSchopps {
804a04381dSchopps 	switch( op ){
814a04381dSchopps 	case NEG:	l = -l;		break;
824a04381dSchopps 	case '~':	l = ~l;		break;
834a04381dSchopps 	case '+':	l += r;		break;
844a04381dSchopps 	case '-':	l -= r;		break;
854a04381dSchopps 	case '*':	l *= r;		break;
864a04381dSchopps 	case '&':	l &= r;		break;
874a04381dSchopps 	case '|':	l |= r;		break;
884a04381dSchopps 	case '^':	l ^= r;		break;
894a04381dSchopps 	case '/':
904a04381dSchopps 		if( r == 0 )
914a04381dSchopps 			perr("Divide by zero");
924a04381dSchopps 		else
934a04381dSchopps 			l /= r;
944a04381dSchopps 		break;
954a04381dSchopps 	case ':':
964a04381dSchopps 		l = (l << 16) | (r & 0xFFFF);
974a04381dSchopps 		break;
984a04381dSchopps 	case LEFT_SHIFT:
994a04381dSchopps 		l <<= r;
1004a04381dSchopps 		break;
1014a04381dSchopps 	case RIGHT_SHIFT:
1024a04381dSchopps 		l >>= r;
1034a04381dSchopps 		break;
1044a04381dSchopps 	}
1054a04381dSchopps 	return l;
1064a04381dSchopps }
1074a04381dSchopps 
1084a04381dSchopps int
eval_expr(expr e,int32_t * vp,unsigned * lp)1094a04381dSchopps eval_expr(expr e, int32_t *vp, unsigned *lp)
1104a04381dSchopps {
1114a04381dSchopps 	e = fold(e);
1124a04381dSchopps 	*vp = eval_subtree(e, lp);
1134a04381dSchopps 	return (*lp < NOT_YET);
1144a04381dSchopps }
1154a04381dSchopps 
1164a04381dSchopps int32_t
eval_subtree(expr e,unsigned * lp)1174a04381dSchopps eval_subtree(expr e, unsigned *lp)
1184a04381dSchopps {
11903b56f7fSlukem 	symbol s;
1204a04381dSchopps 	int32_t v1, v2;
1214a04381dSchopps 	unsigned l2;
1224a04381dSchopps 
1234a04381dSchopps 	switch( e->e_op ){
1244a04381dSchopps 	case SYM:
1254a04381dSchopps 		s = e->e_sym;
1264a04381dSchopps 		*lp = s->lineno;
1274a04381dSchopps 		if( (s->flags & DEFINED) != 0 )
1284a04381dSchopps 			return s->value;
1294a04381dSchopps 		perr("Undefined symbol %s", s->name);
1304a04381dSchopps 		return 0;
1314a04381dSchopps 	case CONST:
1324a04381dSchopps 		*lp = 0;
1334a04381dSchopps 		return e->e_val;
1344a04381dSchopps 	case '.':
1354a04381dSchopps 		*lp = lineno;
1364a04381dSchopps 		return pc;
1374a04381dSchopps 	default:
1384a04381dSchopps 		v1 = eval_subtree(e->e_left, lp);
1394a04381dSchopps 		if( e->e_right == NULL )
1404a04381dSchopps 			return eval_op(e->e_op, v1, 0);
1414a04381dSchopps 		v2 = eval_subtree(e->e_right, &l2);
1424a04381dSchopps 		if( l2 > *lp )
1434a04381dSchopps 			*lp = l2;
1444a04381dSchopps 		return eval_op(e->e_op, v1, v2);
1454a04381dSchopps 	}
1464a04381dSchopps }
147