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