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