1/* tc-i860.c -- Assembler for the Intel i860 architecture. 2 Copyright (C) 1989-2017 Free Software Foundation, Inc. 3 4 Brought back from the dead and completely reworked 5 by Jason Eckhardt <jle@cygnus.com>. 6 7 This file is part of GAS, the GNU Assembler. 8 9 GAS is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3, or (at your option) 12 any later version. 13 14 GAS is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License along 20 with GAS; see the file COPYING. If not, write to the Free Software 21 Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 22 23#include "as.h" 24#include "safe-ctype.h" 25#include "subsegs.h" 26#include "opcode/i860.h" 27#include "elf/i860.h" 28 29 30/* The opcode hash table. */ 31static struct hash_control *op_hash = NULL; 32 33/* These characters always start a comment. */ 34const char comment_chars[] = "#!/"; 35 36/* These characters start a comment at the beginning of a line. */ 37const char line_comment_chars[] = "#/"; 38 39const char line_separator_chars[] = ";"; 40 41/* Characters that can be used to separate the mantissa from the exponent 42 in floating point numbers. */ 43const char EXP_CHARS[] = "eE"; 44 45/* Characters that indicate this number is a floating point constant. 46 As in 0f12.456 or 0d1.2345e12. */ 47const char FLT_CHARS[] = "rRsSfFdDxXpP"; 48 49/* Register prefix (depends on syntax). */ 50static char reg_prefix; 51 52#define MAX_FIXUPS 2 53 54struct i860_it 55{ 56 const char *error; 57 unsigned long opcode; 58 enum expand_type expand; 59 struct i860_fi 60 { 61 expressionS exp; 62 bfd_reloc_code_real_type reloc; 63 int pcrel; 64 valueT fup; 65 } fi[MAX_FIXUPS]; 66} the_insn; 67 68/* The current fixup count. */ 69static int fc; 70 71static char *expr_end; 72 73/* Indicates error if a pseudo operation was expanded after a branch. */ 74static char last_expand; 75 76/* If true, then warn if any pseudo operations were expanded. */ 77static int target_warn_expand = 0; 78 79/* If true, then XP support is enabled. */ 80static int target_xp = 0; 81 82/* If true, then Intel syntax is enabled (default to AT&T/SVR4 syntax). */ 83static int target_intel_syntax = 0; 84 85 86/* Prototypes. */ 87static void i860_process_insn (char *); 88static void s_dual (int); 89static void s_enddual (int); 90static void s_atmp (int); 91static void s_align_wrapper (int); 92static int i860_get_expression (char *); 93static bfd_reloc_code_real_type obtain_reloc_for_imm16 (fixS *, long *); 94#ifdef DEBUG_I860 95static void print_insn (struct i860_it *); 96#endif 97 98const pseudo_typeS md_pseudo_table[] = 99{ 100 {"align", s_align_wrapper, 0}, 101 {"dual", s_dual, 0}, 102 {"enddual", s_enddual, 0}, 103 {"atmp", s_atmp, 0}, 104 {NULL, 0, 0}, 105}; 106 107/* Dual-instruction mode handling. */ 108enum dual 109{ 110 DUAL_OFF = 0, DUAL_ON, DUAL_DDOT, DUAL_ONDDOT, 111}; 112static enum dual dual_mode = DUAL_OFF; 113 114/* Handle ".dual" directive. */ 115static void 116s_dual (int ignore ATTRIBUTE_UNUSED) 117{ 118 if (target_intel_syntax) 119 dual_mode = DUAL_ON; 120 else 121 as_bad (_("Directive .dual available only with -mintel-syntax option")); 122} 123 124/* Handle ".enddual" directive. */ 125static void 126s_enddual (int ignore ATTRIBUTE_UNUSED) 127{ 128 if (target_intel_syntax) 129 dual_mode = DUAL_OFF; 130 else 131 as_bad (_("Directive .enddual available only with -mintel-syntax option")); 132} 133 134/* Temporary register used when expanding assembler pseudo operations. */ 135static int atmp = 31; 136 137static void 138s_atmp (int ignore ATTRIBUTE_UNUSED) 139{ 140 int temp; 141 142 if (! target_intel_syntax) 143 { 144 as_bad (_("Directive .atmp available only with -mintel-syntax option")); 145 demand_empty_rest_of_line (); 146 return; 147 } 148 149 if (strncmp (input_line_pointer, "sp", 2) == 0) 150 { 151 input_line_pointer += 2; 152 atmp = 2; 153 } 154 else if (strncmp (input_line_pointer, "fp", 2) == 0) 155 { 156 input_line_pointer += 2; 157 atmp = 3; 158 } 159 else if (strncmp (input_line_pointer, "r", 1) == 0) 160 { 161 input_line_pointer += 1; 162 temp = get_absolute_expression (); 163 if (temp >= 0 && temp <= 31) 164 atmp = temp; 165 else 166 as_bad (_("Unknown temporary pseudo register")); 167 } 168 else 169 { 170 as_bad (_("Unknown temporary pseudo register")); 171 } 172 demand_empty_rest_of_line (); 173} 174 175/* Handle ".align" directive depending on syntax mode. 176 AT&T/SVR4 syntax uses the standard align directive. However, 177 the Intel syntax additionally allows keywords for the alignment 178 parameter: ".align type", where type is one of {.short, .long, 179 .quad, .single, .double} representing alignments of 2, 4, 180 16, 4, and 8, respectively. */ 181static void 182s_align_wrapper (int arg) 183{ 184 char *parm = input_line_pointer; 185 186 if (target_intel_syntax) 187 { 188 /* Replace a keyword with the equivalent integer so the 189 standard align routine can parse the directive. */ 190 if (strncmp (parm, ".short", 6) == 0) 191 strncpy (parm, " 2", 6); 192 else if (strncmp (parm, ".long", 5) == 0) 193 strncpy (parm, " 4", 5); 194 else if (strncmp (parm, ".quad", 5) == 0) 195 strncpy (parm, " 16", 5); 196 else if (strncmp (parm, ".single", 7) == 0) 197 strncpy (parm, " 4", 7); 198 else if (strncmp (parm, ".double", 7) == 0) 199 strncpy (parm, " 8", 7); 200 201 while (*input_line_pointer == ' ') 202 ++input_line_pointer; 203 } 204 205 s_align_bytes (arg); 206} 207 208/* This function is called once, at assembler startup time. It should 209 set up all the tables and data structures that the MD part of the 210 assembler will need. */ 211void 212md_begin (void) 213{ 214 const char *retval = NULL; 215 int lose = 0; 216 unsigned int i = 0; 217 218 op_hash = hash_new (); 219 220 while (i860_opcodes[i].name != NULL) 221 { 222 const char *name = i860_opcodes[i].name; 223 retval = hash_insert (op_hash, name, (void *) &i860_opcodes[i]); 224 if (retval != NULL) 225 { 226 fprintf (stderr, _("internal error: can't hash `%s': %s\n"), 227 i860_opcodes[i].name, retval); 228 lose = 1; 229 } 230 do 231 { 232 if (i860_opcodes[i].match & i860_opcodes[i].lose) 233 { 234 fprintf (stderr, 235 _("internal error: losing opcode: `%s' \"%s\"\n"), 236 i860_opcodes[i].name, i860_opcodes[i].args); 237 lose = 1; 238 } 239 ++i; 240 } 241 while (i860_opcodes[i].name != NULL 242 && strcmp (i860_opcodes[i].name, name) == 0); 243 } 244 245 if (lose) 246 as_fatal (_("Defective assembler. No assembly attempted.")); 247 248 /* Set the register prefix for either Intel or AT&T/SVR4 syntax. */ 249 reg_prefix = target_intel_syntax ? 0 : '%'; 250} 251 252/* This is the core of the machine-dependent assembler. STR points to a 253 machine dependent instruction. This function emits the frags/bytes 254 it assembles to. */ 255void 256md_assemble (char *str) 257{ 258 char *destp; 259 int num_opcodes = 1; 260 int i; 261 struct i860_it pseudo[3]; 262 263 gas_assert (str); 264 fc = 0; 265 266 /* Assemble the instruction. */ 267 i860_process_insn (str); 268 269 /* Check for expandable flag to produce pseudo-instructions. This 270 is an undesirable feature that should be avoided. */ 271 if (the_insn.expand != 0 && the_insn.expand != XP_ONLY 272 && ! (the_insn.fi[0].fup & (OP_SEL_HA | OP_SEL_H | OP_SEL_L | OP_SEL_GOT 273 | OP_SEL_GOTOFF | OP_SEL_PLT))) 274 { 275 for (i = 0; i < 3; i++) 276 pseudo[i] = the_insn; 277 278 fc = 1; 279 switch (the_insn.expand) 280 { 281 282 case E_DELAY: 283 num_opcodes = 1; 284 break; 285 286 case E_MOV: 287 if (the_insn.fi[0].exp.X_add_symbol == NULL 288 && the_insn.fi[0].exp.X_op_symbol == NULL 289 && (the_insn.fi[0].exp.X_add_number < (1 << 15) 290 && the_insn.fi[0].exp.X_add_number >= -(1 << 15))) 291 break; 292 293 /* Emit "or l%const,r0,ireg_dest". */ 294 pseudo[0].opcode = (the_insn.opcode & 0x001f0000) | 0xe4000000; 295 pseudo[0].fi[0].fup = (OP_IMM_S16 | OP_SEL_L); 296 297 /* Emit "orh h%const,ireg_dest,ireg_dest". */ 298 pseudo[1].opcode = (the_insn.opcode & 0x03ffffff) | 0xec000000 299 | ((the_insn.opcode & 0x001f0000) << 5); 300 pseudo[1].fi[0].fup = (OP_IMM_S16 | OP_SEL_H); 301 302 num_opcodes = 2; 303 break; 304 305 case E_ADDR: 306 if (the_insn.fi[0].exp.X_add_symbol == NULL 307 && the_insn.fi[0].exp.X_op_symbol == NULL 308 && (the_insn.fi[0].exp.X_add_number < (1 << 15) 309 && the_insn.fi[0].exp.X_add_number >= -(1 << 15))) 310 break; 311 312 /* Emit "orh ha%addr_expr,ireg_src2,r31". */ 313 pseudo[0].opcode = 0xec000000 | (the_insn.opcode & 0x03e00000) 314 | (atmp << 16); 315 pseudo[0].fi[0].fup = (OP_IMM_S16 | OP_SEL_HA); 316 317 /* Emit "l%addr_expr(r31),ireg_dest". We pick up the fixup 318 information from the original instruction. */ 319 pseudo[1].opcode = (the_insn.opcode & ~0x03e00000) | (atmp << 21); 320 pseudo[1].fi[0].fup = the_insn.fi[0].fup | OP_SEL_L; 321 322 num_opcodes = 2; 323 break; 324 325 case E_U32: 326 if (the_insn.fi[0].exp.X_add_symbol == NULL 327 && the_insn.fi[0].exp.X_op_symbol == NULL 328 && (the_insn.fi[0].exp.X_add_number < (1 << 16) 329 && the_insn.fi[0].exp.X_add_number >= 0)) 330 break; 331 332 /* Emit "$(opcode)h h%const,ireg_src2,r31". */ 333 pseudo[0].opcode = (the_insn.opcode & 0xf3e0ffff) | 0x0c000000 334 | (atmp << 16); 335 pseudo[0].fi[0].fup = (OP_IMM_S16 | OP_SEL_H); 336 337 /* Emit "$(opcode) l%const,r31,ireg_dest". */ 338 pseudo[1].opcode = (the_insn.opcode & 0xf01f0000) | 0x04000000 339 | (atmp << 21); 340 pseudo[1].fi[0].fup = (OP_IMM_S16 | OP_SEL_L); 341 342 num_opcodes = 2; 343 break; 344 345 case E_AND: 346 if (the_insn.fi[0].exp.X_add_symbol == NULL 347 && the_insn.fi[0].exp.X_op_symbol == NULL 348 && (the_insn.fi[0].exp.X_add_number < (1 << 16) 349 && the_insn.fi[0].exp.X_add_number >= 0)) 350 break; 351 352 /* Emit "andnot h%const,ireg_src2,r31". */ 353 pseudo[0].opcode = (the_insn.opcode & 0x03e0ffff) | 0xd4000000 354 | (atmp << 16); 355 pseudo[0].fi[0].fup = (OP_IMM_S16 | OP_SEL_H); 356 pseudo[0].fi[0].exp.X_add_number = 357 -1 - the_insn.fi[0].exp.X_add_number; 358 359 /* Emit "andnot l%const,r31,ireg_dest". */ 360 pseudo[1].opcode = (the_insn.opcode & 0x001f0000) | 0xd4000000 361 | (atmp << 21); 362 pseudo[1].fi[0].fup = (OP_IMM_S16 | OP_SEL_L); 363 pseudo[1].fi[0].exp.X_add_number = 364 -1 - the_insn.fi[0].exp.X_add_number; 365 366 num_opcodes = 2; 367 break; 368 369 case E_S32: 370 if (the_insn.fi[0].exp.X_add_symbol == NULL 371 && the_insn.fi[0].exp.X_op_symbol == NULL 372 && (the_insn.fi[0].exp.X_add_number < (1 << 15) 373 && the_insn.fi[0].exp.X_add_number >= -(1 << 15))) 374 break; 375 376 /* Emit "orh h%const,r0,r31". */ 377 pseudo[0].opcode = 0xec000000 | (atmp << 16); 378 pseudo[0].fi[0].fup = (OP_IMM_S16 | OP_SEL_H); 379 380 /* Emit "or l%const,r31,r31". */ 381 pseudo[1].opcode = 0xe4000000 | (atmp << 21) | (atmp << 16); 382 pseudo[1].fi[0].fup = (OP_IMM_S16 | OP_SEL_L); 383 384 /* Emit "r31,ireg_src2,ireg_dest". */ 385 pseudo[2].opcode = (the_insn.opcode & ~0x0400ffff) | (atmp << 11); 386 pseudo[2].fi[0].fup = OP_IMM_S16; 387 388 num_opcodes = 3; 389 break; 390 391 default: 392 as_fatal (_("failed sanity check.")); 393 } 394 395 the_insn = pseudo[0]; 396 397 /* Warn if an opcode is expanded after a delayed branch. */ 398 if (num_opcodes > 1 && last_expand == 1) 399 as_warn (_("Expanded opcode after delayed branch: `%s'"), str); 400 401 /* Warn if an opcode is expanded in dual mode. */ 402 if (num_opcodes > 1 && dual_mode != DUAL_OFF) 403 as_warn (_("Expanded opcode in dual mode: `%s'"), str); 404 405 /* Notify if any expansions happen. */ 406 if (target_warn_expand && num_opcodes > 1) 407 as_warn (_("An instruction was expanded (%s)"), str); 408 } 409 410 dwarf2_emit_insn (0); 411 i = 0; 412 do 413 { 414 int tmp; 415 416 /* Output the opcode. Note that the i860 always reads instructions 417 as little-endian data. */ 418 destp = frag_more (4); 419 number_to_chars_littleendian (destp, the_insn.opcode, 4); 420 421 /* Check for expanded opcode after branch or in dual mode. */ 422 last_expand = the_insn.fi[0].pcrel; 423 424 /* Output the symbol-dependent stuff. Only btne and bte will ever 425 loop more than once here, since only they (possibly) have more 426 than one fixup. */ 427 for (tmp = 0; tmp < fc; tmp++) 428 { 429 if (the_insn.fi[tmp].fup != OP_NONE) 430 { 431 fixS *fix; 432 fix = fix_new_exp (frag_now, 433 destp - frag_now->fr_literal, 434 4, 435 &the_insn.fi[tmp].exp, 436 the_insn.fi[tmp].pcrel, 437 the_insn.fi[tmp].reloc); 438 439 /* Despite the odd name, this is a scratch field. We use 440 it to encode operand type information. */ 441 fix->fx_addnumber = the_insn.fi[tmp].fup; 442 } 443 } 444 the_insn = pseudo[++i]; 445 } 446 while (--num_opcodes > 0); 447 448} 449 450/* Assemble the instruction pointed to by STR. */ 451static void 452i860_process_insn (char *str) 453{ 454 char *s; 455 const char *args; 456 char c; 457 struct i860_opcode *insn; 458 char *args_start; 459 unsigned long opcode; 460 unsigned int mask; 461 int match = 0; 462 int comma = 0; 463 464#if 1 /* For compiler warnings. */ 465 args = 0; 466 insn = 0; 467 args_start = 0; 468 opcode = 0; 469#endif 470 471 for (s = str; ISLOWER (*s) || *s == '.' || *s == '3' 472 || *s == '2' || *s == '1'; ++s) 473 ; 474 475 switch (*s) 476 { 477 case '\0': 478 break; 479 480 case ',': 481 comma = 1; 482 483 /*FALLTHROUGH*/ 484 485 case ' ': 486 *s++ = '\0'; 487 break; 488 489 default: 490 as_fatal (_("Unknown opcode: `%s'"), str); 491 } 492 493 /* Check for dual mode ("d.") opcode prefix. */ 494 if (strncmp (str, "d.", 2) == 0) 495 { 496 if (dual_mode == DUAL_ON) 497 dual_mode = DUAL_ONDDOT; 498 else 499 dual_mode = DUAL_DDOT; 500 str += 2; 501 } 502 503 if ((insn = (struct i860_opcode *) hash_find (op_hash, str)) == NULL) 504 { 505 if (dual_mode == DUAL_DDOT || dual_mode == DUAL_ONDDOT) 506 str -= 2; 507 as_bad (_("Unknown opcode: `%s'"), str); 508 return; 509 } 510 511 if (comma) 512 *--s = ','; 513 514 args_start = s; 515 for (;;) 516 { 517 int t; 518 opcode = insn->match; 519 memset (&the_insn, '\0', sizeof (the_insn)); 520 fc = 0; 521 for (t = 0; t < MAX_FIXUPS; t++) 522 { 523 the_insn.fi[t].reloc = BFD_RELOC_NONE; 524 the_insn.fi[t].pcrel = 0; 525 the_insn.fi[t].fup = OP_NONE; 526 } 527 528 /* Build the opcode, checking as we go that the operands match. */ 529 for (args = insn->args; ; ++args) 530 { 531 if (fc > MAX_FIXUPS) 532 abort (); 533 534 switch (*args) 535 { 536 537 /* End of args. */ 538 case '\0': 539 if (*s == '\0') 540 match = 1; 541 break; 542 543 /* These must match exactly. */ 544 case '+': 545 case '(': 546 case ')': 547 case ',': 548 case ' ': 549 if (*s++ == *args) 550 continue; 551 break; 552 553 /* Must be at least one digit. */ 554 case '#': 555 if (ISDIGIT (*s++)) 556 { 557 while (ISDIGIT (*s)) 558 ++s; 559 continue; 560 } 561 break; 562 563 /* Next operand must be a register. */ 564 case '1': 565 case '2': 566 case 'd': 567 /* Check for register prefix if necessary. */ 568 if (reg_prefix && *s != reg_prefix) 569 goto error; 570 else if (reg_prefix) 571 s++; 572 573 switch (*s) 574 { 575 /* Frame pointer. */ 576 case 'f': 577 s++; 578 if (*s++ == 'p') 579 { 580 mask = 0x3; 581 break; 582 } 583 goto error; 584 585 /* Stack pointer. */ 586 case 's': 587 s++; 588 if (*s++ == 'p') 589 { 590 mask = 0x2; 591 break; 592 } 593 goto error; 594 595 /* Any register r0..r31. */ 596 case 'r': 597 s++; 598 if (!ISDIGIT (c = *s++)) 599 { 600 goto error; 601 } 602 if (ISDIGIT (*s)) 603 { 604 if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32) 605 goto error; 606 } 607 else 608 c -= '0'; 609 mask = c; 610 break; 611 612 /* Not this opcode. */ 613 default: 614 goto error; 615 } 616 617 /* Obtained the register, now place it in the opcode. */ 618 switch (*args) 619 { 620 case '1': 621 opcode |= mask << 11; 622 continue; 623 624 case '2': 625 opcode |= mask << 21; 626 continue; 627 628 case 'd': 629 opcode |= mask << 16; 630 continue; 631 632 } 633 break; 634 635 /* Next operand is a floating point register. */ 636 case 'e': 637 case 'f': 638 case 'g': 639 /* Check for register prefix if necessary. */ 640 if (reg_prefix && *s != reg_prefix) 641 goto error; 642 else if (reg_prefix) 643 s++; 644 645 if (*s++ == 'f' && ISDIGIT (*s)) 646 { 647 mask = *s++; 648 if (ISDIGIT (*s)) 649 { 650 mask = 10 * (mask - '0') + (*s++ - '0'); 651 if (mask >= 32) 652 { 653 break; 654 } 655 } 656 else 657 mask -= '0'; 658 659 switch (*args) 660 { 661 662 case 'e': 663 opcode |= mask << 11; 664 continue; 665 666 case 'f': 667 opcode |= mask << 21; 668 continue; 669 670 case 'g': 671 opcode |= mask << 16; 672 if ((opcode & (1 << 10)) && mask != 0 673 && (mask == ((opcode >> 11) & 0x1f))) 674 as_warn (_("Pipelined instruction: fsrc1 = fdest")); 675 continue; 676 } 677 } 678 break; 679 680 /* Next operand must be a control register. */ 681 case 'c': 682 /* Check for register prefix if necessary. */ 683 if (reg_prefix && *s != reg_prefix) 684 goto error; 685 else if (reg_prefix) 686 s++; 687 688 if (strncmp (s, "fir", 3) == 0) 689 { 690 opcode |= 0x0 << 21; 691 s += 3; 692 continue; 693 } 694 if (strncmp (s, "psr", 3) == 0) 695 { 696 opcode |= 0x1 << 21; 697 s += 3; 698 continue; 699 } 700 if (strncmp (s, "dirbase", 7) == 0) 701 { 702 opcode |= 0x2 << 21; 703 s += 7; 704 continue; 705 } 706 if (strncmp (s, "db", 2) == 0) 707 { 708 opcode |= 0x3 << 21; 709 s += 2; 710 continue; 711 } 712 if (strncmp (s, "fsr", 3) == 0) 713 { 714 opcode |= 0x4 << 21; 715 s += 3; 716 continue; 717 } 718 if (strncmp (s, "epsr", 4) == 0) 719 { 720 opcode |= 0x5 << 21; 721 s += 4; 722 continue; 723 } 724 /* The remaining control registers are XP only. */ 725 if (target_xp && strncmp (s, "bear", 4) == 0) 726 { 727 opcode |= 0x6 << 21; 728 s += 4; 729 continue; 730 } 731 if (target_xp && strncmp (s, "ccr", 3) == 0) 732 { 733 opcode |= 0x7 << 21; 734 s += 3; 735 continue; 736 } 737 if (target_xp && strncmp (s, "p0", 2) == 0) 738 { 739 opcode |= 0x8 << 21; 740 s += 2; 741 continue; 742 } 743 if (target_xp && strncmp (s, "p1", 2) == 0) 744 { 745 opcode |= 0x9 << 21; 746 s += 2; 747 continue; 748 } 749 if (target_xp && strncmp (s, "p2", 2) == 0) 750 { 751 opcode |= 0xa << 21; 752 s += 2; 753 continue; 754 } 755 if (target_xp && strncmp (s, "p3", 2) == 0) 756 { 757 opcode |= 0xb << 21; 758 s += 2; 759 continue; 760 } 761 break; 762 763 /* 5-bit immediate in src1. */ 764 case '5': 765 if (! i860_get_expression (s)) 766 { 767 s = expr_end; 768 the_insn.fi[fc].fup |= OP_IMM_U5; 769 fc++; 770 continue; 771 } 772 break; 773 774 /* 26-bit immediate, relative branch (lbroff). */ 775 case 'l': 776 the_insn.fi[fc].pcrel = 1; 777 the_insn.fi[fc].fup |= OP_IMM_BR26; 778 goto immediate; 779 780 /* 16-bit split immediate, relative branch (sbroff). */ 781 case 'r': 782 the_insn.fi[fc].pcrel = 1; 783 the_insn.fi[fc].fup |= OP_IMM_BR16; 784 goto immediate; 785 786 /* 16-bit split immediate. */ 787 case 's': 788 the_insn.fi[fc].fup |= OP_IMM_SPLIT16; 789 goto immediate; 790 791 /* 16-bit split immediate, byte aligned (st.b). */ 792 case 'S': 793 the_insn.fi[fc].fup |= OP_IMM_SPLIT16; 794 goto immediate; 795 796 /* 16-bit split immediate, half-word aligned (st.s). */ 797 case 'T': 798 the_insn.fi[fc].fup |= (OP_IMM_SPLIT16 | OP_ENCODE1 | OP_ALIGN2); 799 goto immediate; 800 801 /* 16-bit split immediate, word aligned (st.l). */ 802 case 'U': 803 the_insn.fi[fc].fup |= (OP_IMM_SPLIT16 | OP_ENCODE1 | OP_ALIGN4); 804 goto immediate; 805 806 /* 16-bit immediate. */ 807 case 'i': 808 the_insn.fi[fc].fup |= OP_IMM_S16; 809 goto immediate; 810 811 /* 16-bit immediate, byte aligned (ld.b). */ 812 case 'I': 813 the_insn.fi[fc].fup |= OP_IMM_S16; 814 goto immediate; 815 816 /* 16-bit immediate, half-word aligned (ld.s). */ 817 case 'J': 818 the_insn.fi[fc].fup |= (OP_IMM_S16 | OP_ENCODE1 | OP_ALIGN2); 819 goto immediate; 820 821 /* 16-bit immediate, word aligned (ld.l, {p}fld.l, fst.l). */ 822 case 'K': 823 if (insn->name[0] == 'l') 824 the_insn.fi[fc].fup |= (OP_IMM_S16 | OP_ENCODE1 | OP_ALIGN4); 825 else 826 the_insn.fi[fc].fup |= (OP_IMM_S16 | OP_ENCODE2 | OP_ALIGN4); 827 goto immediate; 828 829 /* 16-bit immediate, double-word aligned ({p}fld.d, fst.d). */ 830 case 'L': 831 the_insn.fi[fc].fup |= (OP_IMM_S16 | OP_ENCODE3 | OP_ALIGN8); 832 goto immediate; 833 834 /* 16-bit immediate, quad-word aligned (fld.q, fst.q). */ 835 case 'M': 836 the_insn.fi[fc].fup |= (OP_IMM_S16 | OP_ENCODE3 | OP_ALIGN16); 837 838 /*FALLTHROUGH*/ 839 840 /* Handle the immediate for either the Intel syntax or 841 SVR4 syntax. The Intel syntax is "ha%immediate" 842 whereas SVR4 syntax is "[immediate]@ha". */ 843 immediate: 844 if (target_intel_syntax == 0) 845 { 846 /* AT&T/SVR4 syntax. */ 847 if (*s == ' ') 848 s++; 849 850 /* Note that if i860_get_expression() fails, we will still 851 have created U entries in the symbol table for the 852 'symbols' in the input string. Try not to create U 853 symbols for registers, etc. */ 854 if (! i860_get_expression (s)) 855 s = expr_end; 856 else 857 goto error; 858 859 if (strncmp (s, "@ha", 3) == 0) 860 { 861 the_insn.fi[fc].fup |= OP_SEL_HA; 862 s += 3; 863 } 864 else if (strncmp (s, "@h", 2) == 0) 865 { 866 the_insn.fi[fc].fup |= OP_SEL_H; 867 s += 2; 868 } 869 else if (strncmp (s, "@l", 2) == 0) 870 { 871 the_insn.fi[fc].fup |= OP_SEL_L; 872 s += 2; 873 } 874 else if (strncmp (s, "@gotoff", 7) == 0 875 || strncmp (s, "@GOTOFF", 7) == 0) 876 { 877 as_bad (_("Assembler does not yet support PIC")); 878 the_insn.fi[fc].fup |= OP_SEL_GOTOFF; 879 s += 7; 880 } 881 else if (strncmp (s, "@got", 4) == 0 882 || strncmp (s, "@GOT", 4) == 0) 883 { 884 as_bad (_("Assembler does not yet support PIC")); 885 the_insn.fi[fc].fup |= OP_SEL_GOT; 886 s += 4; 887 } 888 else if (strncmp (s, "@plt", 4) == 0 889 || strncmp (s, "@PLT", 4) == 0) 890 { 891 as_bad (_("Assembler does not yet support PIC")); 892 the_insn.fi[fc].fup |= OP_SEL_PLT; 893 s += 4; 894 } 895 896 the_insn.expand = insn->expand; 897 fc++; 898 899 continue; 900 } 901 else 902 { 903 /* Intel syntax. */ 904 if (*s == ' ') 905 s++; 906 if (strncmp (s, "ha%", 3) == 0) 907 { 908 the_insn.fi[fc].fup |= OP_SEL_HA; 909 s += 3; 910 } 911 else if (strncmp (s, "h%", 2) == 0) 912 { 913 the_insn.fi[fc].fup |= OP_SEL_H; 914 s += 2; 915 } 916 else if (strncmp (s, "l%", 2) == 0) 917 { 918 the_insn.fi[fc].fup |= OP_SEL_L; 919 s += 2; 920 } 921 the_insn.expand = insn->expand; 922 923 /* Note that if i860_get_expression() fails, we will still 924 have created U entries in the symbol table for the 925 'symbols' in the input string. Try not to create U 926 symbols for registers, etc. */ 927 if (! i860_get_expression (s)) 928 s = expr_end; 929 else 930 goto error; 931 932 fc++; 933 continue; 934 } 935 break; 936 937 default: 938 as_fatal (_("failed sanity check.")); 939 } 940 break; 941 } 942 error: 943 if (match == 0) 944 { 945 /* Args don't match. */ 946 if (insn[1].name != NULL 947 && ! strcmp (insn->name, insn[1].name)) 948 { 949 ++insn; 950 s = args_start; 951 continue; 952 } 953 else 954 { 955 as_bad (_("Illegal operands for %s"), insn->name); 956 return; 957 } 958 } 959 break; 960 } 961 962 /* Set the dual bit on this instruction if necessary. */ 963 if (dual_mode != DUAL_OFF) 964 { 965 if ((opcode & 0xfc000000) == 0x48000000 || opcode == 0xb0000000) 966 { 967 /* The instruction is a flop or a fnop, so set its dual bit 968 (but check that it is 8-byte aligned). */ 969 if (((frag_now->fr_address + frag_now_fix_octets ()) & 7) == 0) 970 opcode |= (1 << 9); 971 else 972 as_bad (_("'d.%s' must be 8-byte aligned"), insn->name); 973 974 if (dual_mode == DUAL_DDOT) 975 dual_mode = DUAL_OFF; 976 else if (dual_mode == DUAL_ONDDOT) 977 dual_mode = DUAL_ON; 978 } 979 else if (dual_mode == DUAL_DDOT || dual_mode == DUAL_ONDDOT) 980 as_bad (_("Prefix 'd.' invalid for instruction `%s'"), insn->name); 981 } 982 983 the_insn.opcode = opcode; 984 985 /* Only recognize XP instructions when the user has requested it. */ 986 if (insn->expand == XP_ONLY && ! target_xp) 987 as_bad (_("Unknown opcode: `%s'"), insn->name); 988} 989 990static int 991i860_get_expression (char *str) 992{ 993 char *save_in; 994 segT seg; 995 996 save_in = input_line_pointer; 997 input_line_pointer = str; 998 seg = expression (&the_insn.fi[fc].exp); 999 if (seg != absolute_section 1000 && seg != undefined_section 1001 && ! SEG_NORMAL (seg)) 1002 { 1003 the_insn.error = _("bad segment"); 1004 expr_end = input_line_pointer; 1005 input_line_pointer = save_in; 1006 return 1; 1007 } 1008 expr_end = input_line_pointer; 1009 input_line_pointer = save_in; 1010 return 0; 1011} 1012 1013const char * 1014md_atof (int type, char *litP, int *sizeP) 1015{ 1016 return ieee_md_atof (type, litP, sizeP, TRUE); 1017} 1018 1019/* Write out in current endian mode. */ 1020void 1021md_number_to_chars (char *buf, valueT val, int n) 1022{ 1023 if (target_big_endian) 1024 number_to_chars_bigendian (buf, val, n); 1025 else 1026 number_to_chars_littleendian (buf, val, n); 1027} 1028 1029/* This should never be called for i860. */ 1030int 1031md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED, 1032 segT segtype ATTRIBUTE_UNUSED) 1033{ 1034 as_fatal (_("relaxation not supported\n")); 1035} 1036 1037#ifdef DEBUG_I860 1038static void 1039print_insn (struct i860_it *insn) 1040{ 1041 if (insn->error) 1042 fprintf (stderr, "ERROR: %s\n", insn->error); 1043 1044 fprintf (stderr, "opcode = 0x%08lx\t", insn->opcode); 1045 fprintf (stderr, "expand = 0x%x\t", insn->expand); 1046 fprintf (stderr, "reloc = %s\t\n", 1047 bfd_get_reloc_code_name (insn->reloc)); 1048 fprintf (stderr, "exp = {\n"); 1049 fprintf (stderr, "\t\tX_add_symbol = %s\n", 1050 insn->exp.X_add_symbol ? 1051 (S_GET_NAME (insn->exp.X_add_symbol) ? 1052 S_GET_NAME (insn->exp.X_add_symbol) : "???") : "0"); 1053 fprintf (stderr, "\t\tX_op_symbol = %s\n", 1054 insn->exp.X_op_symbol ? 1055 (S_GET_NAME (insn->exp.X_op_symbol) ? 1056 S_GET_NAME (insn->exp.X_op_symbol) : "???") : "0"); 1057 fprintf (stderr, "\t\tX_add_number = %lx\n", 1058 insn->exp.X_add_number); 1059 fprintf (stderr, "}\n"); 1060} 1061#endif /* DEBUG_I860 */ 1062 1063 1064#ifdef OBJ_ELF 1065const char *md_shortopts = "VQ:"; 1066#else 1067const char *md_shortopts = ""; 1068#endif 1069 1070#define OPTION_EB (OPTION_MD_BASE + 0) 1071#define OPTION_EL (OPTION_MD_BASE + 1) 1072#define OPTION_WARN_EXPAND (OPTION_MD_BASE + 2) 1073#define OPTION_XP (OPTION_MD_BASE + 3) 1074#define OPTION_INTEL_SYNTAX (OPTION_MD_BASE + 4) 1075 1076struct option md_longopts[] = { 1077 { "EB", no_argument, NULL, OPTION_EB }, 1078 { "EL", no_argument, NULL, OPTION_EL }, 1079 { "mwarn-expand", no_argument, NULL, OPTION_WARN_EXPAND }, 1080 { "mxp", no_argument, NULL, OPTION_XP }, 1081 { "mintel-syntax",no_argument, NULL, OPTION_INTEL_SYNTAX }, 1082 { NULL, no_argument, NULL, 0 } 1083}; 1084size_t md_longopts_size = sizeof (md_longopts); 1085 1086int 1087md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED) 1088{ 1089 switch (c) 1090 { 1091 case OPTION_EB: 1092 target_big_endian = 1; 1093 break; 1094 1095 case OPTION_EL: 1096 target_big_endian = 0; 1097 break; 1098 1099 case OPTION_WARN_EXPAND: 1100 target_warn_expand = 1; 1101 break; 1102 1103 case OPTION_XP: 1104 target_xp = 1; 1105 break; 1106 1107 case OPTION_INTEL_SYNTAX: 1108 target_intel_syntax = 1; 1109 break; 1110 1111#ifdef OBJ_ELF 1112 /* SVR4 argument compatibility (-V): print version ID. */ 1113 case 'V': 1114 print_version_id (); 1115 break; 1116 1117 /* SVR4 argument compatibility (-Qy, -Qn): controls whether 1118 a .comment section should be emitted or not (ignored). */ 1119 case 'Q': 1120 break; 1121#endif 1122 1123 default: 1124 return 0; 1125 } 1126 1127 return 1; 1128} 1129 1130void 1131md_show_usage (FILE *stream) 1132{ 1133 fprintf (stream, _("\ 1134 -EL generate code for little endian mode (default)\n\ 1135 -EB generate code for big endian mode\n\ 1136 -mwarn-expand warn if pseudo operations are expanded\n\ 1137 -mxp enable i860XP support (disabled by default)\n\ 1138 -mintel-syntax enable Intel syntax (default to AT&T/SVR4)\n")); 1139#ifdef OBJ_ELF 1140 /* SVR4 compatibility flags. */ 1141 fprintf (stream, _("\ 1142 -V print assembler version number\n\ 1143 -Qy, -Qn ignored\n")); 1144#endif 1145} 1146 1147 1148/* We have no need to default values of symbols. */ 1149symbolS * 1150md_undefined_symbol (char *name ATTRIBUTE_UNUSED) 1151{ 1152 return 0; 1153} 1154 1155/* The i860 denotes auto-increment with '++'. */ 1156void 1157md_operand (expressionS *exp) 1158{ 1159 char *s; 1160 1161 for (s = input_line_pointer; *s; s++) 1162 { 1163 if (s[0] == '+' && s[1] == '+') 1164 { 1165 input_line_pointer += 2; 1166 exp->X_op = O_register; 1167 break; 1168 } 1169 } 1170} 1171 1172/* Round up a section size to the appropriate boundary. */ 1173valueT 1174md_section_align (segT segment ATTRIBUTE_UNUSED, 1175 valueT size ATTRIBUTE_UNUSED) 1176{ 1177 /* Byte alignment is fine. */ 1178 return size; 1179} 1180 1181/* On the i860, a PC-relative offset is relative to the address of the 1182 offset plus its size. */ 1183long 1184md_pcrel_from (fixS *fixP) 1185{ 1186 return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address; 1187} 1188 1189/* Determine the relocation needed for non PC-relative 16-bit immediates. 1190 Also adjust the given immediate as necessary. Finally, check that 1191 all constraints (such as alignment) are satisfied. */ 1192static bfd_reloc_code_real_type 1193obtain_reloc_for_imm16 (fixS *fix, long *val) 1194{ 1195 valueT fup = fix->fx_addnumber; 1196 bfd_reloc_code_real_type reloc; 1197 1198 if (fix->fx_pcrel) 1199 abort (); 1200 1201 /* Check alignment restrictions. */ 1202 if ((fup & OP_ALIGN2) && (*val & 0x1)) 1203 as_bad_where (fix->fx_file, fix->fx_line, 1204 _("This immediate requires 0 MOD 2 alignment")); 1205 else if ((fup & OP_ALIGN4) && (*val & 0x3)) 1206 as_bad_where (fix->fx_file, fix->fx_line, 1207 _("This immediate requires 0 MOD 4 alignment")); 1208 else if ((fup & OP_ALIGN8) && (*val & 0x7)) 1209 as_bad_where (fix->fx_file, fix->fx_line, 1210 _("This immediate requires 0 MOD 8 alignment")); 1211 else if ((fup & OP_ALIGN16) && (*val & 0xf)) 1212 as_bad_where (fix->fx_file, fix->fx_line, 1213 _("This immediate requires 0 MOD 16 alignment")); 1214 1215 if (fup & OP_SEL_HA) 1216 { 1217 *val = (*val >> 16) + (*val & 0x8000 ? 1 : 0); 1218 reloc = BFD_RELOC_860_HIGHADJ; 1219 } 1220 else if (fup & OP_SEL_H) 1221 { 1222 *val >>= 16; 1223 reloc = BFD_RELOC_860_HIGH; 1224 } 1225 else if (fup & OP_SEL_L) 1226 { 1227 int num_encode; 1228 if (fup & OP_IMM_SPLIT16) 1229 { 1230 if (fup & OP_ENCODE1) 1231 { 1232 num_encode = 1; 1233 reloc = BFD_RELOC_860_SPLIT1; 1234 } 1235 else if (fup & OP_ENCODE2) 1236 { 1237 num_encode = 2; 1238 reloc = BFD_RELOC_860_SPLIT2; 1239 } 1240 else 1241 { 1242 num_encode = 0; 1243 reloc = BFD_RELOC_860_SPLIT0; 1244 } 1245 } 1246 else 1247 { 1248 if (fup & OP_ENCODE1) 1249 { 1250 num_encode = 1; 1251 reloc = BFD_RELOC_860_LOW1; 1252 } 1253 else if (fup & OP_ENCODE2) 1254 { 1255 num_encode = 2; 1256 reloc = BFD_RELOC_860_LOW2; 1257 } 1258 else if (fup & OP_ENCODE3) 1259 { 1260 num_encode = 3; 1261 reloc = BFD_RELOC_860_LOW3; 1262 } 1263 else 1264 { 1265 num_encode = 0; 1266 reloc = BFD_RELOC_860_LOW0; 1267 } 1268 } 1269 1270 /* Preserve size encode bits. */ 1271 *val &= ~((1 << num_encode) - 1); 1272 } 1273 else 1274 { 1275 /* No selector. What reloc do we generate (???)? */ 1276 reloc = BFD_RELOC_32; 1277 } 1278 1279 return reloc; 1280} 1281 1282/* Attempt to simplify or eliminate a fixup. To indicate that a fixup 1283 has been eliminated, set fix->fx_done. If fix->fx_addsy is non-NULL, 1284 we will have to generate a reloc entry. */ 1285 1286void 1287md_apply_fix (fixS *fix, valueT *valP, segT seg ATTRIBUTE_UNUSED) 1288{ 1289 char *buf; 1290 long val = *valP; 1291 unsigned long insn; 1292 valueT fup; 1293 1294 buf = fix->fx_frag->fr_literal + fix->fx_where; 1295 1296 /* Recall that earlier we stored the opcode little-endian. */ 1297 insn = bfd_getl32 (buf); 1298 1299 /* We stored a fix-up in this oddly-named scratch field. */ 1300 fup = fix->fx_addnumber; 1301 1302 /* Determine the necessary relocations as well as inserting an 1303 immediate into the instruction. */ 1304 if (fup & OP_IMM_U5) 1305 { 1306 if (val & ~0x1f) 1307 as_bad_where (fix->fx_file, fix->fx_line, 1308 _("5-bit immediate too large")); 1309 if (fix->fx_addsy) 1310 as_bad_where (fix->fx_file, fix->fx_line, 1311 _("5-bit field must be absolute")); 1312 1313 insn |= (val & 0x1f) << 11; 1314 bfd_putl32 (insn, buf); 1315 fix->fx_r_type = BFD_RELOC_NONE; 1316 fix->fx_done = 1; 1317 } 1318 else if (fup & OP_IMM_S16) 1319 { 1320 fix->fx_r_type = obtain_reloc_for_imm16 (fix, &val); 1321 1322 /* Insert the immediate. */ 1323 if (fix->fx_addsy) 1324 fix->fx_done = 0; 1325 else 1326 { 1327 insn |= val & 0xffff; 1328 bfd_putl32 (insn, buf); 1329 fix->fx_r_type = BFD_RELOC_NONE; 1330 fix->fx_done = 1; 1331 } 1332 } 1333 else if (fup & OP_IMM_U16) 1334 abort (); 1335 1336 else if (fup & OP_IMM_SPLIT16) 1337 { 1338 fix->fx_r_type = obtain_reloc_for_imm16 (fix, &val); 1339 1340 /* Insert the immediate. */ 1341 if (fix->fx_addsy) 1342 fix->fx_done = 0; 1343 else 1344 { 1345 insn |= val & 0x7ff; 1346 insn |= (val & 0xf800) << 5; 1347 bfd_putl32 (insn, buf); 1348 fix->fx_r_type = BFD_RELOC_NONE; 1349 fix->fx_done = 1; 1350 } 1351 } 1352 else if (fup & OP_IMM_BR16) 1353 { 1354 if (val & 0x3) 1355 as_bad_where (fix->fx_file, fix->fx_line, 1356 _("A branch offset requires 0 MOD 4 alignment")); 1357 1358 val = val >> 2; 1359 1360 /* Insert the immediate. */ 1361 if (fix->fx_addsy) 1362 { 1363 fix->fx_done = 0; 1364 fix->fx_r_type = BFD_RELOC_860_PC16; 1365 } 1366 else 1367 { 1368 insn |= (val & 0x7ff); 1369 insn |= ((val & 0xf800) << 5); 1370 bfd_putl32 (insn, buf); 1371 fix->fx_r_type = BFD_RELOC_NONE; 1372 fix->fx_done = 1; 1373 } 1374 } 1375 else if (fup & OP_IMM_BR26) 1376 { 1377 if (val & 0x3) 1378 as_bad_where (fix->fx_file, fix->fx_line, 1379 _("A branch offset requires 0 MOD 4 alignment")); 1380 1381 val >>= 2; 1382 1383 /* Insert the immediate. */ 1384 if (fix->fx_addsy) 1385 { 1386 fix->fx_r_type = BFD_RELOC_860_PC26; 1387 fix->fx_done = 0; 1388 } 1389 else 1390 { 1391 insn |= (val & 0x3ffffff); 1392 bfd_putl32 (insn, buf); 1393 fix->fx_r_type = BFD_RELOC_NONE; 1394 fix->fx_done = 1; 1395 } 1396 } 1397 else if (fup != OP_NONE) 1398 { 1399 as_bad_where (fix->fx_file, fix->fx_line, 1400 _("Unrecognized fix-up (0x%08lx)"), (unsigned long) fup); 1401 abort (); 1402 } 1403 else 1404 { 1405 /* I believe only fix-ups such as ".long .ep.main-main+0xc8000000" 1406 reach here (???). */ 1407 if (fix->fx_addsy) 1408 { 1409 fix->fx_r_type = BFD_RELOC_32; 1410 fix->fx_done = 0; 1411 } 1412 else 1413 { 1414 insn |= (val & 0xffffffff); 1415 bfd_putl32 (insn, buf); 1416 fix->fx_r_type = BFD_RELOC_NONE; 1417 fix->fx_done = 1; 1418 } 1419 } 1420} 1421 1422/* Generate a machine dependent reloc from a fixup. */ 1423arelent* 1424tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, 1425 fixS *fixp) 1426{ 1427 arelent *reloc; 1428 1429 reloc = XNEW (arelent); 1430 reloc->sym_ptr_ptr = XNEW (asymbol *); 1431 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); 1432 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; 1433 reloc->addend = fixp->fx_offset; 1434 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); 1435 1436 if (! reloc->howto) 1437 { 1438 as_bad_where (fixp->fx_file, fixp->fx_line, 1439 "Cannot represent %s relocation in object file", 1440 bfd_get_reloc_code_name (fixp->fx_r_type)); 1441 } 1442 return reloc; 1443} 1444 1445/* This is called from HANDLE_ALIGN in write.c. Fill in the contents 1446 of an rs_align_code fragment. */ 1447 1448void 1449i860_handle_align (fragS *fragp) 1450{ 1451 /* Instructions are always stored little-endian on the i860. */ 1452 static const unsigned char le_nop[] = { 0x00, 0x00, 0x00, 0xA0 }; 1453 1454 int bytes; 1455 char *p; 1456 1457 if (fragp->fr_type != rs_align_code) 1458 return; 1459 1460 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix; 1461 p = fragp->fr_literal + fragp->fr_fix; 1462 1463 /* Make sure we are on a 4-byte boundary, in case someone has been 1464 putting data into a text section. */ 1465 if (bytes & 3) 1466 { 1467 int fix = bytes & 3; 1468 memset (p, 0, fix); 1469 p += fix; 1470 fragp->fr_fix += fix; 1471 } 1472 1473 memcpy (p, le_nop, 4); 1474 fragp->fr_var = 4; 1475} 1476 1477/* This is called after a user-defined label is seen. We check 1478 if the label has a double colon (valid in Intel syntax mode only), 1479 in which case it should be externalized. */ 1480 1481void 1482i860_check_label (symbolS *labelsym) 1483{ 1484 /* At this point, the current line pointer is sitting on the character 1485 just after the first colon on the label. */ 1486 if (target_intel_syntax && *input_line_pointer == ':') 1487 { 1488 S_SET_EXTERNAL (labelsym); 1489 input_line_pointer++; 1490 } 1491} 1492