1 /* tc-epiphany.c -- Assembler for the Adapteva EPIPHANY 2 Copyright 2009, 2011 Free Software Foundation, Inc. 3 Contributed by Embecosm on behalf of Adapteva, Inc. 4 5 This file is part of GAS, the GNU Assembler. 6 7 GAS is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 GAS is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GAS; see the file COPYING. If not, write to 19 the Free Software Foundation, 51 Franklin Street - Fifth Floor, 20 Boston, MA 02110-1301, USA. */ 21 22 #include "as.h" 23 #include "subsegs.h" 24 #include "symcat.h" 25 #include "opcodes/epiphany-desc.h" 26 #include "opcodes/epiphany-opc.h" 27 #include "cgen.h" 28 #include "elf/common.h" 29 #include "elf/epiphany.h" 30 #include "dwarf2dbg.h" 31 #include "libbfd.h" 32 33 /* Structure to hold all of the different components describing 34 an individual instruction. */ 35 typedef struct 36 { 37 const CGEN_INSN * insn; 38 const CGEN_INSN * orig_insn; 39 CGEN_FIELDS fields; 40 #if CGEN_INT_INSN_P 41 CGEN_INSN_INT buffer [1]; 42 #define INSN_VALUE(buf) (*(buf)) 43 #else 44 unsigned char buffer [CGEN_MAX_INSN_SIZE]; 45 #define INSN_VALUE(buf) (buf) 46 #endif 47 char * addr; 48 fragS * frag; 49 int num_fixups; 50 fixS * fixups [GAS_CGEN_MAX_FIXUPS]; 51 int indices [MAX_OPERAND_INSTANCES]; 52 } 53 epiphany_insn; 54 55 const char comment_chars[] = ";"; 56 const char line_comment_chars[] = "#"; 57 const char line_separator_chars[] = "`"; 58 const char EXP_CHARS[] = "eE"; 59 const char FLT_CHARS[] = "fFdD"; 60 61 /* Flag to detect when switching to code section where insn alignment is 62 implied. */ 63 static bfd_boolean force_code_align = FALSE; 64 65 static void 66 epiphany_elf_section_rtn (int i) 67 { 68 obj_elf_section (i); 69 70 if (force_code_align) 71 { 72 /* The s_align_ptwo function expects that we are just after a .align 73 directive and it will either try and read the align value or stop 74 if end of line so we must fake it out so it thinks we are at the 75 end of the line. */ 76 char *old_input_line_pointer = input_line_pointer; 77 78 input_line_pointer = "\n"; 79 s_align_ptwo (1); 80 force_code_align = FALSE; 81 82 /* Restore. */ 83 input_line_pointer = old_input_line_pointer; 84 } 85 } 86 87 static void 88 epiphany_elf_section_text (int i) 89 { 90 char *old_input_line_pointer; 91 92 obj_elf_text (i); 93 94 /* The s_align_ptwo function expects that we are just after a .align 95 directive and it will either try and read the align value or stop if 96 end of line so we must fake it out so it thinks we are at the end of 97 the line. */ 98 old_input_line_pointer = input_line_pointer; 99 input_line_pointer = "\n"; 100 s_align_ptwo (1); 101 force_code_align = FALSE; 102 /* Restore. */ 103 input_line_pointer = old_input_line_pointer; 104 } 105 106 /* The target specific pseudo-ops which we support. */ 107 const pseudo_typeS md_pseudo_table[] = 108 { 109 { "text", epiphany_elf_section_text, 0 }, 110 { "sect", epiphany_elf_section_rtn, 0 }, 111 /* .word should be 32 bits. */ 112 { "word", cons, 4 }, 113 { "cpu", s_ignore, 0 }, 114 { "thumb_func", s_ignore, 0 }, 115 { "code", s_ignore, 0 }, 116 { NULL, NULL, 0 } 117 }; 118 119 120 121 enum options 122 { 123 OPTION_CPU_EPIPHANY = OPTION_MD_BASE, 124 OPTION_CPU_EPIPHANY16 125 }; 126 127 struct option md_longopts[] = 128 { 129 { "mepiphany ", no_argument, NULL, OPTION_CPU_EPIPHANY }, 130 { "mepiphany16", no_argument, NULL, OPTION_CPU_EPIPHANY16 }, 131 { NULL, no_argument, NULL, 0 }, 132 }; 133 134 size_t md_longopts_size = sizeof (md_longopts); 135 136 const char * md_shortopts = ""; 137 138 int 139 md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED) 140 { 141 return 0; /* No target-specific options. */ 142 } 143 144 void 145 md_show_usage (FILE * stream) 146 { 147 fprintf (stream, _("EPIPHANY specific command line options:\n")); 148 } 149 150 151 void 152 md_begin (void) 153 { 154 /* Initialize the `cgen' interface. */ 155 156 /* Set the machine number and endian. */ 157 gas_cgen_cpu_desc = epiphany_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 158 bfd_mach_epiphany32, 159 CGEN_CPU_OPEN_ENDIAN, 160 CGEN_ENDIAN_LITTLE, 161 CGEN_CPU_OPEN_END); 162 epiphany_cgen_init_asm (gas_cgen_cpu_desc); 163 164 /* This is a callback from cgen to gas to parse operands. */ 165 cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand); 166 167 /* Set the machine type. */ 168 bfd_default_set_arch_mach (stdoutput, bfd_arch_epiphany, bfd_mach_epiphany32); 169 } 170 171 valueT 172 md_section_align (segT segment, valueT size) 173 { 174 int align = bfd_get_section_alignment (stdoutput, segment); 175 176 return ((size + (1 << align) - 1) & (-1 << align)); 177 } 178 179 180 /* Functions concerning relocs. */ 181 182 long 183 md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED) 184 { 185 abort (); 186 } 187 188 /* Write a value out to the object file, using the appropriate endianness. */ 189 190 void 191 md_number_to_chars (char * buf, valueT val, int n) 192 { 193 number_to_chars_littleendian (buf, val, n); 194 } 195 196 int 197 epiphany_elf_section_flags (int flags, 198 int attr ATTRIBUTE_UNUSED, 199 int type ATTRIBUTE_UNUSED) 200 { 201 /* This is used to detect when the section changes to an executable section. 202 This function is called by the elf section processing. When we note an 203 executable section specifier we set an internal flag to denote when 204 word alignment should be forced. */ 205 if (flags & SEC_CODE) 206 force_code_align = TRUE; 207 208 return flags; 209 } 210 211 /* Non-zero if we are generating PIC code. */ 212 int pic_code; 213 214 /* Epiphany er_flags. */ 215 static int epiphany_flags = 0; 216 217 /* Relocations against symbols are done in two 218 parts, with a HI relocation and a LO relocation. Each relocation 219 has only 16 bits of space to store an addend. This means that in 220 order for the linker to handle carries correctly, it must be able 221 to locate both the HI and the LO relocation. This means that the 222 relocations must appear in order in the relocation table. 223 224 In order to implement this, we keep track of each unmatched HI 225 relocation. We then sort them so that they immediately precede the 226 corresponding LO relocation. */ 227 228 struct epiphany_hi_fixup 229 { 230 /* Next HI fixup. */ 231 struct epiphany_hi_fixup *next; 232 233 /* This fixup. */ 234 fixS *fixp; 235 236 /* The section this fixup is in. */ 237 segT seg; 238 }; 239 240 241 #define GOT_NAME "_GLOBAL_OFFSET_TABLE_" 242 static symbolS * GOT_symbol; 243 244 static inline bfd_boolean 245 epiphany_PIC_related_p (symbolS *sym) 246 { 247 expressionS *exp; 248 249 if (! sym) 250 return FALSE; 251 252 if (sym == GOT_symbol) 253 return TRUE; 254 255 exp = symbol_get_value_expression (sym); 256 257 return (exp->X_op == O_PIC_reloc 258 || exp->X_md == BFD_RELOC_EPIPHANY_SIMM24 259 || exp->X_md == BFD_RELOC_EPIPHANY_SIMM8 260 || epiphany_PIC_related_p (exp->X_add_symbol) 261 || epiphany_PIC_related_p (exp->X_op_symbol)); 262 } 263 264 /* Perform target dependent relocations that are done at compile time. 265 There aren't very many of these. */ 266 267 void 268 epiphany_apply_fix (fixS *fixP, valueT *valP, segT seg) 269 { 270 if (fixP->fx_addsy == (symbolS *) NULL) 271 fixP->fx_done = 1; 272 273 if (((int) fixP->fx_r_type < (int) BFD_RELOC_UNUSED) 274 && fixP->fx_done) 275 { 276 /* Install EPIPHANY-dependent relocations HERE because nobody else 277 will. */ 278 char *where = fixP->fx_frag->fr_literal + fixP->fx_where; 279 unsigned char *insn = (unsigned char *)where; 280 valueT value = * valP; 281 282 switch (fixP->fx_r_type) 283 { 284 default: 285 break; 286 287 case BFD_RELOC_NONE: 288 return; 289 290 case BFD_RELOC_EPIPHANY_SIMM11: 291 where[0] = where[0] | ((value & 1) << 7); 292 where[1] = where[1] | ((value & 6) >> 1); 293 where[2] = (value >> 3) & 0xff; 294 return; 295 296 case BFD_RELOC_EPIPHANY_IMM11: 297 where[0] = where[0] | ((value & 1) << 7); 298 where[1] = where[1] | ((value & 6) >> 1); 299 where[2] = (value >> 3) & 0xff; 300 return; 301 302 case BFD_RELOC_EPIPHANY_SIMM8: 303 md_number_to_chars (where+1, value>>1, 1); 304 return; 305 306 case BFD_RELOC_EPIPHANY_SIMM24: 307 md_number_to_chars (where+1, value>>1, 3); 308 return; 309 310 case BFD_RELOC_EPIPHANY_HIGH: 311 value >>= 16; 312 /* fall thru */ 313 case BFD_RELOC_EPIPHANY_LOW: 314 value = (((value & 0xff) << 5) | insn[0]) 315 | (insn[1] << 8) 316 | ((value & 0xff00) << 12) 317 | (insn[2] << 16); 318 md_number_to_chars (where, value, 3); 319 return; 320 } 321 } 322 323 /* Just do the default if we can't special case. */ 324 return gas_cgen_md_apply_fix (fixP, valP, seg); 325 } 326 327 328 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents 329 of an rs_align_code fragment. 0x01a2 is 16-bit pattern for a "nop". */ 330 331 static const unsigned char nop_pattern[] = { 0xa2, 0x01 }; 332 333 void 334 epiphany_handle_align (fragS *fragp) 335 { 336 int bytes, fix; 337 char *p; 338 339 if (fragp->fr_type != rs_align_code) 340 return; 341 342 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix; 343 p = fragp->fr_literal + fragp->fr_fix; 344 fix = 0; 345 346 if (bytes & 1) 347 { 348 fix = 1; 349 *p++ = 0; 350 bytes--; 351 } 352 353 if (bytes & 2) 354 { 355 memcpy (p, nop_pattern, 2); 356 p += 2; 357 bytes -= 2; 358 fix += 2; 359 } 360 fragp->fr_fix += fix; 361 } 362 363 /* Read a comma separated incrementing list of register names 364 and form a bit mask of upto 15 registers 0..14. */ 365 366 static const char * 367 parse_reglist (const char * s, int * mask) 368 { 369 int regmask = 0; 370 371 while (*s) 372 { 373 long value; 374 375 while (*s == ' ') 376 ++s; 377 378 /* Parse a list with "," or "}" as limiters. */ 379 const char *errmsg 380 = cgen_parse_keyword (gas_cgen_cpu_desc, &s, 381 &epiphany_cgen_opval_gr_names, &value); 382 if (errmsg) 383 return errmsg; 384 385 if (value > 15) 386 return _("register number too large for push/pop"); 387 388 regmask |= 1 << value; 389 if (regmask < *mask) 390 return _("register is out of order"); 391 *mask |= regmask; 392 393 while (*s==' ') 394 ++s; 395 396 if (*s == '}') 397 return NULL; 398 else if (*s++ == ',') 399 continue; 400 else 401 return _("bad register list"); 402 } 403 404 return _("malformed reglist in push/pop"); 405 } 406 407 408 void 409 md_assemble (char *str) 410 { 411 epiphany_insn insn; 412 char *errmsg = 0; 413 const char * pperr = 0; 414 int regmask=0, push=0, pop=0; 415 416 memset (&insn, 0, sizeof (insn)); 417 418 /* Special-case push/pop instruction macros. */ 419 if (0 == strncmp (str, "push {", 6)) 420 { 421 char * s = str + 6; 422 push = 1; 423 pperr = parse_reglist (s, ®mask); 424 } 425 else if (0 == strncmp (str, "pop {", 5)) 426 { 427 char * s = str + 5; 428 pop = 1; 429 pperr = parse_reglist (s, ®mask); 430 } 431 432 if (pperr) 433 { 434 as_bad ("%s", pperr); 435 return; 436 } 437 438 if (push && regmask) 439 { 440 char buff[20]; 441 int i,p ATTRIBUTE_UNUSED; 442 443 md_assemble ("mov r15,4"); 444 md_assemble ("sub sp,sp,r15"); 445 446 for (i = 0, p = 1; i <= 15; ++i, regmask >>= 1) 447 { 448 if (regmask == 1) 449 sprintf (buff, "str r%d,[sp]", i); /* Last one. */ 450 else if (regmask & 1) 451 sprintf (buff, "str r%d,[sp],-r15", i); 452 else 453 continue; 454 md_assemble (buff); 455 } 456 return; 457 } 458 else if (pop && regmask) 459 { 460 char buff[20]; 461 int i,p; 462 463 md_assemble ("mov r15,4"); 464 465 for (i = 15, p = 1 << 15; i >= 0; --i, p >>= 1) 466 if (regmask & p) 467 { 468 sprintf (buff, "ldr r%d,[sp],+r15", i); 469 md_assemble (buff); 470 } 471 return; 472 } 473 474 /* Initialize GAS's cgen interface for a new instruction. */ 475 gas_cgen_init_parse (); 476 477 insn.insn = epiphany_cgen_assemble_insn 478 (gas_cgen_cpu_desc, str, &insn.fields, insn.buffer, & errmsg); 479 480 if (!insn.insn) 481 { 482 as_bad ("%s", errmsg); 483 return; 484 } 485 486 if (CGEN_INSN_BITSIZE (insn.insn) == 32) 487 { 488 /* Doesn't really matter what we pass for RELAX_P here. */ 489 gas_cgen_finish_insn (insn.insn, insn.buffer, 490 CGEN_FIELDS_BITSIZE (&insn.fields), 1, NULL); 491 } 492 else 493 { 494 if (CGEN_INSN_BITSIZE (insn.insn) != 16) 495 abort (); 496 497 insn.orig_insn = insn.insn; 498 499 gas_cgen_finish_insn (insn.orig_insn, insn.buffer, 500 CGEN_FIELDS_BITSIZE (&insn.fields), 501 1 /* relax_p */, NULL); 502 } 503 504 /* Checks for behavioral restrictions on LD/ST instructions. */ 505 #define DISPMOD _("destination register modified by displacement-post-modified address") 506 #define LDSTODD _("ldrd/strd requires even:odd register pair") 507 508 /* Helper macros for spliting apart instruction fields. */ 509 #define ADDR_POST_MODIFIED(i) (((i) >> 25) & 0x1) 510 #define ADDR_SIZE(i) (((i) >> 5) & 3) 511 #define ADDR_LOADSTORE(i) (((i) >> 4) & 0x1) 512 513 switch (insn.buffer[0] & 0xf) 514 { 515 /* Post-modify registers cannot be destinations. */ 516 case OP4_LDSTR16P: 517 { 518 if (ADDR_LOADSTORE (insn.buffer[0]) == OP_LOAD) 519 if (insn.fields.f_rd == insn.fields.f_rn /* Postmodify dest. */ 520 || (insn.fields.f_rd+1 == insn.fields.f_rn 521 && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)) 522 { 523 as_bad ("%s", DISPMOD); 524 return; 525 } 526 if ((insn.fields.f_rd & 1) /* Odd-numbered register... */ 527 && insn.fields.f_wordsize == OPW_DOUBLE) /* ...and 64 bit transfer. */ 528 { 529 as_bad ("%s", LDSTODD); 530 return; 531 } 532 break; 533 } 534 535 case OP4_LDSTRP: 536 { 537 if (ADDR_LOADSTORE (insn.buffer[0]) == OP_LOAD) /* A load. */ 538 if (insn.fields.f_rd6 == insn.fields.f_rn6 /* Postmodify dest. */ 539 /* Check for regpair postindexed. */ 540 || (insn.fields.f_rd6 + 1 == insn.fields.f_rn6 541 && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)) 542 { 543 as_bad ("%s", DISPMOD); 544 return; 545 } 546 if ((insn.fields.f_rd6 & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE) 547 /* Lsb of RD odd and 64 bit transfer. */ 548 { 549 as_bad ("%s", LDSTODD); 550 return; 551 } 552 break; 553 } 554 555 case OP4_LDSTR16X: 556 case OP4_LDSTR16D: 557 { 558 /* Check for unaligned load/store double. */ 559 if ((insn.fields.f_rd & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE) 560 /* Lsb of RD odd and 64 bit transfer. */ 561 { 562 as_bad ("%s", LDSTODD); 563 return; 564 } 565 break; 566 } 567 568 case OP4_LDSTRD: 569 { 570 /* Check for load to post-modified register. */ 571 if (ADDR_LOADSTORE (insn.buffer[0]) == OP_LOAD /* A load. */ 572 && ADDR_POST_MODIFIED (insn.buffer[0]) == PMOD_POST /* Post-mod. */ 573 && (insn.fields.f_rd6 == insn.fields.f_rn6 574 || (insn.fields.f_rd6+1 == insn.fields.f_rn6 575 && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE))) 576 { 577 as_bad ("%s", DISPMOD); 578 return; 579 } 580 } 581 /* fall-thru. */ 582 583 case OP4_LDSTRX: 584 { 585 /* Check for unaligned load/store double. */ 586 if ((insn.fields.f_rd6 & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE) 587 { 588 as_bad ("%s", LDSTODD); 589 return; 590 } 591 break; 592 } 593 594 default: 595 break; 596 } 597 } 598 599 /* The syntax in the manual says constants begin with '#'. 600 We just ignore it. */ 601 602 void 603 md_operand (expressionS *expressionP) 604 { 605 if (*input_line_pointer == '#') 606 { 607 input_line_pointer++; 608 expression (expressionP); 609 } 610 } 611 612 symbolS * 613 md_undefined_symbol (char *name ATTRIBUTE_UNUSED) 614 { 615 return NULL; 616 } 617 618 /* Interface to relax_segment. */ 619 620 /* FIXME: Build table by hand, get it working, then machine generate. */ 621 622 const relax_typeS md_relax_table[] = 623 { 624 /* The fields are: 625 1) most positive reach of this state, 626 2) most negative reach of this state, 627 3) how many bytes this mode will add to the size of the current frag 628 4) which index into the table to try if we can't fit into this one. */ 629 630 /* The first entry must be unused because an `rlx_more' value of zero ends 631 each list. */ 632 {1, 1, 0, EPIPHANY_RELAX_NONE}, 633 {0, 0, 0, EPIPHANY_RELAX_NONE}, /* Also a dummy entry to indicate we need to expand codes. */ 634 635 /* The displacement used by GAS is from the end of the 2 byte insn, 636 so we subtract 2 from the following. */ 637 /* 16 bit insn, 8 bit disp -> +127 words, -128 words. */ 638 {0x00000100 - 1 - 2, -0x00000100 - 2, 0, EPIPHANY_RELAX_BRANCH_LONG }, 639 /* 32 bit insn, 24 bit disp -> 25 bit range. */ 640 {0x01000000 - 1 - 2, -0x01000000 - 2, 2, EPIPHANY_RELAX_NONE }, 641 642 /* addi/subi 3 bits -4..+3. */ 643 { 3, -4,0, EPIPHANY_RELAX_ARITH_SIMM11 }, 644 /* addi/subi 11 bits. */ 645 { 1023, -1024,2, EPIPHANY_RELAX_NONE }, 646 647 /* mov r,imm8. */ 648 { 255, 0,0, EPIPHANY_RELAX_MOV_IMM16 }, 649 /* mov r,imm16. */ 650 { 65535, 0,2, EPIPHANY_RELAX_NONE }, 651 652 /* ld/st rd,[rn,imm3]. */ 653 { 7, 0,0, EPIPHANY_RELAX_LDST_IMM11}, 654 /* ld/st rd,[rn,imm11]. */ 655 { 2047, 0,2, EPIPHANY_RELAX_NONE } 656 657 }; 658 659 static const EPIPHANY_RELAX_TYPES relax_insn[] = 660 { 661 EPIPHANY_RELAX_BRANCH_SHORT, /* OP4_BRANCH16 */ 662 EPIPHANY_RELAX_NONE, /* OP4_LDSTR16X */ 663 EPIPHANY_RELAX_NONE, /* OP4_FLOW16 */ 664 EPIPHANY_RELAX_ARITH_SIMM3, /* OP4_IMM16 - special */ 665 EPIPHANY_RELAX_LDST_IMM3, /* OP4_LDSTR16D */ 666 EPIPHANY_RELAX_NONE, /* OP4_LDSTR126P */ 667 EPIPHANY_RELAX_NONE, /* OP4_LSHIFT16 */ 668 EPIPHANY_RELAX_NONE, /* OP4_DSP16 */ 669 EPIPHANY_RELAX_BRANCH_LONG, /* OP4_BRANCH */ 670 EPIPHANY_RELAX_NONE, /* OP4_LDSTRX */ 671 EPIPHANY_RELAX_NONE, /* OP4_ALU16 */ 672 EPIPHANY_RELAX_ARITH_SIMM11, /* OP4_IMM32 - special */ 673 EPIPHANY_RELAX_LDST_IMM11, /* OP4_LDSTRD */ 674 EPIPHANY_RELAX_NONE, /* OP4_LDSTRP */ 675 EPIPHANY_RELAX_NONE, /* OP4_ASHIFT16 */ 676 EPIPHANY_RELAX_NONE /* OP4_MISC */ 677 }; 678 679 long 680 epiphany_relax_frag (segT segment, fragS *fragP, long stretch) 681 { 682 /* Address of branch insn. */ 683 long address ATTRIBUTE_UNUSED = fragP->fr_address + fragP->fr_fix - 2; 684 long growth = 0; 685 686 if (fragP->fr_subtype == EPIPHANY_RELAX_NEED_RELAXING) 687 { 688 EPIPHANY_RELAX_TYPES subtype = relax_insn [*fragP->fr_opcode & 0xf]; 689 690 /* Special cases add/sub vs mov immediates. */ 691 if (subtype == EPIPHANY_RELAX_ARITH_SIMM3) 692 { 693 if ((*fragP->fr_opcode & 0x10) == 0) 694 subtype = EPIPHANY_RELAX_MOV_IMM8; 695 } 696 else if (subtype == EPIPHANY_RELAX_ARITH_SIMM11) 697 { 698 if ((*fragP->fr_opcode & 0x10) == 0) 699 subtype = EPIPHANY_RELAX_MOV_IMM16; 700 } 701 702 /* Remember refinements for the future. */ 703 fragP->fr_subtype = subtype; 704 } 705 706 growth = relax_frag (segment, fragP, stretch); 707 708 return growth; 709 } 710 711 /* Return an initial guess of the length by which a fragment must grow to 712 hold a branch to reach its destination. 713 Also updates fr_type/fr_subtype as necessary. 714 715 Called just before doing relaxation. 716 Any symbol that is now undefined will not become defined. 717 The guess for fr_var is ACTUALLY the growth beyond fr_fix. 718 Whatever we do to grow fr_fix or fr_var contributes to our returned value. 719 Although it may not be explicit in the frag, pretend fr_var starts 720 with a 0 value. */ 721 722 int 723 md_estimate_size_before_relax (fragS *fragP, segT segment) 724 { 725 /* The only thing we have to handle here are symbols outside of the 726 current segment. They may be undefined or in a different segment in 727 which case linker scripts may place them anywhere. 728 However, we can't finish the fragment here and emit the reloc as insn 729 alignment requirements may move the insn about. */ 730 if (S_GET_SEGMENT (fragP->fr_symbol) != segment 731 || S_IS_EXTERNAL (fragP->fr_symbol) 732 || S_IS_WEAK (fragP->fr_symbol)) 733 { 734 /* The symbol is undefined in this segment. Change the 735 relaxation subtype to the max allowable and leave all further 736 handling to md_convert_frag. */ 737 738 EPIPHANY_RELAX_TYPES subtype; 739 /* We haven't relaxed this at all, so the relaxation type may be 740 completely wrong. Set the subtype correctly. */ 741 epiphany_relax_frag (segment, fragP, 0); 742 subtype = fragP->fr_subtype; 743 744 switch (subtype) 745 { 746 case EPIPHANY_RELAX_LDST_IMM3: 747 subtype = EPIPHANY_RELAX_LDST_IMM11; 748 break; 749 case EPIPHANY_RELAX_BRANCH_SHORT: 750 subtype = EPIPHANY_RELAX_BRANCH_LONG; 751 break; 752 case EPIPHANY_RELAX_MOV_IMM8: 753 subtype = EPIPHANY_RELAX_MOV_IMM16; 754 break; 755 case EPIPHANY_RELAX_ARITH_SIMM3: 756 subtype = EPIPHANY_RELAX_ARITH_SIMM11; 757 break; 758 759 default: 760 break; 761 } 762 763 fragP->fr_subtype = subtype; 764 765 { 766 const CGEN_INSN *insn; 767 int i; 768 769 /* Update the recorded insn. */ 770 771 for (i = 0, insn = fragP->fr_cgen.insn; i < 4; i++, insn++) 772 { 773 if ((strcmp (CGEN_INSN_MNEMONIC (insn), 774 CGEN_INSN_MNEMONIC (fragP->fr_cgen.insn)) 775 == 0) 776 && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED)) 777 break; 778 } 779 780 if (i == 4) 781 abort (); 782 783 fragP->fr_cgen.insn = insn; 784 } 785 } 786 787 return md_relax_table[fragP->fr_subtype].rlx_length; 788 } 789 790 /* *FRAGP has been relaxed to its final size, and now needs to have 791 the bytes inside it modified to conform to the new size. 792 793 Called after relaxation is finished. 794 fragP->fr_type == rs_machine_dependent. 795 fragP->fr_subtype is the subtype of what the address relaxed to. */ 796 797 void 798 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, 799 segT sec, 800 fragS *fragP) 801 { 802 char *opcode; 803 char *displacement; 804 int target_address; 805 int opcode_address; 806 int extension; 807 int addend; 808 int opindx = -1; 809 810 opcode = fragP->fr_opcode; 811 812 /* Address opcode resides at in file space. */ 813 opcode_address = fragP->fr_address + fragP->fr_fix - 2; 814 extension = 0; 815 displacement = &opcode[1]; 816 817 /* Set up any addend necessary for branches. */ 818 if (S_GET_SEGMENT (fragP->fr_symbol) != sec 819 || S_IS_EXTERNAL (fragP->fr_symbol) 820 || S_IS_WEAK (fragP->fr_symbol)) 821 { 822 /* Symbol must be resolved by linker. */ 823 if (fragP->fr_offset & 1) 824 as_warn (_("Addend to unresolved symbol not on word boundary.")); 825 addend = 0; 826 } 827 else 828 { 829 /* Address we want to reach in file space. */ 830 target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset; 831 addend = (target_address - (opcode_address & -2)); 832 } 833 834 /* Do all the housekeeping for frag conversions. */ 835 switch (fragP->fr_subtype) 836 { 837 case EPIPHANY_RELAX_ARITH_SIMM11: 838 *opcode |= OP4_IMM32; 839 displacement = &opcode[0]; 840 extension += 3; 841 842 addend 843 = (((addend & 0x7) << 7) 844 | opcode[0] 845 | ((addend & 0x7f8) << 13) 846 | (opcode[1] << 8) 847 | (opcode[2] << 16)); 848 849 opindx = EPIPHANY_OPERAND_SIMM11; 850 break; 851 852 case EPIPHANY_RELAX_BRANCH_LONG: 853 /* Branches differ only in low nibble of instruction being 8 not 0. 854 24 bit displacement goes to bytes 1..3 . */ 855 *opcode |= OP4_BRANCH; 856 extension += 2; 857 858 addend >>= 1; /* Convert to word offset. */ 859 opindx = EPIPHANY_OPERAND_SIMM24; 860 break; 861 862 case EPIPHANY_RELAX_MOV_IMM16: 863 *opcode |= OP4_IMM32; 864 extension += 3; 865 866 addend 867 = (((addend & 0xff00) << 12) 868 | (opcode[2] << 16) 869 | ((addend & 0x00ff) << 5) 870 | (opcode[1] << 8) 871 | opcode[0]); 872 displacement = &opcode[0]; 873 opindx = EPIPHANY_OPERAND_IMM16; 874 break; 875 876 case EPIPHANY_RELAX_LDST_IMM11: 877 *opcode |= OP4_LDSTRD; 878 displacement = &opcode[0]; 879 extension += 3; 880 881 if (addend < 0) 882 /* Convert twos-complement address value to sign-magnitude. */ 883 addend = (-addend & 0x7ff) | 0x800; 884 885 addend 886 = (((addend & 0x7) << 5) 887 | opcode[0] 888 | ((addend & 0xff8) << 13) 889 | (opcode[1] << 8) 890 | (opcode[2] << 16)); 891 892 opindx = EPIPHANY_OPERAND_DISP11; 893 break; 894 895 case EPIPHANY_RELAX_ARITH_SIMM3: 896 addend = ((addend & 7) << 5) | opcode[0]; 897 opindx = EPIPHANY_OPERAND_SIMM3; 898 break; 899 900 case EPIPHANY_RELAX_LDST_IMM3: 901 addend = ((addend & 7) << 5) | opcode[0]; 902 opindx = EPIPHANY_OPERAND_DISP3; 903 904 case EPIPHANY_RELAX_BRANCH_SHORT: 905 addend >>= 1; /* Convert to a word offset. */ 906 displacement = & opcode[1]; 907 opindx = EPIPHANY_OPERAND_SIMM8; 908 break; 909 910 case EPIPHANY_RELAX_MOV_IMM8: 911 addend 912 = (((addend & 0xff) << 5) 913 | opcode[0] 914 | (opcode[1] << 8)); 915 opindx = EPIPHANY_OPERAND_IMM8; 916 break; 917 918 case EPIPHANY_RELAX_NONE: 919 case EPIPHANY_RELAX_NEED_RELAXING: 920 default: /* Anything else? */ 921 as_bad ("unrecognized fragment subtype"); 922 break; 923 } 924 925 /* Create a relocation for symbols that must be resolved by the linker. 926 Otherwise output the completed insn. */ 927 928 if (S_GET_SEGMENT (fragP->fr_symbol) != sec 929 || S_IS_EXTERNAL (fragP->fr_symbol) 930 || S_IS_WEAK (fragP->fr_symbol)) 931 { 932 fixS *fixP; 933 const CGEN_OPERAND *operand 934 = cgen_operand_lookup_by_num (gas_cgen_cpu_desc, opindx); 935 bfd_reloc_code_real_type reloc_type; 936 937 gas_assert (fragP->fr_cgen.insn != 0); 938 939 reloc_type = md_cgen_lookup_reloc (fragP->fr_cgen.insn, operand, NULL); 940 941 fixP = gas_cgen_record_fixup (fragP, 942 /* Offset of insn in frag. */ 943 (opcode - fragP->fr_literal), 944 fragP->fr_cgen.insn, 945 CGEN_INSN_BITSIZE (fragP->fr_cgen.insn) / 8, 946 operand, 947 reloc_type, 948 fragP->fr_symbol, fragP->fr_offset); 949 fixP->fx_r_type = fixP->fx_cgen.opinfo; 950 } 951 952 md_number_to_chars (displacement, (valueT) addend, extension + 1); 953 954 fragP->fr_fix += (extension & -2); /* 0,2 or 4 bytes added. */ 955 } 956 957 958 /* Functions concerning relocs. */ 959 960 /* The location from which a PC relative jump should be calculated, 961 given a PC relative reloc. */ 962 963 long 964 md_pcrel_from_section (fixS *fixP, segT sec) 965 { 966 if (fixP->fx_addsy != (symbolS *) NULL 967 && (!S_IS_DEFINED (fixP->fx_addsy) 968 || (S_GET_SEGMENT (fixP->fx_addsy) != sec) 969 || S_IS_EXTERNAL (fixP->fx_addsy) 970 || S_IS_WEAK (fixP->fx_addsy))) 971 return 0; 972 973 return fixP->fx_frag->fr_address + fixP->fx_where; 974 } 975 976 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP. 977 Returns BFD_RELOC_NONE if no reloc type can be found. 978 *FIXP may be modified if desired. */ 979 980 bfd_reloc_code_real_type 981 md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED, 982 const CGEN_OPERAND *operand, 983 fixS *fixP ATTRIBUTE_UNUSED) 984 { 985 switch (operand->type) 986 { 987 case EPIPHANY_OPERAND_SIMM11: 988 return BFD_RELOC_EPIPHANY_SIMM11; 989 case EPIPHANY_OPERAND_DISP11: 990 return BFD_RELOC_EPIPHANY_IMM11; 991 992 case EPIPHANY_OPERAND_SIMM8: 993 return BFD_RELOC_EPIPHANY_SIMM8; 994 case EPIPHANY_OPERAND_SIMM24: 995 return BFD_RELOC_EPIPHANY_SIMM24; 996 997 case EPIPHANY_OPERAND_IMM8: 998 return BFD_RELOC_EPIPHANY_IMM8; 999 1000 case EPIPHANY_OPERAND_IMM16: 1001 if (0 == strcmp ("movt", CGEN_INSN_MNEMONIC (insn))) 1002 return BFD_RELOC_EPIPHANY_HIGH; 1003 else if (0 == strcmp ("mov", CGEN_INSN_MNEMONIC (insn))) 1004 return BFD_RELOC_EPIPHANY_LOW; 1005 else 1006 as_bad ("unknown imm16 operand"); 1007 /* fall-thru */ 1008 1009 default: 1010 break; 1011 } 1012 return BFD_RELOC_NONE; 1013 } 1014 1015 1016 /* Turn a string in input_line_pointer into a floating point constant 1017 of type TYPE, and store the appropriate bytes in *LITP. The number 1018 of LITTLENUMS emitted is stored in *SIZEP. An error message is 1019 returned, or NULL on OK. */ 1020 1021 /* Equal to MAX_PRECISION in atof-ieee.c. */ 1022 #define MAX_LITTLENUMS 6 1023 1024 char * 1025 md_atof (int type, char *litP, int *sizeP) 1026 { 1027 return ieee_md_atof (type, litP, sizeP, FALSE); 1028 } 1029 1030 /* Return true if can adjust the reloc to be relative to its section 1031 (such as .data) instead of relative to some symbol. */ 1032 1033 bfd_boolean 1034 epiphany_fix_adjustable (fixS *fixP) 1035 { 1036 bfd_reloc_code_real_type reloc_type; 1037 1038 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED) 1039 { 1040 const CGEN_INSN *insn = fixP->fx_cgen.insn; 1041 int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED; 1042 const CGEN_OPERAND *operand = 1043 cgen_operand_lookup_by_num (gas_cgen_cpu_desc, opindex); 1044 1045 reloc_type = md_cgen_lookup_reloc (insn, operand, fixP); 1046 } 1047 else 1048 reloc_type = fixP->fx_r_type; 1049 1050 if (fixP->fx_addsy == NULL) 1051 return TRUE; 1052 1053 /* Prevent all adjustments to global symbols. */ 1054 if (S_IS_EXTERNAL (fixP->fx_addsy)) 1055 return FALSE; 1056 1057 if (S_IS_WEAK (fixP->fx_addsy)) 1058 return FALSE; 1059 1060 if (pic_code 1061 && (reloc_type == BFD_RELOC_EPIPHANY_SIMM24 1062 || reloc_type == BFD_RELOC_EPIPHANY_SIMM8 1063 || reloc_type == BFD_RELOC_EPIPHANY_HIGH 1064 || reloc_type == BFD_RELOC_EPIPHANY_LOW)) 1065 return FALSE; 1066 1067 /* Since we don't use partial_inplace, we must not reduce symbols in 1068 mergable sections to their section symbol. */ 1069 if ((S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) != 0) 1070 return FALSE; 1071 1072 return TRUE; 1073 } 1074 1075 void 1076 epiphany_elf_final_processing (void) 1077 { 1078 elf_elfheader (stdoutput)->e_flags |= epiphany_flags; 1079 } 1080 1081 int 1082 epiphany_cgen_parse_fix_exp (int opinfo, expressionS *exp ATTRIBUTE_UNUSED) 1083 { 1084 LITTLENUM_TYPE words[2]; 1085 1086 switch (opinfo) 1087 { 1088 case BFD_RELOC_EPIPHANY_LOW: 1089 case BFD_RELOC_EPIPHANY_HIGH: 1090 break; 1091 default: 1092 return opinfo; 1093 } 1094 1095 /* Doing a %LOW or %HIGH. */ 1096 switch (exp->X_op) 1097 { 1098 default: 1099 return opinfo; 1100 case O_big: /* Bignum. */ 1101 if (exp->X_add_number > 0) /* Integer value too large. */ 1102 return opinfo; 1103 } 1104 1105 /* Convert to SP number. */ 1106 gen_to_words (words, 2, 8L); 1107 exp->X_add_number = words[1] | (words[0] << 16); 1108 exp->X_op = O_constant; 1109 return opinfo; 1110 } 1111