1 /* tc-mn10300.c -- Assembler code for the Matsushita 10300 2 3 Copyright (C) 1996 Free Software Foundation. 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 2, or (at your option) 10 any later version. 11 12 GAS is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GAS; see the file COPYING. If not, write to 19 the Free Software Foundation, 59 Temple Place - Suite 330, 20 Boston, MA 02111-1307, USA. */ 21 22 #include <stdio.h> 23 #include <ctype.h> 24 #include "as.h" 25 #include "subsegs.h" 26 #include "opcode/mn10300.h" 27 28 /* Structure to hold information about predefined registers. */ 29 struct reg_name 30 { 31 const char *name; 32 int value; 33 }; 34 35 /* Generic assembler global variables which must be defined by all targets. */ 36 37 /* Characters which always start a comment. */ 38 const char comment_chars[] = "#"; 39 40 /* Characters which start a comment at the beginning of a line. */ 41 const char line_comment_chars[] = ";#"; 42 43 /* Characters which may be used to separate multiple commands on a 44 single line. */ 45 const char line_separator_chars[] = ";"; 46 47 /* Characters which are used to indicate an exponent in a floating 48 point number. */ 49 const char EXP_CHARS[] = "eE"; 50 51 /* Characters which mean that a number is a floating point constant, 52 as in 0d1.0. */ 53 const char FLT_CHARS[] = "dD"; 54 55 56 /* local functions */ 57 static unsigned long mn10300 58 PARAMS ((unsigned long insn, const struct mn10300_operand *operand, 59 offsetT val, char *file, unsigned int line)); 60 static int reg_name_search PARAMS ((const struct reg_name *, int, const char *)); 61 static boolean register_name PARAMS ((expressionS *expressionP)); 62 static boolean system_register_name PARAMS ((expressionS *expressionP)); 63 static boolean cc_name PARAMS ((expressionS *expressionP)); 64 65 66 /* fixups */ 67 #define MAX_INSN_FIXUPS (5) 68 struct mn10300_fixup 69 { 70 expressionS exp; 71 int opindex; 72 bfd_reloc_code_real_type reloc; 73 }; 74 struct mn10300_fixup fixups[MAX_INSN_FIXUPS]; 75 static int fc; 76 77 const char *md_shortopts = ""; 78 struct option md_longopts[] = { 79 {NULL, no_argument, NULL, 0} 80 }; 81 size_t md_longopts_size = sizeof(md_longopts); 82 83 /* The target specific pseudo-ops which we support. */ 84 const pseudo_typeS md_pseudo_table[] = 85 { 86 { NULL, NULL, 0 } 87 }; 88 89 /* Opcode hash table. */ 90 static struct hash_control *mn10300_hash; 91 92 /* This table is sorted. Suitable for searching by a binary search. */ 93 static const struct reg_name data_registers[] = 94 { 95 { "d0", 0 }, 96 { "d1", 1 }, 97 { "d2", 2 }, 98 { "d3", 3 }, 99 }; 100 #define DATA_REG_NAME_CNT (sizeof(data_registers) / sizeof(struct reg_name)) 101 102 static const struct reg_name address_registers[] = 103 { 104 { "a0", 0 }, 105 { "a1", 1 }, 106 { "a2", 2 }, 107 { "a3", 3 }, 108 }; 109 #define ADDRESS_REG_NAME_CNT (sizeof(address_registers) / sizeof(struct reg_name)) 110 111 static const struct reg_name other_registers[] = 112 { 113 { "mdr", 0 }, 114 { "psw", 0 }, 115 { "sp", 0 }, 116 }; 117 #define OTHER_REG_NAME_CNT (sizeof(other_registers) / sizeof(struct reg_name)) 118 119 /* reg_name_search does a binary search of the given register table 120 to see if "name" is a valid regiter name. Returns the register 121 number from the array on success, or -1 on failure. */ 122 123 static int 124 reg_name_search (regs, regcount, name) 125 const struct reg_name *regs; 126 int regcount; 127 const char *name; 128 { 129 int middle, low, high; 130 int cmp; 131 132 low = 0; 133 high = regcount - 1; 134 135 do 136 { 137 middle = (low + high) / 2; 138 cmp = strcasecmp (name, regs[middle].name); 139 if (cmp < 0) 140 high = middle - 1; 141 else if (cmp > 0) 142 low = middle + 1; 143 else 144 return regs[middle].value; 145 } 146 while (low <= high); 147 return -1; 148 } 149 150 151 /* Summary of register_name(). 152 * 153 * in: Input_line_pointer points to 1st char of operand. 154 * 155 * out: A expressionS. 156 * The operand may have been a register: in this case, X_op == O_register, 157 * X_add_number is set to the register number, and truth is returned. 158 * Input_line_pointer->(next non-blank) char after operand, or is in 159 * its original state. 160 */ 161 static boolean 162 data_register_name (expressionP) 163 expressionS *expressionP; 164 { 165 int reg_number; 166 char *name; 167 char *start; 168 char c; 169 170 /* Find the spelling of the operand */ 171 start = name = input_line_pointer; 172 173 c = get_symbol_end (); 174 reg_number = reg_name_search (data_registers, DATA_REG_NAME_CNT, name); 175 176 /* look to see if it's in the register table */ 177 if (reg_number >= 0) 178 { 179 expressionP->X_op = O_register; 180 expressionP->X_add_number = reg_number; 181 182 /* make the rest nice */ 183 expressionP->X_add_symbol = NULL; 184 expressionP->X_op_symbol = NULL; 185 *input_line_pointer = c; /* put back the delimiting char */ 186 return true; 187 } 188 else 189 { 190 /* reset the line as if we had not done anything */ 191 *input_line_pointer = c; /* put back the delimiting char */ 192 input_line_pointer = start; /* reset input_line pointer */ 193 return false; 194 } 195 } 196 197 /* Summary of register_name(). 198 * 199 * in: Input_line_pointer points to 1st char of operand. 200 * 201 * out: A expressionS. 202 * The operand may have been a register: in this case, X_op == O_register, 203 * X_add_number is set to the register number, and truth is returned. 204 * Input_line_pointer->(next non-blank) char after operand, or is in 205 * its original state. 206 */ 207 static boolean 208 address_register_name (expressionP) 209 expressionS *expressionP; 210 { 211 int reg_number; 212 char *name; 213 char *start; 214 char c; 215 216 /* Find the spelling of the operand */ 217 start = name = input_line_pointer; 218 219 c = get_symbol_end (); 220 reg_number = reg_name_search (address_registers, ADDRESS_REG_NAME_CNT, name); 221 222 /* look to see if it's in the register table */ 223 if (reg_number >= 0) 224 { 225 expressionP->X_op = O_register; 226 expressionP->X_add_number = reg_number; 227 228 /* make the rest nice */ 229 expressionP->X_add_symbol = NULL; 230 expressionP->X_op_symbol = NULL; 231 *input_line_pointer = c; /* put back the delimiting char */ 232 return true; 233 } 234 else 235 { 236 /* reset the line as if we had not done anything */ 237 *input_line_pointer = c; /* put back the delimiting char */ 238 input_line_pointer = start; /* reset input_line pointer */ 239 return false; 240 } 241 } 242 243 /* Summary of register_name(). 244 * 245 * in: Input_line_pointer points to 1st char of operand. 246 * 247 * out: A expressionS. 248 * The operand may have been a register: in this case, X_op == O_register, 249 * X_add_number is set to the register number, and truth is returned. 250 * Input_line_pointer->(next non-blank) char after operand, or is in 251 * its original state. 252 */ 253 static boolean 254 other_register_name (expressionP) 255 expressionS *expressionP; 256 { 257 int reg_number; 258 char *name; 259 char *start; 260 char c; 261 262 /* Find the spelling of the operand */ 263 start = name = input_line_pointer; 264 265 c = get_symbol_end (); 266 reg_number = reg_name_search (other_registers, OTHER_REG_NAME_CNT, name); 267 268 /* look to see if it's in the register table */ 269 if (reg_number >= 0) 270 { 271 expressionP->X_op = O_register; 272 expressionP->X_add_number = reg_number; 273 274 /* make the rest nice */ 275 expressionP->X_add_symbol = NULL; 276 expressionP->X_op_symbol = NULL; 277 *input_line_pointer = c; /* put back the delimiting char */ 278 return true; 279 } 280 else 281 { 282 /* reset the line as if we had not done anything */ 283 *input_line_pointer = c; /* put back the delimiting char */ 284 input_line_pointer = start; /* reset input_line pointer */ 285 return false; 286 } 287 } 288 289 void 290 md_show_usage (stream) 291 FILE *stream; 292 { 293 fprintf(stream, "MN10300 options:\n\ 294 none yet\n"); 295 } 296 297 int 298 md_parse_option (c, arg) 299 int c; 300 char *arg; 301 { 302 return 0; 303 } 304 305 symbolS * 306 md_undefined_symbol (name) 307 char *name; 308 { 309 return 0; 310 } 311 312 char * 313 md_atof (type, litp, sizep) 314 int type; 315 char *litp; 316 int *sizep; 317 { 318 int prec; 319 LITTLENUM_TYPE words[4]; 320 char *t; 321 int i; 322 323 switch (type) 324 { 325 case 'f': 326 prec = 2; 327 break; 328 329 case 'd': 330 prec = 4; 331 break; 332 333 default: 334 *sizep = 0; 335 return "bad call to md_atof"; 336 } 337 338 t = atof_ieee (input_line_pointer, type, words); 339 if (t) 340 input_line_pointer = t; 341 342 *sizep = prec * 2; 343 344 for (i = prec - 1; i >= 0; i--) 345 { 346 md_number_to_chars (litp, (valueT) words[i], 2); 347 litp += 2; 348 } 349 350 return NULL; 351 } 352 353 354 void 355 md_convert_frag (abfd, sec, fragP) 356 bfd *abfd; 357 asection *sec; 358 fragS *fragP; 359 { 360 /* printf ("call to md_convert_frag \n"); */ 361 abort (); 362 } 363 364 valueT 365 md_section_align (seg, addr) 366 asection *seg; 367 valueT addr; 368 { 369 int align = bfd_get_section_alignment (stdoutput, seg); 370 return ((addr + (1 << align) - 1) & (-1 << align)); 371 } 372 373 void 374 md_begin () 375 { 376 char *prev_name = ""; 377 register const struct mn10300_opcode *op; 378 379 mn10300_hash = hash_new(); 380 381 /* Insert unique names into hash table. The MN10300 instruction set 382 has many identical opcode names that have different opcodes based 383 on the operands. This hash table then provides a quick index to 384 the first opcode with a particular name in the opcode table. */ 385 386 op = mn10300_opcodes; 387 while (op->name) 388 { 389 if (strcmp (prev_name, op->name)) 390 { 391 prev_name = (char *) op->name; 392 hash_insert (mn10300_hash, op->name, (char *) op); 393 } 394 op++; 395 } 396 } 397 398 void 399 md_assemble (str) 400 char *str; 401 { 402 char *s; 403 struct mn10300_opcode *opcode; 404 struct mn10300_opcode *next_opcode; 405 const unsigned char *opindex_ptr; 406 int next_opindex; 407 unsigned long insn, extension, size; 408 char *f; 409 int i; 410 int match; 411 bfd_reloc_code_real_type reloc; 412 413 /* Get the opcode. */ 414 for (s = str; *s != '\0' && ! isspace (*s); s++) 415 ; 416 if (*s != '\0') 417 *s++ = '\0'; 418 419 /* find the first opcode with the proper name */ 420 opcode = (struct mn10300_opcode *)hash_find (mn10300_hash, str); 421 if (opcode == NULL) 422 { 423 as_bad ("Unrecognized opcode: `%s'", str); 424 return; 425 } 426 427 str = s; 428 while (isspace (*str)) 429 ++str; 430 431 input_line_pointer = str; 432 433 for(;;) 434 { 435 const char *errmsg = NULL; 436 int op_idx; 437 char *hold; 438 int extra_shift = 0; 439 440 fc = 0; 441 match = 0; 442 next_opindex = 0; 443 insn = opcode->opcode; 444 extension = 0; 445 for (op_idx = 1, opindex_ptr = opcode->operands; 446 *opindex_ptr != 0; 447 opindex_ptr++, op_idx++) 448 { 449 const struct mn10300_operand *operand; 450 expressionS ex; 451 452 if (next_opindex == 0) 453 { 454 operand = &mn10300_operands[*opindex_ptr]; 455 } 456 else 457 { 458 operand = &mn10300_operands[next_opindex]; 459 next_opindex = 0; 460 } 461 462 errmsg = NULL; 463 464 while (*str == ' ' || *str == ',' || *str == '[' || *str == ']') 465 ++str; 466 467 /* Gather the operand. */ 468 hold = input_line_pointer; 469 input_line_pointer = str; 470 471 if (operand->flags & MN10300_OPERAND_PAREN) 472 { 473 if (*input_line_pointer != ')' && *input_line_pointer != '(') 474 { 475 input_line_pointer = hold; 476 str = hold; 477 goto error; 478 } 479 input_line_pointer++; 480 goto keep_going; 481 } 482 /* See if we can match the operands. */ 483 else if (operand->flags & MN10300_OPERAND_DREG) 484 { 485 if (!data_register_name (&ex)) 486 { 487 input_line_pointer = hold; 488 str = hold; 489 goto error; 490 } 491 } 492 else if (operand->flags & MN10300_OPERAND_AREG) 493 { 494 if (!address_register_name (&ex)) 495 { 496 input_line_pointer = hold; 497 str = hold; 498 goto error; 499 } 500 } 501 else if (operand->flags & MN10300_OPERAND_SP) 502 { 503 char *start = input_line_pointer; 504 char c = get_symbol_end (); 505 506 if (strcmp (start, "sp") != 0) 507 { 508 *input_line_pointer = c; 509 input_line_pointer = hold; 510 str = hold; 511 goto error; 512 } 513 *input_line_pointer = c; 514 goto keep_going; 515 } 516 else if (operand->flags & MN10300_OPERAND_PSW) 517 { 518 char *start = input_line_pointer; 519 char c = get_symbol_end (); 520 521 if (strcmp (start, "psw") != 0) 522 { 523 *input_line_pointer = c; 524 input_line_pointer = hold; 525 str = hold; 526 goto error; 527 } 528 *input_line_pointer = c; 529 goto keep_going; 530 } 531 else if (operand->flags & MN10300_OPERAND_MDR) 532 { 533 char *start = input_line_pointer; 534 char c = get_symbol_end (); 535 536 if (strcmp (start, "mdr") != 0) 537 { 538 *input_line_pointer = c; 539 input_line_pointer = hold; 540 str = hold; 541 goto error; 542 } 543 *input_line_pointer = c; 544 goto keep_going; 545 } 546 else if (data_register_name (&ex)) 547 { 548 input_line_pointer = hold; 549 str = hold; 550 goto error; 551 } 552 else if (address_register_name (&ex)) 553 { 554 input_line_pointer = hold; 555 str = hold; 556 goto error; 557 } 558 else if (other_register_name (&ex)) 559 { 560 input_line_pointer = hold; 561 str = hold; 562 goto error; 563 } 564 else if (*str == ')' || *str == '(') 565 { 566 input_line_pointer = hold; 567 str = hold; 568 goto error; 569 } 570 else 571 { 572 expression (&ex); 573 } 574 575 switch (ex.X_op) 576 { 577 case O_illegal: 578 errmsg = "illegal operand"; 579 goto error; 580 case O_absent: 581 errmsg = "missing operand"; 582 goto error; 583 case O_register: 584 if (operand->flags & (MN10300_OPERAND_DREG 585 | MN10300_OPERAND_AREG) == 0) 586 { 587 input_line_pointer = hold; 588 str = hold; 589 goto error; 590 } 591 592 if (opcode->format == FMT_D1 || opcode->format == FMT_S1) 593 extra_shift = 8; 594 else if (opcode->format == FMT_D2 || opcode->format == FMT_D4 595 || opcode->format == FMT_S2 || opcode->format == FMT_S4 596 || opcode->format == FMT_S6 || opcode->format == FMT_D5) 597 extra_shift = 16; 598 else 599 extra_shift = 0; 600 601 mn10300_insert_operand (&insn, &extension, operand, 602 ex.X_add_number, (char *) NULL, 603 0, extra_shift); 604 605 break; 606 607 case O_constant: 608 /* If this operand can be promoted, and it doesn't 609 fit into the allocated bitfield for this insn, 610 then promote it (ie this opcode does not match). */ 611 if (operand->flags & MN10300_OPERAND_PROMOTE 612 && ! check_operand (insn, operand, ex.X_add_number)) 613 { 614 input_line_pointer = hold; 615 str = hold; 616 goto error; 617 } 618 619 mn10300_insert_operand (&insn, &extension, operand, 620 ex.X_add_number, (char *) NULL, 621 0, 0); 622 break; 623 624 default: 625 /* If this operand can be promoted, then this opcode didn't 626 match since we can't know if it needed promotion! */ 627 if (operand->flags & MN10300_OPERAND_PROMOTE) 628 { 629 input_line_pointer = hold; 630 str = hold; 631 goto error; 632 } 633 634 /* We need to generate a fixup for this expression. */ 635 if (fc >= MAX_INSN_FIXUPS) 636 as_fatal ("too many fixups"); 637 fixups[fc].exp = ex; 638 fixups[fc].opindex = *opindex_ptr; 639 fixups[fc].reloc = BFD_RELOC_UNUSED; 640 ++fc; 641 break; 642 } 643 644 keep_going: 645 str = input_line_pointer; 646 input_line_pointer = hold; 647 648 while (*str == ' ' || *str == ',' || *str == '[' || *str == ']') 649 ++str; 650 651 } 652 653 /* Make sure we used all the operands! */ 654 if (*str != ',') 655 match = 1; 656 657 error: 658 if (match == 0) 659 { 660 next_opcode = opcode + 1; 661 if (next_opcode->opcode != 0 && !strcmp(next_opcode->name, opcode->name)) 662 { 663 opcode = next_opcode; 664 continue; 665 } 666 667 as_bad ("%s", errmsg); 668 return; 669 } 670 break; 671 } 672 673 while (isspace (*str)) 674 ++str; 675 676 if (*str != '\0') 677 as_bad ("junk at end of line: `%s'", str); 678 679 input_line_pointer = str; 680 681 /* Determine the size of the instruction. */ 682 if (opcode->format == FMT_S0) 683 size = 1; 684 685 if (opcode->format == FMT_S1 || opcode->format == FMT_D0) 686 size = 2; 687 688 if (opcode->format == FMT_S2 || opcode->format == FMT_D1) 689 size = 3; 690 691 if (opcode->format == FMT_S4) 692 size = 5; 693 694 if (opcode->format == FMT_S6 || opcode->format == FMT_D5) 695 size = 7; 696 697 if (opcode->format == FMT_D2) 698 size = 4; 699 700 if (opcode->format == FMT_D4) 701 size = 6; 702 703 /* Write out the instruction. */ 704 705 f = frag_more (size); 706 number_to_chars_bigendian (f, insn, size > 4 ? 4 : size); 707 if (size > 4) 708 number_to_chars_bigendian (f + 4, extension, size - 4); 709 } 710 711 712 /* if while processing a fixup, a reloc really needs to be created */ 713 /* then it is done here */ 714 715 arelent * 716 tc_gen_reloc (seg, fixp) 717 asection *seg; 718 fixS *fixp; 719 { 720 arelent *reloc; 721 reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent)); 722 reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym; 723 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; 724 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); 725 if (reloc->howto == (reloc_howto_type *) NULL) 726 { 727 as_bad_where (fixp->fx_file, fixp->fx_line, 728 "reloc %d not supported by object file format", (int)fixp->fx_r_type); 729 return NULL; 730 } 731 reloc->addend = fixp->fx_addnumber; 732 /* printf("tc_gen_reloc: addr=%x addend=%x\n", reloc->address, reloc->addend); */ 733 return reloc; 734 } 735 736 int 737 md_estimate_size_before_relax (fragp, seg) 738 fragS *fragp; 739 asection *seg; 740 { 741 return 0; 742 } 743 744 long 745 md_pcrel_from (fixp) 746 fixS *fixp; 747 { 748 if (fixp->fx_addsy != (symbolS *) NULL && ! S_IS_DEFINED (fixp->fx_addsy)) 749 { 750 /* The symbol is undefined. Let the linker figure it out. */ 751 return 0; 752 } 753 return fixp->fx_frag->fr_address + fixp->fx_where; 754 } 755 756 int 757 md_apply_fix3 (fixp, valuep, seg) 758 fixS *fixp; 759 valueT *valuep; 760 segT seg; 761 { 762 valueT value; 763 char *where; 764 765 fixp->fx_done = 1; 766 return 0; 767 768 if (fixp->fx_addsy == (symbolS *) NULL) 769 { 770 value = *valuep; 771 fixp->fx_done = 1; 772 } 773 else if (fixp->fx_pcrel) 774 value = *valuep; 775 else 776 { 777 value = fixp->fx_offset; 778 if (fixp->fx_subsy != (symbolS *) NULL) 779 { 780 if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section) 781 value -= S_GET_VALUE (fixp->fx_subsy); 782 else 783 { 784 /* We don't actually support subtracting a symbol. */ 785 as_bad_where (fixp->fx_file, fixp->fx_line, 786 "expression too complex"); 787 } 788 } 789 } 790 791 /* printf("md_apply_fix: value=0x%x type=%d\n", value, fixp->fx_r_type); */ 792 793 if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED) 794 { 795 int opindex; 796 const struct mn10300_operand *operand; 797 char *where; 798 unsigned long insn, extension; 799 800 opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED; 801 operand = &mn10300_operands[opindex]; 802 803 /* Fetch the instruction, insert the fully resolved operand 804 value, and stuff the instruction back again. 805 806 Note the instruction has been stored in little endian 807 format! */ 808 where = fixp->fx_frag->fr_literal + fixp->fx_where; 809 810 insn = bfd_getl32((unsigned char *) where); 811 extension = 0; 812 mn10300_insert_operand (&insn, &extension, operand, 813 (offsetT) value, fixp->fx_file, 814 fixp->fx_line, 0); 815 bfd_putl32((bfd_vma) insn, (unsigned char *) where); 816 817 if (fixp->fx_done) 818 { 819 /* Nothing else to do here. */ 820 return 1; 821 } 822 823 /* Determine a BFD reloc value based on the operand information. 824 We are only prepared to turn a few of the operands into relocs. */ 825 826 { 827 as_bad_where(fixp->fx_file, fixp->fx_line, 828 "unresolved expression that must be resolved"); 829 fixp->fx_done = 1; 830 return 1; 831 } 832 } 833 else if (fixp->fx_done) 834 { 835 /* We still have to insert the value into memory! */ 836 where = fixp->fx_frag->fr_literal + fixp->fx_where; 837 if (fixp->fx_size == 1) 838 *where = value & 0xff; 839 if (fixp->fx_size == 2) 840 bfd_putl16(value & 0xffff, (unsigned char *) where); 841 if (fixp->fx_size == 4) 842 bfd_putl32(value, (unsigned char *) where); 843 } 844 845 fixp->fx_addnumber = value; 846 return 1; 847 } 848 849 /* Insert an operand value into an instruction. */ 850 851 static void 852 mn10300_insert_operand (insnp, extensionp, operand, val, file, line, shift) 853 unsigned long *insnp; 854 unsigned long *extensionp; 855 const struct mn10300_operand *operand; 856 offsetT val; 857 char *file; 858 unsigned int line; 859 unsigned int shift; 860 { 861 /* No need to check 32bit operands for a bit. Note that 862 MN10300_OPERAND_SPLIT is an implicit 32bit operand. */ 863 if (operand->bits != 32 864 && (operand->flags & MN10300_OPERAND_SPLIT) == 0) 865 { 866 long min, max; 867 offsetT test; 868 869 if ((operand->flags & MN10300_OPERAND_SIGNED) != 0) 870 { 871 max = (1 << (operand->bits - 1)) - 1; 872 min = - (1 << (operand->bits - 1)); 873 } 874 else 875 { 876 max = (1 << operand->bits) - 1; 877 min = 0; 878 } 879 880 test = val; 881 882 883 if (test < (offsetT) min || test > (offsetT) max) 884 { 885 const char *err = 886 "operand out of range (%s not between %ld and %ld)"; 887 char buf[100]; 888 889 sprint_value (buf, test); 890 if (file == (char *) NULL) 891 as_warn (err, buf, min, max); 892 else 893 as_warn_where (file, line, err, buf, min, max); 894 } 895 } 896 897 if ((operand->flags & MN10300_OPERAND_SPLIT) != 0) 898 { 899 *insnp |= (val >> 32 - operand->bits) & ((1 << operand->bits) - 1); 900 *extensionp |= ((val & ((1 << (32 - operand->bits)) - 1)) 901 << operand->shift); 902 } 903 else if ((operand->flags & MN10300_OPERAND_EXTENDED) == 0) 904 { 905 *insnp |= (((long) val & ((1 << operand->bits) - 1)) 906 << (operand->shift + shift)); 907 908 if ((operand->flags & MN10300_OPERAND_REPEATED) != 0) 909 *insnp |= (((long) val & ((1 << operand->bits) - 1)) 910 << (operand->shift + shift + 2)); 911 } 912 else 913 { 914 *extensionp |= (((long) val & ((1 << operand->bits) - 1)) 915 << (operand->shift + shift)); 916 917 if ((operand->flags & MN10300_OPERAND_REPEATED) != 0) 918 *extensionp |= (((long) val & ((1 << operand->bits) - 1)) 919 << (operand->shift + shift + 2)); 920 } 921 } 922 923 static unsigned long 924 check_operand (insn, operand, val) 925 unsigned long insn; 926 const struct mn10300_operand *operand; 927 offsetT val; 928 { 929 /* No need to check 32bit operands for a bit. Note that 930 MN10300_OPERAND_SPLIT is an implicit 32bit operand. */ 931 if (operand->bits != 32 932 && (operand->flags & MN10300_OPERAND_SPLIT) == 0) 933 { 934 long min, max; 935 offsetT test; 936 937 if ((operand->flags & MN10300_OPERAND_SIGNED) != 0) 938 { 939 max = (1 << (operand->bits - 1)) - 1; 940 min = - (1 << (operand->bits - 1)); 941 } 942 else 943 { 944 max = (1 << operand->bits) - 1; 945 min = 0; 946 } 947 948 test = val; 949 950 951 if (test < (offsetT) min || test > (offsetT) max) 952 return 0; 953 else 954 return 1; 955 } 956 return 1; 957 } 958