1/* tc-ft32.c -- Assemble code for ft32 2 Copyright (C) 2008-2020 Free Software Foundation, Inc. 3 4 This file is part of GAS, the GNU Assembler. 5 6 GAS is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3, or (at your option) 9 any later version. 10 11 GAS is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GAS; see the file COPYING. If not, write to 18 the Free Software Foundation, 51 Franklin Street - Fifth Floor, 19 Boston, MA 02110-1301, USA. */ 20 21/* Contributed by Anthony Green <green@spindazzle.org>. */ 22 23#include "as.h" 24#include "safe-ctype.h" 25#include "opcode/ft32.h" 26 27extern const ft32_opc_info_t ft32_opc_info[128]; 28 29/* See md_parse_option() for meanings of these options. */ 30static char norelax; /* True if -norelax switch seen. */ 31 32const char comment_chars[] = "#"; 33const char line_separator_chars[] = ";"; 34const char line_comment_chars[] = "#"; 35 36static int pending_reloc; 37static htab_t opcode_hash_control; 38 39static valueT md_chars_to_number (char * buf, int n); 40 41const pseudo_typeS md_pseudo_table[] = 42{ 43 {0, 0, 0} 44}; 45 46const char FLT_CHARS[] = "rRsSfFdDxXpP"; 47const char EXP_CHARS[] = "eE"; 48 49/* This function is called once, at assembler startup time. It sets 50 up the hash table with all the opcodes in it, and also initializes 51 some aliases for compatibility with other assemblers. */ 52 53void 54md_begin (void) 55{ 56 const ft32_opc_info_t *opcode; 57 opcode_hash_control = str_htab_create (); 58 59 /* Insert names into hash table. */ 60 for (opcode = ft32_opc_info; opcode->name; opcode++) 61 str_hash_insert (opcode_hash_control, opcode->name, opcode, 0); 62 63 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0); 64 if (!norelax) 65 linkrelax = 1; 66} 67 68/* Parse an expression and then restore the input line pointer. */ 69 70static char * 71parse_exp_save_ilp (char *s, expressionS *op) 72{ 73 char *save = input_line_pointer; 74 75 input_line_pointer = s; 76 expression (op); 77 s = input_line_pointer; 78 input_line_pointer = save; 79 return s; 80} 81 82static int 83parse_condition (char **ptr) 84{ 85 char *s = *ptr; 86 static const struct 87 { 88 const char *name; 89 int bits; 90 } 91 ccs[] = 92 { 93 { "gt," , (2 << FT32_FLD_CR_BIT) | (5 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)}, 94 { "gte," , (2 << FT32_FLD_CR_BIT) | (4 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)}, 95 { "lt," , (2 << FT32_FLD_CR_BIT) | (4 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)}, 96 { "lte," , (2 << FT32_FLD_CR_BIT) | (5 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)}, 97 { "a," , (2 << FT32_FLD_CR_BIT) | (6 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)}, 98 { "ae," , (2 << FT32_FLD_CR_BIT) | (1 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)}, 99 { "be," , (2 << FT32_FLD_CR_BIT) | (6 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)}, 100 { "b," , (2 << FT32_FLD_CR_BIT) | (1 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)}, 101 { "nz," , (2 << FT32_FLD_CR_BIT) | (0 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)}, 102 { "z," , (2 << FT32_FLD_CR_BIT) | (0 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)}, 103 { "nc," , (2 << FT32_FLD_CR_BIT) | (1 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)}, 104 { "c," , (2 << FT32_FLD_CR_BIT) | (1 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)}, 105 { "no," , (2 << FT32_FLD_CR_BIT) | (2 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)}, 106 { "o," , (2 << FT32_FLD_CR_BIT) | (2 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)}, 107 { "ns," , (2 << FT32_FLD_CR_BIT) | (3 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)}, 108 { "s," , (2 << FT32_FLD_CR_BIT) | (3 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)}, 109 { NULL, 0} 110 }, *pc; 111 112 for (pc = ccs; pc->name; pc++) 113 { 114 if (memcmp(pc->name, s, strlen(pc->name)) == 0) 115 { 116 *ptr += strlen(pc->name) - 1; 117 return pc->bits; 118 } 119 } 120 return -1; 121} 122 123static int 124parse_decimal (char **ptr) 125{ 126 int r = 0; 127 char *s = *ptr; 128 129 while (('0' <= *s) && (*s <= '9')) 130 { 131 r *= 10; 132 r += (*s++ - '0'); 133 } 134 *ptr = s; 135 return r; 136} 137 138static int 139parse_register_operand (char **ptr) 140{ 141 int reg; 142 char *s = *ptr; 143 144 if (*s != '$') 145 { 146 as_bad (_("expecting register")); 147 ignore_rest_of_line (); 148 return -1; 149 } 150 if ((s[1] == 's') && (s[2] == 'p')) 151 { 152 reg = 31; 153 } 154 else if ((s[1] == 'c') && (s[2] == 'c')) 155 { 156 reg = 30; 157 } 158 else if ((s[1] == 'f') && (s[2] == 'p')) 159 { 160 reg = 29; 161 } 162 else if (s[1] == 'r') 163 { 164 reg = s[2] - '0'; 165 if ((reg < 0) || (reg > 9)) 166 { 167 as_bad (_("illegal register number")); 168 ignore_rest_of_line (); 169 return -1; 170 } 171 if ((reg == 1) || (reg == 2) || (reg == 3)) 172 { 173 int r2 = s[3] - '0'; 174 if ((r2 >= 0) && (r2 <= 9)) 175 { 176 reg = (reg * 10) + r2; 177 *ptr += 1; 178 } 179 } 180 } 181 else 182 { 183 as_bad (_("illegal register number")); 184 ignore_rest_of_line (); 185 return -1; 186 } 187 188 *ptr += 3; 189 190 return reg; 191} 192 193/* This is the guts of the machine-dependent assembler. STR points to 194 a machine dependent instruction. This function is supposed to emit 195 the frags/bytes it assembles to. */ 196 197void 198md_assemble (char *str) 199{ 200 char *op_start; 201 char *op_end; 202 ft32_opc_info_t *opcode; 203 char *output; 204 int idx = 0; 205 char pend; 206 int nlen = 0; 207 unsigned int b; 208 int f; 209 expressionS arg; 210 bfd_boolean fixed = FALSE; 211 unsigned int sc; 212 bfd_boolean can_sc; 213 214 /* Drop leading whitespace. */ 215 while (*str == ' ') 216 str++; 217 218 /* Find the op code end. */ 219 op_start = str; 220 for (op_end = str; 221 *op_end 222 && !is_end_of_line[*op_end & 0xff] 223 && *op_end != ' ' 224 && *op_end != '.'; 225 op_end++) 226 nlen++; 227 228 pend = *op_end; 229 *op_end = 0; 230 231 if (nlen == 0) 232 as_bad (_("can't find opcode ")); 233 234 opcode = (ft32_opc_info_t *) str_hash_find (opcode_hash_control, op_start); 235 *op_end = pend; 236 237 if (opcode == NULL) 238 { 239 as_bad (_("unknown opcode %s"), op_start); 240 return; 241 } 242 243 b = opcode->bits; 244 f = opcode->fields; 245 246 if (opcode->dw) 247 { 248 int dw; 249 250 if (*op_end == '.') 251 { 252 switch (op_end[1]) 253 { 254 case 'b': 255 dw = 0; 256 break; 257 case 's': 258 dw = 1; 259 break; 260 case 'l': 261 dw = 2; 262 break; 263 default: 264 as_bad (_("unknown width specifier '.%c'"), op_end[1]); 265 return; 266 } 267 op_end += 2; 268 } 269 else 270 { 271 dw = 2; /* default is ".l" */ 272 } 273 b |= dw << FT32_FLD_DW_BIT; 274 } 275 276 while (ISSPACE (*op_end)) 277 op_end++; 278 279 output = frag_more (4); 280 281 while (f) 282 { 283 int lobit = f & -f; 284 285 if (f & lobit) 286 { 287 switch (lobit) 288 { 289 case FT32_FLD_CBCRCV: 290 b |= parse_condition( &op_end); 291 break; 292 case FT32_FLD_CB: 293 b |= parse_decimal (&op_end) << FT32_FLD_CB_BIT; 294 break; 295 case FT32_FLD_R_D: 296 b |= parse_register_operand (&op_end) << FT32_FLD_R_D_BIT; 297 break; 298 case FT32_FLD_CR: 299 b |= (parse_register_operand (&op_end) - 28) << FT32_FLD_CR_BIT; 300 break; 301 case FT32_FLD_CV: 302 b |= parse_decimal (&op_end) << FT32_FLD_CV_BIT; 303 break; 304 case FT32_FLD_R_1: 305 b |= parse_register_operand (&op_end) << FT32_FLD_R_1_BIT; 306 break; 307 case FT32_FLD_RIMM: 308 if (*op_end == '$') 309 { 310 b |= parse_register_operand (&op_end) << FT32_FLD_RIMM_BIT; 311 } 312 else 313 { 314 b |= 0x400 << FT32_FLD_RIMM_BIT; 315 op_end = parse_exp_save_ilp (op_end, &arg); 316 fixed = TRUE; 317 fix_new_exp (frag_now, 318 (output - frag_now->fr_literal), 319 2, 320 &arg, 321 0, 322 BFD_RELOC_FT32_10); 323 } 324 break; 325 case FT32_FLD_R_2: 326 b |= parse_register_operand (&op_end) << FT32_FLD_R_2_BIT; 327 break; 328 case FT32_FLD_K20: 329 op_end = parse_exp_save_ilp (op_end, &arg); 330 fixed = TRUE; 331 fix_new_exp (frag_now, 332 (output - frag_now->fr_literal), 333 3, 334 &arg, 335 0, 336 BFD_RELOC_FT32_20); 337 break; 338 case FT32_FLD_PA: 339 op_end = parse_exp_save_ilp (op_end, &arg); 340 fixed = TRUE; 341 fix_new_exp (frag_now, 342 (output - frag_now->fr_literal), 343 3, 344 &arg, 345 0, 346 BFD_RELOC_FT32_18); 347 break; 348 case FT32_FLD_AA: 349 op_end = parse_exp_save_ilp (op_end, &arg); 350 fixed = TRUE; 351 fix_new_exp (frag_now, 352 (output - frag_now->fr_literal), 353 3, 354 &arg, 355 0, 356 BFD_RELOC_FT32_17); 357 break; 358 case FT32_FLD_K16: 359 op_end = parse_exp_save_ilp (op_end, &arg); 360 fixed = TRUE; 361 fix_new_exp (frag_now, 362 (output - frag_now->fr_literal), 363 2, 364 &arg, 365 0, 366 BFD_RELOC_16); 367 break; 368 case FT32_FLD_K15: 369 op_end = parse_exp_save_ilp (op_end, &arg); 370 if (arg.X_add_number & 0x80) 371 arg.X_add_number ^= 0x7f00; 372 fixed = TRUE; 373 fix_new_exp (frag_now, 374 (output - frag_now->fr_literal), 375 2, 376 &arg, 377 0, 378 BFD_RELOC_FT32_15); 379 break; 380 case FT32_FLD_R_D_POST: 381 b |= parse_register_operand (&op_end) << FT32_FLD_R_D_BIT; 382 break; 383 case FT32_FLD_R_1_POST: 384 b |= parse_register_operand (&op_end) << FT32_FLD_R_1_BIT; 385 break; 386 default: 387 as_bad (_("internal error in argument parsing")); 388 break; 389 } 390 391 f &= ~lobit; 392 393 if (f) 394 { 395 while (ISSPACE (*op_end)) 396 op_end++; 397 398 if (*op_end != ',') 399 { 400 as_bad (_("expected comma separator")); 401 ignore_rest_of_line (); 402 } 403 404 op_end++; 405 while (ISSPACE (*op_end)) 406 op_end++; 407 } 408 } 409 } 410 411 if (*op_end != 0) 412 as_warn (_("extra stuff on line ignored")); 413 414 can_sc = ft32_shortcode (b, &sc); 415 416 if (!fixed && can_sc) 417 { 418 arg.X_op = O_constant; 419 arg.X_add_number = 0; 420 arg.X_add_symbol = NULL; 421 arg.X_op_symbol = NULL; 422 fix_new_exp (frag_now, 423 (output - frag_now->fr_literal), 424 2, 425 &arg, 426 0, 427 BFD_RELOC_FT32_RELAX); 428 } 429 430 output[idx++] = 0xff & (b >> 0); 431 output[idx++] = 0xff & (b >> 8); 432 output[idx++] = 0xff & (b >> 16); 433 output[idx++] = 0xff & (b >> 24); 434 435 dwarf2_emit_insn (4); 436 437 while (ISSPACE (*op_end)) 438 op_end++; 439 440 if (*op_end != 0) 441 as_warn ("extra stuff on line ignored"); 442 443 if (pending_reloc) 444 as_bad ("Something forgot to clean up\n"); 445} 446 447/* Turn a string in input_line_pointer into a floating point constant 448 of type type, and store the appropriate bytes in *LITP. The number 449 of LITTLENUMS emitted is stored in *SIZEP . An error message is 450 returned, or NULL on OK. */ 451 452const char * 453md_atof (int type, char *litP, int *sizeP) 454{ 455 int prec; 456 LITTLENUM_TYPE words[4]; 457 char *t; 458 int i; 459 460 switch (type) 461 { 462 case 'f': 463 prec = 2; 464 break; 465 466 case 'd': 467 prec = 4; 468 break; 469 470 default: 471 *sizeP = 0; 472 return _("bad call to md_atof"); 473 } 474 475 t = atof_ieee (input_line_pointer, type, words); 476 if (t) 477 input_line_pointer = t; 478 479 *sizeP = prec * 2; 480 481 for (i = prec - 1; i >= 0; i--) 482 { 483 md_number_to_chars (litP, (valueT) words[i], 2); 484 litP += 2; 485 } 486 487 return NULL; 488} 489 490const char *md_shortopts = ""; 491 492struct option md_longopts[] = 493{ 494#define OPTION_NORELAX (OPTION_MD_BASE) 495 {"norelax", no_argument, NULL, OPTION_NORELAX}, 496 {"no-relax", no_argument, NULL, OPTION_NORELAX}, 497 {NULL, no_argument, NULL, 0} 498}; 499size_t md_longopts_size = sizeof (md_longopts); 500 501/* We have no target specific options yet, so these next 502 two functions are empty. */ 503int 504md_parse_option (int c ATTRIBUTE_UNUSED, const char *arg ATTRIBUTE_UNUSED) 505{ 506 switch (c) 507 { 508 case OPTION_NORELAX: 509 norelax = 1; 510 break; 511 512 default: 513 return 0; 514 } 515 516 return 1; 517} 518 519void 520md_show_usage (FILE *stream ATTRIBUTE_UNUSED) 521{ 522 fprintf (stream, _("FT32 options:\n")); 523 fprintf (stream, _("\n\ 524-no-relax don't relax relocations\n\ 525 \n")); 526} 527 528/* Convert from target byte order to host byte order. */ 529 530static valueT 531md_chars_to_number (char * buf, int n) 532{ 533 valueT result = 0; 534 unsigned char * where = (unsigned char *) buf; 535 536 while (n--) 537 { 538 result <<= 8; 539 result |= (where[n] & 255); 540 } 541 542 return result; 543} 544 545/* Apply a fixup to the object file. */ 546 547void 548md_apply_fix (fixS *fixP ATTRIBUTE_UNUSED, 549 valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED) 550{ 551 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; 552 long val = *valP; 553 long newval; 554 555 if (linkrelax && fixP->fx_subsy) 556 { 557 /* For a subtraction relocation expression, generate one 558 of the DIFF relocs, with the value being the difference. 559 Note that a sym1 - sym2 expression is adjusted into a 560 section_start_sym + sym4_offset_from_section_start - sym1 561 expression. fixP->fx_addsy holds the section start symbol, 562 fixP->fx_offset holds sym2's offset, and fixP->fx_subsy 563 holds sym1. Calculate the current difference and write value, 564 but leave fx_offset as is - during relaxation, 565 fx_offset - value gives sym1's value. */ 566 567 switch (fixP->fx_r_type) 568 { 569 case BFD_RELOC_32: 570 fixP->fx_r_type = BFD_RELOC_FT32_DIFF32; 571 break; 572 default: 573 as_bad_where (fixP->fx_file, fixP->fx_line, 574 _("expression too complex")); 575 break; 576 } 577 578 val = S_GET_VALUE (fixP->fx_addsy) + 579 fixP->fx_offset - S_GET_VALUE (fixP->fx_subsy); 580 *valP = val; 581 582 fixP->fx_subsy = NULL; 583 } 584 585 /* We don't actually support subtracting a symbol. */ 586 if (fixP->fx_subsy != (symbolS *) NULL) 587 as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex")); 588 589 switch (fixP->fx_r_type) 590 { 591 case BFD_RELOC_FT32_DIFF32: 592 case BFD_RELOC_32: 593 buf[3] = val >> 24; 594 buf[2] = val >> 16; 595 buf[1] = val >> 8; 596 buf[0] = val >> 0; 597 break; 598 599 case BFD_RELOC_16: 600 buf[1] = val >> 8; 601 buf[0] = val >> 0; 602 break; 603 604 case BFD_RELOC_8: 605 *buf = val; 606 break; 607 608 case BFD_RELOC_FT32_10: 609 if (!val) 610 break; 611 newval = md_chars_to_number (buf, 2); 612 newval |= (val & ((1 << 10) - 1)) << FT32_FLD_RIMM_BIT; 613 md_number_to_chars (buf, newval, 2); 614 break; 615 616 case BFD_RELOC_FT32_20: 617 if (!val) 618 break; 619 newval = md_chars_to_number (buf, 3); 620 newval |= val & ((1 << 20) - 1); 621 md_number_to_chars (buf, newval, 3); 622 break; 623 624 case BFD_RELOC_FT32_15: 625 if (!val) 626 break; 627 newval = md_chars_to_number (buf, 2); 628 newval |= val & ((1 << 15) - 1); 629 md_number_to_chars (buf, newval, 2); 630 break; 631 632 case BFD_RELOC_FT32_17: 633 if (!val) 634 break; 635 newval = md_chars_to_number (buf, 3); 636 newval |= val & ((1 << 17) - 1); 637 md_number_to_chars (buf, newval, 3); 638 break; 639 640 case BFD_RELOC_FT32_18: 641 if (!val) 642 break; 643 newval = md_chars_to_number (buf, 4); 644 newval |= (val >> 2) & ((1 << 18) - 1); 645 md_number_to_chars (buf, newval, 4); 646 break; 647 648 case BFD_RELOC_FT32_RELAX: 649 break; 650 651 default: 652 abort (); 653 } 654 655 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) 656 fixP->fx_done = 1; 657} 658 659void 660md_number_to_chars (char *ptr, valueT use, int nbytes) 661{ 662 number_to_chars_littleendian (ptr, use, nbytes); 663} 664 665/* Generate a machine-dependent relocation. */ 666 667arelent * 668tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP) 669{ 670 arelent *relP; 671 bfd_reloc_code_real_type code; 672 673 switch (fixP->fx_r_type) 674 { 675 case BFD_RELOC_32: 676 case BFD_RELOC_16: 677 case BFD_RELOC_8: 678 case BFD_RELOC_FT32_10: 679 case BFD_RELOC_FT32_20: 680 case BFD_RELOC_FT32_15: 681 case BFD_RELOC_FT32_17: 682 case BFD_RELOC_FT32_18: 683 case BFD_RELOC_FT32_RELAX: 684 case BFD_RELOC_FT32_DIFF32: 685 code = fixP->fx_r_type; 686 break; 687 default: 688 as_bad_where (fixP->fx_file, fixP->fx_line, 689 _("Semantics error. This type of operand can not be " 690 "relocated, it must be an assembly-time constant")); 691 return NULL; 692 } 693 694 relP = XNEW (arelent); 695 gas_assert (relP != 0); 696 relP->sym_ptr_ptr = XNEW (asymbol *); 697 *relP->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy); 698 relP->address = fixP->fx_frag->fr_address + fixP->fx_where; 699 700 relP->addend = fixP->fx_offset; 701 702 relP->howto = bfd_reloc_type_lookup (stdoutput, code); 703 if (! relP->howto) 704 { 705 const char *name; 706 707 name = S_GET_NAME (fixP->fx_addsy); 708 if (name == NULL) 709 name = _("<unknown>"); 710 as_fatal (_("Cannot generate relocation type for symbol %s, code %s"), 711 name, bfd_get_reloc_code_name (code)); 712 } 713 714 return relP; 715} 716 717/* TC_FORCE_RELOCATION hook */ 718 719static bfd_boolean 720relaxable_section (asection *sec) 721{ 722 return ((sec->flags & SEC_DEBUGGING) == 0 723 && (sec->flags & SEC_CODE) != 0 724 && (sec->flags & SEC_ALLOC) != 0); 725} 726 727/* Does whatever the xtensa port does. */ 728 729int 730ft32_validate_fix_sub (fixS *fix) 731{ 732 segT add_symbol_segment, sub_symbol_segment; 733 734 /* The difference of two symbols should be resolved by the assembler when 735 linkrelax is not set. If the linker may relax the section containing 736 the symbols, then an Xtensa DIFF relocation must be generated so that 737 the linker knows to adjust the difference value. */ 738 if (!linkrelax || fix->fx_addsy == NULL) 739 return 0; 740 741 /* Make sure both symbols are in the same segment, and that segment is 742 "normal" and relaxable. If the segment is not "normal", then the 743 fix is not valid. If the segment is not "relaxable", then the fix 744 should have been handled earlier. */ 745 add_symbol_segment = S_GET_SEGMENT (fix->fx_addsy); 746 if (! SEG_NORMAL (add_symbol_segment) || 747 ! relaxable_section (add_symbol_segment)) 748 return 0; 749 750 sub_symbol_segment = S_GET_SEGMENT (fix->fx_subsy); 751 return (sub_symbol_segment == add_symbol_segment); 752} 753 754/* TC_FORCE_RELOCATION hook */ 755 756/* If linkrelax is turned on, and the symbol to relocate 757 against is in a relaxable segment, don't compute the value - 758 generate a relocation instead. */ 759 760int 761ft32_force_relocation (fixS *fix) 762{ 763 if (linkrelax && fix->fx_addsy 764 && relaxable_section (S_GET_SEGMENT (fix->fx_addsy))) 765 { 766 return 1; 767 } 768 769 return generic_force_reloc (fix); 770} 771 772bfd_boolean 773ft32_allow_local_subtract (expressionS * left, 774 expressionS * right, 775 segT section) 776{ 777 /* If we are not in relaxation mode, subtraction is OK. */ 778 if (!linkrelax) 779 return TRUE; 780 781 /* If the symbols are not in a code section then they are OK. */ 782 if ((section->flags & SEC_CODE) == 0) 783 return TRUE; 784 785 if (left->X_add_symbol == right->X_add_symbol) 786 return TRUE; 787 788 /* We have to assume that there may be instructions between the 789 two symbols and that relaxation may increase the distance between 790 them. */ 791 return FALSE; 792} 793