1 /* $NetBSD: gsp_eval.c,v 1.5 2025/11/24 08:04:28 nia 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. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 #ifndef lint 33 __RCSID("$NetBSD: gsp_eval.c,v 1.5 2025/11/24 08:04:28 nia Exp $"); 34 #endif 35 36 #include <stdlib.h> 37 #include "gsp_ass.h" 38 #include "gsp_gram.h" 39 40 int32_t eval_op(int, int32_t, int32_t); 41 int32_t eval_subtree(expr, unsigned *); 42 43 expr 44 fold(expr x) 45 { 46 int32_t l; 47 expr lp, rp; 48 49 switch( x->e_op ){ 50 case SYM: 51 case CONST: 52 case '.': 53 return x; 54 } 55 x->e_left = lp = fold(x->e_left); 56 if( x->e_right != NULL ) 57 x->e_right = rp = fold(x->e_right); 58 else 59 rp = NULL; 60 if( lp->e_op == CONST && (rp == NULL || rp->e_op == CONST) ){ 61 /* operator with constant subtree(s) */ 62 if( rp != NULL ){ 63 l = eval_op(x->e_op, lp->e_val, rp->e_val); 64 free(rp); 65 } else 66 l = eval_op(x->e_op, lp->e_val, 0); 67 free(lp); 68 x->e_op = CONST; 69 x->e_val = l; 70 } 71 return x; 72 } 73 74 int32_t 75 eval_op(int op, int32_t l, int32_t r) 76 { 77 switch( op ){ 78 case NEG: l = -l; break; 79 case '~': l = ~l; break; 80 case '+': l += r; break; 81 case '-': l -= r; break; 82 case '*': l *= r; break; 83 case '&': l &= r; break; 84 case '|': l |= r; break; 85 case '^': l ^= r; break; 86 case '/': 87 if( r == 0 ) 88 perr("Divide by zero"); 89 else 90 l /= r; 91 break; 92 case ':': 93 l = (l << 16) | (r & 0xFFFF); 94 break; 95 case LEFT_SHIFT: 96 l <<= r; 97 break; 98 case RIGHT_SHIFT: 99 l >>= r; 100 break; 101 } 102 return l; 103 } 104 105 int 106 eval_expr(expr e, int32_t *vp, unsigned *lp) 107 { 108 e = fold(e); 109 *vp = eval_subtree(e, lp); 110 return (*lp < NOT_YET); 111 } 112 113 int32_t 114 eval_subtree(expr e, unsigned *lp) 115 { 116 symbol s; 117 int32_t v1, v2; 118 unsigned l2; 119 120 switch( e->e_op ){ 121 case SYM: 122 s = e->e_sym; 123 *lp = s->lineno; 124 if( (s->flags & DEFINED) != 0 ) 125 return s->value; 126 perr("Undefined symbol %s", s->name); 127 return 0; 128 case CONST: 129 *lp = 0; 130 return e->e_val; 131 case '.': 132 *lp = lineno; 133 return pc; 134 default: 135 v1 = eval_subtree(e->e_left, lp); 136 if( e->e_right == NULL ) 137 return eval_op(e->e_op, v1, 0); 138 v2 = eval_subtree(e->e_right, &l2); 139 if( l2 > *lp ) 140 *lp = l2; 141 return eval_op(e->e_op, v1, v2); 142 } 143 } 144