145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* 245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Expression handling 345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Copyright (C) 2001-2007 Michael Urman, Peter Johnson 545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Redistribution and use in source and binary forms, with or without 745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * modification, are permitted provided that the following conditions 845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * are met: 945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 1. Redistributions of source code must retain the above copyright 1045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * notice, this list of conditions and the following disclaimer. 1145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 2. Redistributions in binary form must reproduce the above copyright 1245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * notice, this list of conditions and the following disclaimer in the 1345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * documentation and/or other materials provided with the distribution. 1445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 1545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' 1645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE 1945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * POSSIBILITY OF SUCH DAMAGE. 2645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 2745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "util.h" 2845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 2945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "libyasm-stdint.h" 3045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "coretype.h" 3145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "bitvect.h" 3245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 3345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "errwarn.h" 3445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "intnum.h" 3545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "floatnum.h" 3645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "expr.h" 3745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "symrec.h" 3845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 3945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "bytecode.h" 4045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "section.h" 4145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 4245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "arch.h" 4345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 4445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 4545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic /*@only@*/ yasm_expr *expr_level_op 4645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (/*@returned@*/ /*@only@*/ yasm_expr *e, int fold_const, 4745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int simplify_ident, int simplify_reg_mul); 4845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int expr_traverse_nodes_post(/*@null@*/ yasm_expr *e, 4945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@null@*/ void *d, 5045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int (*func) (/*@null@*/ yasm_expr *e, 5145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@null@*/ void *d)); 5245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void expr_delete_term(yasm_expr__item *term, int recurse); 5345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 5445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Bitmap of used items. We should really never need more than 2 at a time, 5545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * so 31 is pretty much overkill. 5645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 5745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic unsigned long itempool_used = 0; 5845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic yasm_expr__item itempool[31]; 5945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 6045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* allocate a new expression node, with children as defined. 6145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * If it's a unary operator, put the element in left and set right=NULL. */ 6245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*@-compmempass@*/ 6345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr * 6445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr_create(yasm_expr_op op, yasm_expr__item *left, 6545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr__item *right, unsigned long line) 6645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 6745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr *ptr, *sube; 6845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned long z; 6945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ptr = yasm_xmalloc(sizeof(yasm_expr)); 7045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 7145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ptr->op = op; 7245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ptr->numterms = 0; 7345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ptr->terms[0].type = YASM_EXPR_NONE; 7445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ptr->terms[1].type = YASM_EXPR_NONE; 7545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (left) { 7645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ptr->terms[0] = *left; /* structure copy */ 7745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org z = (unsigned long)(left-itempool); 7845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (z>=31) 7945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_internal_error(N_("could not find expritem in pool")); 8045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org itempool_used &= ~(1<<z); 8145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ptr->numterms++; 8245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 8345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Search downward until we find something *other* than an 8445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * IDENT, then bring it up to the current level. 8545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 8645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org while (ptr->terms[0].type == YASM_EXPR_EXPR && 8745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ptr->terms[0].data.expn->op == YASM_EXPR_IDENT) { 8845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sube = ptr->terms[0].data.expn; 8945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ptr->terms[0] = sube->terms[0]; /* structure copy */ 9045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@-usereleased@*/ 9145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_xfree(sube); 9245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@=usereleased@*/ 9345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 9445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else { 9545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_internal_error(N_("Right side of expression must exist")); 9645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 9745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 9845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (right) { 9945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ptr->terms[1] = *right; /* structure copy */ 10045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org z = (unsigned long)(right-itempool); 10145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (z>=31) 10245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_internal_error(N_("could not find expritem in pool")); 10345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org itempool_used &= ~(1<<z); 10445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ptr->numterms++; 10545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 10645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Search downward until we find something *other* than an 10745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * IDENT, then bring it up to the current level. 10845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 10945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org while (ptr->terms[1].type == YASM_EXPR_EXPR && 11045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ptr->terms[1].data.expn->op == YASM_EXPR_IDENT) { 11145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sube = ptr->terms[1].data.expn; 11245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ptr->terms[1] = sube->terms[0]; /* structure copy */ 11345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@-usereleased@*/ 11445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_xfree(sube); 11545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@=usereleased@*/ 11645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 11745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 11845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 11945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ptr->line = line; 12045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 12145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return expr_level_op(ptr, 1, 1, 0); 12245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 12345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*@=compmempass@*/ 12445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 12545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* helpers */ 12645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic yasm_expr__item * 12745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_get_item(void) 12845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 12945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int z = 0; 13045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned long v = itempool_used & 0x7fffffff; 13145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 13245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org while (v & 1) { 13345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org v >>= 1; 13445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org z++; 13545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 13645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (z>=31) 13745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_internal_error(N_("too many expritems")); 13845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org itempool_used |= 1<<z; 13945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return &itempool[z]; 14045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 14145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 14245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr__item * 14345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr_precbc(yasm_bytecode *precbc) 14445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 14545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr__item *e = expr_get_item(); 14645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->type = YASM_EXPR_PRECBC; 14745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->data.precbc = precbc; 14845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return e; 14945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 15045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 15145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr__item * 15245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr_sym(yasm_symrec *s) 15345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 15445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr__item *e = expr_get_item(); 15545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->type = YASM_EXPR_SYM; 15645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->data.sym = s; 15745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return e; 15845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 15945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 16045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr__item * 16145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr_expr(yasm_expr *x) 16245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 16345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr__item *e = expr_get_item(); 16445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->type = YASM_EXPR_EXPR; 16545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->data.expn = x; 16645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return e; 16745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 16845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 16945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr__item * 17045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr_int(yasm_intnum *i) 17145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 17245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr__item *e = expr_get_item(); 17345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->type = YASM_EXPR_INT; 17445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->data.intn = i; 17545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return e; 17645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 17745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 17845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr__item * 17945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr_float(yasm_floatnum *f) 18045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 18145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr__item *e = expr_get_item(); 18245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->type = YASM_EXPR_FLOAT; 18345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->data.flt = f; 18445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return e; 18545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 18645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 18745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr__item * 18845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr_reg(uintptr_t reg) 18945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 19045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr__item *e = expr_get_item(); 19145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->type = YASM_EXPR_REG; 19245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->data.reg = reg; 19345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return e; 19445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 19545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 19645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Transforms instances of symrec-symrec [symrec+(-1*symrec)] into single 19745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * expritems if possible. Uses a simple n^2 algorithm because n is usually 19845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * quite small. Also works for precbc-precbc (or symrec-precbc, 19945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * precbc-symrec). 20045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 20145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic /*@only@*/ yasm_expr * 20245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_xform_bc_dist_base(/*@returned@*/ /*@only@*/ yasm_expr *e, 20345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@null@*/ void *cbd, 20445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int (*callback) (yasm_expr__item *ei, 20545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_bytecode *precbc, 20645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_bytecode *precbc2, 20745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org void *cbd)) 20845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 20945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int i; 21045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@dependent@*/ yasm_section *sect; 21145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc; 21245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int numterms; 21345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 21445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Handle symrec-symrec in ADD exprs by looking for (-1*symrec) and 21545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * symrec term pairs (where both symrecs are in the same segment). 21645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 21745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->op != YASM_EXPR_ADD) 21845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return e; 21945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 22045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<e->numterms; i++) { 22145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int j; 22245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr *sube; 22345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum *intn; 22445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_symrec *sym = NULL; 22545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@dependent@*/ yasm_section *sect2; 22645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc2; 22745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 22845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* First look for an (-1*symrec) term */ 22945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[i].type != YASM_EXPR_EXPR) 23045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org continue; 23145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sube = e->terms[i].data.expn; 23245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (sube->op != YASM_EXPR_MUL || sube->numterms != 2) 23345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org continue; 23445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 23545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (sube->terms[0].type == YASM_EXPR_INT && 23645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (sube->terms[1].type == YASM_EXPR_SYM || 23745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sube->terms[1].type == YASM_EXPR_PRECBC)) { 23845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org intn = sube->terms[0].data.intn; 23945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (sube->terms[1].type == YASM_EXPR_PRECBC) 24045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org precbc = sube->terms[1].data.precbc; 24145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else 24245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sym = sube->terms[1].data.sym; 24345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else if ((sube->terms[0].type == YASM_EXPR_SYM || 24445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sube->terms[0].type == YASM_EXPR_PRECBC) && 24545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sube->terms[1].type == YASM_EXPR_INT) { 24645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (sube->terms[0].type == YASM_EXPR_PRECBC) 24745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org precbc = sube->terms[0].data.precbc; 24845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else 24945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sym = sube->terms[0].data.sym; 25045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org intn = sube->terms[1].data.intn; 25145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else 25245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org continue; 25345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 25445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!yasm_intnum_is_neg1(intn)) 25545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org continue; 25645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 25745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (sym && !yasm_symrec_get_label(sym, &precbc)) 25845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org continue; 25945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sect2 = yasm_bc_get_section(precbc); 26045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 26145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Now look for a symrec term in the same segment */ 26245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (j=0; j<e->numterms; j++) { 26345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (((e->terms[j].type == YASM_EXPR_SYM && 26445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_symrec_get_label(e->terms[j].data.sym, &precbc2)) || 26545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (e->terms[j].type == YASM_EXPR_PRECBC && 26645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (precbc2 = e->terms[j].data.precbc))) && 26745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (sect = yasm_bc_get_section(precbc2)) && 26845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sect == sect2 && 26945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org callback(&e->terms[j], precbc, precbc2, cbd)) { 27045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Delete the matching (-1*symrec) term */ 27145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_destroy(sube); 27245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i].type = YASM_EXPR_NONE; 27345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; /* stop looking for matching symrec term */ 27445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 27545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 27645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 27745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 27845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Clean up any deleted (EXPR_NONE) terms */ 27945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org numterms = 0; 28045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<e->numterms; i++) { 28145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[i].type != YASM_EXPR_NONE) 28245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[numterms++] = e->terms[i]; /* structure copy */ 28345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 28445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->numterms != numterms) { 28545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->numterms = numterms; 28645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e = yasm_xrealloc(e, sizeof(yasm_expr)+((numterms<2) ? 0 : 28745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sizeof(yasm_expr__item)*(numterms-2))); 28845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (numterms == 1) 28945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->op = YASM_EXPR_IDENT; 29045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 29145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 29245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return e; 29345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 29445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 29545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int 29645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_xform_bc_dist_cb(yasm_expr__item *ei, yasm_bytecode *precbc, 29745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_bytecode *precbc2, /*@null@*/ void *d) 29845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 29945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum *dist = yasm_calc_bc_dist(precbc, precbc2); 30045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!dist) 30145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 30245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Change the term to an integer */ 30345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ei->type = YASM_EXPR_INT; 30445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ei->data.intn = dist; 30545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 30645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 30745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 30845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Transforms instances of symrec-symrec [symrec+(-1*symrec)] into integers if 30945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * possible. 31045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 31145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic /*@only@*/ yasm_expr * 31245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_xform_bc_dist(/*@returned@*/ /*@only@*/ yasm_expr *e) 31345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 31445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return expr_xform_bc_dist_base(e, NULL, expr_xform_bc_dist_cb); 31545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 31645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 31745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct bc_dist_subst_cbd { 31845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org void (*callback) (unsigned int subst, yasm_bytecode *precbc, 31945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_bytecode *precbc2, void *cbd); 32045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org void *cbd; 32145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned int subst; 32245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} bc_dist_subst_cbd; 32345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 32445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int 32545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_bc_dist_subst_cb(yasm_expr__item *ei, yasm_bytecode *precbc, 32645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_bytecode *precbc2, /*@null@*/ void *d) 32745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 32845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc_dist_subst_cbd *my_cbd = d; 32945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org assert(my_cbd != NULL); 33045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Call higher-level callback */ 33145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org my_cbd->callback(my_cbd->subst, precbc, precbc2, my_cbd->cbd); 33245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Change the term to an subst */ 33345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ei->type = YASM_EXPR_SUBST; 33445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ei->data.subst = my_cbd->subst; 33545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org my_cbd->subst++; 33645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 33745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 33845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 33945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic yasm_expr * 34045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_xform_bc_dist_subst(yasm_expr *e, void *d) 34145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 34245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return expr_xform_bc_dist_base(e, d, expr_bc_dist_subst_cb); 34345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 34445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 34545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgint 34645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr__bc_dist_subst(yasm_expr **ep, void *cbd, 34745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org void (*callback) (unsigned int subst, 34845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_bytecode *precbc, 34945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_bytecode *precbc2, 35045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org void *cbd)) 35145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 35245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc_dist_subst_cbd my_cbd; /* callback info for low-level callback */ 35345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org my_cbd.callback = callback; 35445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org my_cbd.cbd = cbd; 35545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org my_cbd.subst = 0; 35645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *ep = yasm_expr__level_tree(*ep, 1, 1, 1, 0, &expr_xform_bc_dist_subst, 35745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org &my_cbd); 35845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return my_cbd.subst; 35945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 36045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 36145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Negate just a single ExprItem by building a -1*ei subexpression */ 36245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void 36345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_xform_neg_item(yasm_expr *e, yasm_expr__item *ei) 36445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 36545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr *sube = yasm_xmalloc(sizeof(yasm_expr)); 36645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 36745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Build -1*ei subexpression */ 36845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sube->op = YASM_EXPR_MUL; 36945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sube->line = e->line; 37045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sube->numterms = 2; 37145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sube->terms[0].type = YASM_EXPR_INT; 37245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sube->terms[0].data.intn = yasm_intnum_create_int(-1); 37345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sube->terms[1] = *ei; /* structure copy */ 37445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 37545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Replace original ExprItem with subexp */ 37645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ei->type = YASM_EXPR_EXPR; 37745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ei->data.expn = sube; 37845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 37945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 38045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Negates e by multiplying by -1, with distribution over lower-precedence 38145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * operators (eg ADD) and special handling to simplify result w/ADD, NEG, and 38245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * others. 38345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 38445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Returns a possibly reallocated e. 38545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 38645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic /*@only@*/ yasm_expr * 38745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_xform_neg_helper(/*@returned@*/ /*@only@*/ yasm_expr *e) 38845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 38945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr *ne; 39045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int i; 39145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 39245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org switch (e->op) { 39345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_ADD: 39445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* distribute (recursively if expr) over terms */ 39545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<e->numterms; i++) { 39645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[i].type == YASM_EXPR_EXPR) 39745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i].data.expn = 39845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org expr_xform_neg_helper(e->terms[i].data.expn); 39945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else 40045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org expr_xform_neg_item(e, &e->terms[i]); 40145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 40245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 40345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_SUB: 40445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* change op to ADD, and recursively negate left side (if expr) */ 40545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->op = YASM_EXPR_ADD; 40645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[0].type == YASM_EXPR_EXPR) 40745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[0].data.expn = 40845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org expr_xform_neg_helper(e->terms[0].data.expn); 40945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else 41045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org expr_xform_neg_item(e, &e->terms[0]); 41145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 41245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_NEG: 41345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Negating a negated value? Make it an IDENT. */ 41445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->op = YASM_EXPR_IDENT; 41545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 41645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_IDENT: 41745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Negating an ident? Change it into a MUL w/ -1 if there's no 41845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * floatnums present below; if there ARE floatnums, recurse. 41945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 42045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[0].type == YASM_EXPR_FLOAT) 42145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_floatnum_calc(e->terms[0].data.flt, YASM_EXPR_NEG, NULL); 42245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else if (e->terms[0].type == YASM_EXPR_INT) 42345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_calc(e->terms[0].data.intn, YASM_EXPR_NEG, NULL); 42445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else if (e->terms[0].type == YASM_EXPR_EXPR && 42545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr__contains(e->terms[0].data.expn, YASM_EXPR_FLOAT)) 42645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org expr_xform_neg_helper(e->terms[0].data.expn); 42745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else { 42845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->op = YASM_EXPR_MUL; 42945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->numterms = 2; 43045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[1].type = YASM_EXPR_INT; 43145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[1].data.intn = yasm_intnum_create_int(-1); 43245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 43345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 43445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org default: 43545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Everything else. MUL will be combined when it's leveled. 43645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Make a new expr (to replace e) with -1*e. 43745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 43845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ne = yasm_xmalloc(sizeof(yasm_expr)); 43945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ne->op = YASM_EXPR_MUL; 44045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ne->line = e->line; 44145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ne->numterms = 2; 44245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ne->terms[0].type = YASM_EXPR_INT; 44345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ne->terms[0].data.intn = yasm_intnum_create_int(-1); 44445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ne->terms[1].type = YASM_EXPR_EXPR; 44545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ne->terms[1].data.expn = e; 44645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return ne; 44745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 44845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return e; 44945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 45045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 45145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Transforms negatives into expressions that are easier to combine: 45245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * -x -> -1*x 45345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * a-b -> a+(-1*b) 45445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 45545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Call post-order on an expression tree to transform the entire tree. 45645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 45745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Returns a possibly reallocated e. 45845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 45945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic /*@only@*/ yasm_expr * 46045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_xform_neg(/*@returned@*/ /*@only@*/ yasm_expr *e) 46145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 46245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org switch (e->op) { 46345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_NEG: 46445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Turn -x into -1*x */ 46545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->op = YASM_EXPR_IDENT; 46645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return expr_xform_neg_helper(e); 46745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_SUB: 46845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Turn a-b into a+(-1*b) */ 46945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 47045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* change op to ADD, and recursively negate right side (if expr) */ 47145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->op = YASM_EXPR_ADD; 47245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[1].type == YASM_EXPR_EXPR) 47345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[1].data.expn = 47445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org expr_xform_neg_helper(e->terms[1].data.expn); 47545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else 47645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org expr_xform_neg_item(e, &e->terms[1]); 47745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 47845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org default: 47945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 48045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 48145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 48245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return e; 48345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 48445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 48545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Look for simple identities that make the entire result constant: 48645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 0*&x, -1|x, etc. 48745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 48845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int 48945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_is_constant(yasm_expr_op op, yasm_intnum *intn) 49045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 49145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int iszero = yasm_intnum_is_zero(intn); 49245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return ((iszero && op == YASM_EXPR_MUL) || 49345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (iszero && op == YASM_EXPR_AND) || 49445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (iszero && op == YASM_EXPR_LAND) || 49545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (yasm_intnum_is_neg1(intn) && op == YASM_EXPR_OR)); 49645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 49745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 49845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Look for simple "left" identities like 0+x, 1*x, etc. */ 49945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int 50045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_can_destroy_int_left(yasm_expr_op op, yasm_intnum *intn) 50145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 50245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int iszero = yasm_intnum_is_zero(intn); 50345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return ((yasm_intnum_is_pos1(intn) && op == YASM_EXPR_MUL) || 50445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (iszero && op == YASM_EXPR_ADD) || 50545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (yasm_intnum_is_neg1(intn) && op == YASM_EXPR_AND) || 50645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (!iszero && op == YASM_EXPR_LAND) || 50745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (iszero && op == YASM_EXPR_OR) || 50845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (iszero && op == YASM_EXPR_LOR)); 50945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 51045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 51145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Look for simple "right" identities like x+|-0, x*&/1 */ 51245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int 51345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_can_destroy_int_right(yasm_expr_op op, yasm_intnum *intn) 51445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 51545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int iszero = yasm_intnum_is_zero(intn); 51645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int ispos1 = yasm_intnum_is_pos1(intn); 51745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return ((ispos1 && op == YASM_EXPR_MUL) || 51845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (ispos1 && op == YASM_EXPR_DIV) || 51945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (iszero && op == YASM_EXPR_ADD) || 52045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (iszero && op == YASM_EXPR_SUB) || 52145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (yasm_intnum_is_neg1(intn) && op == YASM_EXPR_AND) || 52245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (!iszero && op == YASM_EXPR_LAND) || 52345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (iszero && op == YASM_EXPR_OR) || 52445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (iszero && op == YASM_EXPR_LOR) || 52545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (iszero && op == YASM_EXPR_SHL) || 52645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (iszero && op == YASM_EXPR_SHR)); 52745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 52845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 52945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Check for and simplify identities. Returns new number of expr terms. 53045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Sets e->op = EXPR_IDENT if numterms ends up being 1. 53145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Uses numterms parameter instead of e->numterms for basis of "new" number 53245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * of terms. 53345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Assumes int_term is *only* integer term in e. 53445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * NOTE: Really designed to only be used by expr_level_op(). 53545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 53645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int 537d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.orgexpr_simplify_identity(yasm_expr *e, int numterms, int *int_term, 53845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int simplify_reg_mul) 53945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 54045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int i; 54145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int save_numterms; 54245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 54345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Don't do this step if it's 1*REG. Save and restore numterms so 54445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * yasm_expr__contains() works correctly. 54545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 54645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org save_numterms = e->numterms; 54745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->numterms = numterms; 54845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (simplify_reg_mul || e->op != YASM_EXPR_MUL 549d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org || !yasm_intnum_is_pos1(e->terms[*int_term].data.intn) 55045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org || !yasm_expr__contains(e, YASM_EXPR_REG)) { 55145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Check for simple identities that delete the intnum. 55245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Don't delete if the intnum is the only thing in the expn. 55345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 554d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org if ((*int_term == 0 && numterms > 1 && 55545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org expr_can_destroy_int_left(e->op, e->terms[0].data.intn)) || 556d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org (*int_term > 0 && 557d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org expr_can_destroy_int_right(e->op, 558d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org e->terms[*int_term].data.intn))) { 55945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Delete the intnum */ 560d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org yasm_intnum_destroy(e->terms[*int_term].data.intn); 56145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 56245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Slide everything to its right over by 1 */ 563d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org if (*int_term != numterms-1) /* if it wasn't last.. */ 564d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org memmove(&e->terms[*int_term], &e->terms[*int_term+1], 565d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org (numterms-1-*int_term)*sizeof(yasm_expr__item)); 56645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 56745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Update numterms */ 56845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org numterms--; 569d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org *int_term = -1; /* no longer an int term */ 57045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 57145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 57245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->numterms = save_numterms; 57345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 57445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Check for simple identites that delete everything BUT the intnum. 57545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Don't bother if the intnum is the only thing in the expn. 57645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 577d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org if (numterms > 1 && *int_term != -1 && 578d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org expr_is_constant(e->op, e->terms[*int_term].data.intn)) { 57945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Loop through, deleting everything but the integer term */ 58045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<e->numterms; i++) 581d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org if (i != *int_term) 58245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org expr_delete_term(&e->terms[i], 1); 58345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 58445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Move integer term to the first term (if not already there) */ 585d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org if (*int_term != 0) 586d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org e->terms[0] = e->terms[*int_term]; /* structure copy */ 58745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 58845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Set numterms to 1 */ 58945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org numterms = 1; 59045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 59145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 59245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Compute NOT, NEG, and LNOT on single intnum. */ 593d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org if (numterms == 1 && *int_term == 0 && 59445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (e->op == YASM_EXPR_NOT || e->op == YASM_EXPR_NEG || 59545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->op == YASM_EXPR_LNOT)) 59645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_calc(e->terms[0].data.intn, e->op, NULL); 59745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 59845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Change expression to IDENT if possible. */ 59945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (numterms == 1) 60045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->op = YASM_EXPR_IDENT; 60145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 60245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Return the updated numterms */ 60345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return numterms; 60445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 60545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 60645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Levels the expression tree starting at e. Eg: 60745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * a+(b+c) -> a+b+c 60845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * (a+b)+(c+d) -> a+b+c+d 60945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Naturally, only levels operators that allow more than two operand terms. 61045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * NOTE: only does *one* level of leveling (no recursion). Should be called 61145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * post-order on a tree to combine deeper levels. 61245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Also brings up any IDENT values into the current level (for ALL operators). 61345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Folds (combines by evaluation) *integer* constant values if fold_const != 0. 61445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 61545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Returns a possibly reallocated e. 61645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 61745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*@-mustfree@*/ 61845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic /*@only@*/ yasm_expr * 61945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_level_op(/*@returned@*/ /*@only@*/ yasm_expr *e, int fold_const, 62045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int simplify_ident, int simplify_reg_mul) 62145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 62245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int i, j, o, fold_numterms, level_numterms, level_fold_numterms; 62345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int first_int_term = -1; 62445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 62545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Determine how many operands will need to be brought up (for leveling). 62645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Go ahead and bring up any IDENT'ed values. 62745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 62845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org while (e->op == YASM_EXPR_IDENT && e->terms[0].type == YASM_EXPR_EXPR) { 62945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr *sube = e->terms[0].data.expn; 63045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_xfree(e); 63145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e = sube; 63245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 63345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 63445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* If non-numeric expression, don't fold constants. */ 63545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->op > YASM_EXPR_NONNUM) 63645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fold_const = 0; 63745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 63845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org level_numterms = e->numterms; 63945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org level_fold_numterms = 0; 64045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<e->numterms; i++) { 64145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Search downward until we find something *other* than an 64245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * IDENT, then bring it up to the current level. 64345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 64445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org while (e->terms[i].type == YASM_EXPR_EXPR && 64545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i].data.expn->op == YASM_EXPR_IDENT) { 64645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr *sube = e->terms[i].data.expn; 64745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i] = sube->terms[0]; 64845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_xfree(sube); 64945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 65045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 65145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[i].type == YASM_EXPR_EXPR && 65245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i].data.expn->op == e->op) { 65345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* It's an expression w/the same operator, add in its numterms. 65445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * But don't forget to subtract one for the expr itself! 65545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 65645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org level_numterms += e->terms[i].data.expn->numterms - 1; 65745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 65845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* If we're folding constants, count up the number of constants 65945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * that will be merged in. 66045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 66145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (fold_const) 66245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (j=0; j<e->terms[i].data.expn->numterms; j++) 66345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[i].data.expn->terms[j].type == 66445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org YASM_EXPR_INT) 66545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org level_fold_numterms++; 66645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 66745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 66845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Find the first integer term (if one is present) if we're folding 66945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * constants. 67045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 67145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (fold_const && first_int_term == -1 && 67245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i].type == YASM_EXPR_INT) 67345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org first_int_term = i; 67445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 67545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 67645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Look for other integer terms if there's one and combine. 67745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Also eliminate empty spaces when combining and adjust numterms 67845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * variables. 67945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 68045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fold_numterms = e->numterms; 68145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (first_int_term != -1) { 68245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=first_int_term+1, o=first_int_term+1; i<e->numterms; i++) { 68345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[i].type == YASM_EXPR_INT) { 68445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_calc(e->terms[first_int_term].data.intn, e->op, 68545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i].data.intn); 68645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fold_numterms--; 68745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org level_numterms--; 68845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* make sure to delete folded intnum */ 68945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_destroy(e->terms[i].data.intn); 69045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else if (o != i) { 69145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* copy term if it changed places */ 69245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[o++] = e->terms[i]; 69345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else 69445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org o++; 69545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 69645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 69745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (simplify_ident) { 69845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int new_fold_numterms; 69945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Simplify identities and make IDENT if possible. */ 70045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org new_fold_numterms = 701d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org expr_simplify_identity(e, fold_numterms, &first_int_term, 70245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org simplify_reg_mul); 70345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org level_numterms -= fold_numterms-new_fold_numterms; 70445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fold_numterms = new_fold_numterms; 70545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 70645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (fold_numterms == 1) 70745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->op = YASM_EXPR_IDENT; 70845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 70945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 71045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Only level operators that allow more than two operand terms. 71145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Also don't bother leveling if it's not necessary to bring up any terms. 71245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 71345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if ((e->op != YASM_EXPR_ADD && e->op != YASM_EXPR_MUL && 71445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->op != YASM_EXPR_OR && e->op != YASM_EXPR_AND && 71545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->op != YASM_EXPR_LOR && e->op != YASM_EXPR_LAND && 71645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->op != YASM_EXPR_LXOR && e->op != YASM_EXPR_XOR) || 71745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org level_numterms <= fold_numterms) { 71845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Downsize e if necessary */ 71945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (fold_numterms < e->numterms && e->numterms > 2) 72045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e = yasm_xrealloc(e, sizeof(yasm_expr)+((fold_numterms<2) ? 0 : 72145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sizeof(yasm_expr__item)*(fold_numterms-2))); 72245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Update numterms */ 72345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->numterms = fold_numterms; 72445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return e; 72545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 72645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 72745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Adjust numterms for constant folding from terms being "pulled up". 72845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Careful: if there's no integer term in e, then save space for it. 72945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 73045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (fold_const) { 73145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org level_numterms -= level_fold_numterms; 73245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (first_int_term == -1 && level_fold_numterms != 0) 73345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org level_numterms++; 73445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 73545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 73645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Alloc more (or conceivably less, but not usually) space for e */ 73745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e = yasm_xrealloc(e, sizeof(yasm_expr)+((level_numterms<2) ? 0 : 73845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sizeof(yasm_expr__item)*(level_numterms-2))); 73945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 74045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Copy up ExprItem's. Iterate from right to left to keep the same 74145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * ordering as was present originally. 74245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Combine integer terms as necessary. 74345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 74445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=fold_numterms-1, o=level_numterms-1; i>=0; i--) { 74545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[i].type == YASM_EXPR_EXPR && 74645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i].data.expn->op == e->op) { 74745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* bring up subexpression */ 74845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr *sube = e->terms[i].data.expn; 74945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 75045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* copy terms right to left */ 75145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (j=sube->numterms-1; j>=0; j--) { 75245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (fold_const && sube->terms[j].type == YASM_EXPR_INT) { 75345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Need to fold it in.. but if there's no int term already, 75445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * just copy into a new one. 75545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 75645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (first_int_term == -1) { 75745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org first_int_term = o--; 75845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[first_int_term] = sube->terms[j]; /* struc */ 75945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else { 76045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_calc(e->terms[first_int_term].data.intn, 76145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->op, sube->terms[j].data.intn); 76245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* make sure to delete folded intnum */ 76345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_destroy(sube->terms[j].data.intn); 76445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 76545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else { 76645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (o == first_int_term) 76745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org o--; 76845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[o--] = sube->terms[j]; /* structure copy */ 76945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 77045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 77145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 77245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* delete subexpression, but *don't delete nodes* (as we've just 77345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * copied them!) 77445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 77545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_xfree(sube); 77645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else if (o != i) { 77745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* copy operand if it changed places */ 77845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (o == first_int_term) 77945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org o--; 78045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[o] = e->terms[i]; 78145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* If we moved the first_int_term, change first_int_num too */ 78245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (i == first_int_term) 78345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org first_int_term = o; 78445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org o--; 78545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else 78645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org o--; 78745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 78845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 78945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Simplify identities, make IDENT if possible, and save to e->numterms. */ 79045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (simplify_ident && first_int_term != -1) { 79145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->numterms = expr_simplify_identity(e, level_numterms, 792d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org &first_int_term, simplify_reg_mul); 79345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else { 79445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->numterms = level_numterms; 79545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (level_numterms == 1) 79645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->op = YASM_EXPR_IDENT; 79745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 79845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 79945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return e; 80045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 80145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*@=mustfree@*/ 80245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 80345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef SLIST_HEAD(yasm__exprhead, yasm__exprentry) yasm__exprhead; 80445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct yasm__exprentry { 80545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@reldef@*/ SLIST_ENTRY(yasm__exprentry) next; 80645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@null@*/ const yasm_expr *e; 80745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} yasm__exprentry; 80845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 80945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic yasm_expr * 81045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_expand_equ(yasm_expr *e, yasm__exprhead *eh) 81145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 81245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int i; 81345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm__exprentry ee; 81445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 81545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* traverse terms */ 81645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<e->numterms; i++) { 81745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org const yasm_expr *equ_expr; 81845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 81945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Expand equ's. */ 82045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[i].type == YASM_EXPR_SYM && 82145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (equ_expr = yasm_symrec_get_equ(e->terms[i].data.sym))) { 82245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm__exprentry *np; 82345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 82445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Check for circular reference */ 82545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org SLIST_FOREACH(np, eh, next) { 82645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (np->e == equ_expr) { 82745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_error_set(YASM_ERROR_TOO_COMPLEX, 82845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org N_("circular reference detected")); 82945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return e; 83045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 83145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 83245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 83345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i].type = YASM_EXPR_EXPR; 83445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i].data.expn = yasm_expr_copy(equ_expr); 83545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 83645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Remember we saw this equ and recurse */ 83745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ee.e = equ_expr; 83845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org SLIST_INSERT_HEAD(eh, &ee, next); 83945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i].data.expn = expr_expand_equ(e->terms[i].data.expn, eh); 84045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org SLIST_REMOVE_HEAD(eh, next); 84145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else if (e->terms[i].type == YASM_EXPR_EXPR) 84245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Recurse */ 84345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i].data.expn = expr_expand_equ(e->terms[i].data.expn, eh); 84445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 84545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 84645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return e; 84745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 84845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 84945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic yasm_expr * 85045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_level_tree(yasm_expr *e, int fold_const, int simplify_ident, 85145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int simplify_reg_mul, int calc_bc_dist, 85245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_xform_func expr_xform_extra, 85345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org void *expr_xform_extra_data) 85445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 85545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int i; 85645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 85745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e = expr_xform_neg(e); 85845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 85945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* traverse terms */ 86045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<e->numterms; i++) { 86145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Recurse */ 86245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[i].type == YASM_EXPR_EXPR) 86345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i].data.expn = 86445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org expr_level_tree(e->terms[i].data.expn, fold_const, 86545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org simplify_ident, simplify_reg_mul, calc_bc_dist, 86645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org expr_xform_extra, expr_xform_extra_data); 86745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 86845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 86945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Check for SEG of SEG:OFF, if we match, simplify to just the segment */ 87045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->op == YASM_EXPR_SEG && e->terms[0].type == YASM_EXPR_EXPR && 87145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[0].data.expn->op == YASM_EXPR_SEGOFF) { 87245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->op = YASM_EXPR_IDENT; 87345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[0].data.expn->op = YASM_EXPR_IDENT; 87445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Destroy the second (offset) term */ 87545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[0].data.expn->numterms = 1; 87645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org expr_delete_term(&e->terms[0].data.expn->terms[1], 1); 87745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 87845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 87945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* do callback */ 88045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e = expr_level_op(e, fold_const, simplify_ident, simplify_reg_mul); 88145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (calc_bc_dist || expr_xform_extra) { 88245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (calc_bc_dist) 88345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e = expr_xform_bc_dist(e); 88445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (expr_xform_extra) 88545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e = expr_xform_extra(e, expr_xform_extra_data); 88645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e = expr_level_tree(e, fold_const, simplify_ident, simplify_reg_mul, 88745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 0, NULL, NULL); 88845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 88945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return e; 89045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 89145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 89245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Level an entire expn tree, expanding equ's as we go */ 89345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr * 89445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr__level_tree(yasm_expr *e, int fold_const, int simplify_ident, 89545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int simplify_reg_mul, int calc_bc_dist, 89645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_xform_func expr_xform_extra, 89745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org void *expr_xform_extra_data) 89845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 89945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm__exprhead eh; 90045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org SLIST_INIT(&eh); 90145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 90245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!e) 90345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 90445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 90545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e = expr_expand_equ(e, &eh); 90645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e = expr_level_tree(e, fold_const, simplify_ident, simplify_reg_mul, 90745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org calc_bc_dist, expr_xform_extra, expr_xform_extra_data); 90845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 90945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return e; 91045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 91145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 91245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Comparison function for expr_order_terms(). 91345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Assumes ExprType enum is in canonical order. 91445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 91545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int 91645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_order_terms_compare(const void *va, const void *vb) 91745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 91845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org const yasm_expr__item *a = va, *b = vb; 91945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return (a->type - b->type); 92045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 92145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 92245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Reorder terms of e into canonical order. Only reorders if reordering 92345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * doesn't change meaning of expression. (eg, doesn't reorder SUB). 92445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Canonical order: REG, INT, FLOAT, SYM, EXPR. 92545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Multiple terms of a single type are kept in the same order as in 92645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * the original expression. 92745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * NOTE: Only performs reordering on *one* level (no recursion). 92845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 92945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid 93045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr__order_terms(yasm_expr *e) 93145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 93245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* don't bother reordering if only one element */ 93345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->numterms == 1) 93445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return; 93545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 93645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* only reorder some types of operations */ 93745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org switch (e->op) { 93845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_ADD: 93945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_MUL: 94045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_OR: 94145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_AND: 94245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_XOR: 94345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_LOR: 94445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_LAND: 94545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_LXOR: 94645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Use mergesort to sort. It's fast on already sorted values and a 94745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * stable sort (multiple terms of same type are kept in the same 94845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * order). 94945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 95045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm__mergesort(e->terms, (size_t)e->numterms, 95145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sizeof(yasm_expr__item), expr_order_terms_compare); 95245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 95345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org default: 95445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 95545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 95645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 95745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 95845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void 95945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_item_copy(yasm_expr__item *dest, const yasm_expr__item *src) 96045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 96145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org dest->type = src->type; 96245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org switch (src->type) { 96345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_SYM: 96445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Symbols don't need to be copied */ 96545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org dest->data.sym = src->data.sym; 96645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 96745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_PRECBC: 96845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Nor do direct bytecode references */ 96945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org dest->data.precbc = src->data.precbc; 97045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 97145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_EXPR: 97245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org dest->data.expn = yasm_expr__copy_except(src->data.expn, -1); 97345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 97445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_INT: 97545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org dest->data.intn = yasm_intnum_copy(src->data.intn); 97645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 97745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_FLOAT: 97845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org dest->data.flt = yasm_floatnum_copy(src->data.flt); 97945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 98045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_REG: 98145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org dest->data.reg = src->data.reg; 98245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 98345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_SUBST: 98445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org dest->data.subst = src->data.subst; 98545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 98645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org default: 98745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 98845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 98945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 99045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 99145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Copy entire expression EXCEPT for index "except" at *top level only*. */ 99245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr * 99345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr__copy_except(const yasm_expr *e, int except) 99445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 99545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr *n; 99645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int i; 99745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 99845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org n = yasm_xmalloc(sizeof(yasm_expr) + 99945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sizeof(yasm_expr__item)*(e->numterms<2?0:e->numterms-2)); 100045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 100145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org n->op = e->op; 100245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org n->line = e->line; 100345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org n->numterms = e->numterms; 100445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<e->numterms; i++) { 100545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (i != except) 100645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org expr_item_copy(&n->terms[i], &e->terms[i]); 100745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 100845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 100945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return n; 101045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 101145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 101245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void 101345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_delete_term(yasm_expr__item *term, int recurse) 101445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 101545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org switch (term->type) { 101645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_INT: 101745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_destroy(term->data.intn); 101845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 101945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_FLOAT: 102045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_floatnum_destroy(term->data.flt); 102145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 102245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_EXPR: 102345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (recurse) 102445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_destroy(term->data.expn); 102545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 102645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org default: 102745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 102845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 102945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 103045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 103145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int 103245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_destroy_each(/*@only@*/ yasm_expr *e, /*@unused@*/ void *d) 103345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 103445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int i; 103545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<e->numterms; i++) 103645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org expr_delete_term(&e->terms[i], 0); 103745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_xfree(e); /* free ourselves */ 103845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; /* don't stop recursion */ 103945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 104045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 104145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*@-mustfree@*/ 104245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid 104345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr_destroy(yasm_expr *e) 104445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 104545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org expr_traverse_nodes_post(e, NULL, expr_destroy_each); 104645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 104745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*@=mustfree@*/ 104845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 104945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgint 105045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr_is_op(const yasm_expr *e, yasm_expr_op op) 105145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 105245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return (e->op == op); 105345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 105445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 105545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int 105645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_contains_callback(const yasm_expr__item *ei, void *d) 105745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 105845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr__type *t = d; 105945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return (ei->type & *t); 106045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 106145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 106245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgint 106345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr__contains(const yasm_expr *e, yasm_expr__type t) 106445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 106545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return yasm_expr__traverse_leaves_in_const(e, &t, expr_contains_callback); 106645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 106745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 106845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct subst_cbd { 106945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned int num_items; 107045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org const yasm_expr__item *items; 107145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} subst_cbd; 107245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 107345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int 107445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_subst_callback(yasm_expr__item *ei, void *d) 107545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 107645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org subst_cbd *cbd = d; 107745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (ei->type != YASM_EXPR_SUBST) 107845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 107945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (ei->data.subst >= cbd->num_items) 108045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; /* error */ 108145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org expr_item_copy(ei, &cbd->items[ei->data.subst]); 108245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 108345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 108445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 108545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgint 108645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr__subst(yasm_expr *e, unsigned int num_items, 108745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org const yasm_expr__item *items) 108845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 108945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org subst_cbd cbd; 109045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org cbd.num_items = num_items; 109145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org cbd.items = items; 109245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return yasm_expr__traverse_leaves_in(e, &cbd, expr_subst_callback); 109345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 109445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 109545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Traverse over expression tree, calling func for each operation AFTER the 109645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * branches (if expressions) have been traversed (eg, postorder 109745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * traversal). The data pointer d is passed to each func call. 109845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 109945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Stops early (and returns 1) if func returns 1. Otherwise returns 0. 110045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 110145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int 110245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexpr_traverse_nodes_post(yasm_expr *e, void *d, 110345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int (*func) (/*@null@*/ yasm_expr *e, 110445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@null@*/ void *d)) 110545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 110645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int i; 110745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 110845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!e) 110945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 111045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 111145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* traverse terms */ 111245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<e->numterms; i++) { 111345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[i].type == YASM_EXPR_EXPR && 111445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org expr_traverse_nodes_post(e->terms[i].data.expn, d, func)) 111545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 111645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 111745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 111845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* do callback */ 111945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return func(e, d); 112045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 112145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 112245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Traverse over expression tree in order, calling func for each leaf 112345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * (non-operation). The data pointer d is passed to each func call. 112445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 112545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Stops early (and returns 1) if func returns 1. Otherwise returns 0. 112645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 112745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgint 112845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr__traverse_leaves_in_const(const yasm_expr *e, void *d, 112945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int (*func) (/*@null@*/ const yasm_expr__item *ei, /*@null@*/ void *d)) 113045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 113145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int i; 113245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 113345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!e) 113445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 113545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 113645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<e->numterms; i++) { 113745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[i].type == YASM_EXPR_EXPR) { 113845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (yasm_expr__traverse_leaves_in_const(e->terms[i].data.expn, d, 113945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org func)) 114045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 114145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else { 114245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (func(&e->terms[i], d)) 114345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 114445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 114545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 114645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 114745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 114845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 114945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Traverse over expression tree in order, calling func for each leaf 115045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * (non-operation). The data pointer d is passed to each func call. 115145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 115245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Stops early (and returns 1) if func returns 1. Otherwise returns 0. 115345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 115445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgint 115545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr__traverse_leaves_in(yasm_expr *e, void *d, 115645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int (*func) (/*@null@*/ yasm_expr__item *ei, /*@null@*/ void *d)) 115745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 115845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int i; 115945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 116045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!e) 116145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 116245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 116345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<e->numterms; i++) { 116445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[i].type == YASM_EXPR_EXPR) { 116545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (yasm_expr__traverse_leaves_in(e->terms[i].data.expn, d, func)) 116645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 116745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else { 116845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (func(&e->terms[i], d)) 116945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 117045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 117145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 117245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 117345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 117445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 117545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr * 117645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr_extract_deep_segoff(yasm_expr **ep) 117745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 117845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr *retval; 117945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr *e = *ep; 118045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int i; 118145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 118245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Try to extract at this level */ 118345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org retval = yasm_expr_extract_segoff(ep); 118445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (retval) 118545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return retval; 118645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 118745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Not at this level? Search any expr children. */ 118845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<e->numterms; i++) { 118945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[i].type == YASM_EXPR_EXPR) { 119045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org retval = yasm_expr_extract_deep_segoff(&e->terms[i].data.expn); 119145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (retval) 119245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return retval; 119345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 119445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 119545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 119645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Didn't find one */ 119745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return NULL; 119845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 119945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 120045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr * 120145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr_extract_segoff(yasm_expr **ep) 120245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 120345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr *retval; 120445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr *e = *ep; 120545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 120645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* If not SEG:OFF, we can't do this transformation */ 120745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->op != YASM_EXPR_SEGOFF) 120845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return NULL; 120945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 121045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Extract the SEG portion out to its own expression */ 121145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[0].type == YASM_EXPR_EXPR) 121245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org retval = e->terms[0].data.expn; 121345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else { 121445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Need to build IDENT expression to hold non-expression contents */ 121545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org retval = yasm_xmalloc(sizeof(yasm_expr)); 121645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org retval->op = YASM_EXPR_IDENT; 121745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org retval->numterms = 1; 121845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org retval->terms[0] = e->terms[0]; /* structure copy */ 121945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 122045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 122145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Delete the SEG: portion by changing the expression into an IDENT */ 122245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->op = YASM_EXPR_IDENT; 122345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->numterms = 1; 122445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[0] = e->terms[1]; /* structure copy */ 122545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 122645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return retval; 122745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 122845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 122945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr * 123045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr_extract_wrt(yasm_expr **ep) 123145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 123245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr *retval; 123345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr *e = *ep; 123445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 123545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* If not WRT, we can't do this transformation */ 123645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->op != YASM_EXPR_WRT) 123745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return NULL; 123845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 123945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Extract the right side portion out to its own expression */ 124045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[1].type == YASM_EXPR_EXPR) 124145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org retval = e->terms[1].data.expn; 124245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else { 124345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Need to build IDENT expression to hold non-expression contents */ 124445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org retval = yasm_xmalloc(sizeof(yasm_expr)); 124545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org retval->op = YASM_EXPR_IDENT; 124645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org retval->numterms = 1; 124745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org retval->terms[0] = e->terms[1]; /* structure copy */ 124845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 124945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 125045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Delete the right side portion by changing the expr into an IDENT */ 125145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->op = YASM_EXPR_IDENT; 125245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->numterms = 1; 125345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 125445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return retval; 125545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 125645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 125745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*@-unqualifiedtrans -nullderef -nullstate -onlytrans@*/ 125845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_intnum * 125945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr_get_intnum(yasm_expr **ep, int calc_bc_dist) 126045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 126145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *ep = yasm_expr_simplify(*ep, calc_bc_dist); 126245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 126345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if ((*ep)->op == YASM_EXPR_IDENT && (*ep)->terms[0].type == YASM_EXPR_INT) 126445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return (*ep)->terms[0].data.intn; 126545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else 126645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return (yasm_intnum *)NULL; 126745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 126845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*@=unqualifiedtrans =nullderef -nullstate -onlytrans@*/ 126945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 127045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*@-unqualifiedtrans -nullderef -nullstate -onlytrans@*/ 127145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgconst yasm_symrec * 127245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr_get_symrec(yasm_expr **ep, int simplify) 127345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 127445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (simplify) 127545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *ep = yasm_expr_simplify(*ep, 0); 127645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 127745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if ((*ep)->op == YASM_EXPR_IDENT && (*ep)->terms[0].type == YASM_EXPR_SYM) 127845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return (*ep)->terms[0].data.sym; 127945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else 128045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return (yasm_symrec *)NULL; 128145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 128245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*@=unqualifiedtrans =nullderef -nullstate -onlytrans@*/ 128345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 128445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*@-unqualifiedtrans -nullderef -nullstate -onlytrans@*/ 128545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgconst uintptr_t * 128645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr_get_reg(yasm_expr **ep, int simplify) 128745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 128845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (simplify) 128945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *ep = yasm_expr_simplify(*ep, 0); 129045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 129145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if ((*ep)->op == YASM_EXPR_IDENT && (*ep)->terms[0].type == YASM_EXPR_REG) 129245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return &((*ep)->terms[0].data.reg); 129345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else 129445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return NULL; 129545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 129645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*@=unqualifiedtrans =nullderef -nullstate -onlytrans@*/ 129745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 129845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid 129945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr_print(const yasm_expr *e, FILE *f) 130045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 130145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org char opstr[8]; 130245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int i; 130345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 130445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!e) { 130545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "(nil)"); 130645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return; 130745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 130845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 130945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org switch (e->op) { 131045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_ADD: 131145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "+"); 131245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 131345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_SUB: 131445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "-"); 131545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 131645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_MUL: 131745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "*"); 131845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 131945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_DIV: 132045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "/"); 132145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 132245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_SIGNDIV: 132345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "//"); 132445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 132545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_MOD: 132645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "%"); 132745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 132845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_SIGNMOD: 132945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "%%"); 133045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 133145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_NEG: 133245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "-"); 133345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org opstr[0] = 0; 133445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 133545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_NOT: 133645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "~"); 133745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org opstr[0] = 0; 133845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 133945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_OR: 134045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "|"); 134145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 134245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_AND: 134345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "&"); 134445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 134545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_XOR: 134645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "^"); 134745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 134845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_XNOR: 134945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "XNOR"); 135045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 135145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_NOR: 135245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "NOR"); 135345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 135445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_SHL: 135545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "<<"); 135645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 135745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_SHR: 135845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, ">>"); 135945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 136045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_LOR: 136145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "||"); 136245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 136345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_LAND: 136445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "&&"); 136545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 136645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_LNOT: 136745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "!"); 136845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 136945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_LXOR: 137045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "^^"); 137145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 137245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_LXNOR: 137345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "LXNOR"); 137445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 137545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_LNOR: 137645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "LNOR"); 137745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 137845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_LT: 137945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "<"); 138045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 138145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_GT: 138245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, ">"); 138345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 138445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_LE: 138545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "<="); 138645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 138745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_GE: 138845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, ">="); 138945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 139045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_NE: 139145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "!="); 139245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 139345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_EQ: 139445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, "=="); 139545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 139645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_SEG: 139745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "SEG "); 139845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org opstr[0] = 0; 139945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 140045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_WRT: 140145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, " WRT "); 140245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 140345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_SEGOFF: 140445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, ":"); 140545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 140645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_IDENT: 140745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org opstr[0] = 0; 140845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 140945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org default: 141045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org strcpy(opstr, " !UNK! "); 141145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 141245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 141345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<e->numterms; i++) { 141445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org switch (e->terms[i].type) { 141545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_PRECBC: 141645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "{%lx}", 141745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_bc_next_offset(e->terms[i].data.precbc)); 141845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 141945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_SYM: 142045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%s", yasm_symrec_get_name(e->terms[i].data.sym)); 142145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 142245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_EXPR: 142345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "("); 142445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_print(e->terms[i].data.expn, f); 142545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, ")"); 142645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 142745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_INT: 142845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_print(e->terms[i].data.intn, f); 142945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 143045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_FLOAT: 143145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_floatnum_print(e->terms[i].data.flt, f); 143245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 143345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_REG: 143445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* FIXME */ 143545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*yasm_arch_reg_print(arch, e->terms[i].data.reg, f);*/ 143645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 143745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_SUBST: 143845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "[%u]", e->terms[i].data.subst); 143945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 144045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_NONE: 144145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 144245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 144345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (i < e->numterms-1) 144445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%s", opstr); 144545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 144645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 144745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 144845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgunsigned int 144945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr_size(const yasm_expr *e) 145045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 145145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int i; 145245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int seen = 0; 145345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned int size = 0, newsize; 145445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 145545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->op == YASM_EXPR_IDENT) { 145645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[0].type == YASM_EXPR_SYM) 145745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return yasm_symrec_get_size(e->terms[0].data.sym); 145845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 145945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 146045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->op != YASM_EXPR_ADD && e->op != YASM_EXPR_SUB) 146145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 146245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 146345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<e->numterms; i++) { 146445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org newsize = 0; 146545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org switch (e->terms[i].type) { 146645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_EXPR: 146745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org newsize = yasm_expr_size(e->terms[i].data.expn); 146845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 146945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_SYM: 147045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org newsize = yasm_symrec_get_size(e->terms[i].data.sym); 147145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 147245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org default: 147345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 147445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 147545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (newsize) { 147645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org size = newsize; 147745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (seen) 147845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* either sum of idents (?!) or substract of idents */ 147945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 148045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org seen = 1; 148145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 148245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 148345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* exactly one offset */ 148445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return size; 148545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 148645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 148745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgconst char * 148845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_expr_segment(const yasm_expr *e) 148945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 149045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int i; 149145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int seen = 0; 149245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org const char *segment = NULL; 149345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 149445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->op == YASM_EXPR_IDENT) { 149545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[0].type == YASM_EXPR_SYM) 149645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return yasm_symrec_get_segment(e->terms[0].data.sym); 149745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return NULL; 149845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 149945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->op != YASM_EXPR_ADD && e->op != YASM_EXPR_SUB) 150045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return NULL; 150145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 150245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<e->numterms; i++) { 150345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if ((e->op == YASM_EXPR_ADD || !i) && 150445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i].type == YASM_EXPR_EXPR) { 150545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if ((segment = yasm_expr_segment(e->terms[i].data.expn))) { 150645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (seen) { 150745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* either sum of idents (?!) or substract of idents */ 150845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return NULL; 150945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 151045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org seen = 1; 151145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 151245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 151345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 151445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* exactly one offset */ 151545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return segment; 151645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 1517