145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* 245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Value handling 345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Copyright (C) 2006-2007 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 "value.h" 3845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "symrec.h" 3945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 4045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "bytecode.h" 4145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "section.h" 4245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 4345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "arch.h" 4445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 4545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 4645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid 4745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_value_initialize(/*@out@*/ yasm_value *value, 4845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@null@*/ /*@kept@*/ yasm_expr *e, unsigned int size) 4945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 5045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->abs = e; 5145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->rel = NULL; 5245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->wrt = NULL; 5345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->seg_of = 0; 5445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->rshift = 0; 5545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->curpos_rel = 0; 5645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->ip_rel = 0; 5745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->jump_target = 0; 5845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->section_rel = 0; 5945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->no_warn = 0; 6045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->sign = 0; 6145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->size = size; 6245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 6345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 6445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid 6545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_value_init_sym(/*@out@*/ yasm_value *value, /*@null@*/ yasm_symrec *sym, 6645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned int size) 6745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 6845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->abs = NULL; 6945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->rel = sym; 7045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->wrt = NULL; 7145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->seg_of = 0; 7245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->rshift = 0; 7345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->curpos_rel = 0; 7445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->ip_rel = 0; 7545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->jump_target = 0; 7645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->section_rel = 0; 7745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->no_warn = 0; 7845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->sign = 0; 7945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->size = size; 8045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 8145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 8245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid 8345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_value_init_copy(yasm_value *value, const yasm_value *orig) 8445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 8545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->abs = orig->abs ? yasm_expr_copy(orig->abs) : NULL; 8645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->rel = orig->rel; 8745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->wrt = orig->wrt; 8845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->seg_of = orig->seg_of; 8945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->rshift = orig->rshift; 9045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->curpos_rel = orig->curpos_rel; 9145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->ip_rel = orig->ip_rel; 9245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->jump_target = orig->jump_target; 9345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->section_rel = orig->section_rel; 9445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->no_warn = orig->no_warn; 9545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->sign = orig->sign; 9645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->size = orig->size; 9745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 9845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 9945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid 10045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_value_delete(yasm_value *value) 10145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 10245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->abs) 10345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_destroy(value->abs); 10445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->abs = NULL; 10545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->rel = NULL; 10645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 10745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 10845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid 10945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_value_set_curpos_rel(yasm_value *value, yasm_bytecode *bc, 11045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned int ip_rel) 11145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 11245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->curpos_rel = 1; 11345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->ip_rel = ip_rel; 11445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* In order for us to correctly output curpos-relative values, we must 11545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * have a relative portion of the value. If one doesn't exist, point 11645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * to a custom absolute symbol. 11745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 11845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!value->rel) { 11945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_object *object = yasm_section_get_object(yasm_bc_get_section(bc)); 12045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->rel = yasm_symtab_abs_sym(object->symtab); 12145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 12245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 12345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 12445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int 12545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvalue_finalize_scan(yasm_value *value, yasm_expr *e, 12645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@null@*/ yasm_bytecode *expr_precbc, int ssym_not_ok) 12745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 12845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int i; 12945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@dependent@*/ yasm_section *sect; 13045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc; 13145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 13245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned long shamt; /* for SHR */ 13345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 13445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Yes, this has a maximum upper bound on 32 terms, based on an 13545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * "insane number of terms" (and ease of implementation) WAG. 13645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * The right way to do this would be a stack-based alloca, but that's 13745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * not ISO C. We really don't want to malloc here as this function is 13845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * hit a lot! 13945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 14045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * This is a bitmask to keep things small, as this is a recursive 14145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * routine and we don't want to eat up stack space. 14245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 14345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned long used; /* for ADD */ 14445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 14545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Thanks to this running after a simplify, we don't need to iterate 14645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * down through IDENTs or handle SUB. 14745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 14845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * We scan for a single symrec, gathering info along the way. After 14945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * we've found the symrec, we keep scanning but error if we find 15045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * another one. We pull out the single symrec and any legal operations 15145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * performed on it. 15245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 15345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Also, if we find a float anywhere, we don't allow mixing of a single 15445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * symrec with it. 15545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 15645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org switch (e->op) { 15745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_ADD: 15845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Okay for single symrec anywhere in expr. 15945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Check for single symrec anywhere. 16045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Handle symrec-symrec by checking for (-1*symrec) 16145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * and symrec term pairs (where both symrecs are in the same 16245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * segment). 16345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 16445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->numterms > 32) 16545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm__fatal(N_("expression on line %d has too many add terms;" 16645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org " internal limit of 32"), e->line); 16745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 16845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org used = 0; 16945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 17045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<e->numterms; i++) { 17145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int j; 17245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr *sube; 17345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum *intn; 17445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_symrec *sym; 17545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@dependent@*/ yasm_section *sect2; 17645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc2; 17745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 17845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* First look for an (-1*symrec) term */ 17945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[i].type != YASM_EXPR_EXPR) 18045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org continue; 18145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sube = e->terms[i].data.expn; 18245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 18345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (sube->op != YASM_EXPR_MUL || sube->numterms != 2) { 18445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* recurse instead */ 18545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value_finalize_scan(value, sube, expr_precbc, 18645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ssym_not_ok)) 18745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 18845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org continue; 18945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 19045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 19145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (sube->terms[0].type == YASM_EXPR_INT && 19245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sube->terms[1].type == YASM_EXPR_SYM) { 19345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org intn = sube->terms[0].data.intn; 19445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sym = sube->terms[1].data.sym; 19545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else if (sube->terms[0].type == YASM_EXPR_SYM && 19645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sube->terms[1].type == YASM_EXPR_INT) { 19745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sym = sube->terms[0].data.sym; 19845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org intn = sube->terms[1].data.intn; 19945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else { 20045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value_finalize_scan(value, sube, expr_precbc, 20145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ssym_not_ok)) 20245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 20345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org continue; 20445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 20545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 20645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!yasm_intnum_is_neg1(intn)) { 20745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value_finalize_scan(value, sube, expr_precbc, 20845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ssym_not_ok)) 20945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 21045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org continue; 21145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 21245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 21345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Look for the same symrec term; even if both are external, 21445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * they should cancel out. 21545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 21645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (j=0; j<e->numterms; j++) { 21745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[j].type == YASM_EXPR_SYM 21845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org && e->terms[j].data.sym == sym 21945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org && (used & (1<<j)) == 0) { 22045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Mark as used */ 22145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org used |= 1<<j; 22245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 22345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Replace both symrec portions with 0 */ 22445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_destroy(sube); 22545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i].type = YASM_EXPR_INT; 22645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i].data.intn = yasm_intnum_create_uint(0); 22745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[j].type = YASM_EXPR_INT; 22845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[j].data.intn = yasm_intnum_create_uint(0); 22945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 23045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; /* stop looking */ 23145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 23245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 23345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (j != e->numterms) 23445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org continue; 23545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 23645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!yasm_symrec_get_label(sym, &precbc)) { 23745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value_finalize_scan(value, sube, expr_precbc, 23845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ssym_not_ok)) 23945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 24045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org continue; 24145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 24245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sect2 = yasm_bc_get_section(precbc); 24345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 24445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Now look for a unused symrec term in the same segment */ 24545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (j=0; j<e->numterms; j++) { 24645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[j].type == YASM_EXPR_SYM 24745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org && yasm_symrec_get_label(e->terms[j].data.sym, 24845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org &precbc2) 24945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org && (sect = yasm_bc_get_section(precbc2)) 25045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org && sect == sect2 25145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org && (used & (1<<j)) == 0) { 25245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Mark as used */ 25345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org used |= 1<<j; 25445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; /* stop looking */ 25545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 25645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 25745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 25845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* We didn't match in the same segment. If the 25945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * -1*symrec is actually -1*curpos, we can match 26045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * unused symrec terms in other segments and generate 26145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * a curpos-relative reloc. 26245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 26345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Similarly, handle -1*symrec in other segment via the 26445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * following transformation: 26545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * other-this = (other-.)+(.-this) 26645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * We can only do this transformation if "this" is in 26745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * this expr's segment. 26845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 26945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Don't do this if we've already become curpos-relative. 27045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * The unmatched symrec will be caught below. 27145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 27245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (j == e->numterms && !value->curpos_rel 27345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org && (yasm_symrec_is_curpos(sym) 27445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org || (expr_precbc 27545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org && sect2 == yasm_bc_get_section(expr_precbc)))) { 27645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (j=0; j<e->numterms; j++) { 27745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[j].type == YASM_EXPR_SYM 27845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org && !yasm_symrec_get_equ(e->terms[j].data.sym) 27945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org && !yasm_symrec_is_special(e->terms[j].data.sym) 28045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org && (used & (1<<j)) == 0) { 28145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Mark as used */ 28245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org used |= 1<<j; 28345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Mark value as curpos-relative */ 28445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->rel || ssym_not_ok) 28545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 28645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->rel = e->terms[j].data.sym; 28745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->curpos_rel = 1; 28845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (yasm_symrec_is_curpos(sym)) { 28945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Replace both symrec portions with 0 */ 29045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_destroy(sube); 29145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i].type = YASM_EXPR_INT; 29245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i].data.intn = 29345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_create_uint(0); 29445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[j].type = YASM_EXPR_INT; 29545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[j].data.intn = 29645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_create_uint(0); 29745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else { 29845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Replace positive portion with curpos */ 29945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_object *object = 30045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_section_get_object(sect2); 30145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_symtab *symtab = object->symtab; 30245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[j].data.sym = 30345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_symtab_define_curpos 30445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (symtab, ".", expr_precbc, e->line); 30545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 30645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; /* stop looking */ 30745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 30845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 30945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 31045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 31145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 31245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (j == e->numterms) 31345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; /* We didn't find a match! */ 31445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 31545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 31645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Look for unmatched symrecs. If we've already found one or 31745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * we don't WANT to find one, error out. 31845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 31945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<e->numterms; i++) { 32045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[i].type == YASM_EXPR_SYM 32145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org && (used & (1<<i)) == 0) { 32245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->rel || ssym_not_ok) 32345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 32445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->rel = e->terms[i].data.sym; 32545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* and replace with 0 */ 32645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i].type = YASM_EXPR_INT; 32745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i].data.intn = yasm_intnum_create_uint(0); 32845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 32945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 33045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 33145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_SHR: 33245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Okay for single symrec in LHS and constant on RHS. 33345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Single symrecs are not okay on RHS. 33445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * If RHS is non-constant, don't allow single symrec on LHS. 33545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * XXX: should rshift be an expr instead?? 33645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 33745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 338a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org /* Check for single sym on LHS */ 339a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org if (e->terms[0].type != YASM_EXPR_SYM) 340a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org break; 34145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 342a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org /* If we already have a sym, we can't take another one */ 343a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org if (value->rel || ssym_not_ok) 344a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org return 1; 34545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 346a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org /* RHS must be a positive integer */ 34745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[1].type != YASM_EXPR_INT) 34845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; /* can't shift sym by non-constant integer */ 34945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org shamt = yasm_intnum_get_uint(e->terms[1].data.intn); 35045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if ((shamt + value->rshift) > YASM_VALUE_RSHIFT_MAX) 35145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; /* total shift would be too large */ 352a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org 353a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org /* Update value */ 35445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->rshift += shamt; 355a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org value->rel = e->terms[0].data.sym; 356a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org 357a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org /* Replace symbol with 0 */ 358a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org e->terms[0].type = YASM_EXPR_INT; 359a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org e->terms[0].data.intn = yasm_intnum_create_uint(0); 36045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 36145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Just leave SHR in place */ 36245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 36345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_SEG: 36445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Okay for single symrec (can only be done once). 36545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Not okay for anything BUT a single symrec as an immediate 36645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * child. 36745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 36845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->terms[0].type != YASM_EXPR_SYM) 36945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 37045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 37145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->seg_of) 37245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; /* multiple SEG not legal */ 37345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->seg_of = 1; 37445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 37545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->rel || ssym_not_ok) 37645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; /* got a relative portion somewhere else? */ 37745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->rel = e->terms[0].data.sym; 37845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 37945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* replace with ident'ed 0 */ 38045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->op = YASM_EXPR_IDENT; 38145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[0].type = YASM_EXPR_INT; 38245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[0].data.intn = yasm_intnum_create_uint(0); 38345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 38445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_WRT: 38545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Okay for single symrec in LHS and either a register or single 38645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * symrec (as an immediate child) on RHS. 38745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * If a single symrec on RHS, can only be done once. 38845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * WRT reg is left in expr for arch to look at. 38945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 39045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 39145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Handle RHS */ 39245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org switch (e->terms[1].type) { 39345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_SYM: 39445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->wrt) 39545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 39645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->wrt = e->terms[1].data.sym; 39745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* and drop the WRT portion */ 39845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->op = YASM_EXPR_IDENT; 39945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->numterms = 1; 40045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 40145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_REG: 40245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; /* ignore */ 40345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org default: 40445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 40545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 40645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 40745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Handle LHS */ 40845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org switch (e->terms[0].type) { 40945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_SYM: 41045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->rel || ssym_not_ok) 41145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 41245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->rel = e->terms[0].data.sym; 41345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* and replace with 0 */ 41445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[0].type = YASM_EXPR_INT; 41545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[0].data.intn = yasm_intnum_create_uint(0); 41645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 41745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_EXPR: 41845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* recurse */ 41945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return value_finalize_scan(value, e->terms[0].data.expn, 42045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org expr_precbc, ssym_not_ok); 42145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org default: 42245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; /* ignore */ 42345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 42445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 42545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 42645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org default: 42745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Single symrec not allowed anywhere */ 42845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<e->numterms; i++) { 42945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org switch (e->terms[i].type) { 43045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_SYM: 43145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 43245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_EXPR: 43345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* recurse */ 43445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return value_finalize_scan(value, 43545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[i].data.expn, 43645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org expr_precbc, 1); 43745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org default: 43845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 43945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 44045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 44145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 44245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 44345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 44445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 44545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 44645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 44745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgint 44845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_value_finalize_expr(yasm_value *value, yasm_expr *e, 44945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_bytecode *precbc, unsigned int size) 45045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 45145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!e) { 45245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_value_initialize(value, NULL, size); 45345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 45445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 455d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org yasm_value_initialize(value, e, size); 456d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org return yasm_value_finalize(value, precbc); 457d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org} 458d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org 459d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.orgint 460d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.orgyasm_value_finalize(yasm_value *value, yasm_bytecode *precbc) 461d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org{ 462d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org if (!value->abs) 463d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org return 0; 46445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 465d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL); 46645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 46745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* quit early if there was an issue in simplify() */ 46845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (yasm_error_occurred()) 46945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 47045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 47145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Strip top-level AND masking to an all-1s mask the same size 47245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * of the value size. This allows forced avoidance of overflow warnings. 47345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 47445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->abs->op == YASM_EXPR_AND) { 47545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int term; 47645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 47745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Calculate 1<<size - 1 value */ 47845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum *mask = yasm_intnum_create_uint(1); 47945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum *mask_tmp = yasm_intnum_create_uint(value->size); 48045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_calc(mask, YASM_EXPR_SHL, mask_tmp); 48145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_set_uint(mask_tmp, 1); 48245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_calc(mask, YASM_EXPR_SUB, mask_tmp); 48345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_destroy(mask_tmp); 48445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 48545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Walk terms and delete matching masks */ 48645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (term=value->abs->numterms-1; term>=0; term--) { 48745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->abs->terms[term].type == YASM_EXPR_INT && 48845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_compare(value->abs->terms[term].data.intn, 48945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org mask) == 0) { 49045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Delete the intnum */ 49145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_destroy(value->abs->terms[term].data.intn); 49245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 49345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Slide everything to its right over by 1 */ 49445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (term != value->abs->numterms-1) /* if it wasn't last.. */ 49545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org memmove(&value->abs->terms[term], 49645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org &value->abs->terms[term+1], 49745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (value->abs->numterms-1-term)* 49845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sizeof(yasm_expr__item)); 49945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 50045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Update numterms */ 50145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->abs->numterms--; 50245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 50345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Indicate warnings have been disabled */ 50445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->no_warn = 1; 50545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 50645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 50745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->abs->numterms == 1) 50845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->abs->op = YASM_EXPR_IDENT; 50945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_destroy(mask); 51045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 51145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 51245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Handle trivial (IDENT) cases immediately */ 51345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->abs->op == YASM_EXPR_IDENT) { 51445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org switch (value->abs->terms[0].type) { 51545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_INT: 51645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (yasm_intnum_is_zero(value->abs->terms[0].data.intn)) { 51745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_destroy(value->abs); 51845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->abs = NULL; 51945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 52045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 52145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_REG: 52245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_FLOAT: 52345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 52445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_SYM: 52545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->rel = value->abs->terms[0].data.sym; 52645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_destroy(value->abs); 52745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->abs = NULL; 52845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 52945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case YASM_EXPR_EXPR: 53045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Bring up lower values. */ 53145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org while (value->abs->op == YASM_EXPR_IDENT 53245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org && value->abs->terms[0].type == YASM_EXPR_EXPR) { 53345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr *sube = value->abs->terms[0].data.expn; 53445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_xfree(value->abs); 53545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->abs = sube; 53645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 53745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 53845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org default: 53945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_internal_error(N_("unexpected expr term type")); 54045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 54145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 54245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 54345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value_finalize_scan(value, value->abs, precbc, 0)) 54445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 54545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 54645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL); 54745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 54845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Simplify 0 in abs to NULL */ 54945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->abs->op == YASM_EXPR_IDENT 55045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org && value->abs->terms[0].type == YASM_EXPR_INT 55145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org && yasm_intnum_is_zero(value->abs->terms[0].data.intn)) { 55245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_destroy(value->abs); 55345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->abs = NULL; 55445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 55545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 55645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 55745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 55845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_intnum * 55945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_value_get_intnum(yasm_value *value, yasm_bytecode *bc, int calc_bc_dist) 56045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 56145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@dependent@*/ /*@null@*/ yasm_intnum *intn = NULL; 56245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@only@*/ yasm_intnum *outval; 56345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int sym_local; 56445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 56545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->abs) { 56645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Handle integer expressions, if non-integer or too complex, return 56745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * NULL. 56845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 56945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org intn = yasm_expr_get_intnum(&value->abs, calc_bc_dist); 57045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!intn) 57145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return NULL; 57245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 57345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 57445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->rel) { 57545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* If relative portion is not in bc section, return NULL. 57645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Otherwise get the relative portion's offset. 57745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 57845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@dependent@*/ yasm_bytecode *rel_prevbc; 57945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned long dist; 58045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 58145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!bc) 58245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return NULL; /* Can't calculate relative value */ 58345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 58445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sym_local = yasm_symrec_get_label(value->rel, &rel_prevbc); 58545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->wrt || value->seg_of || value->section_rel || !sym_local) 58645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return NULL; /* we can't handle SEG, WRT, or external symbols */ 58745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (rel_prevbc->section != bc->section) 58845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return NULL; /* not in this section */ 58945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!value->curpos_rel) 59045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return NULL; /* not PC-relative */ 59145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 59245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Calculate value relative to current assembly position */ 59345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org dist = yasm_bc_next_offset(rel_prevbc); 59445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (dist < bc->offset) { 59545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org outval = yasm_intnum_create_uint(bc->offset - dist); 59645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_calc(outval, YASM_EXPR_NEG, NULL); 59745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else { 59845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org dist -= bc->offset; 59945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org outval = yasm_intnum_create_uint(dist); 60045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 60145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 60245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->rshift > 0) { 60345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@only@*/ yasm_intnum *shamt = 60445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_create_uint((unsigned long)value->rshift); 60545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_calc(outval, YASM_EXPR_SHR, shamt); 60645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_destroy(shamt); 60745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 60845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Add in absolute portion */ 60945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (intn) 61045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_calc(outval, YASM_EXPR_ADD, intn); 61145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return outval; 61245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 61345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 61445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (intn) 61545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return yasm_intnum_copy(intn); 61645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 61745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* No absolute or relative portions: output 0 */ 61845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return yasm_intnum_create_uint(0); 61945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 62045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 62145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgint 62245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_value_output_basic(yasm_value *value, /*@out@*/ unsigned char *buf, 62345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org size_t destsize, yasm_bytecode *bc, int warn, 62445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_arch *arch) 62545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 62645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@dependent@*/ /*@null@*/ yasm_intnum *intn = NULL; 62745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@only@*/ yasm_intnum *outval; 62845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int sym_local; 62945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int retval = 1; 63045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned int valsize = value->size; 63145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 63245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->no_warn) 63345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org warn = 0; 63445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 63545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->abs) { 63645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Handle floating point expressions */ 63745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!value->rel && value->abs->op == YASM_EXPR_IDENT 63845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org && value->abs->terms[0].type == YASM_EXPR_FLOAT) { 63945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (yasm_arch_floatnum_tobytes(arch, value->abs->terms[0].data.flt, 64045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org buf, destsize, valsize, 0, warn)) 64145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return -1; 64245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else 64345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 64445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 64545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 64645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Check for complex float expressions */ 64745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (yasm_expr__contains(value->abs, YASM_EXPR_FLOAT)) { 64845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_error_set(YASM_ERROR_FLOATING_POINT, 64945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org N_("floating point expression too complex")); 65045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return -1; 65145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 65245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 65345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Handle normal integer expressions */ 65445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org intn = yasm_expr_get_intnum(&value->abs, 1); 65545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 65645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!intn) { 65745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Second try before erroring: yasm_expr_get_intnum doesn't handle 65845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * SEG:OFF, so try simplifying out any to just the OFF portion, 65945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * then getting the intnum again. 66045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 66145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr *seg = yasm_expr_extract_deep_segoff(&value->abs); 66245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (seg) 66345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_destroy(seg); 66445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org intn = yasm_expr_get_intnum(&value->abs, 1); 66545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 66645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 66745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!intn) { 66845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Still don't have an integer! */ 66945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_error_set(YASM_ERROR_TOO_COMPLEX, 67045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org N_("expression too complex")); 67145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return -1; 67245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 67345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 67445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 67545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Adjust warn for signed/unsigned integer warnings */ 67645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (warn != 0) 67745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org warn = value->sign ? -1 : 1; 67845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 67945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->rel) { 68045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* If relative portion is not in bc section, don't try to handle it 68145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * here. Otherwise get the relative portion's offset. 68245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 68345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@dependent@*/ yasm_bytecode *rel_prevbc; 68445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned long dist; 68545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 68645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org sym_local = yasm_symrec_get_label(value->rel, &rel_prevbc); 68745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->wrt || value->seg_of || value->section_rel || !sym_local) 68845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; /* we can't handle SEG, WRT, or external symbols */ 68945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (rel_prevbc->section != bc->section) 69045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; /* not in this section */ 69145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!value->curpos_rel) 69245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; /* not PC-relative */ 69345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 69445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Calculate value relative to current assembly position */ 69545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org dist = yasm_bc_next_offset(rel_prevbc); 69645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (dist < bc->offset) { 69745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org outval = yasm_intnum_create_uint(bc->offset - dist); 69845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_calc(outval, YASM_EXPR_NEG, NULL); 69945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else { 70045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org dist -= bc->offset; 70145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org outval = yasm_intnum_create_uint(dist); 70245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 70345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 70445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->rshift > 0) { 70545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@only@*/ yasm_intnum *shamt = 70645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_create_uint((unsigned long)value->rshift); 70745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_calc(outval, YASM_EXPR_SHR, shamt); 70845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_destroy(shamt); 70945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 71045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Add in absolute portion */ 71145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (intn) 71245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_calc(outval, YASM_EXPR_ADD, intn); 71345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Output! */ 71445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (yasm_arch_intnum_tobytes(arch, outval, buf, destsize, valsize, 0, 71545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc, warn)) 71645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org retval = -1; 71745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_destroy(outval); 71845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return retval; 71945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 72045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 72145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->seg_of || value->rshift || value->curpos_rel || value->ip_rel 72245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org || value->section_rel) 72345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; /* We can't handle this with just an absolute */ 72445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 72545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (intn) { 72645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Output just absolute portion */ 72745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (yasm_arch_intnum_tobytes(arch, intn, buf, destsize, valsize, 0, bc, 72845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org warn)) 72945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org retval = -1; 73045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else { 73145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* No absolute or relative portions: output 0 */ 73245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org outval = yasm_intnum_create_uint(0); 73345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (yasm_arch_intnum_tobytes(arch, outval, buf, destsize, valsize, 0, 73445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc, warn)) 73545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org retval = -1; 73645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_destroy(outval); 73745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 73845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return retval; 73945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 74045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 74145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid 74245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_value_print(const yasm_value *value, FILE *f, int indent_level) 74345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 74445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*s%u-bit, %ssigned", indent_level, "", value->size, 74545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->sign ? "" : "un"); 74645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*sAbsolute portion=", indent_level, ""); 74745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_print(value->abs, f); 74845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "\n"); 74945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->rel) { 75045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*sRelative to=%s%s\n", indent_level, "", 75145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->seg_of ? "SEG " : "", 75245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_symrec_get_name(value->rel)); 75345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->wrt) 75445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*s(With respect to=%s)\n", indent_level, "", 75545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_symrec_get_name(value->wrt)); 75645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->rshift > 0) 75745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*s(Right shifted by=%u)\n", indent_level, "", 75845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org value->rshift); 75945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->curpos_rel) 76045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*s(Relative to current position)\n", indent_level, 76145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ""); 76245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->ip_rel) 76345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*s(IP-relative)\n", indent_level, ""); 76445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->jump_target) 76545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*s(Jump target)\n", indent_level, ""); 76645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->section_rel) 76745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*s(Section-relative)\n", indent_level, ""); 76845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (value->no_warn) 76945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*s(Overflow warnings disabled)\n", indent_level, ""); 77045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 77145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 772