1/* tc-microblaze.c -- Assemble code for Xilinx MicroBlaze 2 3 Copyright (C) 2009-2020 Free Software Foundation, 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 the Free 19 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 20 02110-1301, USA. */ 21 22#include "as.h" 23#include <stdio.h> 24#include "bfd.h" 25#include "subsegs.h" 26#define DEFINE_TABLE 27#include "../opcodes/microblaze-opc.h" 28#include "../opcodes/microblaze-opcm.h" 29#include "safe-ctype.h" 30#include <string.h> 31#include <dwarf2dbg.h> 32#include "aout/stab_gnu.h" 33 34#ifndef streq 35#define streq(a,b) (strcmp (a, b) == 0) 36#endif 37 38#define OPTION_EB (OPTION_MD_BASE + 0) 39#define OPTION_EL (OPTION_MD_BASE + 1) 40 41void microblaze_generate_symbol (char *sym); 42static bfd_boolean check_spl_reg (unsigned *); 43 44/* Several places in this file insert raw instructions into the 45 object. They should generate the instruction 46 and then use these four macros to crack the instruction value into 47 the appropriate byte values. */ 48#define INST_BYTE0(x) (target_big_endian ? (((x) >> 24) & 0xFF) : ((x) & 0xFF)) 49#define INST_BYTE1(x) (target_big_endian ? (((x) >> 16) & 0xFF) : (((x) >> 8) & 0xFF)) 50#define INST_BYTE2(x) (target_big_endian ? (((x) >> 8) & 0xFF) : (((x) >> 16) & 0xFF)) 51#define INST_BYTE3(x) (target_big_endian ? ((x) & 0xFF) : (((x) >> 24) & 0xFF)) 52 53/* This array holds the chars that always start a comment. If the 54 pre-processor is disabled, these aren't very useful. */ 55const char comment_chars[] = "#"; 56 57const char line_separator_chars[] = ";"; 58 59/* This array holds the chars that only start a comment at the beginning of 60 a line. */ 61const char line_comment_chars[] = "#"; 62 63const int md_reloc_size = 8; /* Size of relocation record. */ 64 65/* Chars that can be used to separate mant 66 from exp in floating point numbers. */ 67const char EXP_CHARS[] = "eE"; 68 69/* Chars that mean this number is a floating point constant 70 As in 0f12.456 71 or 0d1.2345e12. */ 72const char FLT_CHARS[] = "rRsSfFdDxXpP"; 73 74/* INST_PC_OFFSET and INST_NO_OFFSET are 0 and 1. */ 75#define UNDEFINED_PC_OFFSET 2 76#define DEFINED_ABS_SEGMENT 3 77#define DEFINED_PC_OFFSET 4 78#define DEFINED_RO_SEGMENT 5 79#define DEFINED_RW_SEGMENT 6 80#define LARGE_DEFINED_PC_OFFSET 7 81#define GOT_OFFSET 8 82#define PLT_OFFSET 9 83#define GOTOFF_OFFSET 10 84#define TLSGD_OFFSET 11 85#define TLSLD_OFFSET 12 86#define TLSDTPMOD_OFFSET 13 87#define TLSDTPREL_OFFSET 14 88#define TLSGOTTPREL_OFFSET 15 89#define TLSTPREL_OFFSET 16 90#define TEXT_OFFSET 17 91#define TEXT_PC_OFFSET 18 92 93/* Initialize the relax table. */ 94const relax_typeS md_relax_table[] = 95{ 96 { 1, 1, 0, 0 }, /* 0: Unused. */ 97 { 1, 1, 0, 0 }, /* 1: Unused. */ 98 { 1, 1, 0, 0 }, /* 2: Unused. */ 99 { 1, 1, 0, 0 }, /* 3: Unused. */ 100 { 32767, -32768, INST_WORD_SIZE, LARGE_DEFINED_PC_OFFSET }, /* 4: DEFINED_PC_OFFSET. */ 101 { 1, 1, 0, 0 }, /* 5: Unused. */ 102 { 1, 1, 0, 0 }, /* 6: Unused. */ 103 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 7: LARGE_DEFINED_PC_OFFSET. */ 104 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 8: GOT_OFFSET. */ 105 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 9: PLT_OFFSET. */ 106 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 10: GOTOFF_OFFSET. */ 107 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 11: TLSGD_OFFSET. */ 108 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 12: TLSLD_OFFSET. */ 109 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*1, 0 }, /* 13: TLSDTPMOD_OFFSET. */ 110 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 14: TLSDTPREL_OFFSET. */ 111 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 15: TLSGOTTPREL_OFFSET. */ 112 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 16: TLSTPREL_OFFSET. */ 113 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 17: TEXT_OFFSET. */ 114 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 } /* 18: TEXT_PC_OFFSET. */ 115}; 116 117static htab_t opcode_hash_control; /* Opcode mnemonics. */ 118 119static segT sbss_segment = 0; /* Small bss section. */ 120static segT sbss2_segment = 0; /* Section not used. */ 121static segT sdata_segment = 0; /* Small data section. */ 122static segT sdata2_segment = 0; /* Small read-only section. */ 123static segT rodata_segment = 0; /* read-only section. */ 124 125/* Generate a symbol for stabs information. */ 126 127void 128microblaze_generate_symbol (char *sym) 129{ 130#define MICROBLAZE_FAKE_LABEL_NAME "XL0\001" 131 static int microblaze_label_count; 132 sprintf (sym, "%sL%d", MICROBLAZE_FAKE_LABEL_NAME, microblaze_label_count); 133 ++microblaze_label_count; 134} 135 136/* Handle the section changing pseudo-ops. */ 137 138static void 139microblaze_s_text (int ignore ATTRIBUTE_UNUSED) 140{ 141#ifdef OBJ_ELF 142 obj_elf_text (ignore); 143#else 144 s_text (ignore); 145#endif 146} 147 148static void 149microblaze_s_data (int ignore ATTRIBUTE_UNUSED) 150{ 151#ifdef OBJ_ELF 152 obj_elf_change_section (".data", SHT_PROGBITS, SHF_ALLOC+SHF_WRITE, 153 0, 0, 0, 0); 154#else 155 s_data (ignore); 156#endif 157} 158 159/* Things in the .sdata segment are always considered to be in the small data section. */ 160 161static void 162microblaze_s_sdata (int ignore ATTRIBUTE_UNUSED) 163{ 164#ifdef OBJ_ELF 165 obj_elf_change_section (".sdata", SHT_PROGBITS, SHF_ALLOC+SHF_WRITE, 166 0, 0, 0, 0); 167#else 168 s_data (ignore); 169#endif 170} 171 172/* Pseudo op to make file scope bss items. */ 173 174static void 175microblaze_s_lcomm (int xxx ATTRIBUTE_UNUSED) 176{ 177 char *name; 178 char c; 179 char *p; 180 offsetT size; 181 symbolS *symbolP; 182 offsetT align; 183 char *pfrag; 184 int align2; 185 segT current_seg = now_seg; 186 subsegT current_subseg = now_subseg; 187 188 c = get_symbol_name (&name); 189 190 /* Just after name is now '\0'. */ 191 p = input_line_pointer; 192 (void) restore_line_pointer (c); 193 SKIP_WHITESPACE (); 194 if (*input_line_pointer != ',') 195 { 196 as_bad (_("Expected comma after symbol-name: rest of line ignored.")); 197 ignore_rest_of_line (); 198 return; 199 } 200 201 input_line_pointer++; /* skip ',' */ 202 if ((size = get_absolute_expression ()) < 0) 203 { 204 as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) size); 205 ignore_rest_of_line (); 206 return; 207 } 208 209 /* The third argument to .lcomm is the alignment. */ 210 if (*input_line_pointer != ',') 211 align = 8; 212 else 213 { 214 ++input_line_pointer; 215 align = get_absolute_expression (); 216 if (align <= 0) 217 { 218 as_warn (_("ignoring bad alignment")); 219 align = 8; 220 } 221 } 222 223 *p = 0; 224 symbolP = symbol_find_or_make (name); 225 *p = c; 226 227 if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP)) 228 { 229 as_bad (_("Ignoring attempt to re-define symbol `%s'."), 230 S_GET_NAME (symbolP)); 231 ignore_rest_of_line (); 232 return; 233 } 234 235 if (S_GET_VALUE (symbolP) && S_GET_VALUE (symbolP) != (valueT) size) 236 { 237 as_bad (_("Length of .lcomm \"%s\" is already %ld. Not changed to %ld."), 238 S_GET_NAME (symbolP), 239 (long) S_GET_VALUE (symbolP), 240 (long) size); 241 242 ignore_rest_of_line (); 243 return; 244 } 245 246 /* Allocate_bss. */ 247 if (align) 248 { 249 /* Convert to a power of 2 alignment. */ 250 for (align2 = 0; (align & 1) == 0; align >>= 1, ++align2); 251 if (align != 1) 252 { 253 as_bad (_("Common alignment not a power of 2")); 254 ignore_rest_of_line (); 255 return; 256 } 257 } 258 else 259 align2 = 0; 260 261 record_alignment (current_seg, align2); 262 subseg_set (current_seg, current_subseg); 263 if (align2) 264 frag_align (align2, 0, 0); 265 if (S_GET_SEGMENT (symbolP) == current_seg) 266 symbol_get_frag (symbolP)->fr_symbol = 0; 267 symbol_set_frag (symbolP, frag_now); 268 pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size, 269 (char *) 0); 270 *pfrag = 0; 271 S_SET_SIZE (symbolP, size); 272 S_SET_SEGMENT (symbolP, current_seg); 273 subseg_set (current_seg, current_subseg); 274 demand_empty_rest_of_line (); 275} 276 277static void 278microblaze_s_rdata (int localvar) 279{ 280#ifdef OBJ_ELF 281 if (localvar == 0) 282 { 283 /* rodata. */ 284 obj_elf_change_section (".rodata", SHT_PROGBITS, SHF_ALLOC, 285 0, 0, 0, 0); 286 if (rodata_segment == 0) 287 rodata_segment = subseg_new (".rodata", 0); 288 } 289 else 290 { 291 /* 1 .sdata2. */ 292 obj_elf_change_section (".sdata2", SHT_PROGBITS, SHF_ALLOC, 293 0, 0, 0, 0); 294 } 295#else 296 s_data (ignore); 297#endif 298} 299 300static void 301microblaze_s_bss (int localvar) 302{ 303#ifdef OBJ_ELF 304 if (localvar == 0) /* bss. */ 305 obj_elf_change_section (".bss", SHT_NOBITS, SHF_ALLOC+SHF_WRITE, 306 0, 0, 0, 0); 307 else if (localvar == 1) 308 { 309 /* sbss. */ 310 obj_elf_change_section (".sbss", SHT_NOBITS, SHF_ALLOC+SHF_WRITE, 311 0, 0, 0, 0); 312 if (sbss_segment == 0) 313 sbss_segment = subseg_new (".sbss", 0); 314 } 315#else 316 s_data (ignore); 317#endif 318} 319 320/* endp_p is always 1 as this func is called only for .end <funcname> 321 This func consumes the <funcname> and calls regular processing 322 s_func(1) with arg 1 (1 for end). */ 323 324static void 325microblaze_s_func (int end_p ATTRIBUTE_UNUSED) 326{ 327 char *name; 328 restore_line_pointer (get_symbol_name (&name)); 329 s_func (1); 330} 331 332/* Handle the .weakext pseudo-op as defined in Kane and Heinrich. */ 333 334static void 335microblaze_s_weakext (int ignore ATTRIBUTE_UNUSED) 336{ 337 char *name; 338 int c; 339 symbolS *symbolP; 340 expressionS exp; 341 342 c = get_symbol_name (&name); 343 symbolP = symbol_find_or_make (name); 344 S_SET_WEAK (symbolP); 345 (void) restore_line_pointer (c); 346 347 SKIP_WHITESPACE (); 348 349 if (!is_end_of_line[(unsigned char) *input_line_pointer]) 350 { 351 if (S_IS_DEFINED (symbolP)) 352 { 353 as_bad ("Ignoring attempt to redefine symbol `%s'.", 354 S_GET_NAME (symbolP)); 355 ignore_rest_of_line (); 356 return; 357 } 358 359 if (*input_line_pointer == ',') 360 { 361 ++input_line_pointer; 362 SKIP_WHITESPACE (); 363 } 364 365 expression (&exp); 366 if (exp.X_op != O_symbol) 367 { 368 as_bad ("bad .weakext directive"); 369 ignore_rest_of_line (); 370 return; 371 } 372 symbol_set_value_expression (symbolP, &exp); 373 } 374 375 demand_empty_rest_of_line (); 376} 377 378/* This table describes all the machine specific pseudo-ops the assembler 379 has to support. The fields are: 380 Pseudo-op name without dot 381 Function to call to execute this pseudo-op 382 Integer arg to pass to the function. */ 383/* If the pseudo-op is not found in this table, it searches in the obj-elf.c, 384 and then in the read.c table. */ 385const pseudo_typeS md_pseudo_table[] = 386{ 387 {"lcomm", microblaze_s_lcomm, 1}, 388 {"data", microblaze_s_data, 0}, 389 {"data8", cons, 1}, /* Same as byte. */ 390 {"data16", cons, 2}, /* Same as hword. */ 391 {"data32", cons, 4}, /* Same as word. */ 392 {"ent", s_func, 0}, /* Treat ent as function entry point. */ 393 {"end", microblaze_s_func, 1}, /* Treat end as function end point. */ 394 {"gpword", s_rva, 4}, /* gpword label => store resolved label address in data section. */ 395 {"weakext", microblaze_s_weakext, 0}, 396 {"rodata", microblaze_s_rdata, 0}, 397 {"sdata2", microblaze_s_rdata, 1}, 398 {"sdata", microblaze_s_sdata, 0}, 399 {"bss", microblaze_s_bss, 0}, 400 {"sbss", microblaze_s_bss, 1}, 401 {"text", microblaze_s_text, 0}, 402 {"word", cons, 4}, 403 {"frame", s_ignore, 0}, 404 {"mask", s_ignore, 0}, /* Emitted by gcc. */ 405 {NULL, NULL, 0} 406}; 407 408/* This function is called once, at assembler startup time. This should 409 set up all the tables, etc that the MD part of the assembler needs. */ 410 411void 412md_begin (void) 413{ 414 struct op_code_struct * opcode; 415 416 opcode_hash_control = str_htab_create (); 417 418 /* Insert unique names into hash table. */ 419 for (opcode = opcodes; opcode->name; opcode ++) 420 str_hash_insert (opcode_hash_control, opcode->name, opcode, 0); 421} 422 423/* Try to parse a reg name. */ 424 425static char * 426parse_reg (char * s, unsigned * reg) 427{ 428 unsigned tmpreg = 0; 429 430 /* Strip leading whitespace. */ 431 while (ISSPACE (* s)) 432 ++ s; 433 434 if (strncasecmp (s, "rpc", 3) == 0) 435 { 436 *reg = REG_PC; 437 return s + 3; 438 } 439 else if (strncasecmp (s, "rmsr", 4) == 0) 440 { 441 *reg = REG_MSR; 442 return s + 4; 443 } 444 else if (strncasecmp (s, "rear", 4) == 0) 445 { 446 *reg = REG_EAR; 447 return s + 4; 448 } 449 else if (strncasecmp (s, "resr", 4) == 0) 450 { 451 *reg = REG_ESR; 452 return s + 4; 453 } 454 else if (strncasecmp (s, "rfsr", 4) == 0) 455 { 456 *reg = REG_FSR; 457 return s + 4; 458 } 459 else if (strncasecmp (s, "rbtr", 4) == 0) 460 { 461 *reg = REG_BTR; 462 return s + 4; 463 } 464 else if (strncasecmp (s, "redr", 4) == 0) 465 { 466 *reg = REG_EDR; 467 return s + 4; 468 } 469 /* MMU registers start. */ 470 else if (strncasecmp (s, "rpid", 4) == 0) 471 { 472 *reg = REG_PID; 473 return s + 4; 474 } 475 else if (strncasecmp (s, "rzpr", 4) == 0) 476 { 477 *reg = REG_ZPR; 478 return s + 4; 479 } 480 else if (strncasecmp (s, "rtlbx", 5) == 0) 481 { 482 *reg = REG_TLBX; 483 return s + 5; 484 } 485 else if (strncasecmp (s, "rtlblo", 6) == 0) 486 { 487 *reg = REG_TLBLO; 488 return s + 6; 489 } 490 else if (strncasecmp (s, "rtlbhi", 6) == 0) 491 { 492 *reg = REG_TLBHI; 493 return s + 6; 494 } 495 else if (strncasecmp (s, "rtlbsx", 6) == 0) 496 { 497 *reg = REG_TLBSX; 498 return s + 6; 499 } 500 /* MMU registers end. */ 501 else if (strncasecmp (s, "rpvr", 4) == 0) 502 { 503 if (ISDIGIT (s[4]) && ISDIGIT (s[5])) 504 { 505 tmpreg = (s[4]-'0')*10 + s[5] - '0'; 506 s += 6; 507 } 508 509 else if (ISDIGIT (s[4])) 510 { 511 tmpreg = s[4] - '0'; 512 s += 5; 513 } 514 else 515 as_bad (_("register expected, but saw '%.6s'"), s); 516 if ((int) tmpreg >= MIN_PVR_REGNUM && tmpreg <= MAX_PVR_REGNUM) 517 *reg = REG_PVR + tmpreg; 518 else 519 { 520 as_bad (_("Invalid register number at '%.6s'"), s); 521 *reg = REG_PVR; 522 } 523 return s; 524 } 525 else if (strncasecmp (s, "rsp", 3) == 0) 526 { 527 *reg = REG_SP; 528 return s + 3; 529 } 530 else if (strncasecmp (s, "rfsl", 4) == 0) 531 { 532 if (ISDIGIT (s[4]) && ISDIGIT (s[5])) 533 { 534 tmpreg = (s[4] - '0') * 10 + s[5] - '0'; 535 s += 6; 536 } 537 else if (ISDIGIT (s[4])) 538 { 539 tmpreg = s[4] - '0'; 540 s += 5; 541 } 542 else 543 as_bad (_("register expected, but saw '%.6s'"), s); 544 545 if ((int) tmpreg >= MIN_REGNUM && tmpreg <= MAX_REGNUM) 546 *reg = tmpreg; 547 else 548 { 549 as_bad (_("Invalid register number at '%.6s'"), s); 550 *reg = 0; 551 } 552 return s; 553 } 554 /* Stack protection registers. */ 555 else if (strncasecmp (s, "rshr", 4) == 0) 556 { 557 *reg = REG_SHR; 558 return s + 4; 559 } 560 else if (strncasecmp (s, "rslr", 4) == 0) 561 { 562 *reg = REG_SLR; 563 return s + 4; 564 } 565 else 566 { 567 if (TOLOWER (s[0]) == 'r') 568 { 569 if (ISDIGIT (s[1]) && ISDIGIT (s[2])) 570 { 571 tmpreg = (s[1] - '0') * 10 + s[2] - '0'; 572 s += 3; 573 } 574 else if (ISDIGIT (s[1])) 575 { 576 tmpreg = s[1] - '0'; 577 s += 2; 578 } 579 else 580 as_bad (_("register expected, but saw '%.6s'"), s); 581 582 if ((int)tmpreg >= MIN_REGNUM && tmpreg <= MAX_REGNUM) 583 *reg = tmpreg; 584 else 585 { 586 as_bad (_("Invalid register number at '%.6s'"), s); 587 *reg = 0; 588 } 589 return s; 590 } 591 } 592 as_bad (_("register expected, but saw '%.6s'"), s); 593 *reg = 0; 594 return s; 595} 596 597static char * 598parse_exp (char *s, expressionS *e) 599{ 600 char *save; 601 char *new_pointer; 602 603 /* Skip whitespace. */ 604 while (ISSPACE (* s)) 605 ++ s; 606 607 save = input_line_pointer; 608 input_line_pointer = s; 609 610 expression (e); 611 612 if (e->X_op == O_absent) 613 as_fatal (_("missing operand")); 614 615 new_pointer = input_line_pointer; 616 input_line_pointer = save; 617 618 return new_pointer; 619} 620 621/* Symbol modifiers (@GOT, @PLT, @GOTOFF). */ 622#define IMM_NONE 0 623#define IMM_GOT 1 624#define IMM_PLT 2 625#define IMM_GOTOFF 3 626#define IMM_TLSGD 4 627#define IMM_TLSLD 5 628#define IMM_TLSDTPMOD 6 629#define IMM_TLSDTPREL 7 630#define IMM_TLSTPREL 8 631#define IMM_TXTREL 9 632#define IMM_TXTPCREL 10 633#define IMM_MAX 11 634 635struct imm_type { 636 const char *isuffix; /* Suffix String */ 637 int itype; /* Suffix Type */ 638 int otype; /* Offset Type */ 639}; 640 641/* These are NOT in ascending order of type, GOTOFF is ahead to make 642 sure @GOTOFF does not get matched with @GOT */ 643static struct imm_type imm_types[] = { 644 { "NONE", IMM_NONE , 0 }, 645 { "GOTOFF", IMM_GOTOFF , GOTOFF_OFFSET }, 646 { "GOT", IMM_GOT , GOT_OFFSET }, 647 { "PLT", IMM_PLT , PLT_OFFSET }, 648 { "TLSGD", IMM_TLSGD , TLSGD_OFFSET }, 649 { "TLSLDM", IMM_TLSLD, TLSLD_OFFSET }, 650 { "TLSDTPMOD", IMM_TLSDTPMOD, TLSDTPMOD_OFFSET }, 651 { "TLSDTPREL", IMM_TLSDTPREL, TLSDTPREL_OFFSET }, 652 { "TLSTPREL", IMM_TLSTPREL, TLSTPREL_OFFSET }, 653 { "TXTREL", IMM_TXTREL, TEXT_OFFSET }, 654 { "TXTPCREL", IMM_TXTPCREL, TEXT_PC_OFFSET } 655}; 656 657static int 658match_imm (const char *s, int *ilen) 659{ 660 int i; 661 int slen; 662 663 /* Check for matching suffix */ 664 for (i = 1; i < IMM_MAX; i++) 665 { 666 slen = strlen (imm_types[i].isuffix); 667 668 if (strncmp (imm_types[i].isuffix, s, slen) == 0) 669 { 670 *ilen = slen; 671 return imm_types[i].itype; 672 } 673 } /* for */ 674 *ilen = 0; 675 return 0; 676} 677 678static int 679get_imm_otype (int itype) 680{ 681 int i, otype; 682 683 otype = 0; 684 /* Check for matching itype */ 685 for (i = 1; i < IMM_MAX; i++) 686 { 687 if (imm_types[i].itype == itype) 688 { 689 otype = imm_types[i].otype; 690 break; 691 } 692 } 693 return otype; 694} 695 696static symbolS * GOT_symbol; 697 698#define GOT_SYMBOL_NAME "_GLOBAL_OFFSET_TABLE_" 699 700static char * 701parse_imm (char * s, expressionS * e, offsetT min, offsetT max) 702{ 703 char *new_pointer; 704 char *atp; 705 int itype, ilen; 706 707 ilen = 0; 708 709 /* Find the start of "@GOT" or "@PLT" suffix (if any) */ 710 for (atp = s; *atp != '@'; atp++) 711 if (is_end_of_line[(unsigned char) *atp]) 712 break; 713 714 if (*atp == '@') 715 { 716 itype = match_imm (atp + 1, &ilen); 717 if (itype != 0) 718 { 719 *atp = 0; 720 e->X_md = itype; 721 } 722 else 723 { 724 atp = NULL; 725 e->X_md = 0; 726 ilen = 0; 727 } 728 *atp = 0; 729 } 730 else 731 { 732 atp = NULL; 733 e->X_md = 0; 734 } 735 736 if (atp && !GOT_symbol) 737 { 738 GOT_symbol = symbol_find_or_make (GOT_SYMBOL_NAME); 739 } 740 741 new_pointer = parse_exp (s, e); 742 743 if (!GOT_symbol && ! strncmp (s, GOT_SYMBOL_NAME, 20)) 744 { 745 GOT_symbol = symbol_find_or_make (GOT_SYMBOL_NAME); 746 } 747 748 if (e->X_op == O_absent) 749 ; /* An error message has already been emitted. */ 750 else if ((e->X_op != O_constant && e->X_op != O_symbol) ) 751 as_fatal (_("operand must be a constant or a label")); 752 else if (e->X_op == O_constant) 753 { 754 /* Special case: sign extend negative 32-bit values to offsetT size. */ 755 if ((e->X_add_number >> 31) == 1) 756 e->X_add_number |= -((addressT) (1U << 31)); 757 758 if (e->X_add_number < min || e->X_add_number > max) 759 { 760 as_fatal (_("operand must be absolute in range %lx..%lx, not %lx"), 761 (long) min, (long) max, (long) e->X_add_number); 762 } 763 } 764 765 if (atp) 766 { 767 *atp = '@'; /* restore back (needed?) */ 768 if (new_pointer >= atp) 769 new_pointer += ilen + 1; /* sizeof (imm_suffix) + 1 for '@' */ 770 } 771 return new_pointer; 772} 773 774static char * 775check_got (int * got_type, int * got_len) 776{ 777 char *new_pointer; 778 char *atp; 779 char *past_got; 780 int first, second; 781 char *tmpbuf; 782 783 /* Find the start of "@GOT" or "@PLT" suffix (if any). */ 784 for (atp = input_line_pointer; *atp != '@'; atp++) 785 if (is_end_of_line[(unsigned char) *atp]) 786 return NULL; 787 788 if (strncmp (atp + 1, "GOTOFF", 5) == 0) 789 { 790 *got_len = 6; 791 *got_type = IMM_GOTOFF; 792 } 793 else if (strncmp (atp + 1, "GOT", 3) == 0) 794 { 795 *got_len = 3; 796 *got_type = IMM_GOT; 797 } 798 else if (strncmp (atp + 1, "PLT", 3) == 0) 799 { 800 *got_len = 3; 801 *got_type = IMM_PLT; 802 } 803 else 804 return NULL; 805 806 if (!GOT_symbol) 807 GOT_symbol = symbol_find_or_make (GOT_SYMBOL_NAME); 808 809 first = atp - input_line_pointer; 810 811 past_got = atp + *got_len + 1; 812 for (new_pointer = past_got; !is_end_of_line[(unsigned char) *new_pointer++];) 813 ; 814 second = new_pointer - past_got; 815 /* One extra byte for ' ' and one for NUL. */ 816 tmpbuf = XNEWVEC (char, first + second + 2); 817 memcpy (tmpbuf, input_line_pointer, first); 818 tmpbuf[first] = ' '; /* @GOTOFF is replaced with a single space. */ 819 memcpy (tmpbuf + first + 1, past_got, second); 820 tmpbuf[first + second + 1] = '\0'; 821 822 return tmpbuf; 823} 824 825extern bfd_reloc_code_real_type 826parse_cons_expression_microblaze (expressionS *exp, int size) 827{ 828 if (size == 4) 829 { 830 /* Handle @GOTOFF et.al. */ 831 char *save, *gotfree_copy; 832 int got_len, got_type; 833 834 save = input_line_pointer; 835 gotfree_copy = check_got (& got_type, & got_len); 836 if (gotfree_copy) 837 input_line_pointer = gotfree_copy; 838 839 expression (exp); 840 841 if (gotfree_copy) 842 { 843 exp->X_md = got_type; 844 input_line_pointer = save + (input_line_pointer - gotfree_copy) 845 + got_len; 846 free (gotfree_copy); 847 } 848 } 849 else 850 expression (exp); 851 return BFD_RELOC_NONE; 852} 853 854/* This is the guts of the machine-dependent assembler. STR points to a 855 machine dependent instruction. This function is supposed to emit 856 the frags/bytes it assembles to. */ 857 858static const char * str_microblaze_ro_anchor = "RO"; 859static const char * str_microblaze_rw_anchor = "RW"; 860 861static bfd_boolean 862check_spl_reg (unsigned * reg) 863{ 864 if ((*reg == REG_MSR) || (*reg == REG_PC) 865 || (*reg == REG_EAR) || (*reg == REG_ESR) 866 || (*reg == REG_FSR) || (*reg == REG_BTR) || (*reg == REG_EDR) 867 || (*reg == REG_PID) || (*reg == REG_ZPR) 868 || (*reg == REG_TLBX) || (*reg == REG_TLBLO) 869 || (*reg == REG_TLBHI) || (*reg == REG_TLBSX) 870 || (*reg == REG_SHR) || (*reg == REG_SLR) 871 || (*reg >= REG_PVR+MIN_PVR_REGNUM && *reg <= REG_PVR+MAX_PVR_REGNUM)) 872 return TRUE; 873 874 return FALSE; 875} 876 877/* Here we decide which fixups can be adjusted to make them relative to 878 the beginning of the section instead of the symbol. Basically we need 879 to make sure that the dynamic relocations are done correctly, so in 880 some cases we force the original symbol to be used. */ 881 882int 883tc_microblaze_fix_adjustable (struct fix *fixP) 884{ 885 if (GOT_symbol && fixP->fx_subsy == GOT_symbol) 886 return 0; 887 888 if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GOTOFF 889 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_32_GOTOFF 890 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GOT 891 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_PLT 892 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSGD 893 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSLD 894 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_32_TLSDTPMOD 895 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_32_TLSDTPREL 896 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSDTPREL 897 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL 898 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSTPREL) 899 return 0; 900 901 return 1; 902} 903 904void 905md_assemble (char * str) 906{ 907 char * op_start; 908 char * op_end; 909 struct op_code_struct * opcode, *opcode1; 910 char * output = NULL; 911 int nlen = 0; 912 int i; 913 unsigned long inst, inst1; 914 unsigned reg1; 915 unsigned reg2; 916 unsigned reg3; 917 unsigned isize; 918 unsigned int immed, temp; 919 expressionS exp; 920 char name[20]; 921 922 /* Drop leading whitespace. */ 923 while (ISSPACE (* str)) 924 str ++; 925 926 /* Find the op code end. */ 927 for (op_start = op_end = str; 928 *op_end && !is_end_of_line[(unsigned char) *op_end] && *op_end != ' '; 929 op_end++) 930 { 931 name[nlen] = op_start[nlen]; 932 nlen++; 933 if (nlen == sizeof (name) - 1) 934 break; 935 } 936 937 name [nlen] = 0; 938 939 if (nlen == 0) 940 { 941 as_bad (_("can't find opcode ")); 942 return; 943 } 944 945 opcode = (struct op_code_struct *) str_hash_find (opcode_hash_control, name); 946 if (opcode == NULL) 947 { 948 as_bad (_("unknown opcode \"%s\""), name); 949 return; 950 } 951 952 inst = opcode->bit_sequence; 953 isize = 4; 954 955 switch (opcode->inst_type) 956 { 957 case INST_TYPE_RD_R1_R2: 958 if (strcmp (op_end, "")) 959 op_end = parse_reg (op_end + 1, ®1); /* Get rd. */ 960 else 961 { 962 as_fatal (_("Error in statement syntax")); 963 reg1 = 0; 964 } 965 if (strcmp (op_end, "")) 966 op_end = parse_reg (op_end + 1, ®2); /* Get r1. */ 967 else 968 { 969 as_fatal (_("Error in statement syntax")); 970 reg2 = 0; 971 } 972 if (strcmp (op_end, "")) 973 op_end = parse_reg (op_end + 1, ®3); /* Get r2. */ 974 else 975 { 976 as_fatal (_("Error in statement syntax")); 977 reg3 = 0; 978 } 979 980 /* Check for spl registers. */ 981 if (check_spl_reg (& reg1)) 982 as_fatal (_("Cannot use special register with this instruction")); 983 if (check_spl_reg (& reg2)) 984 as_fatal (_("Cannot use special register with this instruction")); 985 if (check_spl_reg (& reg3)) 986 as_fatal (_("Cannot use special register with this instruction")); 987 988 if (streq (name, "sub")) 989 { 990 /* sub rd, r1, r2 becomes rsub rd, r2, r1. */ 991 inst |= (reg1 << RD_LOW) & RD_MASK; 992 inst |= (reg3 << RA_LOW) & RA_MASK; 993 inst |= (reg2 << RB_LOW) & RB_MASK; 994 } 995 else 996 { 997 inst |= (reg1 << RD_LOW) & RD_MASK; 998 inst |= (reg2 << RA_LOW) & RA_MASK; 999 inst |= (reg3 << RB_LOW) & RB_MASK; 1000 } 1001 output = frag_more (isize); 1002 break; 1003 1004 case INST_TYPE_RD_R1_IMM: 1005 if (strcmp (op_end, "")) 1006 op_end = parse_reg (op_end + 1, ®1); /* Get rd. */ 1007 else 1008 { 1009 as_fatal (_("Error in statement syntax")); 1010 reg1 = 0; 1011 } 1012 if (strcmp (op_end, "")) 1013 op_end = parse_reg (op_end + 1, ®2); /* Get r1. */ 1014 else 1015 { 1016 as_fatal (_("Error in statement syntax")); 1017 reg2 = 0; 1018 } 1019 if (strcmp (op_end, "")) 1020 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM); 1021 else 1022 as_fatal (_("Error in statement syntax")); 1023 1024 /* Check for spl registers. */ 1025 if (check_spl_reg (& reg1)) 1026 as_fatal (_("Cannot use special register with this instruction")); 1027 if (check_spl_reg (& reg2)) 1028 as_fatal (_("Cannot use special register with this instruction")); 1029 1030 if (exp.X_op != O_constant || exp.X_md == IMM_TXTPCREL) 1031 { 1032 const char *opc; 1033 relax_substateT subtype; 1034 1035 if (streq (name, "lmi")) 1036 as_fatal (_("lmi pseudo instruction should not use a label in imm field")); 1037 else if (streq (name, "smi")) 1038 as_fatal (_("smi pseudo instruction should not use a label in imm field")); 1039 1040 if (reg2 == REG_ROSDP) 1041 opc = str_microblaze_ro_anchor; 1042 else if (reg2 == REG_RWSDP) 1043 opc = str_microblaze_rw_anchor; 1044 else 1045 opc = NULL; 1046 if (exp.X_md != 0) 1047 subtype = get_imm_otype(exp.X_md); 1048 else 1049 subtype = opcode->inst_offset_type; 1050 1051 output = frag_var (rs_machine_dependent, 1052 isize * 2, /* maxm of 2 words. */ 1053 isize, /* minm of 1 word. */ 1054 subtype, /* PC-relative or not. */ 1055 exp.X_add_symbol, 1056 exp.X_add_number, 1057 (char *) opc); 1058 immed = 0; 1059 } 1060 else 1061 { 1062 output = frag_more (isize); 1063 immed = exp.X_add_number; 1064 } 1065 1066 if (streq (name, "lmi") || streq (name, "smi")) 1067 { 1068 /* Load/store 32-d consecutive registers. Used on exit/entry 1069 to subroutines to save and restore registers to stack. 1070 Generate 32-d insts. */ 1071 int count; 1072 1073 count = 32 - reg1; 1074 if (streq (name, "lmi")) 1075 opcode 1076 = (struct op_code_struct *) str_hash_find (opcode_hash_control, 1077 "lwi"); 1078 else 1079 opcode 1080 = (struct op_code_struct *) str_hash_find (opcode_hash_control, 1081 "swi"); 1082 if (opcode == NULL) 1083 { 1084 as_bad (_("unknown opcode \"%s\""), "lwi"); 1085 return; 1086 } 1087 inst = opcode->bit_sequence; 1088 inst |= (reg1 << RD_LOW) & RD_MASK; 1089 inst |= (reg2 << RA_LOW) & RA_MASK; 1090 inst |= (immed << IMM_LOW) & IMM_MASK; 1091 1092 for (i = 0; i < count - 1; i++) 1093 { 1094 output[0] = INST_BYTE0 (inst); 1095 output[1] = INST_BYTE1 (inst); 1096 output[2] = INST_BYTE2 (inst); 1097 output[3] = INST_BYTE3 (inst); 1098 output = frag_more (isize); 1099 immed = immed + 4; 1100 reg1++; 1101 inst = opcode->bit_sequence; 1102 inst |= (reg1 << RD_LOW) & RD_MASK; 1103 inst |= (reg2 << RA_LOW) & RA_MASK; 1104 inst |= (immed << IMM_LOW) & IMM_MASK; 1105 } 1106 } 1107 else 1108 { 1109 temp = immed & 0xFFFF8000; 1110 if ((temp != 0) && (temp != 0xFFFF8000)) 1111 { 1112 /* Needs an immediate inst. */ 1113 opcode1 1114 = (struct op_code_struct *) str_hash_find (opcode_hash_control, 1115 "imm"); 1116 if (opcode1 == NULL) 1117 { 1118 as_bad (_("unknown opcode \"%s\""), "imm"); 1119 return; 1120 } 1121 1122 inst1 = opcode1->bit_sequence; 1123 inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK; 1124 output[0] = INST_BYTE0 (inst1); 1125 output[1] = INST_BYTE1 (inst1); 1126 output[2] = INST_BYTE2 (inst1); 1127 output[3] = INST_BYTE3 (inst1); 1128 output = frag_more (isize); 1129 } 1130 inst |= (reg1 << RD_LOW) & RD_MASK; 1131 inst |= (reg2 << RA_LOW) & RA_MASK; 1132 inst |= (immed << IMM_LOW) & IMM_MASK; 1133 } 1134 break; 1135 1136 case INST_TYPE_RD_R1_IMM5: 1137 if (strcmp (op_end, "")) 1138 op_end = parse_reg (op_end + 1, ®1); /* Get rd. */ 1139 else 1140 { 1141 as_fatal (_("Error in statement syntax")); 1142 reg1 = 0; 1143 } 1144 if (strcmp (op_end, "")) 1145 op_end = parse_reg (op_end + 1, ®2); /* Get r1. */ 1146 else 1147 { 1148 as_fatal (_("Error in statement syntax")); 1149 reg2 = 0; 1150 } 1151 if (strcmp (op_end, "")) 1152 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM); 1153 else 1154 as_fatal (_("Error in statement syntax")); 1155 1156 /* Check for spl registers. */ 1157 if (check_spl_reg (®1)) 1158 as_fatal (_("Cannot use special register with this instruction")); 1159 if (check_spl_reg (®2)) 1160 as_fatal (_("Cannot use special register with this instruction")); 1161 1162 if (exp.X_op != O_constant) 1163 as_warn (_("Symbol used as immediate for shift instruction")); 1164 else 1165 { 1166 output = frag_more (isize); 1167 immed = exp.X_add_number; 1168 } 1169 1170 if (immed != (immed % 32)) 1171 { 1172 as_warn (_("Shift value > 32. using <value %% 32>")); 1173 immed = immed % 32; 1174 } 1175 inst |= (reg1 << RD_LOW) & RD_MASK; 1176 inst |= (reg2 << RA_LOW) & RA_MASK; 1177 inst |= (immed << IMM_LOW) & IMM5_MASK; 1178 break; 1179 1180 case INST_TYPE_R1_R2: 1181 if (strcmp (op_end, "")) 1182 op_end = parse_reg (op_end + 1, ®1); /* Get r1. */ 1183 else 1184 { 1185 as_fatal (_("Error in statement syntax")); 1186 reg1 = 0; 1187 } 1188 if (strcmp (op_end, "")) 1189 op_end = parse_reg (op_end + 1, ®2); /* Get r2. */ 1190 else 1191 { 1192 as_fatal (_("Error in statement syntax")); 1193 reg2 = 0; 1194 } 1195 1196 /* Check for spl registers. */ 1197 if (check_spl_reg (& reg1)) 1198 as_fatal (_("Cannot use special register with this instruction")); 1199 if (check_spl_reg (& reg2)) 1200 as_fatal (_("Cannot use special register with this instruction")); 1201 1202 inst |= (reg1 << RA_LOW) & RA_MASK; 1203 inst |= (reg2 << RB_LOW) & RB_MASK; 1204 output = frag_more (isize); 1205 break; 1206 1207 case INST_TYPE_RD_R1: 1208 if (strcmp (op_end, "")) 1209 op_end = parse_reg (op_end + 1, ®1); /* Get rd. */ 1210 else 1211 { 1212 as_fatal (_("Error in statement syntax")); 1213 reg1 = 0; 1214 } 1215 if (strcmp (op_end, "")) 1216 op_end = parse_reg (op_end + 1, ®2); /* Get r1. */ 1217 else 1218 { 1219 as_fatal (_("Error in statement syntax")); 1220 reg2 =0; 1221 } 1222 1223 /* Check for spl registers. */ 1224 if (check_spl_reg (®1)) 1225 as_fatal (_("Cannot use special register with this instruction")); 1226 if (check_spl_reg (®2)) 1227 as_fatal (_("Cannot use special register with this instruction")); 1228 1229 inst |= (reg1 << RD_LOW) & RD_MASK; 1230 inst |= (reg2 << RA_LOW) & RA_MASK; 1231 output = frag_more (isize); 1232 break; 1233 1234 case INST_TYPE_RD_RFSL: 1235 if (strcmp (op_end, "")) 1236 op_end = parse_reg (op_end + 1, ®1); /* Get rd. */ 1237 else 1238 { 1239 as_fatal (_("Error in statement syntax")); 1240 reg1 = 0; 1241 } 1242 if (strcmp (op_end, "")) 1243 op_end = parse_reg (op_end + 1, &immed); /* Get rfslN. */ 1244 else 1245 { 1246 as_fatal (_("Error in statement syntax")); 1247 immed = 0; 1248 } 1249 1250 /* Check for spl registers. */ 1251 if (check_spl_reg (®1)) 1252 as_fatal (_("Cannot use special register with this instruction")); 1253 1254 inst |= (reg1 << RD_LOW) & RD_MASK; 1255 inst |= (immed << IMM_LOW) & RFSL_MASK; 1256 output = frag_more (isize); 1257 break; 1258 1259 case INST_TYPE_RD_IMM15: 1260 if (strcmp (op_end, "")) 1261 op_end = parse_reg (op_end + 1, ®1); /* Get rd. */ 1262 else 1263 { 1264 as_fatal (_("Error in statement syntax")); 1265 reg1 = 0; 1266 } 1267 1268 if (strcmp (op_end, "")) 1269 op_end = parse_imm (op_end + 1, & exp, MIN_IMM15, MAX_IMM15); 1270 else 1271 as_fatal (_("Error in statement syntax")); 1272 1273 /* Check for spl registers. */ 1274 if (check_spl_reg (®1)) 1275 as_fatal (_("Cannot use special register with this instruction")); 1276 1277 if (exp.X_op != O_constant) 1278 as_fatal (_("Symbol used as immediate value for msrset/msrclr instructions")); 1279 else 1280 { 1281 output = frag_more (isize); 1282 immed = exp.X_add_number; 1283 } 1284 inst |= (reg1 << RD_LOW) & RD_MASK; 1285 inst |= (immed << IMM_LOW) & IMM15_MASK; 1286 break; 1287 1288 case INST_TYPE_R1_RFSL: 1289 if (strcmp (op_end, "")) 1290 op_end = parse_reg (op_end + 1, ®1); /* Get r1. */ 1291 else 1292 { 1293 as_fatal (_("Error in statement syntax")); 1294 reg1 = 0; 1295 } 1296 if (strcmp (op_end, "")) 1297 op_end = parse_reg (op_end + 1, &immed); /* Get rfslN. */ 1298 else 1299 { 1300 as_fatal (_("Error in statement syntax")); 1301 immed = 0; 1302 } 1303 1304 /* Check for spl registers. */ 1305 if (check_spl_reg (®1)) 1306 as_fatal (_("Cannot use special register with this instruction")); 1307 1308 inst |= (reg1 << RA_LOW) & RA_MASK; 1309 inst |= (immed << IMM_LOW) & RFSL_MASK; 1310 output = frag_more (isize); 1311 break; 1312 1313 case INST_TYPE_RFSL: 1314 if (strcmp (op_end, "")) 1315 op_end = parse_reg (op_end + 1, &immed); /* Get rfslN. */ 1316 else 1317 { 1318 as_fatal (_("Error in statement syntax")); 1319 immed = 0; 1320 } 1321 inst |= (immed << IMM_LOW) & RFSL_MASK; 1322 output = frag_more (isize); 1323 break; 1324 1325 case INST_TYPE_R1: 1326 if (strcmp (op_end, "")) 1327 op_end = parse_reg (op_end + 1, ®1); /* Get r1. */ 1328 else 1329 { 1330 as_fatal (_("Error in statement syntax")); 1331 reg1 = 0; 1332 } 1333 1334 /* Check for spl registers. */ 1335 if (check_spl_reg (®1)) 1336 as_fatal (_("Cannot use special register with this instruction")); 1337 1338 inst |= (reg1 << RA_LOW) & RA_MASK; 1339 output = frag_more (isize); 1340 break; 1341 1342 /* For tuqula insn...:) */ 1343 case INST_TYPE_RD: 1344 if (strcmp (op_end, "")) 1345 op_end = parse_reg (op_end + 1, ®1); /* Get rd. */ 1346 else 1347 { 1348 as_fatal (_("Error in statement syntax")); 1349 reg1 = 0; 1350 } 1351 1352 /* Check for spl registers. */ 1353 if (check_spl_reg (®1)) 1354 as_fatal (_("Cannot use special register with this instruction")); 1355 1356 inst |= (reg1 << RD_LOW) & RD_MASK; 1357 output = frag_more (isize); 1358 break; 1359 1360 case INST_TYPE_RD_SPECIAL: 1361 if (strcmp (op_end, "")) 1362 op_end = parse_reg (op_end + 1, ®1); /* Get rd. */ 1363 else 1364 { 1365 as_fatal (_("Error in statement syntax")); 1366 reg1 = 0; 1367 } 1368 if (strcmp (op_end, "")) 1369 op_end = parse_reg (op_end + 1, ®2); /* Get r1. */ 1370 else 1371 { 1372 as_fatal (_("Error in statement syntax")); 1373 reg2 = 0; 1374 } 1375 1376 if (reg2 == REG_MSR) 1377 immed = opcode->immval_mask | REG_MSR_MASK; 1378 else if (reg2 == REG_PC) 1379 immed = opcode->immval_mask | REG_PC_MASK; 1380 else if (reg2 == REG_EAR) 1381 immed = opcode->immval_mask | REG_EAR_MASK; 1382 else if (reg2 == REG_ESR) 1383 immed = opcode->immval_mask | REG_ESR_MASK; 1384 else if (reg2 == REG_FSR) 1385 immed = opcode->immval_mask | REG_FSR_MASK; 1386 else if (reg2 == REG_BTR) 1387 immed = opcode->immval_mask | REG_BTR_MASK; 1388 else if (reg2 == REG_EDR) 1389 immed = opcode->immval_mask | REG_EDR_MASK; 1390 else if (reg2 == REG_PID) 1391 immed = opcode->immval_mask | REG_PID_MASK; 1392 else if (reg2 == REG_ZPR) 1393 immed = opcode->immval_mask | REG_ZPR_MASK; 1394 else if (reg2 == REG_TLBX) 1395 immed = opcode->immval_mask | REG_TLBX_MASK; 1396 else if (reg2 == REG_TLBLO) 1397 immed = opcode->immval_mask | REG_TLBLO_MASK; 1398 else if (reg2 == REG_TLBHI) 1399 immed = opcode->immval_mask | REG_TLBHI_MASK; 1400 else if (reg2 == REG_SHR) 1401 immed = opcode->immval_mask | REG_SHR_MASK; 1402 else if (reg2 == REG_SLR) 1403 immed = opcode->immval_mask | REG_SLR_MASK; 1404 else if (reg2 >= (REG_PVR+MIN_PVR_REGNUM) && reg2 <= (REG_PVR+MAX_PVR_REGNUM)) 1405 immed = opcode->immval_mask | REG_PVR_MASK | reg2; 1406 else 1407 as_fatal (_("invalid value for special purpose register")); 1408 inst |= (reg1 << RD_LOW) & RD_MASK; 1409 inst |= (immed << IMM_LOW) & IMM_MASK; 1410 output = frag_more (isize); 1411 break; 1412 1413 case INST_TYPE_SPECIAL_R1: 1414 if (strcmp (op_end, "")) 1415 op_end = parse_reg (op_end + 1, ®1); /* Get rd. */ 1416 else 1417 { 1418 as_fatal (_("Error in statement syntax")); 1419 reg1 = 0; 1420 } 1421 if (strcmp (op_end, "")) 1422 op_end = parse_reg (op_end + 1, ®2); /* Get r1. */ 1423 else 1424 { 1425 as_fatal (_("Error in statement syntax")); 1426 reg2 = 0; 1427 } 1428 1429 if (reg1 == REG_MSR) 1430 immed = opcode->immval_mask | REG_MSR_MASK; 1431 else if (reg1 == REG_PC) 1432 immed = opcode->immval_mask | REG_PC_MASK; 1433 else if (reg1 == REG_EAR) 1434 immed = opcode->immval_mask | REG_EAR_MASK; 1435 else if (reg1 == REG_ESR) 1436 immed = opcode->immval_mask | REG_ESR_MASK; 1437 else if (reg1 == REG_FSR) 1438 immed = opcode->immval_mask | REG_FSR_MASK; 1439 else if (reg1 == REG_BTR) 1440 immed = opcode->immval_mask | REG_BTR_MASK; 1441 else if (reg1 == REG_EDR) 1442 immed = opcode->immval_mask | REG_EDR_MASK; 1443 else if (reg1 == REG_PID) 1444 immed = opcode->immval_mask | REG_PID_MASK; 1445 else if (reg1 == REG_ZPR) 1446 immed = opcode->immval_mask | REG_ZPR_MASK; 1447 else if (reg1 == REG_TLBX) 1448 immed = opcode->immval_mask | REG_TLBX_MASK; 1449 else if (reg1 == REG_TLBLO) 1450 immed = opcode->immval_mask | REG_TLBLO_MASK; 1451 else if (reg1 == REG_TLBHI) 1452 immed = opcode->immval_mask | REG_TLBHI_MASK; 1453 else if (reg1 == REG_TLBSX) 1454 immed = opcode->immval_mask | REG_TLBSX_MASK; 1455 else if (reg1 == REG_SHR) 1456 immed = opcode->immval_mask | REG_SHR_MASK; 1457 else if (reg1 == REG_SLR) 1458 immed = opcode->immval_mask | REG_SLR_MASK; 1459 else 1460 as_fatal (_("invalid value for special purpose register")); 1461 inst |= (reg2 << RA_LOW) & RA_MASK; 1462 inst |= (immed << IMM_LOW) & IMM_MASK; 1463 output = frag_more (isize); 1464 break; 1465 1466 case INST_TYPE_R1_R2_SPECIAL: 1467 if (strcmp (op_end, "")) 1468 op_end = parse_reg (op_end + 1, ®1); /* Get r1. */ 1469 else 1470 { 1471 as_fatal (_("Error in statement syntax")); 1472 reg1 = 0; 1473 } 1474 if (strcmp (op_end, "")) 1475 op_end = parse_reg (op_end + 1, ®2); /* Get r2. */ 1476 else 1477 { 1478 as_fatal (_("Error in statement syntax")); 1479 reg2 =0; 1480 } 1481 1482 /* Check for spl registers. */ 1483 if (check_spl_reg (®1)) 1484 as_fatal (_("Cannot use special register with this instruction")); 1485 if (check_spl_reg (®2)) 1486 as_fatal (_("Cannot use special register with this instruction")); 1487 1488 /* insn wic ra, rb => wic ra, ra, rb. */ 1489 inst |= (reg1 << RA_LOW) & RA_MASK; 1490 inst |= (reg2 << RB_LOW) & RB_MASK; 1491 1492 output = frag_more (isize); 1493 break; 1494 1495 case INST_TYPE_RD_R2: 1496 if (strcmp (op_end, "")) 1497 op_end = parse_reg (op_end + 1, ®1); /* Get rd. */ 1498 else 1499 { 1500 as_fatal (_("Error in statement syntax")); 1501 reg1 = 0; 1502 } 1503 if (strcmp (op_end, "")) 1504 op_end = parse_reg (op_end + 1, ®2); /* Get r2. */ 1505 else 1506 { 1507 as_fatal (_("Error in statement syntax")); 1508 reg2 = 0; 1509 } 1510 1511 /* Check for spl registers. */ 1512 if (check_spl_reg (®1)) 1513 as_fatal (_("Cannot use special register with this instruction")); 1514 if (check_spl_reg (®2)) 1515 as_fatal (_("Cannot use special register with this instruction")); 1516 1517 inst |= (reg1 << RD_LOW) & RD_MASK; 1518 inst |= (reg2 << RB_LOW) & RB_MASK; 1519 output = frag_more (isize); 1520 break; 1521 1522 case INST_TYPE_R1_IMM: 1523 if (strcmp (op_end, "")) 1524 op_end = parse_reg (op_end + 1, ®1); /* Get r1. */ 1525 else 1526 { 1527 as_fatal (_("Error in statement syntax")); 1528 reg1 = 0; 1529 } 1530 if (strcmp (op_end, "")) 1531 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM); 1532 else 1533 as_fatal (_("Error in statement syntax")); 1534 1535 /* Check for spl registers. */ 1536 if (check_spl_reg (®1)) 1537 as_fatal (_("Cannot use special register with this instruction")); 1538 1539 if (exp.X_op != O_constant) 1540 { 1541 char *opc = NULL; 1542 relax_substateT subtype; 1543 1544 if (exp.X_md != 0) 1545 subtype = get_imm_otype(exp.X_md); 1546 else 1547 subtype = opcode->inst_offset_type; 1548 1549 output = frag_var (rs_machine_dependent, 1550 isize * 2, /* maxm of 2 words. */ 1551 isize, /* minm of 1 word. */ 1552 subtype, /* PC-relative or not. */ 1553 exp.X_add_symbol, 1554 exp.X_add_number, 1555 opc); 1556 immed = 0; 1557 } 1558 else 1559 { 1560 output = frag_more (isize); 1561 immed = exp.X_add_number; 1562 } 1563 1564 temp = immed & 0xFFFF8000; 1565 if ((temp != 0) && (temp != 0xFFFF8000)) 1566 { 1567 /* Needs an immediate inst. */ 1568 opcode1 1569 = (struct op_code_struct *) str_hash_find (opcode_hash_control, 1570 "imm"); 1571 if (opcode1 == NULL) 1572 { 1573 as_bad (_("unknown opcode \"%s\""), "imm"); 1574 return; 1575 } 1576 1577 inst1 = opcode1->bit_sequence; 1578 inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK; 1579 output[0] = INST_BYTE0 (inst1); 1580 output[1] = INST_BYTE1 (inst1); 1581 output[2] = INST_BYTE2 (inst1); 1582 output[3] = INST_BYTE3 (inst1); 1583 output = frag_more (isize); 1584 } 1585 1586 inst |= (reg1 << RA_LOW) & RA_MASK; 1587 inst |= (immed << IMM_LOW) & IMM_MASK; 1588 break; 1589 1590 case INST_TYPE_RD_IMM: 1591 if (strcmp (op_end, "")) 1592 op_end = parse_reg (op_end + 1, ®1); /* Get rd. */ 1593 else 1594 { 1595 as_fatal (_("Error in statement syntax")); 1596 reg1 = 0; 1597 } 1598 if (strcmp (op_end, "")) 1599 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM); 1600 else 1601 as_fatal (_("Error in statement syntax")); 1602 1603 /* Check for spl registers. */ 1604 if (check_spl_reg (®1)) 1605 as_fatal (_("Cannot use special register with this instruction")); 1606 1607 if (exp.X_op != O_constant) 1608 { 1609 char *opc = NULL; 1610 relax_substateT subtype; 1611 1612 if (exp.X_md != 0) 1613 subtype = get_imm_otype(exp.X_md); 1614 else 1615 subtype = opcode->inst_offset_type; 1616 1617 output = frag_var (rs_machine_dependent, 1618 isize * 2, /* maxm of 2 words. */ 1619 isize, /* minm of 1 word. */ 1620 subtype, /* PC-relative or not. */ 1621 exp.X_add_symbol, 1622 exp.X_add_number, 1623 opc); 1624 immed = 0; 1625 } 1626 else 1627 { 1628 output = frag_more (isize); 1629 immed = exp.X_add_number; 1630 } 1631 1632 temp = immed & 0xFFFF8000; 1633 if ((temp != 0) && (temp != 0xFFFF8000)) 1634 { 1635 /* Needs an immediate inst. */ 1636 opcode1 1637 = (struct op_code_struct *) str_hash_find (opcode_hash_control, 1638 "imm"); 1639 if (opcode1 == NULL) 1640 { 1641 as_bad (_("unknown opcode \"%s\""), "imm"); 1642 return; 1643 } 1644 1645 inst1 = opcode1->bit_sequence; 1646 inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK; 1647 output[0] = INST_BYTE0 (inst1); 1648 output[1] = INST_BYTE1 (inst1); 1649 output[2] = INST_BYTE2 (inst1); 1650 output[3] = INST_BYTE3 (inst1); 1651 output = frag_more (isize); 1652 } 1653 1654 inst |= (reg1 << RD_LOW) & RD_MASK; 1655 inst |= (immed << IMM_LOW) & IMM_MASK; 1656 break; 1657 1658 case INST_TYPE_R2: 1659 if (strcmp (op_end, "")) 1660 op_end = parse_reg (op_end + 1, ®2); /* Get r2. */ 1661 else 1662 { 1663 as_fatal (_("Error in statement syntax")); 1664 reg2 = 0; 1665 } 1666 1667 /* Check for spl registers. */ 1668 if (check_spl_reg (®2)) 1669 as_fatal (_("Cannot use special register with this instruction")); 1670 1671 inst |= (reg2 << RB_LOW) & RB_MASK; 1672 output = frag_more (isize); 1673 break; 1674 1675 case INST_TYPE_IMM: 1676 if (streq (name, "imm")) 1677 as_fatal (_("An IMM instruction should not be present in the .s file")); 1678 1679 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM); 1680 1681 if (exp.X_op != O_constant) 1682 { 1683 char *opc = NULL; 1684 relax_substateT subtype; 1685 1686 if (exp.X_md != 0) 1687 subtype = get_imm_otype(exp.X_md); 1688 else 1689 subtype = opcode->inst_offset_type; 1690 1691 output = frag_var (rs_machine_dependent, 1692 isize * 2, /* maxm of 2 words. */ 1693 isize, /* minm of 1 word. */ 1694 subtype, /* PC-relative or not. */ 1695 exp.X_add_symbol, 1696 exp.X_add_number, 1697 opc); 1698 immed = 0; 1699 } 1700 else 1701 { 1702 output = frag_more (isize); 1703 immed = exp.X_add_number; 1704 } 1705 1706 1707 temp = immed & 0xFFFF8000; 1708 if ((temp != 0) && (temp != 0xFFFF8000)) 1709 { 1710 /* Needs an immediate inst. */ 1711 opcode1 1712 = (struct op_code_struct *) str_hash_find (opcode_hash_control, 1713 "imm"); 1714 if (opcode1 == NULL) 1715 { 1716 as_bad (_("unknown opcode \"%s\""), "imm"); 1717 return; 1718 } 1719 1720 inst1 = opcode1->bit_sequence; 1721 inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK; 1722 output[0] = INST_BYTE0 (inst1); 1723 output[1] = INST_BYTE1 (inst1); 1724 output[2] = INST_BYTE2 (inst1); 1725 output[3] = INST_BYTE3 (inst1); 1726 output = frag_more (isize); 1727 } 1728 inst |= (immed << IMM_LOW) & IMM_MASK; 1729 break; 1730 1731 case INST_TYPE_NONE: 1732 output = frag_more (isize); 1733 break; 1734 1735 case INST_TYPE_IMM5: 1736 if (strcmp(op_end, "")) 1737 op_end = parse_imm (op_end + 1, & exp, MIN_IMM5, MAX_IMM5); 1738 else 1739 as_fatal(_("Error in statement syntax")); 1740 if (exp.X_op != O_constant) { 1741 as_warn(_("Symbol used as immediate for mbar instruction")); 1742 } else { 1743 output = frag_more (isize); 1744 immed = exp.X_add_number; 1745 } 1746 if (immed != (immed % 32)) { 1747 as_warn(_("Immediate value for mbar > 32. using <value %% 32>")); 1748 immed = immed % 32; 1749 } 1750 inst |= (immed << IMM_MBAR); 1751 break; 1752 1753 default: 1754 as_fatal (_("unimplemented opcode \"%s\""), name); 1755 } 1756 1757 /* Drop whitespace after all the operands have been parsed. */ 1758 while (ISSPACE (* op_end)) 1759 op_end ++; 1760 1761 /* Give warning message if the insn has more operands than required. */ 1762 if (strcmp (op_end, opcode->name) && strcmp (op_end, "")) 1763 as_warn (_("ignoring operands: %s "), op_end); 1764 1765 output[0] = INST_BYTE0 (inst); 1766 output[1] = INST_BYTE1 (inst); 1767 output[2] = INST_BYTE2 (inst); 1768 output[3] = INST_BYTE3 (inst); 1769 1770#ifdef OBJ_ELF 1771 dwarf2_emit_insn (4); 1772#endif 1773} 1774 1775symbolS * 1776md_undefined_symbol (char * name ATTRIBUTE_UNUSED) 1777{ 1778 return NULL; 1779} 1780 1781/* Turn a string in input_line_pointer into a floating point constant of type 1782 type, and store the appropriate bytes in *litP. The number of LITTLENUMS 1783 emitted is stored in *sizeP. An error message is returned, or NULL on OK.*/ 1784 1785const char * 1786md_atof (int type, char * litP, int * sizeP) 1787{ 1788 int prec; 1789 LITTLENUM_TYPE words[MAX_LITTLENUMS]; 1790 int i; 1791 char * t; 1792 1793 switch (type) 1794 { 1795 case 'f': 1796 case 'F': 1797 case 's': 1798 case 'S': 1799 prec = 2; 1800 break; 1801 1802 case 'd': 1803 case 'D': 1804 case 'r': 1805 case 'R': 1806 prec = 4; 1807 break; 1808 1809 case 'x': 1810 case 'X': 1811 prec = 6; 1812 break; 1813 1814 case 'p': 1815 case 'P': 1816 prec = 6; 1817 break; 1818 1819 default: 1820 *sizeP = 0; 1821 return _("Bad call to MD_NTOF()"); 1822 } 1823 1824 t = atof_ieee (input_line_pointer, type, words); 1825 1826 if (t) 1827 input_line_pointer = t; 1828 1829 *sizeP = prec * sizeof (LITTLENUM_TYPE); 1830 1831 if (! target_big_endian) 1832 { 1833 for (i = prec - 1; i >= 0; i--) 1834 { 1835 md_number_to_chars (litP, (valueT) words[i], 1836 sizeof (LITTLENUM_TYPE)); 1837 litP += sizeof (LITTLENUM_TYPE); 1838 } 1839 } 1840 else 1841 for (i = 0; i < prec; i++) 1842 { 1843 md_number_to_chars (litP, (valueT) words[i], 1844 sizeof (LITTLENUM_TYPE)); 1845 litP += sizeof (LITTLENUM_TYPE); 1846 } 1847 1848 return NULL; 1849} 1850 1851const char * md_shortopts = ""; 1852 1853struct option md_longopts[] = 1854{ 1855 {"EB", no_argument, NULL, OPTION_EB}, 1856 {"EL", no_argument, NULL, OPTION_EL}, 1857 { NULL, no_argument, NULL, 0} 1858}; 1859 1860size_t md_longopts_size = sizeof (md_longopts); 1861 1862int md_short_jump_size; 1863 1864void 1865md_create_short_jump (char * ptr ATTRIBUTE_UNUSED, 1866 addressT from_Nddr ATTRIBUTE_UNUSED, 1867 addressT to_Nddr ATTRIBUTE_UNUSED, 1868 fragS * frag ATTRIBUTE_UNUSED, 1869 symbolS * to_symbol ATTRIBUTE_UNUSED) 1870{ 1871 as_fatal (_("failed sanity check: short_jump")); 1872} 1873 1874void 1875md_create_long_jump (char * ptr ATTRIBUTE_UNUSED, 1876 addressT from_Nddr ATTRIBUTE_UNUSED, 1877 addressT to_Nddr ATTRIBUTE_UNUSED, 1878 fragS * frag ATTRIBUTE_UNUSED, 1879 symbolS * to_symbol ATTRIBUTE_UNUSED) 1880{ 1881 as_fatal (_("failed sanity check: long_jump")); 1882} 1883 1884/* Called after relaxing, change the frags so they know how big they are. */ 1885 1886void 1887md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, 1888 segT sec ATTRIBUTE_UNUSED, 1889 fragS * fragP) 1890{ 1891 fixS *fixP; 1892 1893 switch (fragP->fr_subtype) 1894 { 1895 case UNDEFINED_PC_OFFSET: 1896 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol, 1897 fragP->fr_offset, TRUE, BFD_RELOC_64_PCREL); 1898 fragP->fr_fix += INST_WORD_SIZE * 2; 1899 fragP->fr_var = 0; 1900 break; 1901 case DEFINED_ABS_SEGMENT: 1902 if (fragP->fr_symbol == GOT_symbol) 1903 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol, 1904 fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_64_GOTPC); 1905 else 1906 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol, 1907 fragP->fr_offset, FALSE, BFD_RELOC_64); 1908 fragP->fr_fix += INST_WORD_SIZE * 2; 1909 fragP->fr_var = 0; 1910 break; 1911 case DEFINED_RO_SEGMENT: 1912 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol, 1913 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_32_ROSDA); 1914 fragP->fr_fix += INST_WORD_SIZE; 1915 fragP->fr_var = 0; 1916 break; 1917 case DEFINED_RW_SEGMENT: 1918 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol, 1919 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_32_RWSDA); 1920 fragP->fr_fix += INST_WORD_SIZE; 1921 fragP->fr_var = 0; 1922 break; 1923 case DEFINED_PC_OFFSET: 1924 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol, 1925 fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_32_LO_PCREL); 1926 fragP->fr_fix += INST_WORD_SIZE; 1927 fragP->fr_var = 0; 1928 break; 1929 case LARGE_DEFINED_PC_OFFSET: 1930 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol, 1931 fragP->fr_offset, TRUE, BFD_RELOC_64_PCREL); 1932 fragP->fr_fix += INST_WORD_SIZE * 2; 1933 fragP->fr_var = 0; 1934 break; 1935 case GOT_OFFSET: 1936 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol, 1937 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_GOT); 1938 fragP->fr_fix += INST_WORD_SIZE * 2; 1939 fragP->fr_var = 0; 1940 break; 1941 case TEXT_OFFSET: 1942 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol, 1943 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TEXTREL); 1944 fragP->fr_fix += INST_WORD_SIZE * 2; 1945 fragP->fr_var = 0; 1946 break; 1947 case TEXT_PC_OFFSET: 1948 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol, 1949 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TEXTPCREL); 1950 fragP->fr_fix += INST_WORD_SIZE * 2; 1951 fragP->fr_var = 0; 1952 break; 1953 case PLT_OFFSET: 1954 fixP = fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol, 1955 fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_64_PLT); 1956 /* fixP->fx_plt = 1; */ 1957 (void) fixP; 1958 fragP->fr_fix += INST_WORD_SIZE * 2; 1959 fragP->fr_var = 0; 1960 break; 1961 case GOTOFF_OFFSET: 1962 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol, 1963 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_GOTOFF); 1964 fragP->fr_fix += INST_WORD_SIZE * 2; 1965 fragP->fr_var = 0; 1966 break; 1967 case TLSGD_OFFSET: 1968 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol, 1969 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TLSGD); 1970 fragP->fr_fix += INST_WORD_SIZE * 2; 1971 fragP->fr_var = 0; 1972 break; 1973 case TLSLD_OFFSET: 1974 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol, 1975 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TLSLD); 1976 fragP->fr_fix += INST_WORD_SIZE * 2; 1977 fragP->fr_var = 0; 1978 break; 1979 case TLSDTPREL_OFFSET: 1980 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol, 1981 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TLSDTPREL); 1982 fragP->fr_fix += INST_WORD_SIZE * 2; 1983 fragP->fr_var = 0; 1984 break; 1985 1986 default: 1987 abort (); 1988 } 1989} 1990 1991/* Applies the desired value to the specified location. 1992 Also sets up addends for 'rela' type relocations. */ 1993void 1994md_apply_fix (fixS * fixP, 1995 valueT * valp, 1996 segT segment) 1997{ 1998 char * buf = fixP->fx_where + &fixP->fx_frag->fr_literal[0]; 1999 const char * file = fixP->fx_file ? fixP->fx_file : _("unknown"); 2000 const char * symname; 2001 /* Note: use offsetT because it is signed, valueT is unsigned. */ 2002 offsetT val = (offsetT) * valp; 2003 int i; 2004 struct op_code_struct * opcode1; 2005 unsigned long inst1; 2006 2007 symname = fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : _("<unknown>"); 2008 2009 /* fixP->fx_offset is supposed to be set up correctly for all 2010 symbol relocations. */ 2011 if (fixP->fx_addsy == NULL) 2012 { 2013 if (!fixP->fx_pcrel) 2014 fixP->fx_offset = val; /* Absolute relocation. */ 2015 else 2016 fprintf (stderr, "NULL symbol PC-relative relocation? offset = %08x, val = %08x\n", 2017 (unsigned int) fixP->fx_offset, (unsigned int) val); 2018 } 2019 2020 /* If we aren't adjusting this fixup to be against the section 2021 symbol, we need to adjust the value. */ 2022 if (fixP->fx_addsy != NULL) 2023 { 2024 if (S_IS_WEAK (fixP->fx_addsy) 2025 || (symbol_used_in_reloc_p (fixP->fx_addsy) 2026 && (((bfd_section_flags (S_GET_SEGMENT (fixP->fx_addsy)) 2027 & SEC_LINK_ONCE) != 0) 2028 || !strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)), 2029 ".gnu.linkonce", 2030 sizeof (".gnu.linkonce") - 1)))) 2031 { 2032 val -= S_GET_VALUE (fixP->fx_addsy); 2033 if (val != 0 && ! fixP->fx_pcrel) 2034 { 2035 /* In this case, the bfd_install_relocation routine will 2036 incorrectly add the symbol value back in. We just want 2037 the addend to appear in the object file. 2038 FIXME: If this makes VALUE zero, we're toast. */ 2039 val -= S_GET_VALUE (fixP->fx_addsy); 2040 } 2041 } 2042 } 2043 2044 /* If the fix is relative to a symbol which is not defined, or not 2045 in the same segment as the fix, we cannot resolve it here. */ 2046 /* fixP->fx_addsy is NULL if valp contains the entire relocation. */ 2047 if (fixP->fx_addsy != NULL 2048 && (!S_IS_DEFINED (fixP->fx_addsy) 2049 || (S_GET_SEGMENT (fixP->fx_addsy) != segment))) 2050 { 2051 fixP->fx_done = 0; 2052#ifdef OBJ_ELF 2053 /* For ELF we can just return and let the reloc that will be generated 2054 take care of everything. For COFF we still have to insert 'val' 2055 into the insn since the addend field will be ignored. */ 2056 /* return; */ 2057#endif 2058 } 2059 /* All fixups in the text section must be handled in the linker. */ 2060 else if (segment->flags & SEC_CODE) 2061 fixP->fx_done = 0; 2062 else if (!fixP->fx_pcrel && fixP->fx_addsy != NULL) 2063 fixP->fx_done = 0; 2064 else 2065 fixP->fx_done = 1; 2066 2067 switch (fixP->fx_r_type) 2068 { 2069 case BFD_RELOC_MICROBLAZE_32_LO: 2070 case BFD_RELOC_MICROBLAZE_32_LO_PCREL: 2071 if (target_big_endian) 2072 { 2073 buf[2] |= ((val >> 8) & 0xff); 2074 buf[3] |= (val & 0xff); 2075 } 2076 else 2077 { 2078 buf[1] |= ((val >> 8) & 0xff); 2079 buf[0] |= (val & 0xff); 2080 } 2081 break; 2082 case BFD_RELOC_MICROBLAZE_32_ROSDA: 2083 case BFD_RELOC_MICROBLAZE_32_RWSDA: 2084 /* Don't do anything if the symbol is not defined. */ 2085 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy)) 2086 { 2087 if (((val & 0xFFFF8000) != 0) && ((val & 0xFFFF8000) != 0xFFFF8000)) 2088 as_bad_where (file, fixP->fx_line, 2089 _("pcrel for branch to %s too far (0x%x)"), 2090 symname, (int) val); 2091 if (target_big_endian) 2092 { 2093 buf[2] |= ((val >> 8) & 0xff); 2094 buf[3] |= (val & 0xff); 2095 } 2096 else 2097 { 2098 buf[1] |= ((val >> 8) & 0xff); 2099 buf[0] |= (val & 0xff); 2100 } 2101 } 2102 break; 2103 case BFD_RELOC_32: 2104 case BFD_RELOC_RVA: 2105 case BFD_RELOC_32_PCREL: 2106 case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM: 2107 /* Don't do anything if the symbol is not defined. */ 2108 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy)) 2109 { 2110 if (target_big_endian) 2111 { 2112 buf[0] |= ((val >> 24) & 0xff); 2113 buf[1] |= ((val >> 16) & 0xff); 2114 buf[2] |= ((val >> 8) & 0xff); 2115 buf[3] |= (val & 0xff); 2116 } 2117 else 2118 { 2119 buf[3] |= ((val >> 24) & 0xff); 2120 buf[2] |= ((val >> 16) & 0xff); 2121 buf[1] |= ((val >> 8) & 0xff); 2122 buf[0] |= (val & 0xff); 2123 } 2124 } 2125 break; 2126 case BFD_RELOC_64_PCREL: 2127 case BFD_RELOC_64: 2128 case BFD_RELOC_MICROBLAZE_64_TEXTREL: 2129 /* Add an imm instruction. First save the current instruction. */ 2130 for (i = 0; i < INST_WORD_SIZE; i++) 2131 buf[i + INST_WORD_SIZE] = buf[i]; 2132 2133 /* Generate the imm instruction. */ 2134 opcode1 2135 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imm"); 2136 if (opcode1 == NULL) 2137 { 2138 as_bad (_("unknown opcode \"%s\""), "imm"); 2139 return; 2140 } 2141 2142 inst1 = opcode1->bit_sequence; 2143 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy)) 2144 inst1 |= ((val & 0xFFFF0000) >> 16) & IMM_MASK; 2145 2146 buf[0] = INST_BYTE0 (inst1); 2147 buf[1] = INST_BYTE1 (inst1); 2148 buf[2] = INST_BYTE2 (inst1); 2149 buf[3] = INST_BYTE3 (inst1); 2150 2151 /* Add the value only if the symbol is defined. */ 2152 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy)) 2153 { 2154 if (target_big_endian) 2155 { 2156 buf[6] |= ((val >> 8) & 0xff); 2157 buf[7] |= (val & 0xff); 2158 } 2159 else 2160 { 2161 buf[5] |= ((val >> 8) & 0xff); 2162 buf[4] |= (val & 0xff); 2163 } 2164 } 2165 break; 2166 2167 case BFD_RELOC_MICROBLAZE_64_TLSDTPREL: 2168 case BFD_RELOC_MICROBLAZE_64_TLSGD: 2169 case BFD_RELOC_MICROBLAZE_64_TLSLD: 2170 S_SET_THREAD_LOCAL (fixP->fx_addsy); 2171 /* Fall through. */ 2172 2173 case BFD_RELOC_MICROBLAZE_64_GOTPC: 2174 case BFD_RELOC_MICROBLAZE_64_GOT: 2175 case BFD_RELOC_MICROBLAZE_64_PLT: 2176 case BFD_RELOC_MICROBLAZE_64_GOTOFF: 2177 case BFD_RELOC_MICROBLAZE_64_TEXTPCREL: 2178 /* Add an imm instruction. First save the current instruction. */ 2179 for (i = 0; i < INST_WORD_SIZE; i++) 2180 buf[i + INST_WORD_SIZE] = buf[i]; 2181 2182 /* Generate the imm instruction. */ 2183 opcode1 2184 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imm"); 2185 if (opcode1 == NULL) 2186 { 2187 as_bad (_("unknown opcode \"%s\""), "imm"); 2188 return; 2189 } 2190 2191 inst1 = opcode1->bit_sequence; 2192 2193 /* We can fixup call to a defined non-global address 2194 within the same section only. */ 2195 buf[0] = INST_BYTE0 (inst1); 2196 buf[1] = INST_BYTE1 (inst1); 2197 buf[2] = INST_BYTE2 (inst1); 2198 buf[3] = INST_BYTE3 (inst1); 2199 return; 2200 2201 default: 2202 break; 2203 } 2204 2205 if (fixP->fx_addsy == NULL) 2206 { 2207 /* This fixup has been resolved. Create a reloc in case the linker 2208 moves code around due to relaxing. */ 2209 if (fixP->fx_r_type == BFD_RELOC_64_PCREL) 2210 fixP->fx_r_type = BFD_RELOC_MICROBLAZE_64_NONE; 2211 else 2212 fixP->fx_r_type = BFD_RELOC_NONE; 2213 fixP->fx_addsy = section_symbol (absolute_section); 2214 } 2215 return; 2216} 2217 2218void 2219md_operand (expressionS * expressionP) 2220{ 2221 /* Ignore leading hash symbol, if present. */ 2222 if (*input_line_pointer == '#') 2223 { 2224 input_line_pointer ++; 2225 expression (expressionP); 2226 } 2227} 2228 2229/* Called just before address relaxation, return the length 2230 by which a fragment must grow to reach it's destination. */ 2231 2232int 2233md_estimate_size_before_relax (fragS * fragP, 2234 segT segment_type) 2235{ 2236 sbss_segment = bfd_get_section_by_name (stdoutput, ".sbss"); 2237 sbss2_segment = bfd_get_section_by_name (stdoutput, ".sbss2"); 2238 sdata_segment = bfd_get_section_by_name (stdoutput, ".sdata"); 2239 sdata2_segment = bfd_get_section_by_name (stdoutput, ".sdata2"); 2240 2241 switch (fragP->fr_subtype) 2242 { 2243 case INST_PC_OFFSET: 2244 /* Used to be a PC-relative branch. */ 2245 if (!fragP->fr_symbol) 2246 { 2247 /* We know the abs value: Should never happen. */ 2248 as_bad (_("Absolute PC-relative value in relaxation code. Assembler error.....")); 2249 abort (); 2250 } 2251 else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type && 2252 !S_IS_WEAK (fragP->fr_symbol)) 2253 { 2254 fragP->fr_subtype = DEFINED_PC_OFFSET; 2255 /* Don't know now whether we need an imm instruction. */ 2256 fragP->fr_var = INST_WORD_SIZE; 2257 } 2258 else if (S_IS_DEFINED (fragP->fr_symbol) 2259 && (((S_GET_SEGMENT (fragP->fr_symbol))->flags & SEC_CODE) == 0)) 2260 { 2261 /* Cannot have a PC-relative branch to a diff segment. */ 2262 as_bad (_("PC relative branch to label %s which is not in the instruction space"), 2263 S_GET_NAME (fragP->fr_symbol)); 2264 fragP->fr_subtype = UNDEFINED_PC_OFFSET; 2265 fragP->fr_var = INST_WORD_SIZE*2; 2266 } 2267 else 2268 { 2269 fragP->fr_subtype = UNDEFINED_PC_OFFSET; 2270 fragP->fr_var = INST_WORD_SIZE*2; 2271 } 2272 break; 2273 2274 case INST_NO_OFFSET: 2275 case TEXT_OFFSET: 2276 /* Used to be a reference to somewhere which was unknown. */ 2277 if (fragP->fr_symbol) 2278 { 2279 if (fragP->fr_opcode == NULL) 2280 { 2281 /* Used as an absolute value. */ 2282 if (fragP->fr_subtype == INST_NO_OFFSET) 2283 fragP->fr_subtype = DEFINED_ABS_SEGMENT; 2284 /* Variable part does not change. */ 2285 fragP->fr_var = INST_WORD_SIZE*2; 2286 } 2287 else if (streq (fragP->fr_opcode, str_microblaze_ro_anchor)) 2288 { 2289 /* It is accessed using the small data read only anchor. */ 2290 if ((S_GET_SEGMENT (fragP->fr_symbol) == bfd_com_section_ptr) 2291 || (S_GET_SEGMENT (fragP->fr_symbol) == sdata2_segment) 2292 || (S_GET_SEGMENT (fragP->fr_symbol) == sbss2_segment) 2293 || (! S_IS_DEFINED (fragP->fr_symbol))) 2294 { 2295 fragP->fr_subtype = DEFINED_RO_SEGMENT; 2296 fragP->fr_var = INST_WORD_SIZE; 2297 } 2298 else 2299 { 2300 /* Variable not in small data read only segment accessed 2301 using small data read only anchor. */ 2302 const char *file = fragP->fr_file ? fragP->fr_file : _("unknown"); 2303 2304 as_bad_where (file, fragP->fr_line, 2305 _("Variable is accessed using small data read " 2306 "only anchor, but it is not in the small data " 2307 "read only section")); 2308 fragP->fr_subtype = DEFINED_RO_SEGMENT; 2309 fragP->fr_var = INST_WORD_SIZE; 2310 } 2311 } 2312 else if (streq (fragP->fr_opcode, str_microblaze_rw_anchor)) 2313 { 2314 if ((S_GET_SEGMENT (fragP->fr_symbol) == bfd_com_section_ptr) 2315 || (S_GET_SEGMENT (fragP->fr_symbol) == sdata_segment) 2316 || (S_GET_SEGMENT (fragP->fr_symbol) == sbss_segment) 2317 || (!S_IS_DEFINED (fragP->fr_symbol))) 2318 { 2319 /* It is accessed using the small data read write anchor. */ 2320 fragP->fr_subtype = DEFINED_RW_SEGMENT; 2321 fragP->fr_var = INST_WORD_SIZE; 2322 } 2323 else 2324 { 2325 const char *file = fragP->fr_file ? fragP->fr_file : _("unknown"); 2326 2327 as_bad_where (file, fragP->fr_line, 2328 _("Variable is accessed using small data read " 2329 "write anchor, but it is not in the small data " 2330 "read write section")); 2331 fragP->fr_subtype = DEFINED_RW_SEGMENT; 2332 fragP->fr_var = INST_WORD_SIZE; 2333 } 2334 } 2335 else 2336 { 2337 as_bad (_("Incorrect fr_opcode value in frag. Internal error.....")); 2338 abort (); 2339 } 2340 } 2341 else 2342 { 2343 /* We know the abs value: Should never happen. */ 2344 as_bad (_("Absolute value in relaxation code. Assembler error.....")); 2345 abort (); 2346 } 2347 break; 2348 2349 case UNDEFINED_PC_OFFSET: 2350 case LARGE_DEFINED_PC_OFFSET: 2351 case DEFINED_ABS_SEGMENT: 2352 case GOT_OFFSET: 2353 case PLT_OFFSET: 2354 case GOTOFF_OFFSET: 2355 case TEXT_PC_OFFSET: 2356 case TLSGD_OFFSET: 2357 case TLSLD_OFFSET: 2358 case TLSTPREL_OFFSET: 2359 case TLSDTPREL_OFFSET: 2360 fragP->fr_var = INST_WORD_SIZE*2; 2361 break; 2362 case DEFINED_RO_SEGMENT: 2363 case DEFINED_RW_SEGMENT: 2364 case DEFINED_PC_OFFSET: 2365 case TLSDTPMOD_OFFSET: 2366 fragP->fr_var = INST_WORD_SIZE; 2367 break; 2368 default: 2369 abort (); 2370 } 2371 2372 return fragP->fr_var; 2373} 2374 2375/* Put number into target byte order. */ 2376 2377void 2378md_number_to_chars (char * ptr, valueT use, int nbytes) 2379{ 2380 if (target_big_endian) 2381 number_to_chars_bigendian (ptr, use, nbytes); 2382 else 2383 number_to_chars_littleendian (ptr, use, nbytes); 2384} 2385 2386/* Round up a section size to the appropriate boundary. */ 2387 2388valueT 2389md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) 2390{ 2391 return size; /* Byte alignment is fine. */ 2392} 2393 2394 2395/* The location from which a PC relative jump should be calculated, 2396 given a PC relative reloc. */ 2397 2398long 2399md_pcrel_from_section (fixS * fixp, segT sec ATTRIBUTE_UNUSED) 2400{ 2401#ifdef OBJ_ELF 2402 /* If the symbol is undefined or defined in another section 2403 we leave the add number alone for the linker to fix it later. 2404 Only account for the PC pre-bump (No PC-pre-bump on the Microblaze). */ 2405 2406 if (fixp->fx_addsy != (symbolS *) NULL 2407 && (!S_IS_DEFINED (fixp->fx_addsy) 2408 || (S_GET_SEGMENT (fixp->fx_addsy) != sec))) 2409 return 0; 2410 else 2411 { 2412 /* The case where we are going to resolve things... */ 2413 if (fixp->fx_r_type == BFD_RELOC_64_PCREL) 2414 return fixp->fx_where + fixp->fx_frag->fr_address + INST_WORD_SIZE; 2415 else 2416 return fixp->fx_where + fixp->fx_frag->fr_address; 2417 } 2418#endif 2419} 2420 2421 2422#define F(SZ,PCREL) (((SZ) << 1) + (PCREL)) 2423#define MAP(SZ,PCREL,TYPE) case F (SZ, PCREL): code = (TYPE); break 2424 2425arelent * 2426tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp) 2427{ 2428 arelent * rel; 2429 bfd_reloc_code_real_type code; 2430 2431 switch (fixp->fx_r_type) 2432 { 2433 case BFD_RELOC_NONE: 2434 case BFD_RELOC_MICROBLAZE_64_NONE: 2435 case BFD_RELOC_32: 2436 case BFD_RELOC_MICROBLAZE_32_LO: 2437 case BFD_RELOC_MICROBLAZE_32_LO_PCREL: 2438 case BFD_RELOC_RVA: 2439 case BFD_RELOC_64: 2440 case BFD_RELOC_64_PCREL: 2441 case BFD_RELOC_MICROBLAZE_32_ROSDA: 2442 case BFD_RELOC_MICROBLAZE_32_RWSDA: 2443 case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM: 2444 case BFD_RELOC_MICROBLAZE_64_GOTPC: 2445 case BFD_RELOC_MICROBLAZE_64_GOT: 2446 case BFD_RELOC_MICROBLAZE_64_PLT: 2447 case BFD_RELOC_MICROBLAZE_64_GOTOFF: 2448 case BFD_RELOC_MICROBLAZE_32_GOTOFF: 2449 case BFD_RELOC_MICROBLAZE_64_TLSGD: 2450 case BFD_RELOC_MICROBLAZE_64_TLSLD: 2451 case BFD_RELOC_MICROBLAZE_32_TLSDTPMOD: 2452 case BFD_RELOC_MICROBLAZE_32_TLSDTPREL: 2453 case BFD_RELOC_MICROBLAZE_64_TLSDTPREL: 2454 case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL: 2455 case BFD_RELOC_MICROBLAZE_64_TLSTPREL: 2456 case BFD_RELOC_MICROBLAZE_64_TEXTPCREL: 2457 case BFD_RELOC_MICROBLAZE_64_TEXTREL: 2458 code = fixp->fx_r_type; 2459 break; 2460 2461 default: 2462 switch (F (fixp->fx_size, fixp->fx_pcrel)) 2463 { 2464 MAP (1, 0, BFD_RELOC_8); 2465 MAP (2, 0, BFD_RELOC_16); 2466 MAP (4, 0, BFD_RELOC_32); 2467 MAP (1, 1, BFD_RELOC_8_PCREL); 2468 MAP (2, 1, BFD_RELOC_16_PCREL); 2469 MAP (4, 1, BFD_RELOC_32_PCREL); 2470 default: 2471 code = fixp->fx_r_type; 2472 as_bad (_("Can not do %d byte %srelocation"), 2473 fixp->fx_size, 2474 fixp->fx_pcrel ? _("pc-relative ") : ""); 2475 } 2476 break; 2477 } 2478 2479 rel = XNEW (arelent); 2480 rel->sym_ptr_ptr = XNEW (asymbol *); 2481 2482 if (code == BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM) 2483 *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy); 2484 else 2485 *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); 2486 2487 rel->address = fixp->fx_frag->fr_address + fixp->fx_where; 2488 /* Always pass the addend along! */ 2489 rel->addend = fixp->fx_offset; 2490 rel->howto = bfd_reloc_type_lookup (stdoutput, code); 2491 2492 if (rel->howto == NULL) 2493 { 2494 as_bad_where (fixp->fx_file, fixp->fx_line, 2495 _("Cannot represent relocation type %s"), 2496 bfd_get_reloc_code_name (code)); 2497 2498 /* Set howto to a garbage value so that we can keep going. */ 2499 rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32); 2500 gas_assert (rel->howto != NULL); 2501 } 2502 return rel; 2503} 2504 2505int 2506md_parse_option (int c, const char * arg ATTRIBUTE_UNUSED) 2507{ 2508 switch (c) 2509 { 2510 case OPTION_EB: 2511 target_big_endian = 1; 2512 break; 2513 case OPTION_EL: 2514 target_big_endian = 0; 2515 break; 2516 default: 2517 return 0; 2518 } 2519 return 1; 2520} 2521 2522void 2523md_show_usage (FILE * stream ATTRIBUTE_UNUSED) 2524{ 2525 /* fprintf(stream, _("\ 2526 MicroBlaze options:\n\ 2527 -noSmall Data in the comm and data sections do not go into the small data section\n")); */ 2528} 2529 2530 2531/* Create a fixup for a cons expression. If parse_cons_expression_microblaze 2532 found a machine specific op in an expression, 2533 then we create relocs accordingly. */ 2534 2535void 2536cons_fix_new_microblaze (fragS * frag, 2537 int where, 2538 int size, 2539 expressionS *exp, 2540 bfd_reloc_code_real_type r) 2541{ 2542 if ((exp->X_op == O_subtract) && (exp->X_add_symbol) && 2543 (exp->X_op_symbol) && (now_seg != absolute_section) && (size == 4) 2544 && (!S_IS_LOCAL (exp->X_op_symbol))) 2545 r = BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM; 2546 else if (exp->X_md == IMM_GOTOFF && exp->X_op == O_symbol_rva) 2547 { 2548 exp->X_op = O_symbol; 2549 r = BFD_RELOC_MICROBLAZE_32_GOTOFF; 2550 } 2551 else 2552 { 2553 switch (size) 2554 { 2555 case 1: 2556 r = BFD_RELOC_8; 2557 break; 2558 case 2: 2559 r = BFD_RELOC_16; 2560 break; 2561 case 4: 2562 r = BFD_RELOC_32; 2563 break; 2564 case 8: 2565 r = BFD_RELOC_64; 2566 break; 2567 default: 2568 as_bad (_("unsupported BFD relocation size %u"), size); 2569 r = BFD_RELOC_32; 2570 break; 2571 } 2572 } 2573 fix_new_exp (frag, where, size, exp, 0, r); 2574} 2575