1179404Sobrien/* $NetBSD: gsp_eval.c,v 1.3 1998/04/09 00:32:40 tv Exp $ */ 2179404Sobrien/* 3208737Sjmallett * GSP assembler - expression evaluation 4179404Sobrien * 5179404Sobrien * Copyright (c) 1993 Paul Mackerras. 6179404Sobrien * All rights reserved. 7179404Sobrien * 8179404Sobrien * Redistribution and use in source and binary forms, with or without 9179404Sobrien * modification, are permitted provided that the following conditions 10179404Sobrien * are met: 11179404Sobrien * 1. Redistributions of source code must retain the above copyright 12179404Sobrien * notice, this list of conditions and the following disclaimer. 13179404Sobrien * 2. Redistributions in binary form must reproduce the above copyright 14179404Sobrien * notice, this list of conditions and the following disclaimer in the 15179404Sobrien * documentation and/or other materials provided with the distribution. 16179404Sobrien * 3. All advertising materials mentioning features or use of this software 17179404Sobrien * must display the following acknowledgement: 18179404Sobrien * This product includes software developed by Paul Mackerras. 19179404Sobrien * 4. The name of the author may not be used to endorse or promote products 20179404Sobrien * derived from this software without specific prior written permission 21179404Sobrien * 22179404Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23179404Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24208737Sjmallett * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25179404Sobrien * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26179404Sobrien * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27179404Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28179404Sobrien * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29179404Sobrien * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30179404Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31179404Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32179404Sobrien */ 33179404Sobrien 34179404Sobrien#include <sys/cdefs.h> 35179404Sobrien#ifndef lint 36179404Sobrien__RCSID("$NetBSD: gsp_eval.c,v 1.3 1998/04/09 00:32:40 tv Exp $"); 37179404Sobrien#endif 38179404Sobrien 39179404Sobrien#include <stdlib.h> 40179404Sobrien#include "gsp_ass.h" 41179404Sobrien#include "gsp_gram.h" 42179404Sobrien 43179404Sobrienint32_t eval_op(int, int32_t, int32_t); 44179404Sobrienint32_t eval_subtree(expr, unsigned *); 45179404Sobrien 46179404Sobrienexpr 47179404Sobrienfold(expr x) 48179404Sobrien{ 49179404Sobrien int32_t l; 50179404Sobrien expr lp, rp; 51179404Sobrien 52179404Sobrien switch( x->e_op ){ 53179404Sobrien case SYM: 54179404Sobrien case CONST: 55179404Sobrien case '.': 56179404Sobrien return x; 57179404Sobrien } 58179404Sobrien x->e_left = lp = fold(x->e_left); 59179404Sobrien if( x->e_right != NULL ) 60179404Sobrien x->e_right = rp = fold(x->e_right); 61179404Sobrien else 62179404Sobrien rp = NULL; 63179404Sobrien if( lp->e_op == CONST && (rp == NULL || rp->e_op == CONST) ){ 64179404Sobrien /* operator with constant subtree(s) */ 65179404Sobrien if( rp != NULL ){ 66179404Sobrien l = eval_op(x->e_op, lp->e_val, rp->e_val); 67179404Sobrien free(rp); 68179404Sobrien } else 69179404Sobrien l = eval_op(x->e_op, lp->e_val, 0); 70179404Sobrien free(lp); 71179404Sobrien x->e_op = CONST; 72179404Sobrien x->e_val = l; 73179404Sobrien } 74179404Sobrien return x; 75179404Sobrien} 76179404Sobrien 77179404Sobrienint32_t 78179404Sobrieneval_op(int op, int32_t l, int32_t r) 79208737Sjmallett{ 80208737Sjmallett switch( op ){ 81179404Sobrien case NEG: l = -l; break; 82179404Sobrien case '~': l = ~l; break; 83179404Sobrien case '+': l += r; break; 84179404Sobrien case '-': l -= r; break; 85179404Sobrien case '*': l *= r; break; 86179404Sobrien case '&': l &= r; break; 87179404Sobrien case '|': l |= r; break; 88179404Sobrien case '^': l ^= r; break; 89179404Sobrien case '/': 90179404Sobrien if( r == 0 ) 91179404Sobrien perr("Divide by zero"); 92208737Sjmallett else 93208737Sjmallett l /= r; 94208737Sjmallett break; 95218822Sdim case ':': 96179404Sobrien l = (l << 16) | (r & 0xFFFF); 97179404Sobrien break; 98179404Sobrien case LEFT_SHIFT: 99179404Sobrien l <<= r; 100179404Sobrien break; 101218822Sdim case RIGHT_SHIFT: 102218822Sdim l >>= r; 103218822Sdim break; 104179404Sobrien } 105179404Sobrien return l; 106179404Sobrien} 107179404Sobrien 108179404Sobrienint 109179404Sobrieneval_expr(expr e, int32_t *vp, unsigned *lp) 110179404Sobrien{ 111179404Sobrien e = fold(e); 112179404Sobrien *vp = eval_subtree(e, lp); 113179404Sobrien return (*lp < NOT_YET); 114179404Sobrien} 115179404Sobrien 116179404Sobrienint32_t 117179404Sobrieneval_subtree(expr e, unsigned *lp) 118179404Sobrien{ 119179404Sobrien symbol s; 120179404Sobrien int32_t v1, v2; 121179404Sobrien unsigned l2; 122179404Sobrien 123179404Sobrien switch( e->e_op ){ 124179404Sobrien case SYM: 125179404Sobrien s = e->e_sym; 126179404Sobrien *lp = s->lineno; 127179404Sobrien if( (s->flags & DEFINED) != 0 ) 128208737Sjmallett return s->value; 129208737Sjmallett perr("Undefined symbol %s", s->name); 130208737Sjmallett return 0; 131208737Sjmallett case CONST: 132208737Sjmallett *lp = 0; 133208737Sjmallett return e->e_val; 134218822Sdim case '.': 135208737Sjmallett *lp = lineno; 136208737Sjmallett return pc; 137208737Sjmallett default: 138218822Sdim v1 = eval_subtree(e->e_left, lp); 139208737Sjmallett if( e->e_right == NULL ) 140208737Sjmallett return eval_op(e->e_op, v1, 0); 141208737Sjmallett v2 = eval_subtree(e->e_right, &l2); 142208737Sjmallett if( l2 > *lp ) 143218822Sdim *lp = l2; 144208737Sjmallett return eval_op(e->e_op, v1, v2); 145208737Sjmallett } 146208737Sjmallett} 147218822Sdim