1 /* tc-frv.c -- Assembler for the Fujitsu FRV. 2 Copyright (C) 2002-2016 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 #include "as.h" 22 #include "subsegs.h" 23 #include "symcat.h" 24 #include "opcodes/frv-desc.h" 25 #include "opcodes/frv-opc.h" 26 #include "cgen.h" 27 #include "libbfd.h" 28 #include "elf/common.h" 29 #include "elf/frv.h" 30 #include "dwarf2dbg.h" 31 32 /* Structure to hold all of the different components describing 33 an individual instruction. */ 34 typedef 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 } 52 frv_insn; 53 54 enum vliw_insn_type 55 { 56 VLIW_GENERIC_TYPE, /* Don't care about this insn. */ 57 VLIW_BRANCH_TYPE, /* A Branch. */ 58 VLIW_LABEL_TYPE, /* A Label. */ 59 VLIW_NOP_TYPE, /* A NOP. */ 60 VLIW_BRANCH_HAS_NOPS /* A Branch that requires NOPS. */ 61 }; 62 63 /* We're going to use these in the fr_subtype field to mark 64 whether to keep inserted nops. */ 65 66 #define NOP_KEEP 1 /* Keep these NOPS. */ 67 #define NOP_DELETE 2 /* Delete these NOPS. */ 68 69 #define DO_COUNT TRUE 70 #define DONT_COUNT FALSE 71 72 /* A list of insns within a VLIW insn. */ 73 struct vliw_insn_list 74 { 75 /* The type of this insn. */ 76 enum vliw_insn_type type; 77 78 /* The corresponding gas insn information. */ 79 const CGEN_INSN *insn; 80 81 /* For branches and labels, the symbol that is referenced. */ 82 symbolS *sym; 83 84 /* For branches, the frag containing the single nop that was generated. */ 85 fragS *snop_frag; 86 87 /* For branches, the frag containing the double nop that was generated. */ 88 fragS *dnop_frag; 89 90 /* Pointer to raw data for this insn. */ 91 char *address; 92 93 /* Next insn in list. */ 94 struct vliw_insn_list *next; 95 }; 96 97 static struct vliw_insn_list single_nop_insn = { 98 VLIW_NOP_TYPE, NULL, NULL, NULL, NULL, NULL, NULL }; 99 100 static struct vliw_insn_list double_nop_insn = { 101 VLIW_NOP_TYPE, NULL, NULL, NULL, NULL, NULL, NULL }; 102 103 struct vliw_chain 104 { 105 int num; 106 int insn_count; 107 struct vliw_insn_list *insn_list; 108 struct vliw_chain *next; 109 }; 110 111 static struct vliw_chain *vliw_chain_top; 112 static struct vliw_chain *current_vliw_chain; 113 static struct vliw_chain *previous_vliw_chain; 114 static struct vliw_insn_list *current_vliw_insn; 115 116 const char comment_chars[] = ";"; 117 const char line_comment_chars[] = "#"; 118 const char line_separator_chars[] = "!"; 119 const char EXP_CHARS[] = "eE"; 120 const char FLT_CHARS[] = "dD"; 121 122 static FRV_VLIW vliw; 123 124 /* Default machine */ 125 126 #ifdef DEFAULT_CPU_FRV 127 #define DEFAULT_MACHINE bfd_mach_frv 128 #define DEFAULT_FLAGS EF_FRV_CPU_GENERIC 129 130 #else 131 #ifdef DEFAULT_CPU_FR300 132 #define DEFAULT_MACHINE bfd_mach_fr300 133 #define DEFAULT_FLAGS EF_FRV_CPU_FR300 134 135 #else 136 #ifdef DEFAULT_CPU_SIMPLE 137 #define DEFAULT_MACHINE bfd_mach_frvsimple 138 #define DEFAULT_FLAGS EF_FRV_CPU_SIMPLE 139 140 #else 141 #ifdef DEFAULT_CPU_TOMCAT 142 #define DEFAULT_MACHINE bfd_mach_frvtomcat 143 #define DEFAULT_FLAGS EF_FRV_CPU_TOMCAT 144 145 #else 146 #ifdef DEFAULT_CPU_FR400 147 #define DEFAULT_MACHINE bfd_mach_fr400 148 #define DEFAULT_FLAGS EF_FRV_CPU_FR400 149 150 #else 151 #ifdef DEFAULT_CPU_FR550 152 #define DEFAULT_MACHINE bfd_mach_fr550 153 #define DEFAULT_FLAGS EF_FRV_CPU_FR550 154 155 #else 156 #define DEFAULT_MACHINE bfd_mach_fr500 157 #define DEFAULT_FLAGS EF_FRV_CPU_FR500 158 #endif 159 #endif 160 #endif 161 #endif 162 #endif 163 #endif 164 165 #ifdef TE_LINUX 166 # define DEFAULT_FDPIC EF_FRV_FDPIC 167 #else 168 # define DEFAULT_FDPIC 0 169 #endif 170 171 static unsigned long frv_mach = bfd_mach_frv; 172 static bfd_boolean fr400_audio; 173 174 /* Flags to set in the elf header */ 175 static flagword frv_flags = DEFAULT_FLAGS | DEFAULT_FDPIC; 176 177 static int frv_user_set_flags_p = 0; 178 static int frv_pic_p = 0; 179 static const char *frv_pic_flag = DEFAULT_FDPIC ? "-mfdpic" : (const char *)0; 180 181 /* Print tomcat-specific debugging info. */ 182 static int tomcat_debug = 0; 183 184 /* Tomcat-specific NOP statistics. */ 185 static int tomcat_stats = 0; 186 static int tomcat_doubles = 0; 187 static int tomcat_singles = 0; 188 189 /* Forward reference to static functions */ 190 static void frv_set_flags (int); 191 static void frv_pic_ptr (int); 192 193 /* The target specific pseudo-ops which we support. */ 194 const pseudo_typeS md_pseudo_table[] = 195 { 196 { "eflags", frv_set_flags, 0 }, 197 { "word", cons, 4 }, 198 { "picptr", frv_pic_ptr, 4 }, 199 { NULL, NULL, 0 } 200 }; 201 202 203 #define FRV_SHORTOPTS "G:" 205 const char * md_shortopts = FRV_SHORTOPTS; 206 207 #define OPTION_GPR_32 (OPTION_MD_BASE) 208 #define OPTION_GPR_64 (OPTION_MD_BASE + 1) 209 #define OPTION_FPR_32 (OPTION_MD_BASE + 2) 210 #define OPTION_FPR_64 (OPTION_MD_BASE + 3) 211 #define OPTION_SOFT_FLOAT (OPTION_MD_BASE + 4) 212 #define OPTION_DWORD_YES (OPTION_MD_BASE + 5) 213 #define OPTION_DWORD_NO (OPTION_MD_BASE + 6) 214 #define OPTION_DOUBLE (OPTION_MD_BASE + 7) 215 #define OPTION_NO_DOUBLE (OPTION_MD_BASE + 8) 216 #define OPTION_MEDIA (OPTION_MD_BASE + 9) 217 #define OPTION_NO_MEDIA (OPTION_MD_BASE + 10) 218 #define OPTION_CPU (OPTION_MD_BASE + 11) 219 #define OPTION_PIC (OPTION_MD_BASE + 12) 220 #define OPTION_BIGPIC (OPTION_MD_BASE + 13) 221 #define OPTION_LIBPIC (OPTION_MD_BASE + 14) 222 #define OPTION_MULADD (OPTION_MD_BASE + 15) 223 #define OPTION_NO_MULADD (OPTION_MD_BASE + 16) 224 #define OPTION_TOMCAT_DEBUG (OPTION_MD_BASE + 17) 225 #define OPTION_TOMCAT_STATS (OPTION_MD_BASE + 18) 226 #define OPTION_PACK (OPTION_MD_BASE + 19) 227 #define OPTION_NO_PACK (OPTION_MD_BASE + 20) 228 #define OPTION_FDPIC (OPTION_MD_BASE + 21) 229 #define OPTION_NOPIC (OPTION_MD_BASE + 22) 230 231 struct option md_longopts[] = 232 { 233 { "mgpr-32", no_argument, NULL, OPTION_GPR_32 }, 234 { "mgpr-64", no_argument, NULL, OPTION_GPR_64 }, 235 { "mfpr-32", no_argument, NULL, OPTION_FPR_32 }, 236 { "mfpr-64", no_argument, NULL, OPTION_FPR_64 }, 237 { "mhard-float", no_argument, NULL, OPTION_FPR_64 }, 238 { "msoft-float", no_argument, NULL, OPTION_SOFT_FLOAT }, 239 { "mdword", no_argument, NULL, OPTION_DWORD_YES }, 240 { "mno-dword", no_argument, NULL, OPTION_DWORD_NO }, 241 { "mdouble", no_argument, NULL, OPTION_DOUBLE }, 242 { "mno-double", no_argument, NULL, OPTION_NO_DOUBLE }, 243 { "mmedia", no_argument, NULL, OPTION_MEDIA }, 244 { "mno-media", no_argument, NULL, OPTION_NO_MEDIA }, 245 { "mcpu", required_argument, NULL, OPTION_CPU }, 246 { "mpic", no_argument, NULL, OPTION_PIC }, 247 { "mPIC", no_argument, NULL, OPTION_BIGPIC }, 248 { "mlibrary-pic", no_argument, NULL, OPTION_LIBPIC }, 249 { "mmuladd", no_argument, NULL, OPTION_MULADD }, 250 { "mno-muladd", no_argument, NULL, OPTION_NO_MULADD }, 251 { "mtomcat-debug", no_argument, NULL, OPTION_TOMCAT_DEBUG }, 252 { "mtomcat-stats", no_argument, NULL, OPTION_TOMCAT_STATS }, 253 { "mpack", no_argument, NULL, OPTION_PACK }, 254 { "mno-pack", no_argument, NULL, OPTION_NO_PACK }, 255 { "mfdpic", no_argument, NULL, OPTION_FDPIC }, 256 { "mnopic", no_argument, NULL, OPTION_NOPIC }, 257 { NULL, no_argument, NULL, 0 }, 258 }; 259 260 size_t md_longopts_size = sizeof (md_longopts); 261 262 /* What value to give to bfd_set_gp_size. */ 263 static int g_switch_value = 8; 264 265 int 266 md_parse_option (int c, const char *arg) 267 { 268 switch (c) 269 { 270 default: 271 return 0; 272 273 case 'G': 274 g_switch_value = atoi (arg); 275 if (! g_switch_value) 276 frv_flags |= EF_FRV_G0; 277 break; 278 279 case OPTION_GPR_32: 280 frv_flags = (frv_flags & ~EF_FRV_GPR_MASK) | EF_FRV_GPR_32; 281 break; 282 283 case OPTION_GPR_64: 284 frv_flags = (frv_flags & ~EF_FRV_GPR_MASK) | EF_FRV_GPR_64; 285 break; 286 287 case OPTION_FPR_32: 288 frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_32; 289 break; 290 291 case OPTION_FPR_64: 292 frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_64; 293 break; 294 295 case OPTION_SOFT_FLOAT: 296 frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_NONE; 297 break; 298 299 case OPTION_DWORD_YES: 300 frv_flags = (frv_flags & ~EF_FRV_DWORD_MASK) | EF_FRV_DWORD_YES; 301 break; 302 303 case OPTION_DWORD_NO: 304 frv_flags = (frv_flags & ~EF_FRV_DWORD_MASK) | EF_FRV_DWORD_NO; 305 break; 306 307 case OPTION_DOUBLE: 308 frv_flags |= EF_FRV_DOUBLE; 309 break; 310 311 case OPTION_NO_DOUBLE: 312 frv_flags &= ~EF_FRV_DOUBLE; 313 break; 314 315 case OPTION_MEDIA: 316 frv_flags |= EF_FRV_MEDIA; 317 break; 318 319 case OPTION_NO_MEDIA: 320 frv_flags &= ~EF_FRV_MEDIA; 321 break; 322 323 case OPTION_MULADD: 324 frv_flags |= EF_FRV_MULADD; 325 break; 326 327 case OPTION_NO_MULADD: 328 frv_flags &= ~EF_FRV_MULADD; 329 break; 330 331 case OPTION_PACK: 332 frv_flags &= ~EF_FRV_NOPACK; 333 break; 334 335 case OPTION_NO_PACK: 336 frv_flags |= EF_FRV_NOPACK; 337 break; 338 339 case OPTION_CPU: 340 { 341 const char *p; 342 int cpu_flags = EF_FRV_CPU_GENERIC; 343 344 /* Identify the processor type */ 345 p = arg; 346 if (strcmp (p, "frv") == 0) 347 { 348 cpu_flags = EF_FRV_CPU_GENERIC; 349 frv_mach = bfd_mach_frv; 350 } 351 352 else if (strcmp (p, "fr500") == 0) 353 { 354 cpu_flags = EF_FRV_CPU_FR500; 355 frv_mach = bfd_mach_fr500; 356 } 357 358 else if (strcmp (p, "fr550") == 0) 359 { 360 cpu_flags = EF_FRV_CPU_FR550; 361 frv_mach = bfd_mach_fr550; 362 } 363 364 else if (strcmp (p, "fr450") == 0) 365 { 366 cpu_flags = EF_FRV_CPU_FR450; 367 frv_mach = bfd_mach_fr450; 368 } 369 370 else if (strcmp (p, "fr405") == 0) 371 { 372 cpu_flags = EF_FRV_CPU_FR405; 373 frv_mach = bfd_mach_fr400; 374 fr400_audio = TRUE; 375 } 376 377 else if (strcmp (p, "fr400") == 0) 378 { 379 cpu_flags = EF_FRV_CPU_FR400; 380 frv_mach = bfd_mach_fr400; 381 fr400_audio = FALSE; 382 } 383 384 else if (strcmp (p, "fr300") == 0) 385 { 386 cpu_flags = EF_FRV_CPU_FR300; 387 frv_mach = bfd_mach_fr300; 388 } 389 390 else if (strcmp (p, "simple") == 0) 391 { 392 cpu_flags = EF_FRV_CPU_SIMPLE; 393 frv_mach = bfd_mach_frvsimple; 394 frv_flags |= EF_FRV_NOPACK; 395 } 396 397 else if (strcmp (p, "tomcat") == 0) 398 { 399 cpu_flags = EF_FRV_CPU_TOMCAT; 400 frv_mach = bfd_mach_frvtomcat; 401 } 402 403 else 404 { 405 as_fatal (_("Unknown cpu -mcpu=%s"), arg); 406 return 0; 407 } 408 409 frv_flags = (frv_flags & ~EF_FRV_CPU_MASK) | cpu_flags; 410 } 411 break; 412 413 case OPTION_PIC: 414 frv_flags |= EF_FRV_PIC; 415 frv_pic_p = 1; 416 frv_pic_flag = "-fpic"; 417 break; 418 419 case OPTION_BIGPIC: 420 frv_flags |= EF_FRV_BIGPIC; 421 frv_pic_p = 1; 422 frv_pic_flag = "-fPIC"; 423 break; 424 425 case OPTION_LIBPIC: 426 frv_flags |= (EF_FRV_LIBPIC | EF_FRV_G0); 427 frv_pic_p = 1; 428 frv_pic_flag = "-mlibrary-pic"; 429 g_switch_value = 0; 430 break; 431 432 case OPTION_FDPIC: 433 frv_flags |= EF_FRV_FDPIC; 434 frv_pic_flag = "-mfdpic"; 435 break; 436 437 case OPTION_NOPIC: 438 frv_flags &= ~(EF_FRV_FDPIC | EF_FRV_PIC 439 | EF_FRV_BIGPIC | EF_FRV_LIBPIC); 440 frv_pic_flag = 0; 441 break; 442 443 case OPTION_TOMCAT_DEBUG: 444 tomcat_debug = 1; 445 break; 446 447 case OPTION_TOMCAT_STATS: 448 tomcat_stats = 1; 449 break; 450 } 451 452 return 1; 453 } 454 455 void 456 md_show_usage (FILE * stream) 457 { 458 fprintf (stream, _("FRV specific command line options:\n")); 459 fprintf (stream, _("-G n Put data <= n bytes in the small data area\n")); 460 fprintf (stream, _("-mgpr-32 Mark generated file as only using 32 GPRs\n")); 461 fprintf (stream, _("-mgpr-64 Mark generated file as using all 64 GPRs\n")); 462 fprintf (stream, _("-mfpr-32 Mark generated file as only using 32 FPRs\n")); 463 fprintf (stream, _("-mfpr-64 Mark generated file as using all 64 FPRs\n")); 464 fprintf (stream, _("-msoft-float Mark generated file as using software FP\n")); 465 fprintf (stream, _("-mdword Mark generated file as using a 8-byte stack alignment\n")); 466 fprintf (stream, _("-mno-dword Mark generated file as using a 4-byte stack alignment\n")); 467 fprintf (stream, _("-mdouble Mark generated file as using double precision FP insns\n")); 468 fprintf (stream, _("-mmedia Mark generated file as using media insns\n")); 469 fprintf (stream, _("-mmuladd Mark generated file as using multiply add/subtract insns\n")); 470 fprintf (stream, _("-mpack Allow instructions to be packed\n")); 471 fprintf (stream, _("-mno-pack Do not allow instructions to be packed\n")); 472 fprintf (stream, _("-mpic Mark generated file as using small position independent code\n")); 473 fprintf (stream, _("-mPIC Mark generated file as using large position independent code\n")); 474 fprintf (stream, _("-mlibrary-pic Mark generated file as using position indepedent code for libraries\n")); 475 fprintf (stream, _("-mfdpic Assemble for the FDPIC ABI\n")); 476 fprintf (stream, _("-mnopic Disable -mpic, -mPIC, -mlibrary-pic and -mfdpic\n")); 477 fprintf (stream, _("-mcpu={fr500|fr550|fr400|fr405|fr450|fr300|frv|simple|tomcat}\n")); 478 fprintf (stream, _(" Record the cpu type\n")); 479 fprintf (stream, _("-mtomcat-stats Print out stats for tomcat workarounds\n")); 480 fprintf (stream, _("-mtomcat-debug Debug tomcat workarounds\n")); 481 } 482 483 484 void 486 md_begin (void) 487 { 488 /* Initialize the `cgen' interface. */ 489 490 /* Set the machine number and endian. */ 491 gas_cgen_cpu_desc = frv_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0, 492 CGEN_CPU_OPEN_ENDIAN, 493 CGEN_ENDIAN_BIG, 494 CGEN_CPU_OPEN_END); 495 frv_cgen_init_asm (gas_cgen_cpu_desc); 496 497 /* This is a callback from cgen to gas to parse operands. */ 498 cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand); 499 500 /* Set the ELF flags if desired. */ 501 if (frv_flags) 502 bfd_set_private_flags (stdoutput, frv_flags); 503 504 /* Set the machine type */ 505 bfd_default_set_arch_mach (stdoutput, bfd_arch_frv, frv_mach); 506 507 /* Set up gp size so we can put local common items in .sbss */ 508 bfd_set_gp_size (stdoutput, g_switch_value); 509 510 frv_vliw_reset (& vliw, frv_mach, frv_flags); 511 } 512 513 bfd_boolean 514 frv_md_fdpic_enabled (void) 515 { 516 return (frv_flags & EF_FRV_FDPIC) != 0; 517 } 518 519 int chain_num = 0; 520 521 static struct vliw_insn_list * 522 frv_insert_vliw_insn (bfd_boolean count) 523 { 524 struct vliw_insn_list *vliw_insn_list_entry; 525 struct vliw_chain *vliw_chain_entry; 526 527 if (current_vliw_chain == NULL) 528 { 529 vliw_chain_entry = XNEW (struct vliw_chain); 530 vliw_chain_entry->insn_count = 0; 531 vliw_chain_entry->insn_list = NULL; 532 vliw_chain_entry->next = NULL; 533 vliw_chain_entry->num = chain_num++; 534 535 if (!vliw_chain_top) 536 vliw_chain_top = vliw_chain_entry; 537 current_vliw_chain = vliw_chain_entry; 538 if (previous_vliw_chain) 539 previous_vliw_chain->next = vliw_chain_entry; 540 } 541 542 vliw_insn_list_entry = XNEW (struct vliw_insn_list); 543 vliw_insn_list_entry->type = VLIW_GENERIC_TYPE; 544 vliw_insn_list_entry->insn = NULL; 545 vliw_insn_list_entry->sym = NULL; 546 vliw_insn_list_entry->snop_frag = NULL; 547 vliw_insn_list_entry->dnop_frag = NULL; 548 vliw_insn_list_entry->next = NULL; 549 550 if (count) 551 current_vliw_chain->insn_count++; 552 553 if (current_vliw_insn) 554 current_vliw_insn->next = vliw_insn_list_entry; 555 current_vliw_insn = vliw_insn_list_entry; 556 557 if (!current_vliw_chain->insn_list) 558 current_vliw_chain->insn_list = current_vliw_insn; 559 560 return vliw_insn_list_entry; 561 } 562 563 /* Identify the following cases: 564 565 1) A VLIW insn that contains both a branch and the branch destination. 566 This requires the insertion of two vliw instructions before the 567 branch. The first consists of two nops. The second consists of 568 a single nop. 569 570 2) A single instruction VLIW insn which is the destination of a branch 571 that is in the next VLIW insn. This requires the insertion of a vliw 572 insn containing two nops before the branch. 573 574 3) A double instruction VLIW insn which contains the destination of a 575 branch that is in the next VLIW insn. This requires the insertion of 576 a VLIW insn containing a single nop before the branch. 577 578 4) A single instruction VLIW insn which contains branch destination (x), 579 followed by a single instruction VLIW insn which does not contain 580 the branch to (x), followed by a VLIW insn which does contain the branch 581 to (x). This requires the insertion of a VLIW insn containing a single 582 nop before the VLIW instruction containing the branch. 583 584 */ 585 #define FRV_IS_NOP(insn) (insn.buffer[0] == FRV_NOP_PACK || insn.buffer[0] == FRV_NOP_NOPACK) 586 #define FRV_NOP_PACK 0x00880000 /* ori.p gr0,0,gr0 */ 587 #define FRV_NOP_NOPACK 0x80880000 /* ori gr0,0,gr0 */ 588 589 /* Check a vliw insn for an insn of type containing the sym passed in label_sym. */ 590 591 static struct vliw_insn_list * 592 frv_find_in_vliw (enum vliw_insn_type vliw_insn_type, 593 struct vliw_chain *this_chain, 594 symbolS *label_sym) 595 { 596 597 struct vliw_insn_list *the_insn; 598 599 if (!this_chain) 600 return NULL; 601 602 for (the_insn = this_chain->insn_list; the_insn; the_insn = the_insn->next) 603 { 604 if (the_insn->type == vliw_insn_type 605 && the_insn->sym == label_sym) 606 return the_insn; 607 } 608 609 return NULL; 610 } 611 612 enum vliw_nop_type 613 { 614 /* A Vliw insn containing a single nop insn. */ 615 VLIW_SINGLE_NOP, 616 617 /* A Vliw insn containing two nop insns. */ 618 VLIW_DOUBLE_NOP, 619 620 /* Two vliw insns. The first containing two nop insns. 621 The second contain a single nop insn. */ 622 VLIW_DOUBLE_THEN_SINGLE_NOP 623 }; 624 625 static void 626 frv_debug_tomcat (struct vliw_chain *start_chain) 627 { 628 struct vliw_chain *this_chain; 629 struct vliw_insn_list *this_insn; 630 int i = 1; 631 632 for (this_chain = start_chain; this_chain; this_chain = this_chain->next, i++) 633 { 634 fprintf (stderr, "\nVliw Insn #%d, #insns: %d\n", i, this_chain->insn_count); 635 636 for (this_insn = this_chain->insn_list; this_insn; this_insn = this_insn->next) 637 { 638 if (this_insn->type == VLIW_LABEL_TYPE) 639 fprintf (stderr, "Label Value: %p\n", this_insn->sym); 640 else if (this_insn->type == VLIW_BRANCH_TYPE) 641 fprintf (stderr, "%s to %p\n", this_insn->insn->base->name, this_insn->sym); 642 else if (this_insn->type == VLIW_BRANCH_HAS_NOPS) 643 fprintf (stderr, "nop'd %s to %p\n", this_insn->insn->base->name, this_insn->sym); 644 else if (this_insn->type == VLIW_NOP_TYPE) 645 fprintf (stderr, "Nop\n"); 646 else 647 fprintf (stderr, " %s\n", this_insn->insn->base->name); 648 } 649 } 650 } 651 652 static void 653 frv_adjust_vliw_count (struct vliw_chain *this_chain) 654 { 655 struct vliw_insn_list *this_insn; 656 657 this_chain->insn_count = 0; 658 659 for (this_insn = this_chain->insn_list; 660 this_insn; 661 this_insn = this_insn->next) 662 { 663 if (this_insn->type != VLIW_LABEL_TYPE) 664 this_chain->insn_count++; 665 } 666 667 } 668 669 /* Insert the desired nop combination in the vliw chain before insert_before_insn. 670 Rechain the vliw insn. */ 671 672 static struct vliw_chain * 673 frv_tomcat_shuffle (enum vliw_nop_type this_nop_type, 674 struct vliw_chain *vliw_to_split, 675 struct vliw_insn_list *insert_before_insn) 676 { 677 678 bfd_boolean pack_prev = FALSE; 679 struct vliw_chain *return_me = NULL; 680 struct vliw_insn_list *prev_insn = NULL; 681 struct vliw_insn_list *curr_insn = vliw_to_split->insn_list; 682 683 struct vliw_chain *double_nop = XNEW (struct vliw_chain); 684 struct vliw_chain *single_nop = XNEW (struct vliw_chain); 685 struct vliw_chain *second_part = XNEW (struct vliw_chain); 686 struct vliw_chain *curr_vliw = vliw_chain_top; 687 struct vliw_chain *prev_vliw = NULL; 688 689 while (curr_insn && curr_insn != insert_before_insn) 690 { 691 /* We can't set the packing bit on a label. If we have the case 692 label 1: 693 label 2: 694 label 3: 695 branch that needs nops 696 Then don't set pack bit later. */ 697 698 if (curr_insn->type != VLIW_LABEL_TYPE) 699 pack_prev = TRUE; 700 prev_insn = curr_insn; 701 curr_insn = curr_insn->next; 702 } 703 704 while (curr_vliw && curr_vliw != vliw_to_split) 705 { 706 prev_vliw = curr_vliw; 707 curr_vliw = curr_vliw->next; 708 } 709 710 switch (this_nop_type) 711 { 712 case VLIW_SINGLE_NOP: 713 if (!prev_insn) 714 { 715 /* Branch is first, Insert the NOP prior to this vliw insn. */ 716 if (prev_vliw) 717 prev_vliw->next = single_nop; 718 else 719 vliw_chain_top = single_nop; 720 single_nop->next = vliw_to_split; 721 vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS; 722 return_me = vliw_to_split; 723 } 724 else 725 { 726 /* Set the packing bit on the previous insn. */ 727 if (pack_prev) 728 { 729 char *buffer = prev_insn->address; 730 buffer[0] |= 0x80; 731 } 732 /* The branch is in the middle. Split this vliw insn into first 733 and second parts. Insert the NOP inbetween. */ 734 735 second_part->insn_list = insert_before_insn; 736 second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS; 737 second_part->next = vliw_to_split->next; 738 frv_adjust_vliw_count (second_part); 739 740 single_nop->next = second_part; 741 742 vliw_to_split->next = single_nop; 743 prev_insn->next = NULL; 744 745 return_me = second_part; 746 frv_adjust_vliw_count (vliw_to_split); 747 } 748 break; 749 750 case VLIW_DOUBLE_NOP: 751 if (!prev_insn) 752 { 753 /* Branch is first, Insert the NOP prior to this vliw insn. */ 754 if (prev_vliw) 755 prev_vliw->next = double_nop; 756 else 757 vliw_chain_top = double_nop; 758 759 double_nop->next = vliw_to_split; 760 return_me = vliw_to_split; 761 vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS; 762 } 763 else 764 { 765 /* Set the packing bit on the previous insn. */ 766 if (pack_prev) 767 { 768 char *buffer = prev_insn->address; 769 buffer[0] |= 0x80; 770 } 771 772 /* The branch is in the middle. Split this vliw insn into first 773 and second parts. Insert the NOP inbetween. */ 774 second_part->insn_list = insert_before_insn; 775 second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS; 776 second_part->next = vliw_to_split->next; 777 frv_adjust_vliw_count (second_part); 778 779 double_nop->next = second_part; 780 781 vliw_to_split->next = single_nop; 782 prev_insn->next = NULL; 783 frv_adjust_vliw_count (vliw_to_split); 784 785 return_me = second_part; 786 } 787 break; 788 789 case VLIW_DOUBLE_THEN_SINGLE_NOP: 790 double_nop->next = single_nop; 791 double_nop->insn_count = 2; 792 double_nop->insn_list = &double_nop_insn; 793 single_nop->insn_count = 1; 794 single_nop->insn_list = &single_nop_insn; 795 796 if (!prev_insn) 797 { 798 /* The branch is the first insn in this vliw. Don't split the vliw. Insert 799 the nops prior to this vliw. */ 800 if (prev_vliw) 801 prev_vliw->next = double_nop; 802 else 803 vliw_chain_top = double_nop; 804 805 single_nop->next = vliw_to_split; 806 return_me = vliw_to_split; 807 vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS; 808 } 809 else 810 { 811 /* Set the packing bit on the previous insn. */ 812 if (pack_prev) 813 { 814 char *buffer = prev_insn->address; 815 buffer[0] |= 0x80; 816 } 817 818 /* The branch is in the middle of this vliw insn. Split into first and 819 second parts. Insert the nop vliws in between. */ 820 second_part->insn_list = insert_before_insn; 821 second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS; 822 second_part->next = vliw_to_split->next; 823 frv_adjust_vliw_count (second_part); 824 825 single_nop->next = second_part; 826 827 vliw_to_split->next = double_nop; 828 prev_insn->next = NULL; 829 frv_adjust_vliw_count (vliw_to_split); 830 831 return_me = second_part; 832 } 833 break; 834 } 835 836 return return_me; 837 } 838 839 static void 840 frv_tomcat_analyze_vliw_chains (void) 841 { 842 struct vliw_chain *vliw1 = NULL; 843 struct vliw_chain *vliw2 = NULL; 844 struct vliw_chain *vliw3 = NULL; 845 846 struct vliw_insn_list *this_insn = NULL; 847 struct vliw_insn_list *temp_insn = NULL; 848 849 /* We potentially need to look at three VLIW insns to determine if the 850 workaround is required. Set them up. Ignore existing nops during analysis. */ 851 852 #define FRV_SET_VLIW_WINDOW(VLIW1, VLIW2, VLIW3) \ 853 if (VLIW1 && VLIW1->next) \ 854 VLIW2 = VLIW1->next; \ 855 else \ 856 VLIW2 = NULL; \ 857 if (VLIW2 && VLIW2->next) \ 858 VLIW3 = VLIW2->next; \ 859 else \ 860 VLIW3 = NULL 861 862 vliw1 = vliw_chain_top; 863 864 workaround_top: 865 866 FRV_SET_VLIW_WINDOW (vliw1, vliw2, vliw3); 867 868 if (!vliw1) 869 return; 870 871 if (vliw1->insn_count == 1) 872 { 873 /* check vliw1 for a label. */ 874 if (vliw1->insn_list->type == VLIW_LABEL_TYPE) 875 { 876 temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, vliw1->insn_list->sym); 877 if (temp_insn) 878 { 879 vliw1 = frv_tomcat_shuffle (VLIW_DOUBLE_NOP, vliw2, vliw1->insn_list); 880 temp_insn->dnop_frag->fr_subtype = NOP_KEEP; 881 vliw1 = vliw1->next; 882 if (tomcat_stats) 883 tomcat_doubles++; 884 goto workaround_top; 885 } 886 else if (vliw2 887 && vliw2->insn_count == 1 888 && (temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw3, vliw1->insn_list->sym)) != NULL) 889 { 890 temp_insn->snop_frag->fr_subtype = NOP_KEEP; 891 vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw3, vliw3->insn_list); 892 if (tomcat_stats) 893 tomcat_singles++; 894 goto workaround_top; 895 } 896 } 897 } 898 899 if (vliw1->insn_count == 2) 900 { 901 /* Check vliw1 for a label. */ 902 for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next) 903 { 904 if (this_insn->type == VLIW_LABEL_TYPE) 905 { 906 if ((temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, this_insn->sym)) != NULL) 907 { 908 temp_insn->snop_frag->fr_subtype = NOP_KEEP; 909 vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw2, this_insn); 910 if (tomcat_stats) 911 tomcat_singles++; 912 } 913 else 914 vliw1 = vliw1->next; 915 goto workaround_top; 916 } 917 } 918 } 919 /* Examine each insn in this VLIW. Look for the workaround criteria. */ 920 for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next) 921 { 922 /* Don't look at labels or nops. */ 923 while (this_insn 924 && (this_insn->type == VLIW_LABEL_TYPE 925 || this_insn->type == VLIW_NOP_TYPE 926 || this_insn->type == VLIW_BRANCH_HAS_NOPS)) 927 this_insn = this_insn->next; 928 929 if (!this_insn) 930 { 931 vliw1 = vliw2; 932 goto workaround_top; 933 } 934 935 if (frv_is_branch_insn (this_insn->insn)) 936 { 937 if ((temp_insn = frv_find_in_vliw (VLIW_LABEL_TYPE, vliw1, this_insn->sym)) != NULL) 938 { 939 /* Insert [nop/nop] [nop] before branch. */ 940 this_insn->snop_frag->fr_subtype = NOP_KEEP; 941 this_insn->dnop_frag->fr_subtype = NOP_KEEP; 942 vliw1 = frv_tomcat_shuffle (VLIW_DOUBLE_THEN_SINGLE_NOP, vliw1, this_insn); 943 goto workaround_top; 944 } 945 } 946 947 948 } 949 /* This vliw insn checks out okay. Take a look at the next one. */ 950 vliw1 = vliw1->next; 951 goto workaround_top; 952 } 953 954 void 955 frv_tomcat_workaround (void) 956 { 957 if (frv_mach != bfd_mach_frvtomcat) 958 return; 959 960 if (tomcat_debug) 961 frv_debug_tomcat (vliw_chain_top); 962 963 frv_tomcat_analyze_vliw_chains (); 964 965 if (tomcat_stats) 966 { 967 fprintf (stderr, "Inserted %d Single Nops\n", tomcat_singles); 968 fprintf (stderr, "Inserted %d Double Nops\n", tomcat_doubles); 969 } 970 } 971 972 static int 973 fr550_check_insn_acc_range (frv_insn *insn, int low, int hi) 974 { 975 int acc; 976 switch (CGEN_INSN_NUM (insn->insn)) 977 { 978 case FRV_INSN_MADDACCS: 979 case FRV_INSN_MSUBACCS: 980 case FRV_INSN_MDADDACCS: 981 case FRV_INSN_MDSUBACCS: 982 case FRV_INSN_MASACCS: 983 case FRV_INSN_MDASACCS: 984 acc = insn->fields.f_ACC40Si; 985 if (acc < low || acc > hi) 986 return 1; /* out of range */ 987 acc = insn->fields.f_ACC40Sk; 988 if (acc < low || acc > hi) 989 return 1; /* out of range */ 990 break; 991 case FRV_INSN_MMULHS: 992 case FRV_INSN_MMULHU: 993 case FRV_INSN_MMULXHS: 994 case FRV_INSN_MMULXHU: 995 case FRV_INSN_CMMULHS: 996 case FRV_INSN_CMMULHU: 997 case FRV_INSN_MQMULHS: 998 case FRV_INSN_MQMULHU: 999 case FRV_INSN_MQMULXHS: 1000 case FRV_INSN_MQMULXHU: 1001 case FRV_INSN_CMQMULHS: 1002 case FRV_INSN_CMQMULHU: 1003 case FRV_INSN_MMACHS: 1004 case FRV_INSN_MMRDHS: 1005 case FRV_INSN_CMMACHS: 1006 case FRV_INSN_MQMACHS: 1007 case FRV_INSN_CMQMACHS: 1008 case FRV_INSN_MQXMACHS: 1009 case FRV_INSN_MQXMACXHS: 1010 case FRV_INSN_MQMACXHS: 1011 case FRV_INSN_MCPXRS: 1012 case FRV_INSN_MCPXIS: 1013 case FRV_INSN_CMCPXRS: 1014 case FRV_INSN_CMCPXIS: 1015 case FRV_INSN_MQCPXRS: 1016 case FRV_INSN_MQCPXIS: 1017 acc = insn->fields.f_ACC40Sk; 1018 if (acc < low || acc > hi) 1019 return 1; /* out of range */ 1020 break; 1021 case FRV_INSN_MMACHU: 1022 case FRV_INSN_MMRDHU: 1023 case FRV_INSN_CMMACHU: 1024 case FRV_INSN_MQMACHU: 1025 case FRV_INSN_CMQMACHU: 1026 case FRV_INSN_MCPXRU: 1027 case FRV_INSN_MCPXIU: 1028 case FRV_INSN_CMCPXRU: 1029 case FRV_INSN_CMCPXIU: 1030 case FRV_INSN_MQCPXRU: 1031 case FRV_INSN_MQCPXIU: 1032 acc = insn->fields.f_ACC40Uk; 1033 if (acc < low || acc > hi) 1034 return 1; /* out of range */ 1035 break; 1036 default: 1037 break; 1038 } 1039 return 0; /* all is ok */ 1040 } 1041 1042 static int 1043 fr550_check_acc_range (FRV_VLIW *vlw, frv_insn *insn) 1044 { 1045 switch ((*vlw->current_vliw)[vlw->next_slot - 1]) 1046 { 1047 case UNIT_FM0: 1048 case UNIT_FM2: 1049 return fr550_check_insn_acc_range (insn, 0, 3); 1050 case UNIT_FM1: 1051 case UNIT_FM3: 1052 return fr550_check_insn_acc_range (insn, 4, 7); 1053 default: 1054 break; 1055 } 1056 return 0; /* all is ok */ 1057 } 1058 1059 /* Return true if the target implements instruction INSN. */ 1060 1061 static bfd_boolean 1062 target_implements_insn_p (const CGEN_INSN *insn) 1063 { 1064 switch (frv_mach) 1065 { 1066 default: 1067 /* bfd_mach_frv or generic. */ 1068 return TRUE; 1069 1070 case bfd_mach_fr300: 1071 case bfd_mach_frvsimple: 1072 return CGEN_INSN_MACH_HAS_P (insn, MACH_SIMPLE); 1073 1074 case bfd_mach_fr400: 1075 return ((fr400_audio || !CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_AUDIO)) 1076 && CGEN_INSN_MACH_HAS_P (insn, MACH_FR400)); 1077 1078 case bfd_mach_fr450: 1079 return CGEN_INSN_MACH_HAS_P (insn, MACH_FR450); 1080 1081 case bfd_mach_fr500: 1082 return CGEN_INSN_MACH_HAS_P (insn, MACH_FR500); 1083 1084 case bfd_mach_fr550: 1085 return CGEN_INSN_MACH_HAS_P (insn, MACH_FR550); 1086 } 1087 } 1088 1089 void 1090 md_assemble (char *str) 1091 { 1092 frv_insn insn; 1093 char *errmsg; 1094 int packing_constraint; 1095 finished_insnS finished_insn; 1096 fragS *double_nop_frag = NULL; 1097 fragS *single_nop_frag = NULL; 1098 struct vliw_insn_list *vliw_insn_list_entry = NULL; 1099 1100 /* Initialize GAS's cgen interface for a new instruction. */ 1101 gas_cgen_init_parse (); 1102 1103 memset (&insn, 0, sizeof (insn)); 1104 1105 insn.insn = frv_cgen_assemble_insn 1106 (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, &errmsg); 1107 1108 if (!insn.insn) 1109 { 1110 as_bad ("%s", errmsg); 1111 return; 1112 } 1113 1114 /* If the cpu is tomcat, then we need to insert nops to workaround 1115 hardware limitations. We need to keep track of each vliw unit 1116 and examine the length of the unit and the individual insns 1117 within the unit to determine the number and location of the 1118 required nops. */ 1119 if (frv_mach == bfd_mach_frvtomcat) 1120 { 1121 /* If we've just finished a VLIW insn OR this is a branch, 1122 then start up a new frag. Fill it with nops. We will get rid 1123 of those that are not required after we've seen all of the 1124 instructions but before we start resolving fixups. */ 1125 if ( !FRV_IS_NOP (insn) 1126 && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack)) 1127 { 1128 char *buffer; 1129 1130 frag_wane (frag_now); 1131 frag_new (0); 1132 double_nop_frag = frag_now; 1133 buffer = frag_var (rs_machine_dependent, 8, 8, NOP_DELETE, NULL, 0, 0); 1134 md_number_to_chars (buffer, FRV_NOP_PACK, 4); 1135 md_number_to_chars (buffer+4, FRV_NOP_NOPACK, 4); 1136 1137 frag_wane (frag_now); 1138 frag_new (0); 1139 single_nop_frag = frag_now; 1140 buffer = frag_var (rs_machine_dependent, 4, 4, NOP_DELETE, NULL, 0, 0); 1141 md_number_to_chars (buffer, FRV_NOP_NOPACK, 4); 1142 } 1143 1144 vliw_insn_list_entry = frv_insert_vliw_insn (DO_COUNT); 1145 vliw_insn_list_entry->insn = insn.insn; 1146 if (frv_is_branch_insn (insn.insn)) 1147 vliw_insn_list_entry->type = VLIW_BRANCH_TYPE; 1148 1149 if ( !FRV_IS_NOP (insn) 1150 && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack)) 1151 { 1152 vliw_insn_list_entry->snop_frag = single_nop_frag; 1153 vliw_insn_list_entry->dnop_frag = double_nop_frag; 1154 } 1155 } 1156 1157 /* Make sure that this insn does not violate the VLIW packing constraints. */ 1158 /* -mno-pack disallows any packing whatsoever. */ 1159 if (frv_flags & EF_FRV_NOPACK) 1160 { 1161 if (! insn.fields.f_pack) 1162 { 1163 as_bad (_("VLIW packing used for -mno-pack")); 1164 return; 1165 } 1166 } 1167 /* -mcpu=FRV is an idealized FR-V implementation that supports all of the 1168 instructions, don't do vliw checking. */ 1169 else if (frv_mach != bfd_mach_frv) 1170 { 1171 if (!target_implements_insn_p (insn.insn)) 1172 { 1173 as_bad (_("Instruction not supported by this architecture")); 1174 return; 1175 } 1176 packing_constraint = frv_vliw_add_insn (& vliw, insn.insn); 1177 if (frv_mach == bfd_mach_fr550 && ! packing_constraint) 1178 packing_constraint = fr550_check_acc_range (& vliw, & insn); 1179 if (insn.fields.f_pack) 1180 frv_vliw_reset (& vliw, frv_mach, frv_flags); 1181 if (packing_constraint) 1182 { 1183 as_bad (_("VLIW packing constraint violation")); 1184 return; 1185 } 1186 } 1187 1188 /* Doesn't really matter what we pass for RELAX_P here. */ 1189 gas_cgen_finish_insn (insn.insn, insn.buffer, 1190 CGEN_FIELDS_BITSIZE (& insn.fields), 1, &finished_insn); 1191 1192 1193 /* If the cpu is tomcat, then we need to insert nops to workaround 1194 hardware limitations. We need to keep track of each vliw unit 1195 and examine the length of the unit and the individual insns 1196 within the unit to determine the number and location of the 1197 required nops. */ 1198 if (frv_mach == bfd_mach_frvtomcat) 1199 { 1200 if (vliw_insn_list_entry) 1201 vliw_insn_list_entry->address = finished_insn.addr; 1202 else 1203 abort(); 1204 1205 if (insn.fields.f_pack) 1206 { 1207 /* We've completed a VLIW insn. */ 1208 previous_vliw_chain = current_vliw_chain; 1209 current_vliw_chain = NULL; 1210 current_vliw_insn = NULL; 1211 } 1212 } 1213 } 1214 1215 /* The syntax in the manual says constants begin with '#'. 1216 We just ignore it. */ 1217 1218 void 1219 md_operand (expressionS *expressionP) 1220 { 1221 if (* input_line_pointer == '#') 1222 { 1223 input_line_pointer ++; 1224 expression (expressionP); 1225 } 1226 } 1227 1228 valueT 1229 md_section_align (segT segment, valueT size) 1230 { 1231 int align = bfd_get_section_alignment (stdoutput, segment); 1232 return ((size + (1 << align) - 1) & -(1 << align)); 1233 } 1234 1235 symbolS * 1236 md_undefined_symbol (char *name ATTRIBUTE_UNUSED) 1237 { 1238 return 0; 1239 } 1240 1241 /* Interface to relax_segment. */ 1243 1244 /* FIXME: Build table by hand, get it working, then machine generate. */ 1245 const relax_typeS md_relax_table[] = 1246 { 1247 {1, 1, 0, 0}, 1248 {511 - 2 - 2, -512 - 2 + 2, 0, 2 }, 1249 {0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 }, 1250 {0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 } 1251 }; 1252 1253 long 1254 frv_relax_frag (fragS *fragP ATTRIBUTE_UNUSED, long stretch ATTRIBUTE_UNUSED) 1255 { 1256 return 0; 1257 } 1258 1259 /* Return an initial guess of the length by which a fragment must grow to 1260 hold a branch to reach its destination. 1261 Also updates fr_type/fr_subtype as necessary. 1262 1263 Called just before doing relaxation. 1264 Any symbol that is now undefined will not become defined. 1265 The guess for fr_var is ACTUALLY the growth beyond fr_fix. 1266 Whatever we do to grow fr_fix or fr_var contributes to our returned value. 1267 Although it may not be explicit in the frag, pretend fr_var starts with a 1268 0 value. */ 1269 1270 int 1271 md_estimate_size_before_relax (fragS *fragP, segT segment ATTRIBUTE_UNUSED) 1272 { 1273 switch (fragP->fr_subtype) 1274 { 1275 case NOP_KEEP: 1276 return fragP->fr_var; 1277 1278 default: 1279 case NOP_DELETE: 1280 return 0; 1281 } 1282 } 1283 1284 /* *fragP has been relaxed to its final size, and now needs to have 1285 the bytes inside it modified to conform to the new size. 1286 1287 Called after relaxation is finished. 1288 fragP->fr_type == rs_machine_dependent. 1289 fragP->fr_subtype is the subtype of what the address relaxed to. */ 1290 1291 void 1292 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, 1293 segT sec ATTRIBUTE_UNUSED, 1294 fragS *fragP) 1295 { 1296 switch (fragP->fr_subtype) 1297 { 1298 default: 1299 case NOP_DELETE: 1300 return; 1301 1302 case NOP_KEEP: 1303 fragP->fr_fix = fragP->fr_var; 1304 fragP->fr_var = 0; 1305 return; 1306 } 1307 } 1308 1309 /* Functions concerning relocs. */ 1311 1312 /* The location from which a PC relative jump should be calculated, 1313 given a PC relative reloc. */ 1314 1315 long 1316 md_pcrel_from_section (fixS *fixP, segT sec) 1317 { 1318 if (TC_FORCE_RELOCATION (fixP) 1319 || (fixP->fx_addsy != (symbolS *) NULL 1320 && S_GET_SEGMENT (fixP->fx_addsy) != sec)) 1321 { 1322 /* If we can't adjust this relocation, or if it references a 1323 local symbol in a different section (which 1324 TC_FORCE_RELOCATION can't check), let the linker figure it 1325 out. */ 1326 return 0; 1327 } 1328 1329 return (fixP->fx_frag->fr_address + fixP->fx_where) & ~1; 1330 } 1331 1332 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP. 1333 Returns BFD_RELOC_NONE if no reloc type can be found. 1334 *FIXP may be modified if desired. */ 1335 1336 bfd_reloc_code_real_type 1337 md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED, 1338 const CGEN_OPERAND *operand, 1339 fixS *fixP) 1340 { 1341 switch (operand->type) 1342 { 1343 case FRV_OPERAND_LABEL16: 1344 fixP->fx_pcrel = TRUE; 1345 return BFD_RELOC_FRV_LABEL16; 1346 1347 case FRV_OPERAND_LABEL24: 1348 fixP->fx_pcrel = TRUE; 1349 1350 if (fixP->fx_cgen.opinfo != 0) 1351 return fixP->fx_cgen.opinfo; 1352 1353 return BFD_RELOC_FRV_LABEL24; 1354 1355 case FRV_OPERAND_UHI16: 1356 case FRV_OPERAND_ULO16: 1357 case FRV_OPERAND_SLO16: 1358 case FRV_OPERAND_CALLANN: 1359 case FRV_OPERAND_LDANN: 1360 case FRV_OPERAND_LDDANN: 1361 /* The relocation type should be recorded in opinfo */ 1362 if (fixP->fx_cgen.opinfo != 0) 1363 return fixP->fx_cgen.opinfo; 1364 break; 1365 1366 case FRV_OPERAND_D12: 1367 case FRV_OPERAND_S12: 1368 if (fixP->fx_cgen.opinfo != 0) 1369 return fixP->fx_cgen.opinfo; 1370 1371 return BFD_RELOC_FRV_GPREL12; 1372 1373 case FRV_OPERAND_U12: 1374 return BFD_RELOC_FRV_GPRELU12; 1375 1376 default: 1377 break; 1378 } 1379 return BFD_RELOC_NONE; 1380 } 1381 1382 1383 /* See whether we need to force a relocation into the output file. 1384 This is used to force out switch and PC relative relocations when 1385 relaxing. */ 1386 1387 int 1388 frv_force_relocation (fixS *fix) 1389 { 1390 switch (fix->fx_r_type < BFD_RELOC_UNUSED 1391 ? (int) fix->fx_r_type 1392 : fix->fx_cgen.opinfo) 1393 { 1394 case BFD_RELOC_FRV_GPREL12: 1395 case BFD_RELOC_FRV_GPRELU12: 1396 case BFD_RELOC_FRV_GPREL32: 1397 case BFD_RELOC_FRV_GPRELHI: 1398 case BFD_RELOC_FRV_GPRELLO: 1399 case BFD_RELOC_FRV_GOT12: 1400 case BFD_RELOC_FRV_GOTHI: 1401 case BFD_RELOC_FRV_GOTLO: 1402 case BFD_RELOC_FRV_FUNCDESC_VALUE: 1403 case BFD_RELOC_FRV_FUNCDESC_GOTOFF12: 1404 case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI: 1405 case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO: 1406 case BFD_RELOC_FRV_GOTOFF12: 1407 case BFD_RELOC_FRV_GOTOFFHI: 1408 case BFD_RELOC_FRV_GOTOFFLO: 1409 case BFD_RELOC_FRV_GETTLSOFF: 1410 case BFD_RELOC_FRV_TLSDESC_VALUE: 1411 case BFD_RELOC_FRV_GOTTLSDESC12: 1412 case BFD_RELOC_FRV_GOTTLSDESCHI: 1413 case BFD_RELOC_FRV_GOTTLSDESCLO: 1414 case BFD_RELOC_FRV_TLSMOFF12: 1415 case BFD_RELOC_FRV_TLSMOFFHI: 1416 case BFD_RELOC_FRV_TLSMOFFLO: 1417 case BFD_RELOC_FRV_GOTTLSOFF12: 1418 case BFD_RELOC_FRV_GOTTLSOFFHI: 1419 case BFD_RELOC_FRV_GOTTLSOFFLO: 1420 case BFD_RELOC_FRV_TLSOFF: 1421 case BFD_RELOC_FRV_TLSDESC_RELAX: 1422 case BFD_RELOC_FRV_GETTLSOFF_RELAX: 1423 case BFD_RELOC_FRV_TLSOFF_RELAX: 1424 return 1; 1425 1426 default: 1427 break; 1428 } 1429 1430 return generic_force_reloc (fix); 1431 } 1432 1433 /* Apply a fixup that could be resolved within the assembler. */ 1434 1435 void 1436 md_apply_fix (fixS *fixP, valueT *valP, segT seg) 1437 { 1438 if (fixP->fx_addsy == 0) 1439 switch (fixP->fx_cgen.opinfo) 1440 { 1441 case BFD_RELOC_FRV_HI16: 1442 *valP >>= 16; 1443 /* Fall through. */ 1444 case BFD_RELOC_FRV_LO16: 1445 *valP &= 0xffff; 1446 break; 1447 1448 /* We need relocations for these, even if their symbols reduce 1449 to constants. */ 1450 case BFD_RELOC_FRV_GPREL12: 1451 case BFD_RELOC_FRV_GPRELU12: 1452 case BFD_RELOC_FRV_GPREL32: 1453 case BFD_RELOC_FRV_GPRELHI: 1454 case BFD_RELOC_FRV_GPRELLO: 1455 case BFD_RELOC_FRV_GOT12: 1456 case BFD_RELOC_FRV_GOTHI: 1457 case BFD_RELOC_FRV_GOTLO: 1458 case BFD_RELOC_FRV_FUNCDESC_VALUE: 1459 case BFD_RELOC_FRV_FUNCDESC_GOTOFF12: 1460 case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI: 1461 case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO: 1462 case BFD_RELOC_FRV_GOTOFF12: 1463 case BFD_RELOC_FRV_GOTOFFHI: 1464 case BFD_RELOC_FRV_GOTOFFLO: 1465 case BFD_RELOC_FRV_GETTLSOFF: 1466 case BFD_RELOC_FRV_TLSDESC_VALUE: 1467 case BFD_RELOC_FRV_GOTTLSDESC12: 1468 case BFD_RELOC_FRV_GOTTLSDESCHI: 1469 case BFD_RELOC_FRV_GOTTLSDESCLO: 1470 case BFD_RELOC_FRV_TLSMOFF12: 1471 case BFD_RELOC_FRV_TLSMOFFHI: 1472 case BFD_RELOC_FRV_TLSMOFFLO: 1473 case BFD_RELOC_FRV_GOTTLSOFF12: 1474 case BFD_RELOC_FRV_GOTTLSOFFHI: 1475 case BFD_RELOC_FRV_GOTTLSOFFLO: 1476 case BFD_RELOC_FRV_TLSOFF: 1477 case BFD_RELOC_FRV_TLSDESC_RELAX: 1478 case BFD_RELOC_FRV_GETTLSOFF_RELAX: 1479 case BFD_RELOC_FRV_TLSOFF_RELAX: 1480 fixP->fx_addsy = abs_section_sym; 1481 break; 1482 } 1483 else 1484 switch (fixP->fx_cgen.opinfo) 1485 { 1486 case BFD_RELOC_FRV_GETTLSOFF: 1487 case BFD_RELOC_FRV_TLSDESC_VALUE: 1488 case BFD_RELOC_FRV_GOTTLSDESC12: 1489 case BFD_RELOC_FRV_GOTTLSDESCHI: 1490 case BFD_RELOC_FRV_GOTTLSDESCLO: 1491 case BFD_RELOC_FRV_TLSMOFF12: 1492 case BFD_RELOC_FRV_TLSMOFFHI: 1493 case BFD_RELOC_FRV_TLSMOFFLO: 1494 case BFD_RELOC_FRV_GOTTLSOFF12: 1495 case BFD_RELOC_FRV_GOTTLSOFFHI: 1496 case BFD_RELOC_FRV_GOTTLSOFFLO: 1497 case BFD_RELOC_FRV_TLSOFF: 1498 case BFD_RELOC_FRV_TLSDESC_RELAX: 1499 case BFD_RELOC_FRV_GETTLSOFF_RELAX: 1500 case BFD_RELOC_FRV_TLSOFF_RELAX: 1501 /* Mark TLS symbols as such. */ 1502 if (S_GET_SEGMENT (fixP->fx_addsy) != absolute_section) 1503 S_SET_THREAD_LOCAL (fixP->fx_addsy); 1504 break; 1505 } 1506 1507 gas_cgen_md_apply_fix (fixP, valP, seg); 1508 return; 1509 } 1510 1511 1512 /* Write a value out to the object file, using the appropriate endianness. */ 1514 1515 void 1516 frv_md_number_to_chars (char *buf, valueT val, int n) 1517 { 1518 number_to_chars_bigendian (buf, val, n); 1519 } 1520 1521 const char * 1522 md_atof (int type, char *litP, int *sizeP) 1523 { 1524 return ieee_md_atof (type, litP, sizeP, TRUE); 1525 } 1526 1527 bfd_boolean 1528 frv_fix_adjustable (fixS *fixP) 1529 { 1530 bfd_reloc_code_real_type reloc_type; 1531 1532 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED) 1533 { 1534 const CGEN_INSN *insn = NULL; 1535 int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED; 1536 const CGEN_OPERAND *operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex); 1537 reloc_type = md_cgen_lookup_reloc (insn, operand, fixP); 1538 } 1539 else 1540 reloc_type = fixP->fx_r_type; 1541 1542 /* We need the symbol name for the VTABLE entries */ 1543 if ( reloc_type == BFD_RELOC_VTABLE_INHERIT 1544 || reloc_type == BFD_RELOC_VTABLE_ENTRY 1545 || reloc_type == BFD_RELOC_FRV_GPREL12 1546 || reloc_type == BFD_RELOC_FRV_GPRELU12) 1547 return 0; 1548 1549 return 1; 1550 } 1551 1552 /* Allow user to set flags bits. */ 1553 void 1554 frv_set_flags (int arg ATTRIBUTE_UNUSED) 1555 { 1556 flagword new_flags = get_absolute_expression (); 1557 flagword new_mask = ~ (flagword)0; 1558 1559 frv_user_set_flags_p = 1; 1560 if (*input_line_pointer == ',') 1561 { 1562 ++input_line_pointer; 1563 new_mask = get_absolute_expression (); 1564 } 1565 1566 frv_flags = (frv_flags & ~new_mask) | (new_flags & new_mask); 1567 bfd_set_private_flags (stdoutput, frv_flags); 1568 } 1569 1570 /* Frv specific function to handle 4 byte initializations for pointers that are 1571 considered 'safe' for use with pic support. Until frv_frob_file{,_section} 1572 is run, we encode it a BFD_RELOC_CTOR, and it is turned back into a normal 1573 BFD_RELOC_32 at that time. */ 1574 1575 void 1576 frv_pic_ptr (int nbytes) 1577 { 1578 expressionS exp; 1579 char *p; 1580 1581 if (nbytes != 4) 1582 abort (); 1583 1584 #ifdef md_flush_pending_output 1585 md_flush_pending_output (); 1586 #endif 1587 1588 if (is_it_end_of_statement ()) 1589 { 1590 demand_empty_rest_of_line (); 1591 return; 1592 } 1593 1594 #ifdef md_cons_align 1595 md_cons_align (nbytes); 1596 #endif 1597 1598 do 1599 { 1600 bfd_reloc_code_real_type reloc_type = BFD_RELOC_CTOR; 1601 1602 if (strncasecmp (input_line_pointer, "funcdesc(", 9) == 0) 1603 { 1604 input_line_pointer += 9; 1605 expression (&exp); 1606 if (*input_line_pointer == ')') 1607 input_line_pointer++; 1608 else 1609 as_bad (_("missing ')'")); 1610 reloc_type = BFD_RELOC_FRV_FUNCDESC; 1611 } 1612 else if (strncasecmp (input_line_pointer, "tlsmoff(", 8) == 0) 1613 { 1614 input_line_pointer += 8; 1615 expression (&exp); 1616 if (*input_line_pointer == ')') 1617 input_line_pointer++; 1618 else 1619 as_bad (_("missing ')'")); 1620 reloc_type = BFD_RELOC_FRV_TLSMOFF; 1621 } 1622 else 1623 expression (&exp); 1624 1625 p = frag_more (4); 1626 memset (p, 0, 4); 1627 fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &exp, 0, 1628 reloc_type); 1629 } 1630 while (*input_line_pointer++ == ','); 1631 1632 input_line_pointer--; /* Put terminator back into stream. */ 1633 demand_empty_rest_of_line (); 1634 } 1635 1636 1637 1639 #ifdef DEBUG 1640 #define DPRINTF1(A) fprintf (stderr, A) 1641 #define DPRINTF2(A,B) fprintf (stderr, A, B) 1642 #define DPRINTF3(A,B,C) fprintf (stderr, A, B, C) 1643 1644 #else 1645 #define DPRINTF1(A) 1646 #define DPRINTF2(A,B) 1647 #define DPRINTF3(A,B,C) 1648 #endif 1649 1650 /* Go through a the sections looking for relocations that are problematical for 1651 pic. If not pic, just note that this object can't be linked with pic. If 1652 it is pic, see if it needs to be marked so that it will be fixed up, or if 1653 not possible, issue an error. */ 1654 1655 static void 1656 frv_frob_file_section (bfd *abfd, asection *sec, void *ptr ATTRIBUTE_UNUSED) 1657 { 1658 segment_info_type *seginfo = seg_info (sec); 1659 fixS *fixp; 1660 CGEN_CPU_DESC cd = gas_cgen_cpu_desc; 1661 flagword flags = bfd_get_section_flags (abfd, sec); 1662 1663 /* Skip relocations in known sections (.ctors, .dtors, and .gcc_except_table) 1664 since we can fix those up by hand. */ 1665 int known_section_p = (sec->name 1666 && sec->name[0] == '.' 1667 && ((sec->name[1] == 'c' 1668 && strcmp (sec->name, ".ctor") == 0) 1669 || (sec->name[1] == 'd' 1670 && strcmp (sec->name, ".dtor") == 0) 1671 || (sec->name[1] == 'g' 1672 && strcmp (sec->name, ".gcc_except_table") == 0))); 1673 1674 DPRINTF3 ("\nFrv section %s%s\n", sec->name, (known_section_p) ? ", known section" : ""); 1675 if ((flags & SEC_ALLOC) == 0) 1676 { 1677 DPRINTF1 ("\tSkipping non-loaded section\n"); 1678 return; 1679 } 1680 1681 for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next) 1682 { 1683 symbolS *s = fixp->fx_addsy; 1684 bfd_reloc_code_real_type reloc; 1685 int non_pic_p; 1686 int opindex; 1687 const CGEN_OPERAND *operand; 1688 const CGEN_INSN *insn = fixp->fx_cgen.insn; 1689 1690 if (fixp->fx_done) 1691 { 1692 DPRINTF1 ("\tSkipping reloc that has already been done\n"); 1693 continue; 1694 } 1695 1696 if (fixp->fx_pcrel) 1697 { 1698 DPRINTF1 ("\tSkipping reloc that is PC relative\n"); 1699 continue; 1700 } 1701 1702 if (! s) 1703 { 1704 DPRINTF1 ("\tSkipping reloc without symbol\n"); 1705 continue; 1706 } 1707 1708 if (fixp->fx_r_type < BFD_RELOC_UNUSED) 1709 { 1710 opindex = -1; 1711 reloc = fixp->fx_r_type; 1712 } 1713 else 1714 { 1715 opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED; 1716 operand = cgen_operand_lookup_by_num (cd, opindex); 1717 reloc = md_cgen_lookup_reloc (insn, operand, fixp); 1718 } 1719 1720 DPRINTF3 ("\treloc %s\t%s", bfd_get_reloc_code_name (reloc), S_GET_NAME (s)); 1721 1722 non_pic_p = 0; 1723 switch (reloc) 1724 { 1725 default: 1726 break; 1727 1728 case BFD_RELOC_32: 1729 /* Skip relocations in known sections (.ctors, .dtors, and 1730 .gcc_except_table) since we can fix those up by hand. Also 1731 skip forward references to constants. Also skip a difference 1732 of two symbols, which still uses the BFD_RELOC_32 at this 1733 point. */ 1734 if (! known_section_p 1735 && S_GET_SEGMENT (s) != absolute_section 1736 && !fixp->fx_subsy 1737 && (flags & (SEC_READONLY | SEC_CODE)) == 0) 1738 { 1739 non_pic_p = 1; 1740 } 1741 break; 1742 1743 /* FIXME -- should determine if any of the GP relocation really uses 1744 gr16 (which is not pic safe) or not. Right now, assume if we 1745 aren't being compiled with -mpic, the usage is non pic safe, but 1746 is safe with -mpic. */ 1747 case BFD_RELOC_FRV_GPREL12: 1748 case BFD_RELOC_FRV_GPRELU12: 1749 case BFD_RELOC_FRV_GPREL32: 1750 case BFD_RELOC_FRV_GPRELHI: 1751 case BFD_RELOC_FRV_GPRELLO: 1752 non_pic_p = ! frv_pic_p; 1753 break; 1754 1755 case BFD_RELOC_FRV_LO16: 1756 case BFD_RELOC_FRV_HI16: 1757 if (S_GET_SEGMENT (s) != absolute_section) 1758 non_pic_p = 1; 1759 break; 1760 1761 case BFD_RELOC_VTABLE_INHERIT: 1762 case BFD_RELOC_VTABLE_ENTRY: 1763 non_pic_p = 1; 1764 break; 1765 1766 /* If this is a blessed BFD_RELOC_32, convert it back to the normal 1767 relocation. */ 1768 case BFD_RELOC_CTOR: 1769 fixp->fx_r_type = BFD_RELOC_32; 1770 break; 1771 } 1772 1773 if (non_pic_p) 1774 { 1775 DPRINTF1 (" (Non-pic relocation)\n"); 1776 if (frv_pic_p) 1777 as_warn_where (fixp->fx_file, fixp->fx_line, 1778 _("Relocation %s is not safe for %s"), 1779 bfd_get_reloc_code_name (reloc), frv_pic_flag); 1780 1781 else if ((frv_flags & EF_FRV_NON_PIC_RELOCS) == 0) 1782 { 1783 frv_flags |= EF_FRV_NON_PIC_RELOCS; 1784 bfd_set_private_flags (abfd, frv_flags); 1785 } 1786 } 1787 #ifdef DEBUG 1788 else 1789 DPRINTF1 ("\n"); 1790 #endif 1791 } 1792 } 1793 1794 /* After all of the symbols have been adjusted, go over the file looking 1795 for any relocations that pic won't support. */ 1796 1797 void 1798 frv_frob_file (void) 1799 { 1800 bfd_map_over_sections (stdoutput, frv_frob_file_section, (void *) 0); 1801 } 1802 1803 void 1804 frv_frob_label (symbolS *this_label) 1805 { 1806 struct vliw_insn_list *vliw_insn_list_entry; 1807 1808 dwarf2_emit_label (this_label); 1809 if (frv_mach != bfd_mach_frvtomcat) 1810 return; 1811 1812 if (now_seg != text_section) 1813 return; 1814 1815 vliw_insn_list_entry = frv_insert_vliw_insn(DONT_COUNT); 1816 vliw_insn_list_entry->type = VLIW_LABEL_TYPE; 1817 vliw_insn_list_entry->sym = this_label; 1818 } 1819 1820 fixS * 1821 frv_cgen_record_fixup_exp (fragS *frag, 1822 int where, 1823 const CGEN_INSN *insn, 1824 int length, 1825 const CGEN_OPERAND *operand, 1826 int opinfo, 1827 expressionS *exp) 1828 { 1829 fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length, 1830 operand, opinfo, exp); 1831 1832 if (frv_mach == bfd_mach_frvtomcat 1833 && current_vliw_insn 1834 && current_vliw_insn->type == VLIW_BRANCH_TYPE 1835 && exp != NULL) 1836 current_vliw_insn->sym = exp->X_add_symbol; 1837 1838 return fixP; 1839 } 1840