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