1 /* 2 * Value handling 3 * 4 * Copyright (C) 2006-2007 Peter Johnson 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 #include "util.h" 28 29 #include "libyasm-stdint.h" 30 #include "coretype.h" 31 #include "bitvect.h" 32 33 #include "errwarn.h" 34 #include "intnum.h" 35 #include "floatnum.h" 36 #include "expr.h" 37 #include "value.h" 38 #include "symrec.h" 39 40 #include "bytecode.h" 41 #include "section.h" 42 43 #include "arch.h" 44 45 46 void 47 yasm_value_initialize(/*@out@*/ yasm_value *value, 48 /*@null@*/ /*@kept@*/ yasm_expr *e, unsigned int size) 49 { 50 value->abs = e; 51 value->rel = NULL; 52 value->wrt = NULL; 53 value->seg_of = 0; 54 value->rshift = 0; 55 value->curpos_rel = 0; 56 value->ip_rel = 0; 57 value->jump_target = 0; 58 value->section_rel = 0; 59 value->no_warn = 0; 60 value->sign = 0; 61 value->size = size; 62 } 63 64 void 65 yasm_value_init_sym(/*@out@*/ yasm_value *value, /*@null@*/ yasm_symrec *sym, 66 unsigned int size) 67 { 68 value->abs = NULL; 69 value->rel = sym; 70 value->wrt = NULL; 71 value->seg_of = 0; 72 value->rshift = 0; 73 value->curpos_rel = 0; 74 value->ip_rel = 0; 75 value->jump_target = 0; 76 value->section_rel = 0; 77 value->no_warn = 0; 78 value->sign = 0; 79 value->size = size; 80 } 81 82 void 83 yasm_value_init_copy(yasm_value *value, const yasm_value *orig) 84 { 85 value->abs = orig->abs ? yasm_expr_copy(orig->abs) : NULL; 86 value->rel = orig->rel; 87 value->wrt = orig->wrt; 88 value->seg_of = orig->seg_of; 89 value->rshift = orig->rshift; 90 value->curpos_rel = orig->curpos_rel; 91 value->ip_rel = orig->ip_rel; 92 value->jump_target = orig->jump_target; 93 value->section_rel = orig->section_rel; 94 value->no_warn = orig->no_warn; 95 value->sign = orig->sign; 96 value->size = orig->size; 97 } 98 99 void 100 yasm_value_delete(yasm_value *value) 101 { 102 if (value->abs) 103 yasm_expr_destroy(value->abs); 104 value->abs = NULL; 105 value->rel = NULL; 106 } 107 108 void 109 yasm_value_set_curpos_rel(yasm_value *value, yasm_bytecode *bc, 110 unsigned int ip_rel) 111 { 112 value->curpos_rel = 1; 113 value->ip_rel = ip_rel; 114 /* In order for us to correctly output curpos-relative values, we must 115 * have a relative portion of the value. If one doesn't exist, point 116 * to a custom absolute symbol. 117 */ 118 if (!value->rel) { 119 yasm_object *object = yasm_section_get_object(yasm_bc_get_section(bc)); 120 value->rel = yasm_symtab_abs_sym(object->symtab); 121 } 122 } 123 124 static int 125 value_finalize_scan(yasm_value *value, yasm_expr *e, 126 /*@null@*/ yasm_bytecode *expr_precbc, int ssym_not_ok) 127 { 128 int i; 129 /*@dependent@*/ yasm_section *sect; 130 /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc; 131 132 unsigned long shamt; /* for SHR */ 133 134 /* Yes, this has a maximum upper bound on 32 terms, based on an 135 * "insane number of terms" (and ease of implementation) WAG. 136 * The right way to do this would be a stack-based alloca, but that's 137 * not ISO C. We really don't want to malloc here as this function is 138 * hit a lot! 139 * 140 * This is a bitmask to keep things small, as this is a recursive 141 * routine and we don't want to eat up stack space. 142 */ 143 unsigned long used; /* for ADD */ 144 145 /* Thanks to this running after a simplify, we don't need to iterate 146 * down through IDENTs or handle SUB. 147 * 148 * We scan for a single symrec, gathering info along the way. After 149 * we've found the symrec, we keep scanning but error if we find 150 * another one. We pull out the single symrec and any legal operations 151 * performed on it. 152 * 153 * Also, if we find a float anywhere, we don't allow mixing of a single 154 * symrec with it. 155 */ 156 switch (e->op) { 157 case YASM_EXPR_ADD: 158 /* Okay for single symrec anywhere in expr. 159 * Check for single symrec anywhere. 160 * Handle symrec-symrec by checking for (-1*symrec) 161 * and symrec term pairs (where both symrecs are in the same 162 * segment). 163 */ 164 if (e->numterms > 32) 165 yasm__fatal(N_("expression on line %d has too many add terms;" 166 " internal limit of 32"), e->line); 167 168 used = 0; 169 170 for (i=0; i<e->numterms; i++) { 171 int j; 172 yasm_expr *sube; 173 yasm_intnum *intn; 174 yasm_symrec *sym; 175 /*@dependent@*/ yasm_section *sect2; 176 /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc2; 177 178 /* First look for an (-1*symrec) term */ 179 if (e->terms[i].type != YASM_EXPR_EXPR) 180 continue; 181 sube = e->terms[i].data.expn; 182 183 if (sube->op != YASM_EXPR_MUL || sube->numterms != 2) { 184 /* recurse instead */ 185 if (value_finalize_scan(value, sube, expr_precbc, 186 ssym_not_ok)) 187 return 1; 188 continue; 189 } 190 191 if (sube->terms[0].type == YASM_EXPR_INT && 192 sube->terms[1].type == YASM_EXPR_SYM) { 193 intn = sube->terms[0].data.intn; 194 sym = sube->terms[1].data.sym; 195 } else if (sube->terms[0].type == YASM_EXPR_SYM && 196 sube->terms[1].type == YASM_EXPR_INT) { 197 sym = sube->terms[0].data.sym; 198 intn = sube->terms[1].data.intn; 199 } else { 200 if (value_finalize_scan(value, sube, expr_precbc, 201 ssym_not_ok)) 202 return 1; 203 continue; 204 } 205 206 if (!yasm_intnum_is_neg1(intn)) { 207 if (value_finalize_scan(value, sube, expr_precbc, 208 ssym_not_ok)) 209 return 1; 210 continue; 211 } 212 213 /* Look for the same symrec term; even if both are external, 214 * they should cancel out. 215 */ 216 for (j=0; j<e->numterms; j++) { 217 if (e->terms[j].type == YASM_EXPR_SYM 218 && e->terms[j].data.sym == sym 219 && (used & (1<<j)) == 0) { 220 /* Mark as used */ 221 used |= 1<<j; 222 223 /* Replace both symrec portions with 0 */ 224 yasm_expr_destroy(sube); 225 e->terms[i].type = YASM_EXPR_INT; 226 e->terms[i].data.intn = yasm_intnum_create_uint(0); 227 e->terms[j].type = YASM_EXPR_INT; 228 e->terms[j].data.intn = yasm_intnum_create_uint(0); 229 230 break; /* stop looking */ 231 } 232 } 233 if (j != e->numterms) 234 continue; 235 236 if (!yasm_symrec_get_label(sym, &precbc)) { 237 if (value_finalize_scan(value, sube, expr_precbc, 238 ssym_not_ok)) 239 return 1; 240 continue; 241 } 242 sect2 = yasm_bc_get_section(precbc); 243 244 /* Now look for a unused symrec term in the same segment */ 245 for (j=0; j<e->numterms; j++) { 246 if (e->terms[j].type == YASM_EXPR_SYM 247 && yasm_symrec_get_label(e->terms[j].data.sym, 248 &precbc2) 249 && (sect = yasm_bc_get_section(precbc2)) 250 && sect == sect2 251 && (used & (1<<j)) == 0) { 252 /* Mark as used */ 253 used |= 1<<j; 254 break; /* stop looking */ 255 } 256 } 257 258 /* We didn't match in the same segment. If the 259 * -1*symrec is actually -1*curpos, we can match 260 * unused symrec terms in other segments and generate 261 * a curpos-relative reloc. 262 * 263 * Similarly, handle -1*symrec in other segment via the 264 * following transformation: 265 * other-this = (other-.)+(.-this) 266 * We can only do this transformation if "this" is in 267 * this expr's segment. 268 * 269 * Don't do this if we've already become curpos-relative. 270 * The unmatched symrec will be caught below. 271 */ 272 if (j == e->numterms && !value->curpos_rel 273 && (yasm_symrec_is_curpos(sym) 274 || (expr_precbc 275 && sect2 == yasm_bc_get_section(expr_precbc)))) { 276 for (j=0; j<e->numterms; j++) { 277 if (e->terms[j].type == YASM_EXPR_SYM 278 && !yasm_symrec_get_equ(e->terms[j].data.sym) 279 && !yasm_symrec_is_special(e->terms[j].data.sym) 280 && (used & (1<<j)) == 0) { 281 /* Mark as used */ 282 used |= 1<<j; 283 /* Mark value as curpos-relative */ 284 if (value->rel || ssym_not_ok) 285 return 1; 286 value->rel = e->terms[j].data.sym; 287 value->curpos_rel = 1; 288 if (yasm_symrec_is_curpos(sym)) { 289 /* Replace both symrec portions with 0 */ 290 yasm_expr_destroy(sube); 291 e->terms[i].type = YASM_EXPR_INT; 292 e->terms[i].data.intn = 293 yasm_intnum_create_uint(0); 294 e->terms[j].type = YASM_EXPR_INT; 295 e->terms[j].data.intn = 296 yasm_intnum_create_uint(0); 297 } else { 298 /* Replace positive portion with curpos */ 299 yasm_object *object = 300 yasm_section_get_object(sect2); 301 yasm_symtab *symtab = object->symtab; 302 e->terms[j].data.sym = 303 yasm_symtab_define_curpos 304 (symtab, ".", expr_precbc, e->line); 305 } 306 break; /* stop looking */ 307 } 308 } 309 } 310 311 312 if (j == e->numterms) 313 return 1; /* We didn't find a match! */ 314 } 315 316 /* Look for unmatched symrecs. If we've already found one or 317 * we don't WANT to find one, error out. 318 */ 319 for (i=0; i<e->numterms; i++) { 320 if (e->terms[i].type == YASM_EXPR_SYM 321 && (used & (1<<i)) == 0) { 322 if (value->rel || ssym_not_ok) 323 return 1; 324 value->rel = e->terms[i].data.sym; 325 /* and replace with 0 */ 326 e->terms[i].type = YASM_EXPR_INT; 327 e->terms[i].data.intn = yasm_intnum_create_uint(0); 328 } 329 } 330 break; 331 case YASM_EXPR_SHR: 332 /* Okay for single symrec in LHS and constant on RHS. 333 * Single symrecs are not okay on RHS. 334 * If RHS is non-constant, don't allow single symrec on LHS. 335 * XXX: should rshift be an expr instead?? 336 */ 337 338 /* Check for single sym on LHS */ 339 if (e->terms[0].type != YASM_EXPR_SYM) 340 break; 341 342 /* If we already have a sym, we can't take another one */ 343 if (value->rel || ssym_not_ok) 344 return 1; 345 346 /* RHS must be a positive integer */ 347 if (e->terms[1].type != YASM_EXPR_INT) 348 return 1; /* can't shift sym by non-constant integer */ 349 shamt = yasm_intnum_get_uint(e->terms[1].data.intn); 350 if ((shamt + value->rshift) > YASM_VALUE_RSHIFT_MAX) 351 return 1; /* total shift would be too large */ 352 353 /* Update value */ 354 value->rshift += shamt; 355 value->rel = e->terms[0].data.sym; 356 357 /* Replace symbol with 0 */ 358 e->terms[0].type = YASM_EXPR_INT; 359 e->terms[0].data.intn = yasm_intnum_create_uint(0); 360 361 /* Just leave SHR in place */ 362 break; 363 case YASM_EXPR_SEG: 364 /* Okay for single symrec (can only be done once). 365 * Not okay for anything BUT a single symrec as an immediate 366 * child. 367 */ 368 if (e->terms[0].type != YASM_EXPR_SYM) 369 return 1; 370 371 if (value->seg_of) 372 return 1; /* multiple SEG not legal */ 373 value->seg_of = 1; 374 375 if (value->rel || ssym_not_ok) 376 return 1; /* got a relative portion somewhere else? */ 377 value->rel = e->terms[0].data.sym; 378 379 /* replace with ident'ed 0 */ 380 e->op = YASM_EXPR_IDENT; 381 e->terms[0].type = YASM_EXPR_INT; 382 e->terms[0].data.intn = yasm_intnum_create_uint(0); 383 break; 384 case YASM_EXPR_WRT: 385 /* Okay for single symrec in LHS and either a register or single 386 * symrec (as an immediate child) on RHS. 387 * If a single symrec on RHS, can only be done once. 388 * WRT reg is left in expr for arch to look at. 389 */ 390 391 /* Handle RHS */ 392 switch (e->terms[1].type) { 393 case YASM_EXPR_SYM: 394 if (value->wrt) 395 return 1; 396 value->wrt = e->terms[1].data.sym; 397 /* and drop the WRT portion */ 398 e->op = YASM_EXPR_IDENT; 399 e->numterms = 1; 400 break; 401 case YASM_EXPR_REG: 402 break; /* ignore */ 403 default: 404 return 1; 405 } 406 407 /* Handle LHS */ 408 switch (e->terms[0].type) { 409 case YASM_EXPR_SYM: 410 if (value->rel || ssym_not_ok) 411 return 1; 412 value->rel = e->terms[0].data.sym; 413 /* and replace with 0 */ 414 e->terms[0].type = YASM_EXPR_INT; 415 e->terms[0].data.intn = yasm_intnum_create_uint(0); 416 break; 417 case YASM_EXPR_EXPR: 418 /* recurse */ 419 return value_finalize_scan(value, e->terms[0].data.expn, 420 expr_precbc, ssym_not_ok); 421 default: 422 break; /* ignore */ 423 } 424 425 break; 426 default: 427 /* Single symrec not allowed anywhere */ 428 for (i=0; i<e->numterms; i++) { 429 switch (e->terms[i].type) { 430 case YASM_EXPR_SYM: 431 return 1; 432 case YASM_EXPR_EXPR: 433 /* recurse */ 434 return value_finalize_scan(value, 435 e->terms[i].data.expn, 436 expr_precbc, 1); 437 default: 438 break; 439 } 440 } 441 break; 442 } 443 444 return 0; 445 } 446 447 int 448 yasm_value_finalize_expr(yasm_value *value, yasm_expr *e, 449 yasm_bytecode *precbc, unsigned int size) 450 { 451 if (!e) { 452 yasm_value_initialize(value, NULL, size); 453 return 0; 454 } 455 yasm_value_initialize(value, e, size); 456 return yasm_value_finalize(value, precbc); 457 } 458 459 int 460 yasm_value_finalize(yasm_value *value, yasm_bytecode *precbc) 461 { 462 if (!value->abs) 463 return 0; 464 465 value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL); 466 467 /* quit early if there was an issue in simplify() */ 468 if (yasm_error_occurred()) 469 return 1; 470 471 /* Strip top-level AND masking to an all-1s mask the same size 472 * of the value size. This allows forced avoidance of overflow warnings. 473 */ 474 if (value->abs->op == YASM_EXPR_AND) { 475 int term; 476 477 /* Calculate 1<<size - 1 value */ 478 yasm_intnum *mask = yasm_intnum_create_uint(1); 479 yasm_intnum *mask_tmp = yasm_intnum_create_uint(value->size); 480 yasm_intnum_calc(mask, YASM_EXPR_SHL, mask_tmp); 481 yasm_intnum_set_uint(mask_tmp, 1); 482 yasm_intnum_calc(mask, YASM_EXPR_SUB, mask_tmp); 483 yasm_intnum_destroy(mask_tmp); 484 485 /* Walk terms and delete matching masks */ 486 for (term=value->abs->numterms-1; term>=0; term--) { 487 if (value->abs->terms[term].type == YASM_EXPR_INT && 488 yasm_intnum_compare(value->abs->terms[term].data.intn, 489 mask) == 0) { 490 /* Delete the intnum */ 491 yasm_intnum_destroy(value->abs->terms[term].data.intn); 492 493 /* Slide everything to its right over by 1 */ 494 if (term != value->abs->numterms-1) /* if it wasn't last.. */ 495 memmove(&value->abs->terms[term], 496 &value->abs->terms[term+1], 497 (value->abs->numterms-1-term)* 498 sizeof(yasm_expr__item)); 499 500 /* Update numterms */ 501 value->abs->numterms--; 502 503 /* Indicate warnings have been disabled */ 504 value->no_warn = 1; 505 } 506 } 507 if (value->abs->numterms == 1) 508 value->abs->op = YASM_EXPR_IDENT; 509 yasm_intnum_destroy(mask); 510 } 511 512 /* Handle trivial (IDENT) cases immediately */ 513 if (value->abs->op == YASM_EXPR_IDENT) { 514 switch (value->abs->terms[0].type) { 515 case YASM_EXPR_INT: 516 if (yasm_intnum_is_zero(value->abs->terms[0].data.intn)) { 517 yasm_expr_destroy(value->abs); 518 value->abs = NULL; 519 } 520 return 0; 521 case YASM_EXPR_REG: 522 case YASM_EXPR_FLOAT: 523 return 0; 524 case YASM_EXPR_SYM: 525 value->rel = value->abs->terms[0].data.sym; 526 yasm_expr_destroy(value->abs); 527 value->abs = NULL; 528 return 0; 529 case YASM_EXPR_EXPR: 530 /* Bring up lower values. */ 531 while (value->abs->op == YASM_EXPR_IDENT 532 && value->abs->terms[0].type == YASM_EXPR_EXPR) { 533 yasm_expr *sube = value->abs->terms[0].data.expn; 534 yasm_xfree(value->abs); 535 value->abs = sube; 536 } 537 break; 538 default: 539 yasm_internal_error(N_("unexpected expr term type")); 540 } 541 } 542 543 if (value_finalize_scan(value, value->abs, precbc, 0)) 544 return 1; 545 546 value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL); 547 548 /* Simplify 0 in abs to NULL */ 549 if (value->abs->op == YASM_EXPR_IDENT 550 && value->abs->terms[0].type == YASM_EXPR_INT 551 && yasm_intnum_is_zero(value->abs->terms[0].data.intn)) { 552 yasm_expr_destroy(value->abs); 553 value->abs = NULL; 554 } 555 return 0; 556 } 557 558 yasm_intnum * 559 yasm_value_get_intnum(yasm_value *value, yasm_bytecode *bc, int calc_bc_dist) 560 { 561 /*@dependent@*/ /*@null@*/ yasm_intnum *intn = NULL; 562 /*@only@*/ yasm_intnum *outval; 563 int sym_local; 564 565 if (value->abs) { 566 /* Handle integer expressions, if non-integer or too complex, return 567 * NULL. 568 */ 569 intn = yasm_expr_get_intnum(&value->abs, calc_bc_dist); 570 if (!intn) 571 return NULL; 572 } 573 574 if (value->rel) { 575 /* If relative portion is not in bc section, return NULL. 576 * Otherwise get the relative portion's offset. 577 */ 578 /*@dependent@*/ yasm_bytecode *rel_prevbc; 579 unsigned long dist; 580 581 if (!bc) 582 return NULL; /* Can't calculate relative value */ 583 584 sym_local = yasm_symrec_get_label(value->rel, &rel_prevbc); 585 if (value->wrt || value->seg_of || value->section_rel || !sym_local) 586 return NULL; /* we can't handle SEG, WRT, or external symbols */ 587 if (rel_prevbc->section != bc->section) 588 return NULL; /* not in this section */ 589 if (!value->curpos_rel) 590 return NULL; /* not PC-relative */ 591 592 /* Calculate value relative to current assembly position */ 593 dist = yasm_bc_next_offset(rel_prevbc); 594 if (dist < bc->offset) { 595 outval = yasm_intnum_create_uint(bc->offset - dist); 596 yasm_intnum_calc(outval, YASM_EXPR_NEG, NULL); 597 } else { 598 dist -= bc->offset; 599 outval = yasm_intnum_create_uint(dist); 600 } 601 602 if (value->rshift > 0) { 603 /*@only@*/ yasm_intnum *shamt = 604 yasm_intnum_create_uint((unsigned long)value->rshift); 605 yasm_intnum_calc(outval, YASM_EXPR_SHR, shamt); 606 yasm_intnum_destroy(shamt); 607 } 608 /* Add in absolute portion */ 609 if (intn) 610 yasm_intnum_calc(outval, YASM_EXPR_ADD, intn); 611 return outval; 612 } 613 614 if (intn) 615 return yasm_intnum_copy(intn); 616 617 /* No absolute or relative portions: output 0 */ 618 return yasm_intnum_create_uint(0); 619 } 620 621 int 622 yasm_value_output_basic(yasm_value *value, /*@out@*/ unsigned char *buf, 623 size_t destsize, yasm_bytecode *bc, int warn, 624 yasm_arch *arch) 625 { 626 /*@dependent@*/ /*@null@*/ yasm_intnum *intn = NULL; 627 /*@only@*/ yasm_intnum *outval; 628 int sym_local; 629 int retval = 1; 630 unsigned int valsize = value->size; 631 632 if (value->no_warn) 633 warn = 0; 634 635 if (value->abs) { 636 /* Handle floating point expressions */ 637 if (!value->rel && value->abs->op == YASM_EXPR_IDENT 638 && value->abs->terms[0].type == YASM_EXPR_FLOAT) { 639 if (yasm_arch_floatnum_tobytes(arch, value->abs->terms[0].data.flt, 640 buf, destsize, valsize, 0, warn)) 641 return -1; 642 else 643 return 1; 644 } 645 646 /* Check for complex float expressions */ 647 if (yasm_expr__contains(value->abs, YASM_EXPR_FLOAT)) { 648 yasm_error_set(YASM_ERROR_FLOATING_POINT, 649 N_("floating point expression too complex")); 650 return -1; 651 } 652 653 /* Handle normal integer expressions */ 654 intn = yasm_expr_get_intnum(&value->abs, 1); 655 656 if (!intn) { 657 /* Second try before erroring: yasm_expr_get_intnum doesn't handle 658 * SEG:OFF, so try simplifying out any to just the OFF portion, 659 * then getting the intnum again. 660 */ 661 yasm_expr *seg = yasm_expr_extract_deep_segoff(&value->abs); 662 if (seg) 663 yasm_expr_destroy(seg); 664 intn = yasm_expr_get_intnum(&value->abs, 1); 665 } 666 667 if (!intn) { 668 /* Still don't have an integer! */ 669 yasm_error_set(YASM_ERROR_TOO_COMPLEX, 670 N_("expression too complex")); 671 return -1; 672 } 673 } 674 675 /* Adjust warn for signed/unsigned integer warnings */ 676 if (warn != 0) 677 warn = value->sign ? -1 : 1; 678 679 if (value->rel) { 680 /* If relative portion is not in bc section, don't try to handle it 681 * here. Otherwise get the relative portion's offset. 682 */ 683 /*@dependent@*/ yasm_bytecode *rel_prevbc; 684 unsigned long dist; 685 686 sym_local = yasm_symrec_get_label(value->rel, &rel_prevbc); 687 if (value->wrt || value->seg_of || value->section_rel || !sym_local) 688 return 0; /* we can't handle SEG, WRT, or external symbols */ 689 if (rel_prevbc->section != bc->section) 690 return 0; /* not in this section */ 691 if (!value->curpos_rel) 692 return 0; /* not PC-relative */ 693 694 /* Calculate value relative to current assembly position */ 695 dist = yasm_bc_next_offset(rel_prevbc); 696 if (dist < bc->offset) { 697 outval = yasm_intnum_create_uint(bc->offset - dist); 698 yasm_intnum_calc(outval, YASM_EXPR_NEG, NULL); 699 } else { 700 dist -= bc->offset; 701 outval = yasm_intnum_create_uint(dist); 702 } 703 704 if (value->rshift > 0) { 705 /*@only@*/ yasm_intnum *shamt = 706 yasm_intnum_create_uint((unsigned long)value->rshift); 707 yasm_intnum_calc(outval, YASM_EXPR_SHR, shamt); 708 yasm_intnum_destroy(shamt); 709 } 710 /* Add in absolute portion */ 711 if (intn) 712 yasm_intnum_calc(outval, YASM_EXPR_ADD, intn); 713 /* Output! */ 714 if (yasm_arch_intnum_tobytes(arch, outval, buf, destsize, valsize, 0, 715 bc, warn)) 716 retval = -1; 717 yasm_intnum_destroy(outval); 718 return retval; 719 } 720 721 if (value->seg_of || value->rshift || value->curpos_rel || value->ip_rel 722 || value->section_rel) 723 return 0; /* We can't handle this with just an absolute */ 724 725 if (intn) { 726 /* Output just absolute portion */ 727 if (yasm_arch_intnum_tobytes(arch, intn, buf, destsize, valsize, 0, bc, 728 warn)) 729 retval = -1; 730 } else { 731 /* No absolute or relative portions: output 0 */ 732 outval = yasm_intnum_create_uint(0); 733 if (yasm_arch_intnum_tobytes(arch, outval, buf, destsize, valsize, 0, 734 bc, warn)) 735 retval = -1; 736 yasm_intnum_destroy(outval); 737 } 738 return retval; 739 } 740 741 void 742 yasm_value_print(const yasm_value *value, FILE *f, int indent_level) 743 { 744 fprintf(f, "%*s%u-bit, %ssigned", indent_level, "", value->size, 745 value->sign ? "" : "un"); 746 fprintf(f, "%*sAbsolute portion=", indent_level, ""); 747 yasm_expr_print(value->abs, f); 748 fprintf(f, "\n"); 749 if (value->rel) { 750 fprintf(f, "%*sRelative to=%s%s\n", indent_level, "", 751 value->seg_of ? "SEG " : "", 752 yasm_symrec_get_name(value->rel)); 753 if (value->wrt) 754 fprintf(f, "%*s(With respect to=%s)\n", indent_level, "", 755 yasm_symrec_get_name(value->wrt)); 756 if (value->rshift > 0) 757 fprintf(f, "%*s(Right shifted by=%u)\n", indent_level, "", 758 value->rshift); 759 if (value->curpos_rel) 760 fprintf(f, "%*s(Relative to current position)\n", indent_level, 761 ""); 762 if (value->ip_rel) 763 fprintf(f, "%*s(IP-relative)\n", indent_level, ""); 764 if (value->jump_target) 765 fprintf(f, "%*s(Jump target)\n", indent_level, ""); 766 if (value->section_rel) 767 fprintf(f, "%*s(Section-relative)\n", indent_level, ""); 768 if (value->no_warn) 769 fprintf(f, "%*s(Overflow warnings disabled)\n", indent_level, ""); 770 } 771 } 772