1 /* tc-dlx.c -- Assemble for the DLX 2 Copyright 2002, 2003, 2004, 2005, 2007, 2009, 2010, 2012 3 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 /* Initially created by Kuang Hwa Lin, 3/20/2002. */ 23 24 #include "as.h" 25 #include "safe-ctype.h" 26 #include "tc-dlx.h" 27 #include "opcode/dlx.h" 28 29 /* Make it easier to clone this machine desc into another one. */ 30 #define machine_opcode dlx_opcode 31 #define machine_opcodes dlx_opcodes 32 #define machine_ip dlx_ip 33 #define machine_it dlx_it 34 35 #define NO_RELOC BFD_RELOC_NONE 36 #define RELOC_DLX_REL26 BFD_RELOC_DLX_JMP26 37 #define RELOC_DLX_16 BFD_RELOC_16 38 #define RELOC_DLX_REL16 BFD_RELOC_16_PCREL_S2 39 #define RELOC_DLX_HI16 BFD_RELOC_HI16_S 40 #define RELOC_DLX_LO16 BFD_RELOC_LO16 41 #define RELOC_DLX_VTINHERIT BFD_RELOC_VTABLE_INHERIT 42 #define RELOC_DLX_VTENTRY BFD_RELOC_VTABLE_ENTRY 43 44 /* handle of the OPCODE hash table */ 45 static struct hash_control *op_hash = NULL; 46 47 struct machine_it 48 { 49 char *error; 50 unsigned long opcode; 51 struct nlist *nlistp; 52 expressionS exp; 53 int pcrel; 54 int size; 55 int reloc_offset; /* Offset of reloc within insn. */ 56 int reloc; 57 int HI; 58 int LO; 59 } 60 the_insn; 61 62 /* This array holds the chars that always start a comment. If the 63 pre-processor is disabled, these aren't very useful. */ 64 const char comment_chars[] = ";"; 65 66 /* This array holds the chars that only start a comment at the beginning of 67 a line. If the line seems to have the form '# 123 filename' 68 .line and .file directives will appear in the pre-processed output. */ 69 /* Note that input_file.c hand checks for '#' at the beginning of the 70 first line of the input file. This is because the compiler outputs 71 #NO_APP at the beginning of its output. */ 72 /* Also note that comments like this one will always work. */ 73 const char line_comment_chars[] = "#"; 74 75 /* We needed an unused char for line separation to work around the 76 lack of macros, using sed and such. */ 77 const char line_separator_chars[] = "@"; 78 79 /* Chars that can be used to separate mant from exp in floating point nums. */ 80 const char EXP_CHARS[] = "eE"; 81 82 /* Chars that mean this number is a floating point constant. 83 As in 0f12.456 84 or 0d1.2345e12. */ 85 const char FLT_CHARS[] = "rRsSfFdDxXpP"; 86 87 static void 88 insert_sreg (char *regname, int regnum) 89 { 90 /* Must be large enough to hold the names of the special registers. */ 91 char buf[80]; 92 int i; 93 94 symbol_table_insert (symbol_new (regname, reg_section, (valueT) regnum, 95 &zero_address_frag)); 96 for (i = 0; regname[i]; i++) 97 buf[i] = ISLOWER (regname[i]) ? TOUPPER (regname[i]) : regname[i]; 98 buf[i] = '\0'; 99 100 symbol_table_insert (symbol_new (buf, reg_section, (valueT) regnum, 101 &zero_address_frag)); 102 } 103 104 /* Install symbol definitions for assorted special registers. 105 See MIPS Assembly Language Programmer's Guide page 1-4 */ 106 107 static void 108 define_some_regs (void) 109 { 110 /* Software representation. */ 111 insert_sreg ("zero", 0); 112 insert_sreg ("at", 1); 113 insert_sreg ("v0", 2); 114 insert_sreg ("v1", 3); 115 insert_sreg ("a0", 4); 116 insert_sreg ("a1", 5); 117 insert_sreg ("a2", 6); 118 insert_sreg ("a3", 7); 119 insert_sreg ("t0", 8); 120 insert_sreg ("t1", 9); 121 insert_sreg ("t2", 10); 122 insert_sreg ("t3", 11); 123 insert_sreg ("t4", 12); 124 insert_sreg ("t5", 13); 125 insert_sreg ("t6", 14); 126 insert_sreg ("t7", 15); 127 insert_sreg ("s0", 16); 128 insert_sreg ("s1", 17); 129 insert_sreg ("s2", 18); 130 insert_sreg ("s3", 19); 131 insert_sreg ("s4", 20); 132 insert_sreg ("s5", 21); 133 insert_sreg ("s6", 22); 134 insert_sreg ("s7", 23); 135 insert_sreg ("t8", 24); 136 insert_sreg ("t9", 25); 137 insert_sreg ("k0", 26); 138 insert_sreg ("k1", 27); 139 insert_sreg ("gp", 28); 140 insert_sreg ("sp", 29); 141 insert_sreg ("fp", 30); 142 insert_sreg ("ra", 31); 143 /* Special registers. */ 144 insert_sreg ("pc", 0); 145 insert_sreg ("npc", 1); 146 insert_sreg ("iad", 2); 147 } 148 149 /* Subroutine check the string to match an register. */ 150 151 static int 152 match_sft_register (char *name) 153 { 154 #define MAX_REG_NO 35 155 /* Currently we have 35 software registers defined - 156 we borrowed from MIPS. */ 157 static char *soft_reg[] = 158 { 159 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", 160 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", 161 "s0", "s1", "s2", "s3", "s4", "s5", "s7", "k0", "k1", 162 "gp", "sp", "fp", "ra", "pc", "npc", "iad", 163 "EndofTab" /* End of the Table indicator */ 164 }; 165 char low_name[21], *ptr; 166 int idx; 167 168 for (ptr = name,idx = 0; *ptr != '\0'; ptr++) 169 low_name[idx++] = TOLOWER (*ptr); 170 171 low_name[idx] = '\0'; 172 idx = 0; 173 174 while (idx < MAX_REG_NO && strcmp (soft_reg[idx], & low_name [0])) 175 idx += 1; 176 177 return idx < MAX_REG_NO; 178 } 179 180 /* Subroutine check the string to match an register. */ 181 182 static int 183 is_ldst_registers (char *name) 184 { 185 char *ptr = name; 186 187 /* The first character of the register name got to be either %, $, r of R. */ 188 if ((ptr[0] == '%' || ptr[0] == '$' || ptr[0] == 'r' || ptr[0] == 'R') 189 && ISDIGIT ((unsigned char) ptr[1])) 190 return 1; 191 192 /* Now check the software register representation. */ 193 return match_sft_register (ptr); 194 } 195 196 /* Subroutine of s_proc so targets can choose a different default prefix. 197 If DEFAULT_PREFIX is NULL, use the target's "leading char". */ 198 199 static void 200 s_proc (int end_p) 201 { 202 /* Record the current function so that we can issue an error message for 203 misplaced .func,.endfunc, and also so that .endfunc needs no 204 arguments. */ 205 static char *current_name; 206 static char *current_label; 207 208 if (end_p) 209 { 210 if (current_name == NULL) 211 { 212 as_bad (_("missing .proc")); 213 ignore_rest_of_line (); 214 return; 215 } 216 217 current_name = current_label = NULL; 218 SKIP_WHITESPACE (); 219 while (!is_end_of_line[(unsigned char) *input_line_pointer]) 220 input_line_pointer++; 221 } 222 else 223 { 224 char *name, *label; 225 char delim1, delim2; 226 227 if (current_name != NULL) 228 { 229 as_bad (_(".endfunc missing for previous .proc")); 230 ignore_rest_of_line (); 231 return; 232 } 233 234 name = input_line_pointer; 235 delim1 = get_symbol_end (); 236 name = xstrdup (name); 237 *input_line_pointer = delim1; 238 SKIP_WHITESPACE (); 239 240 if (*input_line_pointer != ',') 241 { 242 char leading_char = 0; 243 244 leading_char = bfd_get_symbol_leading_char (stdoutput); 245 /* Missing entry point, use function's name with the leading 246 char prepended. */ 247 if (leading_char) 248 { 249 unsigned len = strlen (name) + 1; 250 label = xmalloc (len + 1); 251 label[0] = leading_char; 252 memcpy (label + 1, name, len); 253 } 254 else 255 label = name; 256 } 257 else 258 { 259 ++input_line_pointer; 260 SKIP_WHITESPACE (); 261 label = input_line_pointer; 262 delim2 = get_symbol_end (); 263 label = xstrdup (label); 264 *input_line_pointer = delim2; 265 } 266 267 current_name = name; 268 current_label = label; 269 } 270 demand_empty_rest_of_line (); 271 } 272 273 /* This function is called once, at assembler startup time. It should 274 set up all the tables, etc., that the MD part of the assembler will 275 need. */ 276 277 void 278 md_begin (void) 279 { 280 const char *retval = NULL; 281 int lose = 0; 282 unsigned int i; 283 284 /* Create a new hash table. */ 285 op_hash = hash_new (); 286 287 /* Hash up all the opcodes for fast use later. */ 288 for (i = 0; i < num_dlx_opcodes; i++) 289 { 290 const char *name = machine_opcodes[i].name; 291 292 retval = hash_insert (op_hash, name, (void *) &machine_opcodes[i]); 293 294 if (retval != NULL) 295 { 296 fprintf (stderr, _("internal error: can't hash `%s': %s\n"), 297 machine_opcodes[i].name, retval); 298 lose = 1; 299 } 300 } 301 302 if (lose) 303 as_fatal (_("Broken assembler. No assembly attempted.")); 304 305 define_some_regs (); 306 } 307 308 /* This function will check the opcode and return 1 if the opcode is one 309 of the load/store instruction, and it will fix the operand string to 310 the standard form so we can use the standard parse_operand routine. */ 311 312 #define READ_OP 0x100 313 #define WRITE_OP 0x200 314 static char iBuf[81]; 315 316 static char * 317 dlx_parse_loadop (char * str) 318 { 319 char *ptr = str; 320 int idx = 0; 321 322 /* The last pair of ()/[] is the register, all other are the 323 reloc displacement, and if there is a register then it ought 324 to have a pair of ()/[] 325 This is not necessarily true, what if the load instruction come 326 without the register and with %hi/%lo modifier? */ 327 for (idx = 0; idx < 72 && ptr[idx] != '\0'; idx++) 328 ; 329 330 if (idx == 72) 331 { 332 badoperand_load: 333 as_bad (_("Bad operand for a load instruction: <%s>"), str); 334 return NULL; 335 } 336 else 337 { 338 int i, pb = 0; 339 int m2 = 0; 340 char rs1[7], rd[7], endm, match = '0'; 341 char imm[72]; 342 343 idx -= 1; 344 switch (str[idx]) 345 { 346 case ')': 347 match = '('; 348 endm = ')'; 349 break; 350 case ']': 351 match = '['; 352 endm = ']'; 353 break; 354 default: 355 /* No register indicated, fill in zero. */ 356 rs1[0] = 'r'; 357 rs1[1] = '0'; 358 rs1[2] = '\0'; 359 match = 0; 360 endm = 0; 361 m2 = 1; 362 } 363 364 if (!m2) 365 { 366 /* Searching for (/[ which will match the ]/). */ 367 for (pb = idx - 1; str[pb] != match; pb -= 1) 368 /* Match can only be either '[' or '(', if it is 369 '(' then this can be a normal expression, we'll treat 370 it as an operand. */ 371 if (str[pb] == endm || pb < (idx - 5)) 372 goto load_no_rs1; 373 pb += 1; 374 375 for (i = 0; (pb + i) < idx; i++) 376 rs1[i] = str[pb+i]; 377 378 rs1[i] = '\0'; 379 380 if (is_ldst_registers (& rs1[0])) 381 /* Point to the last character of the imm. */ 382 pb -= 1; 383 else 384 { 385 load_no_rs1: 386 if (match == '[') 387 goto badoperand_load; 388 /* No register indicated, fill in zero and restore the imm. */ 389 rs1[0] = 'r'; 390 rs1[1] = '0'; 391 rs1[2] = '\0'; 392 m2 = 1; 393 } 394 } 395 396 /* Duplicate the first register. */ 397 for (i = 0; i < 7 && str[i] != ','; i++) 398 rd[i] = ptr[i]; 399 400 if (str[i] != ',') 401 goto badoperand_load; 402 else 403 rd[i] = '\0'; 404 405 /* Copy the immd. */ 406 if (m2) 407 /* Put the '\0' back in. */ 408 pb = idx + 1; 409 410 for (i++, m2 = 0; i < pb; m2++,i++) 411 imm[m2] = ptr[i]; 412 413 imm[m2] = '\0'; 414 415 /* Assemble the instruction to gas internal format. */ 416 for (i = 0; rd[i] != '\0'; i++) 417 iBuf[i] = rd[i]; 418 419 iBuf[i++] = ','; 420 421 for (pb = 0 ; rs1[pb] != '\0'; i++, pb++) 422 iBuf[i] = rs1[pb]; 423 424 iBuf[i++] = ','; 425 426 for (pb = 0; imm[pb] != '\0'; i++, pb++) 427 iBuf[i] = imm[pb]; 428 429 iBuf[i] = '\0'; 430 return iBuf; 431 } 432 } 433 434 static char * 435 dlx_parse_storeop (char * str) 436 { 437 char *ptr = str; 438 int idx = 0; 439 440 /* Search for the ','. */ 441 for (idx = 0; idx < 72 && ptr[idx] != ','; idx++) 442 ; 443 444 if (idx == 72) 445 { 446 badoperand_store: 447 as_bad (_("Bad operand for a store instruction: <%s>"), str); 448 return NULL; 449 } 450 else 451 { 452 /* idx now points to the ','. */ 453 int i, pb = 0; 454 int comma = idx; 455 int m2 = 0; 456 char rs1[7], rd[7], endm, match = '0'; 457 char imm[72]; 458 459 /* Now parse the '(' and ')', and make idx point to ')'. */ 460 idx -= 1; 461 switch (str[idx]) 462 { 463 case ')': 464 match = '('; 465 endm = ')'; 466 break; 467 case ']': 468 match = '['; 469 endm = ']'; 470 break; 471 default: 472 /* No register indicated, fill in zero. */ 473 rs1[0] = 'r'; 474 rs1[1] = '0'; 475 rs1[2] = '\0'; 476 match = 0; 477 endm = 0; 478 m2 = 1; 479 } 480 481 if (!m2) 482 { 483 /* Searching for (/[ which will match the ]/). */ 484 for (pb = idx - 1; str[pb] != match; pb -= 1) 485 if (pb < (idx - 5) || str[pb] == endm) 486 goto store_no_rs1; 487 pb += 1; 488 489 for (i = 0; (pb + i) < idx; i++) 490 rs1[i] = str[pb + i]; 491 492 rs1[i] = '\0'; 493 494 if (is_ldst_registers (& rs1[0])) 495 /* Point to the last character of the imm. */ 496 pb -= 1; 497 else 498 { 499 store_no_rs1: 500 if (match == '[') 501 goto badoperand_store; 502 503 /* No register indicated, fill in zero and restore the imm. */ 504 rs1[0] = 'r'; 505 rs1[1] = '0'; 506 rs1[2] = '\0'; 507 pb = comma; 508 } 509 } 510 else 511 /* No register was specified. */ 512 pb = comma; 513 514 /* Duplicate the first register. */ 515 for (i = comma + 1; (str[i] == ' ' || str[i] == '\t'); i++) 516 ; 517 518 for (m2 = 0; (m2 < 7 && str[i] != '\0'); i++, m2++) 519 { 520 if (str[i] != ' ' && str[i] != '\t') 521 rd[m2] = str[i]; 522 else 523 goto badoperand_store; 524 } 525 526 if (str[i] != '\0') 527 goto badoperand_store; 528 else 529 rd[m2] = '\0'; 530 531 /* Copy the immd. */ 532 for (i = 0; i < pb; i++) 533 imm[i] = ptr[i]; 534 535 imm[i] = '\0'; 536 537 /* Assemble the instruction to gas internal format. */ 538 for (i = 0; rd[i] != '\0'; i++) 539 iBuf[i] = rd[i]; 540 iBuf[i++] = ','; 541 for (pb = 0 ; rs1[pb] != '\0'; i++, pb++) 542 iBuf[i] = rs1[pb]; 543 iBuf[i++] = ','; 544 for (pb = 0; imm[pb] != '\0'; i++, pb++) 545 iBuf[i] = imm[pb]; 546 iBuf[i] = '\0'; 547 return iBuf; 548 } 549 } 550 551 static char * 552 fix_ld_st_operand (unsigned long opcode, char* str) 553 { 554 /* Check the opcode. */ 555 switch ((int) opcode) 556 { 557 case LBOP: 558 case LBUOP: 559 case LSBUOP: 560 case LHOP: 561 case LHUOP: 562 case LSHUOP: 563 case LWOP: 564 case LSWOP: 565 return dlx_parse_loadop (str); 566 case SBOP: 567 case SHOP: 568 case SWOP: 569 return dlx_parse_storeop (str); 570 default: 571 return str; 572 } 573 } 574 575 static int 576 hilo_modifier_ok (char *s) 577 { 578 char *ptr = s; 579 int idx, count = 1; 580 581 if (*ptr != '(') 582 return 1; 583 584 for (idx = 1; ptr[idx] != '\0' && ptr[idx] != '[' && idx < 73; idx += 1) 585 { 586 if (count == 0) 587 return count; 588 589 if (ptr[idx] == '(') 590 count += 1; 591 592 if (ptr[idx] == ')') 593 count -= 1; 594 } 595 596 return (count == 0) ? 1:0; 597 } 598 599 static char * 600 parse_operand (char *s, expressionS *operandp) 601 { 602 char *save = input_line_pointer; 603 char *new_pos; 604 605 the_insn.HI = the_insn.LO = 0; 606 607 /* Search for %hi and %lo, make a mark and skip it. */ 608 if (strncmp (s, "%hi", 3) == 0) 609 { 610 s += 3; 611 the_insn.HI = 1; 612 } 613 else 614 { 615 if (strncmp (s, "%lo", 3) == 0) 616 { 617 s += 3; 618 the_insn.LO = 1; 619 } 620 else 621 the_insn.LO = 0; 622 } 623 624 if (the_insn.HI || the_insn.LO) 625 { 626 if (!hilo_modifier_ok (s)) 627 as_bad (_("Expression Error for operand modifier %%hi/%%lo\n")); 628 } 629 630 /* Check for the % and $ register representation */ 631 if ((s[0] == '%' || s[0] == '$' || s[0] == 'r' || s[0] == 'R') 632 && ISDIGIT ((unsigned char) s[1])) 633 { 634 /* We have a numeric register expression. No biggy. */ 635 s += 1; 636 input_line_pointer = s; 637 (void) expression (operandp); 638 if (operandp->X_op != O_constant 639 || operandp->X_add_number > 31) 640 as_bad (_("Invalid expression after %%%%\n")); 641 operandp->X_op = O_register; 642 } 643 else 644 { 645 /* Normal operand parsing. */ 646 input_line_pointer = s; 647 (void) expression (operandp); 648 } 649 650 new_pos = input_line_pointer; 651 input_line_pointer = save; 652 return new_pos; 653 } 654 655 /* Instruction parsing. Takes a string containing the opcode. 656 Operands are at input_line_pointer. Output is in the_insn. 657 Warnings or errors are generated. */ 658 659 static void 660 machine_ip (char *str) 661 { 662 char *s; 663 const char *args; 664 struct machine_opcode *insn; 665 unsigned long opcode; 666 expressionS the_operand; 667 expressionS *operand = &the_operand; 668 unsigned int reg, reg_shift = 0; 669 670 /* Fixup the opcode string to all lower cases, and also 671 allow numerical digits. */ 672 s = str; 673 674 if (ISALPHA (*s)) 675 for (; ISALNUM (*s); ++s) 676 if (ISUPPER (*s)) 677 *s = TOLOWER (*s); 678 679 switch (*s) 680 { 681 case '\0': 682 break; 683 684 /* FIXME-SOMEDAY more whitespace. */ 685 case ' ': 686 *s++ = '\0'; 687 break; 688 689 default: 690 as_bad (_("Unknown opcode: `%s'"), str); 691 return; 692 } 693 694 /* Hash the opcode, insn will have the string from opcode table. 695 also initialized the_insn struct. */ 696 if ((insn = (struct machine_opcode *) hash_find (op_hash, str)) == NULL) 697 { 698 /* Handle the ret and return macro here. */ 699 if ((strcmp (str, "ret") == 0) || (strcmp (str, "return") == 0)) 700 { 701 memset (&the_insn, '\0', sizeof (the_insn)); 702 the_insn.reloc = NO_RELOC; 703 the_insn.pcrel = 0; 704 the_insn.opcode = 705 (unsigned long)(JROP | 0x03e00000); /* 0x03e00000 = r31 << 21 */ 706 } 707 else 708 as_bad (_("Unknown opcode `%s'."), str); 709 710 return; 711 } 712 713 opcode = insn->opcode; 714 memset (&the_insn, '\0', sizeof (the_insn)); 715 the_insn.reloc = NO_RELOC; 716 the_insn.pcrel = 0; 717 718 /* Set the sip reloc HI16 flag. */ 719 if (!set_dlx_skip_hi16_flag (1)) 720 as_bad (_("Can not set dlx_skip_hi16_flag")); 721 722 /* Fix the operand string if it is one of load store instructions. */ 723 s = fix_ld_st_operand (opcode, s); 724 725 /* Build the opcode, checking as we go to make sure that the 726 operands match. 727 If an operand matches, we modify the_insn or opcode appropriately, 728 and do a "continue". If an operand fails to match, we "break". */ 729 if (insn->args[0] != '\0' && insn->args[0] != 'N') 730 { 731 /* Prime the pump. */ 732 if (*s == '\0') 733 { 734 as_bad (_("Missing arguments for opcode <%s>."), str); 735 return; 736 } 737 else 738 s = parse_operand (s, operand); 739 } 740 else if (insn->args[0] == 'N') 741 { 742 /* Clean up the insn and done! */ 743 the_insn.opcode = opcode; 744 return; 745 } 746 747 /* Parse through the args (this is from opcode table), *s point to 748 the current character of the instruction stream. */ 749 for (args = insn->args;; ++args) 750 { 751 switch (*args) 752 { 753 /* End of Line. */ 754 case '\0': 755 /* End of args. */ 756 if (*s == '\0') 757 { 758 /* We are truly done. */ 759 the_insn.opcode = opcode; 760 /* Clean up the HI and LO mark. */ 761 the_insn.HI = 0; 762 the_insn.LO = 0; 763 return; 764 } 765 766 the_insn.HI = 0; 767 the_insn.LO = 0; 768 as_bad (_("Too many operands: %s"), s); 769 break; 770 771 /* ',' Args separator */ 772 case ',': 773 /* Must match a comma. */ 774 if (*s++ == ',') 775 { 776 /* Parse next operand. */ 777 s = parse_operand (s, operand); 778 continue; 779 } 780 break; 781 782 /* It can be a 'a' register or 'i' operand. */ 783 case 'P': 784 /* Macro move operand/reg. */ 785 if (operand->X_op == O_register) 786 { 787 /* Its a register. */ 788 reg_shift = 21; 789 goto general_reg; 790 } 791 792 /* The immediate 16 bits literal, bit 0-15. */ 793 case 'i': 794 /* offset, unsigned. */ 795 case 'I': 796 /* offset, signed. */ 797 if (operand->X_op == O_constant) 798 { 799 if (the_insn.HI) 800 operand->X_add_number >>= 16; 801 802 opcode |= operand->X_add_number & 0xFFFF; 803 804 if (the_insn.HI && the_insn.LO) 805 as_bad (_("Both the_insn.HI and the_insn.LO are set : %s"), s); 806 else 807 { 808 the_insn.HI = 0; 809 the_insn.LO = 0; 810 } 811 continue; 812 } 813 814 the_insn.reloc = (the_insn.HI) ? RELOC_DLX_HI16 815 : (the_insn.LO ? RELOC_DLX_LO16 : RELOC_DLX_16); 816 the_insn.reloc_offset = 2; 817 the_insn.size = 2; 818 the_insn.pcrel = 0; 819 the_insn.exp = * operand; 820 the_insn.HI = 0; 821 the_insn.LO = 0; 822 continue; 823 824 case 'd': 825 /* offset, signed. */ 826 if (operand->X_op == O_constant) 827 { 828 opcode |= operand->X_add_number & 0xFFFF; 829 continue; 830 } 831 the_insn.reloc = RELOC_DLX_REL16; 832 the_insn.reloc_offset = 0; /* BIG-ENDIAN Byte 3 of insn. */ 833 the_insn.size = 4; 834 the_insn.pcrel = 1; 835 the_insn.exp = *operand; 836 continue; 837 838 /* The immediate 26 bits literal, bit 0-25. */ 839 case 'D': 840 /* offset, signed. */ 841 if (operand->X_op == O_constant) 842 { 843 opcode |= operand->X_add_number & 0x3FFFFFF; 844 continue; 845 } 846 the_insn.reloc = RELOC_DLX_REL26; 847 the_insn.reloc_offset = 0; /* BIG-ENDIAN Byte 3 of insn. */ 848 the_insn.size = 4; 849 the_insn.pcrel = 1; 850 the_insn.exp = *operand; 851 continue; 852 853 /* Type 'a' Register. */ 854 case 'a': 855 /* A general register at bits 21-25, rs1. */ 856 reg_shift = 21; 857 goto general_reg; 858 859 /* Type 'b' Register. */ 860 case 'b': 861 /* A general register at bits 16-20, rs2/rd. */ 862 reg_shift = 16; 863 goto general_reg; 864 865 /* Type 'c' Register. */ 866 case 'c': 867 /* A general register at bits 11-15, rd. */ 868 reg_shift = 11; 869 870 general_reg: 871 know (operand->X_add_symbol == 0); 872 know (operand->X_op_symbol == 0); 873 reg = operand->X_add_number; 874 if (reg & 0xffffffe0) 875 as_fatal (_("failed regnum sanity check.")); 876 else 877 /* Got the register, now figure out where it goes in the opcode. */ 878 opcode |= reg << reg_shift; 879 880 switch (*args) 881 { 882 case 'a': 883 case 'b': 884 case 'c': 885 case 'P': 886 continue; 887 } 888 as_fatal (_("failed general register sanity check.")); 889 break; 890 891 default: 892 BAD_CASE (*args); 893 } 894 895 /* Types or values of args don't match. */ 896 as_bad (_("Invalid operands")); 897 return; 898 } 899 } 900 901 /* Assemble a single instruction. Its label has already been handled 902 by the generic front end. We just parse opcode and operands, and 903 produce the bytes of data and relocation. */ 904 905 void 906 md_assemble (char *str) 907 { 908 char *toP; 909 fixS *fixP; 910 bit_fixS *bitP; 911 912 know (str); 913 machine_ip (str); 914 toP = frag_more (4); 915 dwarf2_emit_insn (4); 916 917 /* Put out the opcode. */ 918 md_number_to_chars (toP, the_insn.opcode, 4); 919 920 /* Put out the symbol-dependent stuff. */ 921 if (the_insn.reloc != NO_RELOC) 922 { 923 fixP = fix_new_exp (frag_now, 924 (toP - frag_now->fr_literal + the_insn.reloc_offset), 925 the_insn.size, & the_insn.exp, the_insn.pcrel, 926 the_insn.reloc); 927 928 /* Turn off complaints that the addend is 929 too large for things like foo+100000@ha. */ 930 switch (the_insn.reloc) 931 { 932 case RELOC_DLX_HI16: 933 case RELOC_DLX_LO16: 934 fixP->fx_no_overflow = 1; 935 break; 936 default: 937 break; 938 } 939 940 switch (fixP->fx_r_type) 941 { 942 case RELOC_DLX_REL26: 943 bitP = malloc (sizeof (bit_fixS)); 944 bitP->fx_bit_size = 26; 945 bitP->fx_bit_offset = 25; 946 bitP->fx_bit_base = the_insn.opcode & 0xFC000000; 947 bitP->fx_bit_base_adj = 0; 948 bitP->fx_bit_max = 0; 949 bitP->fx_bit_min = 0; 950 bitP->fx_bit_add = 0x03FFFFFF; 951 fixP->fx_bit_fixP = bitP; 952 break; 953 case RELOC_DLX_LO16: 954 case RELOC_DLX_REL16: 955 bitP = malloc (sizeof (bit_fixS)); 956 bitP->fx_bit_size = 16; 957 bitP->fx_bit_offset = 15; 958 bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000; 959 bitP->fx_bit_base_adj = 0; 960 bitP->fx_bit_max = 0; 961 bitP->fx_bit_min = 0; 962 bitP->fx_bit_add = 0x0000FFFF; 963 fixP->fx_bit_fixP = bitP; 964 break; 965 case RELOC_DLX_HI16: 966 bitP = malloc (sizeof (bit_fixS)); 967 bitP->fx_bit_size = 16; 968 bitP->fx_bit_offset = 15; 969 bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000; 970 bitP->fx_bit_base_adj = 0; 971 bitP->fx_bit_max = 0; 972 bitP->fx_bit_min = 0; 973 bitP->fx_bit_add = 0x0000FFFF; 974 fixP->fx_bit_fixP = bitP; 975 break; 976 default: 977 fixP->fx_bit_fixP = NULL; 978 break; 979 } 980 } 981 } 982 983 /* This is identical to the md_atof in m68k.c. I think this is right, 984 but I'm not sure. Dlx will not use it anyway, so I just leave it 985 here for now. */ 986 987 char * 988 md_atof (int type, char *litP, int *sizeP) 989 { 990 return ieee_md_atof (type, litP, sizeP, TRUE); 991 } 992 993 /* Write out big-endian. */ 994 void 995 md_number_to_chars (char *buf, valueT val, int n) 996 { 997 number_to_chars_bigendian (buf, val, n); 998 } 999 1000 bfd_boolean 1001 md_dlx_fix_adjustable (fixS *fixP) 1002 { 1003 /* We need the symbol name for the VTABLE entries. */ 1004 return (fixP->fx_r_type != BFD_RELOC_VTABLE_INHERIT 1005 && fixP->fx_r_type != BFD_RELOC_VTABLE_ENTRY); 1006 } 1007 1008 void 1009 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) 1010 { 1011 long val = *valP; 1012 char *place = fixP->fx_where + fixP->fx_frag->fr_literal; 1013 1014 switch (fixP->fx_r_type) 1015 { 1016 case RELOC_DLX_LO16: 1017 case RELOC_DLX_REL16: 1018 if (fixP->fx_bit_fixP != NULL) 1019 { 1020 val = (val & 0x0000FFFF) | fixP->fx_bit_fixP->fx_bit_base; 1021 free (fixP->fx_bit_fixP); 1022 fixP->fx_bit_fixP = NULL; 1023 } 1024 #ifdef DEBUG 1025 else 1026 know ((fixP->fx_bit_fixP != NULL)); 1027 #endif 1028 break; 1029 1030 case RELOC_DLX_HI16: 1031 if (fixP->fx_bit_fixP != NULL) 1032 { 1033 val = (val >> 16) | fixP->fx_bit_fixP->fx_bit_base; 1034 free (fixP->fx_bit_fixP); 1035 fixP->fx_bit_fixP = NULL; 1036 } 1037 #ifdef DEBUG 1038 else 1039 know ((fixP->fx_bit_fixP != NULL)); 1040 #endif 1041 break; 1042 1043 case RELOC_DLX_REL26: 1044 if (fixP->fx_bit_fixP != NULL) 1045 { 1046 val = (val & 0x03FFFFFF) | fixP->fx_bit_fixP->fx_bit_base; 1047 free (fixP->fx_bit_fixP); 1048 fixP->fx_bit_fixP = NULL; 1049 } 1050 #ifdef DEBUG 1051 else 1052 know ((fixP->fx_bit_fixP != NULL)); 1053 #endif 1054 break; 1055 1056 case BFD_RELOC_VTABLE_INHERIT: 1057 /* This borrowed from tc-ppc.c on a whim. */ 1058 fixP->fx_done = 0; 1059 if (fixP->fx_addsy 1060 && !S_IS_DEFINED (fixP->fx_addsy) 1061 && !S_IS_WEAK (fixP->fx_addsy)) 1062 S_SET_WEAK (fixP->fx_addsy); 1063 return; 1064 1065 case BFD_RELOC_VTABLE_ENTRY: 1066 fixP->fx_done = 0; 1067 return; 1068 1069 default: 1070 break; 1071 } 1072 1073 number_to_chars_bigendian (place, val, fixP->fx_size); 1074 if (fixP->fx_addsy == NULL) 1075 fixP->fx_done = 1; 1076 } 1077 1078 const char *md_shortopts = ""; 1079 1080 struct option md_longopts[] = 1081 { 1082 {NULL, no_argument, NULL, 0} 1083 }; 1084 1085 size_t md_longopts_size = sizeof (md_longopts); 1086 1087 int 1088 md_parse_option (int c ATTRIBUTE_UNUSED, 1089 char *arg ATTRIBUTE_UNUSED) 1090 { 1091 return 0; 1092 } 1093 1094 void 1095 md_show_usage (FILE *stream ATTRIBUTE_UNUSED) 1096 { 1097 } 1098 1099 /* This is called when a line is unrecognized. */ 1100 1101 int 1102 dlx_unrecognized_line (int c) 1103 { 1104 int lab; 1105 char *s; 1106 1107 if (c != '$' || ! ISDIGIT ((unsigned char) input_line_pointer[0])) 1108 return 0; 1109 1110 s = input_line_pointer; 1111 1112 lab = 0; 1113 while (ISDIGIT ((unsigned char) *s)) 1114 { 1115 lab = lab * 10 + *s - '0'; 1116 ++s; 1117 } 1118 1119 if (*s != ':') 1120 /* Not a label definition. */ 1121 return 0; 1122 1123 if (dollar_label_defined (lab)) 1124 { 1125 as_bad (_("label \"$%d\" redefined"), lab); 1126 return 0; 1127 } 1128 1129 define_dollar_label (lab); 1130 colon (dollar_label_name (lab, 0)); 1131 input_line_pointer = s + 1; 1132 1133 return 1; 1134 } 1135 1136 /* Default the values of symbols known that should be "predefined". We 1137 don't bother to predefine them unless you actually use one, since there 1138 are a lot of them. */ 1139 1140 symbolS * 1141 md_undefined_symbol (char *name ATTRIBUTE_UNUSED) 1142 { 1143 return NULL; 1144 } 1145 1146 /* Parse an operand that is machine-specific, the function was called 1147 in expr.c by operand() function, when everything failed before it 1148 call a quit. */ 1149 1150 void 1151 md_operand (expressionS* expressionP) 1152 { 1153 /* Check for the #number representation */ 1154 if (input_line_pointer[0] == '#' && 1155 ISDIGIT ((unsigned char) input_line_pointer[1])) 1156 { 1157 /* We have a numeric number expression. No biggy. */ 1158 input_line_pointer += 1; /* Skip # */ 1159 1160 (void) expression (expressionP); 1161 1162 if (expressionP->X_op != O_constant) 1163 as_bad (_("Invalid expression after # number\n")); 1164 } 1165 1166 return; 1167 } 1168 1169 /* Round up a section size to the appropriate boundary. */ 1170 1171 valueT 1172 md_section_align (segT segment ATTRIBUTE_UNUSED, 1173 valueT size) 1174 { 1175 /* Byte alignment is fine. */ 1176 return size; 1177 } 1178 1179 /* Exactly what point is a PC-relative offset relative TO? 1180 On the 29000, they're relative to the address of the instruction, 1181 which we have set up as the address of the fixup too. */ 1182 1183 long 1184 md_pcrel_from (fixS* fixP) 1185 { 1186 return 4 + fixP->fx_where + fixP->fx_frag->fr_address; 1187 } 1188 1189 /* Translate internal representation of relocation info to BFD target 1190 format. 1191 FIXME: To what extent can we get all relevant targets to use this? 1192 The above FIXME is from a29k, but I think it is also needed here. */ 1193 1194 arelent * 1195 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, 1196 fixS *fixP) 1197 { 1198 arelent * reloc; 1199 1200 reloc = xmalloc (sizeof (arelent)); 1201 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type); 1202 1203 if (reloc->howto == NULL) 1204 { 1205 as_bad_where (fixP->fx_file, fixP->fx_line, 1206 _("internal error: can't export reloc type %d (`%s')"), 1207 fixP->fx_r_type, 1208 bfd_get_reloc_code_name (fixP->fx_r_type)); 1209 return NULL; 1210 } 1211 1212 gas_assert (!fixP->fx_pcrel == !reloc->howto->pc_relative); 1213 1214 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); 1215 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy); 1216 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where; 1217 1218 if (fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY) 1219 reloc->address = fixP->fx_offset; 1220 reloc->addend = 0; 1221 1222 return reloc; 1223 } 1224 1225 const pseudo_typeS 1226 dlx_pseudo_table[] = 1227 { 1228 /* Some additional ops that are used by gcc-dlx. */ 1229 {"asciiz", stringer, 8 + 1}, 1230 {"half", cons, 2}, 1231 {"dword", cons, 8}, 1232 {"word", cons, 4}, 1233 {"proc", s_proc, 0}, 1234 {"endproc", s_proc, 1}, 1235 {NULL, NULL, 0} 1236 }; 1237 1238 void 1239 dlx_pop_insert (void) 1240 { 1241 pop_insert (dlx_pseudo_table); 1242 return ; 1243 } 1244