1 /* tc-msp430.c -- Assembler code for the Texas Instruments MSP430 2 3 Copyright (C) 2002, 2003 Free Software Foundation, Inc. 4 Contributed by Dmitry Diky <diwil@mail.ru> 5 6 This file is part of GAS, the GNU Assembler. 7 8 GAS is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2, or (at your option) 11 any later version. 12 13 GAS is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with GAS; see the file COPYING. If not, write to 20 the Free Software Foundation, 59 Temple Place - Suite 330, 21 Boston, MA 02111-1307, USA. */ 22 23 #include <stdio.h> 24 #include <string.h> 25 #include <stdlib.h> 26 #include <limits.h> 27 28 #define PUSH_1X_WORKAROUND 29 #include "as.h" 30 #include "subsegs.h" 31 #include "opcode/msp430.h" 32 #include "safe-ctype.h" 33 34 const char comment_chars[] = ";"; 35 const char line_comment_chars[] = "#"; 36 const char line_separator_chars[] = ""; 37 const char EXP_CHARS[] = "eE"; 38 const char FLT_CHARS[] = "dD"; 39 40 /* Handle long expressions. */ 41 extern LITTLENUM_TYPE generic_bignum[]; 42 43 static struct hash_control *msp430_hash; 44 45 static unsigned int msp430_operands 46 PARAMS ((struct msp430_opcode_s *, char *)); 47 static int msp430_srcoperand 48 PARAMS ((struct msp430_operand_s *, char *, int, int *)); 49 static int msp430_dstoperand 50 PARAMS ((struct msp430_operand_s *, char *, int)); 51 static char *parse_exp 52 PARAMS ((char *, expressionS *)); 53 static inline char *skip_space 54 PARAMS ((char *)); 55 static int check_reg 56 PARAMS ((char *)); 57 static void msp430_set_arch 58 PARAMS ((int)); 59 static void show_mcu_list 60 PARAMS ((FILE *)); 61 static void del_spaces 62 PARAMS ((char *)); 63 64 #define MAX_OP_LEN 256 65 66 struct mcu_type_s 67 { 68 char *name; 69 int isa; 70 int mach; 71 }; 72 73 #define MSP430_ISA_11 11 74 #define MSP430_ISA_110 110 75 #define MSP430_ISA_12 12 76 #define MSP430_ISA_13 13 77 #define MSP430_ISA_14 14 78 #define MSP430_ISA_15 15 79 #define MSP430_ISA_16 16 80 #define MSP430_ISA_31 31 81 #define MSP430_ISA_32 32 82 #define MSP430_ISA_33 33 83 #define MSP430_ISA_41 41 84 #define MSP430_ISA_42 42 85 #define MSP430_ISA_43 43 86 #define MSP430_ISA_44 44 87 88 #define CHECK_RELOC_MSP430 ((imm_op || byte_op)?BFD_RELOC_MSP430_16_BYTE:BFD_RELOC_MSP430_16) 89 #define CHECK_RELOC_MSP430_PCREL ((imm_op || byte_op)?BFD_RELOC_MSP430_16_PCREL_BYTE:BFD_RELOC_MSP430_16_PCREL) 90 91 static struct mcu_type_s mcu_types[] = 92 { 93 {"msp1", MSP430_ISA_11, bfd_mach_msp11}, 94 {"msp2", MSP430_ISA_14, bfd_mach_msp14}, 95 {"msp430x110", MSP430_ISA_11, bfd_mach_msp11}, 96 {"msp430x112", MSP430_ISA_11, bfd_mach_msp11}, 97 {"msp430x1101",MSP430_ISA_110, bfd_mach_msp110}, 98 {"msp430x1111",MSP430_ISA_110, bfd_mach_msp110}, 99 {"msp430x1121",MSP430_ISA_110, bfd_mach_msp110}, 100 {"msp430x1122",MSP430_ISA_11, bfd_mach_msp110}, 101 {"msp430x1132",MSP430_ISA_11, bfd_mach_msp110}, 102 103 {"msp430x122", MSP430_ISA_12, bfd_mach_msp12}, 104 {"msp430x123", MSP430_ISA_12, bfd_mach_msp12}, 105 {"msp430x1222",MSP430_ISA_12, bfd_mach_msp12}, 106 {"msp430x1232",MSP430_ISA_12, bfd_mach_msp12}, 107 108 {"msp430x133", MSP430_ISA_13, bfd_mach_msp13}, 109 {"msp430x135", MSP430_ISA_13, bfd_mach_msp13}, 110 {"msp430x1331",MSP430_ISA_13, bfd_mach_msp13}, 111 {"msp430x1351",MSP430_ISA_13, bfd_mach_msp13}, 112 {"msp430x147", MSP430_ISA_14, bfd_mach_msp14}, 113 {"msp430x148", MSP430_ISA_14, bfd_mach_msp14}, 114 {"msp430x149", MSP430_ISA_14, bfd_mach_msp14}, 115 116 {"msp430x155", MSP430_ISA_15, bfd_mach_msp15}, 117 {"msp430x156", MSP430_ISA_15, bfd_mach_msp15}, 118 {"msp430x157", MSP430_ISA_15, bfd_mach_msp15}, 119 {"msp430x167", MSP430_ISA_16, bfd_mach_msp16}, 120 {"msp430x168", MSP430_ISA_16, bfd_mach_msp16}, 121 {"msp430x169", MSP430_ISA_16, bfd_mach_msp16}, 122 123 {"msp430x311", MSP430_ISA_31, bfd_mach_msp31}, 124 {"msp430x312", MSP430_ISA_31, bfd_mach_msp31}, 125 {"msp430x313", MSP430_ISA_31, bfd_mach_msp31}, 126 {"msp430x314", MSP430_ISA_31, bfd_mach_msp31}, 127 {"msp430x315", MSP430_ISA_31, bfd_mach_msp31}, 128 {"msp430x323", MSP430_ISA_32, bfd_mach_msp32}, 129 {"msp430x325", MSP430_ISA_32, bfd_mach_msp32}, 130 {"msp430x336", MSP430_ISA_33, bfd_mach_msp33}, 131 {"msp430x337", MSP430_ISA_33, bfd_mach_msp33}, 132 133 {"msp430x412", MSP430_ISA_41, bfd_mach_msp41}, 134 {"msp430x413", MSP430_ISA_41, bfd_mach_msp41}, 135 136 {"msp430xE423", MSP430_ISA_42, bfd_mach_msp42}, 137 {"msp430xE425", MSP430_ISA_42, bfd_mach_msp42}, 138 {"msp430xE427", MSP430_ISA_42, bfd_mach_msp42}, 139 {"msp430xW423", MSP430_ISA_42, bfd_mach_msp42}, 140 {"msp430xW425", MSP430_ISA_42, bfd_mach_msp42}, 141 {"msp430xW427", MSP430_ISA_42, bfd_mach_msp42}, 142 143 {"msp430x435", MSP430_ISA_43, bfd_mach_msp43}, 144 {"msp430x436", MSP430_ISA_43, bfd_mach_msp43}, 145 {"msp430x437", MSP430_ISA_43, bfd_mach_msp43}, 146 {"msp430x447", MSP430_ISA_44, bfd_mach_msp44}, 147 {"msp430x448", MSP430_ISA_44, bfd_mach_msp44}, 148 {"msp430x449", MSP430_ISA_44, bfd_mach_msp44}, 149 150 {NULL, 0, 0} 151 }; 152 153 154 static struct mcu_type_s default_mcu = 155 { "msp430x11", MSP430_ISA_11, bfd_mach_msp11 }; 156 157 static struct mcu_type_s *msp430_mcu = &default_mcu; 158 159 const pseudo_typeS md_pseudo_table[] = 160 { 161 {"arch", msp430_set_arch, 0}, 162 {NULL, NULL, 0} 163 }; 164 165 #define OPTION_MMCU 'm' 166 167 const char *md_shortopts = "m:"; 168 169 struct option md_longopts[] = 170 { 171 {"mmcu", required_argument, NULL, OPTION_MMCU}, 172 {NULL, no_argument, NULL, 0} 173 }; 174 175 size_t md_longopts_size = sizeof (md_longopts); 176 177 static void 178 show_mcu_list (stream) 179 FILE *stream; 180 { 181 int i; 182 183 fprintf (stream, _("Known MCU names:\n")); 184 185 for (i = 0; mcu_types[i].name; i++) 186 fprintf (stream, _("\t %s\n"), mcu_types[i].name); 187 188 fprintf (stream, "\n"); 189 } 190 191 void 192 md_show_usage (stream) 193 FILE *stream; 194 { 195 fprintf (stream, 196 _("MSP430 options:\n" 197 " -mmcu=[msp430-name] select microcontroller type\n" 198 " msp430x110 msp430x112\n" 199 " msp430x1101 msp430x1111\n" 200 " msp430x1121 msp430x1122 msp430x1132\n" 201 " msp430x122 msp430x123\n" 202 " msp430x1222 msp430x1232\n" 203 " msp430x133 msp430x135\n" 204 " msp430x1331 msp430x1351\n" 205 " msp430x147 msp430x148 msp430x149\n" 206 " msp430x155 msp430x156 msp430x157\n" 207 " msp430x167 msp430x168 msp430x169\n" 208 " msp430x311 msp430x312 msp430x313 msp430x314 msp430x315\n" 209 " msp430x323 msp430x325\n" 210 " msp430x336 msp430x337\n" 211 " msp430x412 msp430x413\n" 212 " msp430xE423 msp430xE425 msp430E427\n" 213 " msp430xW423 msp430xW425 msp430W427\n" 214 " msp430x435 msp430x436 msp430x437\n" 215 " msp430x447 msp430x448 msp430x449\n")); 216 217 show_mcu_list (stream); 218 } 219 220 static char * 221 extract_word (char *from, char *to, int limit) 222 { 223 char *op_start; 224 char *op_end; 225 int size = 0; 226 227 /* Drop leading whitespace. */ 228 from = skip_space (from); 229 *to = 0; 230 231 /* Find the op code end. */ 232 for (op_start = op_end = from; *op_end != 0 && is_part_of_name (*op_end);) 233 { 234 to[size++] = *op_end++; 235 if (size + 1 >= limit) 236 break; 237 } 238 239 to[size] = 0; 240 return op_end; 241 } 242 243 static void 244 msp430_set_arch (dummy) 245 int dummy ATTRIBUTE_UNUSED; 246 { 247 char *str = (char *) alloca (32); /* 32 for good measure. */ 248 249 input_line_pointer = extract_word (input_line_pointer, str, 32); 250 251 md_parse_option (OPTION_MMCU, str); 252 bfd_set_arch_mach (stdoutput, TARGET_ARCH, msp430_mcu->mach); 253 } 254 255 int 256 md_parse_option (c, arg) 257 int c; 258 char *arg; 259 { 260 int i; 261 262 switch (c) 263 { 264 case OPTION_MMCU: 265 for (i = 0; mcu_types[i].name; ++i) 266 if (strcmp (mcu_types[i].name, arg) == 0) 267 break; 268 269 if (!mcu_types[i].name) 270 { 271 show_mcu_list (stderr); 272 as_fatal (_("unknown MCU: %s\n"), arg); 273 } 274 275 if (msp430_mcu == &default_mcu || msp430_mcu->mach == mcu_types[i].mach) 276 msp430_mcu = &mcu_types[i]; 277 else 278 as_fatal (_("redefinition of mcu type %s' to %s'"), 279 msp430_mcu->name, mcu_types[i].name); 280 return 1; 281 } 282 283 return 0; 284 } 285 286 symbolS * 287 md_undefined_symbol (name) 288 char *name ATTRIBUTE_UNUSED; 289 { 290 return 0; 291 } 292 293 static inline char * 294 skip_space (s) 295 char *s; 296 { 297 while (ISSPACE (*s)) 298 ++s; 299 return s; 300 } 301 302 /* Delete spaces from s: X ( r 1 2) => X(r12). */ 303 304 static void 305 del_spaces (s) 306 char *s; 307 { 308 while (*s) 309 { 310 if (ISSPACE (*s)) 311 { 312 char *m = s + 1; 313 314 while (ISSPACE (*m) && *m) 315 m++; 316 memmove (s, m, strlen (m) + 1); 317 } 318 else 319 s++; 320 } 321 } 322 323 /* Extract one word from FROM and copy it to TO. Delimeters are ",;\n" */ 324 325 static char * 326 extract_operand (char *from, char *to, int limit) 327 { 328 int size = 0; 329 330 /* Drop leading whitespace. */ 331 from = skip_space (from); 332 333 while (size < limit && *from) 334 { 335 *(to + size) = *from; 336 if (*from == ',' || *from == ';' || *from == '\n') 337 break; 338 from++; 339 size++; 340 } 341 342 *(to + size) = 0; 343 del_spaces (to); 344 345 from++; 346 347 return from; 348 } 349 350 static char * 351 extract_cmd (char *from, char *to, int limit) 352 { 353 int size = 0; 354 355 while (*from && ! ISSPACE (*from) && *from != '.' && limit > size) 356 { 357 *(to + size) = *from; 358 from++; 359 size++; 360 } 361 362 *(to + size) = 0; 363 364 return from; 365 } 366 367 /* Turn a string in input_line_pointer into a floating point constant 368 of type TYPE, and store the appropriate bytes in *LITP. The number 369 of LITTLENUMS emitted is stored in *SIZEP. An error message is 370 returned, or NULL on OK. */ 371 372 char * 373 md_atof (type, litP, sizeP) 374 int type; 375 char *litP; 376 int *sizeP; 377 { 378 int prec; 379 LITTLENUM_TYPE words[4]; 380 LITTLENUM_TYPE *wordP; 381 char *t; 382 383 switch (type) 384 { 385 case 'f': 386 prec = 2; 387 break; 388 case 'd': 389 prec = 4; 390 break; 391 default: 392 *sizeP = 0; 393 return _("bad call to md_atof"); 394 } 395 396 t = atof_ieee (input_line_pointer, type, words); 397 if (t) 398 input_line_pointer = t; 399 400 *sizeP = prec * sizeof (LITTLENUM_TYPE); 401 402 /* This loop outputs the LITTLENUMs in REVERSE order. */ 403 for (wordP = words + prec - 1; prec--;) 404 { 405 md_number_to_chars (litP, (valueT) (*wordP--), sizeof (LITTLENUM_TYPE)); 406 litP += sizeof (LITTLENUM_TYPE); 407 } 408 409 return NULL; 410 } 411 412 void 413 md_convert_frag (abfd, sec, fragP) 414 bfd *abfd ATTRIBUTE_UNUSED; 415 asection *sec ATTRIBUTE_UNUSED; 416 fragS *fragP ATTRIBUTE_UNUSED; 417 { 418 abort (); 419 } 420 421 void 422 md_begin () 423 { 424 struct msp430_opcode_s *opcode; 425 msp430_hash = hash_new (); 426 427 for (opcode = msp430_opcodes; opcode->name; opcode++) 428 hash_insert (msp430_hash, opcode->name, (char *) opcode); 429 430 bfd_set_arch_mach (stdoutput, TARGET_ARCH, msp430_mcu->mach); 431 } 432 433 void 434 md_assemble (str) 435 char *str; 436 { 437 struct msp430_opcode_s *opcode; 438 char cmd[32]; 439 unsigned int i = 0; 440 441 str = skip_space (str); /* Skip leading spaces. */ 442 str = extract_cmd (str, cmd, sizeof (cmd)); 443 444 while (cmd[i] && i < sizeof (cmd)) 445 { 446 char a = TOLOWER (cmd[i]); 447 cmd[i] = a; 448 i++; 449 } 450 451 if (!cmd[0]) 452 { 453 as_bad (_("can't find opcode ")); 454 return; 455 } 456 457 opcode = (struct msp430_opcode_s *) hash_find (msp430_hash, cmd); 458 459 if (opcode == NULL) 460 { 461 as_bad (_("unknown opcode `%s'"), cmd); 462 return; 463 } 464 465 { 466 char *__t = input_line_pointer; 467 msp430_operands (opcode, str); 468 input_line_pointer = __t; 469 } 470 } 471 472 /* Parse instruction operands. 473 Return binary opcode. */ 474 475 static unsigned int 476 msp430_operands (opcode, line) 477 struct msp430_opcode_s *opcode; 478 char *line; 479 { 480 int bin = opcode->bin_opcode; /* opcode mask. */ 481 int __is; 482 char l1[MAX_OP_LEN], l2[MAX_OP_LEN]; 483 char *frag; 484 int where; 485 struct msp430_operand_s op1, op2; 486 int res = 0; 487 static short ZEROS = 0; 488 int byte_op, imm_op; 489 490 /* opcode is the one from opcodes table 491 line contains something like 492 [.w] @r2+, 5(R1) 493 or 494 .b @r2+, 5(R1). */ 495 496 /* Check if byte or word operation. */ 497 if (*line == '.' && TOLOWER (*(line + 1)) == 'b') 498 { 499 bin |= BYTE_OPERATION; 500 byte_op = 1; 501 } 502 else 503 byte_op = 0; 504 505 /* skip .[bwBW]. */ 506 while (! ISSPACE (*line) && *line) 507 line++; 508 509 if (opcode->insn_opnumb && (!*line || *line == '\n')) 510 { 511 as_bad (_("instruction %s requires %d operand(s)"), 512 opcode->name, opcode->insn_opnumb); 513 return 0; 514 } 515 516 memset (l1, 0, sizeof (l1)); 517 memset (l2, 0, sizeof (l2)); 518 memset (&op1, 0, sizeof (op1)); 519 memset (&op2, 0, sizeof (op2)); 520 521 imm_op = 0; 522 523 switch (opcode->fmt) 524 { 525 case 0: /* Emulated. */ 526 switch (opcode->insn_opnumb) 527 { 528 case 0: 529 /* Set/clear bits instructions. */ 530 __is = 2; 531 frag = frag_more (__is); 532 bfd_putl16 ((bfd_vma) bin, frag); 533 break; 534 case 1: 535 /* Something which works with destination operand. */ 536 line = extract_operand (line, l1, sizeof (l1)); 537 res = msp430_dstoperand (&op1, l1, opcode->bin_opcode); 538 if (res) 539 break; 540 541 bin |= (op1.reg | (op1.am << 7)); 542 __is = 1 + op1.ol; 543 frag = frag_more (2 * __is); 544 where = frag - frag_now->fr_literal; 545 bfd_putl16 ((bfd_vma) bin, frag); 546 547 if (op1.mode == OP_EXP) 548 { 549 where += 2; 550 bfd_putl16 ((bfd_vma) ZEROS, frag + 2); 551 552 if (op1.reg) 553 fix_new_exp (frag_now, where, 2, 554 &(op1.exp), FALSE, CHECK_RELOC_MSP430); 555 else 556 fix_new_exp (frag_now, where, 2, 557 &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL); 558 } 559 break; 560 561 case 2: 562 { 563 /* Shift instruction. */ 564 line = extract_operand (line, l1, sizeof (l1)); 565 strncpy (l2, l1, sizeof (l2)); 566 l2[sizeof (l2) - 1] = '\0'; 567 res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op); 568 res += msp430_dstoperand (&op2, l2, opcode->bin_opcode); 569 570 if (res) 571 break; /* An error occurred. All warnings were done before. */ 572 573 bin |= (op2.reg | (op1.reg << 8) | (op1.am << 4) | (op2.am << 7)); 574 575 __is = 1 + op1.ol + op2.ol; /* insn size in words. */ 576 frag = frag_more (2 * __is); 577 where = frag - frag_now->fr_literal; 578 bfd_putl16 ((bfd_vma) bin, frag); 579 580 if (op1.mode == OP_EXP) 581 { 582 where += 2; /* Advance 'where' as we do not know _where_. */ 583 bfd_putl16 ((bfd_vma) ZEROS, frag + 2); 584 585 if (op1.reg || (op1.reg == 0 && op1.am == 3)) /* Not PC relative. */ 586 fix_new_exp (frag_now, where, 2, 587 &(op1.exp), FALSE, CHECK_RELOC_MSP430); 588 else 589 fix_new_exp (frag_now, where, 2, 590 &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL); 591 } 592 593 if (op2.mode == OP_EXP) 594 { 595 imm_op = 0; 596 bfd_putl16 ((bfd_vma) ZEROS, frag + 2 + ((__is == 3) ? 2 : 0)); 597 598 if (op2.reg) /* Not PC relative. */ 599 fix_new_exp (frag_now, where + 2, 2, 600 &(op2.exp), FALSE, CHECK_RELOC_MSP430); 601 else 602 fix_new_exp (frag_now, where + 2, 2, 603 &(op2.exp), TRUE, CHECK_RELOC_MSP430_PCREL); 604 } 605 break; 606 } 607 case 3: 608 /* Branch instruction => mov dst, r0. */ 609 line = extract_operand (line, l1, sizeof (l1)); 610 611 res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op); 612 if (res) 613 break; 614 615 byte_op = 0; 616 imm_op = 0; 617 618 bin |= ((op1.reg << 8) | (op1.am << 4)); 619 __is = 1 + op1.ol; 620 frag = frag_more (2 * __is); 621 where = frag - frag_now->fr_literal; 622 bfd_putl16 ((bfd_vma) bin, frag); 623 624 if (op1.mode == OP_EXP) 625 { 626 where += 2; 627 bfd_putl16 ((bfd_vma) ZEROS, frag + 2); 628 629 if (op1.reg || (op1.reg == 0 && op1.am == 3)) 630 fix_new_exp (frag_now, where, 2, 631 &(op1.exp), FALSE, CHECK_RELOC_MSP430); 632 else 633 fix_new_exp (frag_now, where, 2, 634 &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL); 635 } 636 break; 637 } 638 break; 639 640 case 1: /* Format 1, double operand. */ 641 line = extract_operand (line, l1, sizeof (l1)); 642 line = extract_operand (line, l2, sizeof (l2)); 643 res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op); 644 res += msp430_dstoperand (&op2, l2, opcode->bin_opcode); 645 646 if (res) 647 break; /* Error occurred. All warnings were done before. */ 648 649 bin |= (op2.reg | (op1.reg << 8) | (op1.am << 4) | (op2.am << 7)); 650 651 __is = 1 + op1.ol + op2.ol; /* insn size in words. */ 652 frag = frag_more (2 * __is); 653 where = frag - frag_now->fr_literal; 654 bfd_putl16 ((bfd_vma) bin, frag); 655 656 if (op1.mode == OP_EXP) 657 { 658 where += 2; /* Advance where as we do not know _where_. */ 659 bfd_putl16 ((bfd_vma) ZEROS, frag + 2); 660 661 if (op1.reg || (op1.reg == 0 && op1.am == 3)) /* Not PC relative. */ 662 fix_new_exp (frag_now, where, 2, 663 &(op1.exp), FALSE, CHECK_RELOC_MSP430); 664 else 665 fix_new_exp (frag_now, where, 2, 666 &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL); 667 } 668 669 if (op2.mode == OP_EXP) 670 { 671 imm_op = 0; 672 bfd_putl16 ((bfd_vma) ZEROS, frag + 2 + ((__is == 3) ? 2 : 0)); 673 674 if (op2.reg) /* Not PC relative. */ 675 fix_new_exp (frag_now, where + 2, 2, 676 &(op2.exp), FALSE, CHECK_RELOC_MSP430); 677 else 678 fix_new_exp (frag_now, where + 2, 2, 679 &(op2.exp), TRUE, CHECK_RELOC_MSP430_PCREL); 680 } 681 break; 682 683 case 2: /* Single-operand mostly instr. */ 684 if (opcode->insn_opnumb == 0) 685 { 686 /* reti instruction. */ 687 frag = frag_more (2); 688 bfd_putl16 ((bfd_vma) bin, frag); 689 break; 690 } 691 692 line = extract_operand (line, l1, sizeof (l1)); 693 res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op); 694 if (res) 695 break; /* Error in operand. */ 696 697 bin |= op1.reg | (op1.am << 4); 698 __is = 1 + op1.ol; 699 frag = frag_more (2 * __is); 700 where = frag - frag_now->fr_literal; 701 bfd_putl16 ((bfd_vma) bin, frag); 702 703 if (op1.mode == OP_EXP) 704 { 705 bfd_putl16 ((bfd_vma) ZEROS, frag + 2); 706 707 if (op1.reg || (op1.reg == 0 && op1.am == 3)) /* Not PC relative. */ 708 fix_new_exp (frag_now, where + 2, 2, 709 &(op1.exp), FALSE, CHECK_RELOC_MSP430); 710 else 711 fix_new_exp (frag_now, where + 2, 2, 712 &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL); 713 } 714 break; 715 716 case 3: /* Conditional jumps instructions. */ 717 line = extract_operand (line, l1, sizeof (l1)); 718 /* l1 is a label. */ 719 if (l1[0]) 720 { 721 char *m = l1; 722 expressionS exp; 723 724 if (*m == '$') 725 m++; 726 727 parse_exp (m, &exp); 728 frag = frag_more (2); /* Instr size is 1 word. */ 729 730 /* In order to handle something like: 731 732 and #0x8000, r5 733 tst r5 734 jz 4 ; skip next 4 bytes 735 inv r5 736 inc r5 737 nop ; will jump here if r5 positive or zero 738 739 jCOND -n ;assumes jump n bytes backward: 740 741 mov r5,r6 742 jmp -2 743 744 is equal to: 745 lab: 746 mov r5,r6 747 jmp lab 748 749 jCOND $n ; jump from PC in either direction. */ 750 751 if (exp.X_op == O_constant) 752 { 753 int x = exp.X_add_number; 754 755 if (x & 1) 756 { 757 as_warn (_("Even number required. Rounded to %d"), x + 1); 758 x++; 759 } 760 761 if ((*l1 == '$' && x > 0) || x < 0) 762 x -= 2; 763 764 x >>= 1; 765 766 if (x > 512 || x < -511) 767 { 768 as_bad (_("Wrong displacement %d"), x << 1); 769 break; 770 } 771 772 bin |= x & 0x3ff; 773 bfd_putl16 ((bfd_vma) bin, frag); 774 } 775 else if (exp.X_op == O_symbol && *l1 != '$') 776 { 777 where = frag - frag_now->fr_literal; 778 fix_new_exp (frag_now, where, 2, 779 &exp, TRUE, BFD_RELOC_MSP430_10_PCREL); 780 781 bfd_putl16 ((bfd_vma) bin, frag); 782 } 783 else if (*l1 == '$') 784 { 785 as_bad (_("instruction requires label sans '$'")); 786 break; 787 } 788 else 789 { 790 as_bad (_ 791 ("instruction requires label or value in range -511:512")); 792 break; 793 } 794 } 795 else 796 { 797 as_bad (_("instruction requires label")); 798 break; 799 } 800 break; 801 802 default: 803 as_bad (_("Ilegal instruction or not implmented opcode.")); 804 } 805 806 input_line_pointer = line; 807 return 0; 808 } 809 810 static int 811 msp430_dstoperand (op, l, bin) 812 struct msp430_operand_s *op; 813 char *l; 814 int bin; 815 { 816 int dummy; 817 int ret = msp430_srcoperand (op, l, bin, &dummy); 818 if (ret) 819 return ret; 820 821 if (op->am == 2) 822 { 823 char *__tl = "0"; 824 825 op->mode = OP_EXP; 826 op->am = 1; 827 op->ol = 1; 828 parse_exp (__tl, &(op->exp)); 829 if (op->exp.X_op != O_constant || op->exp.X_add_number != 0) 830 { 831 as_bad (_("Internal bug. Try to use 0(r%d) instead of @r%d"), 832 op->reg, op->reg); 833 return 1; 834 } 835 return 0; 836 } 837 838 if (op->am > 1) 839 { 840 as_bad (_ 841 ("this addressing mode is not applicable for destination operand")); 842 return 1; 843 } 844 return 0; 845 } 846 847 848 static int 849 check_reg (t) 850 char *t; 851 { 852 /* If this is a reg numb, str 't' must be a number from 0 - 15. */ 853 854 if (strlen (t) > 2 && *(t + 2) != '+') 855 return 1; 856 857 while (*t) 858 { 859 if ((*t < '0' || *t > '9') && *t != '+') 860 break; 861 t++; 862 } 863 864 if (*t) 865 return 1; 866 867 return 0; 868 } 869 870 871 static int 872 msp430_srcoperand (op, l, bin, imm_op) 873 struct msp430_operand_s *op; 874 char *l; 875 int bin; 876 int *imm_op; 877 { 878 char *__tl = l; 879 880 /* Check if an immediate #VALUE. The hash sign should be only at the beginning! */ 881 if (*l == '#') 882 { 883 char *h = l; 884 int vshift = -1; 885 int rval = 0; 886 887 /* Check if there is: 888 llo(x) - least significant 16 bits, x &= 0xffff 889 lhi(x) - x = (x >> 16) & 0xffff, 890 hlo(x) - x = (x >> 32) & 0xffff, 891 hhi(x) - x = (x >> 48) & 0xffff 892 The value _MUST_ be constant expression: #hlo(1231231231). */ 893 894 *imm_op = 1; 895 896 if (strncasecmp (h, "#llo(", 5) == 0) 897 { 898 vshift = 0; 899 rval = 3; 900 } 901 else if (strncasecmp (h, "#lhi(", 5) == 0) 902 { 903 vshift = 1; 904 rval = 3; 905 } 906 else if (strncasecmp (h, "#hlo(", 5) == 0) 907 { 908 vshift = 2; 909 rval = 3; 910 } 911 else if (strncasecmp (h, "#hhi(", 5) == 0) 912 { 913 vshift = 3; 914 rval = 3; 915 } 916 else if (strncasecmp (h, "#lo(", 4) == 0) 917 { 918 vshift = 0; 919 rval = 2; 920 } 921 else if (strncasecmp (h, "#hi(", 4) == 0) 922 { 923 vshift = 1; 924 rval = 2; 925 } 926 927 op->reg = 0; /* Reg PC. */ 928 op->am = 3; 929 op->ol = 1; /* Immediate will follow an instruction. */ 930 __tl = h + 1 + rval; 931 op->mode = OP_EXP; 932 parse_exp (__tl, &(op->exp)); 933 if (op->exp.X_op == O_constant) 934 { 935 int x = op->exp.X_add_number; 936 937 if (vshift == 0) 938 { 939 x = x & 0xffff; 940 op->exp.X_add_number = x; 941 } 942 else if (vshift == 1) 943 { 944 x = (x >> 16) & 0xffff; 945 op->exp.X_add_number = x; 946 } 947 else if (vshift > 1) 948 { 949 if (x < 0) 950 op->exp.X_add_number = -1; 951 else 952 op->exp.X_add_number = 0; /* Nothing left. */ 953 x = op->exp.X_add_number; 954 } 955 956 if (op->exp.X_add_number > 65535 || op->exp.X_add_number < -32768) 957 { 958 as_bad (_("value %ld out of range. Use #lo() or #hi()"), x); 959 return 1; 960 } 961 962 /* Now check constants. */ 963 /* Substitute register mode with a constant generator if applicable. */ 964 965 x = (short) x; /* Extend sign. */ 966 967 if (x == 0) 968 { 969 op->reg = 3; 970 op->am = 0; 971 op->ol = 0; 972 op->mode = OP_REG; 973 } 974 else if (x == 1) 975 { 976 op->reg = 3; 977 op->am = 1; 978 op->ol = 0; 979 op->mode = OP_REG; 980 } 981 else if (x == 2) 982 { 983 op->reg = 3; 984 op->am = 2; 985 op->ol = 0; 986 op->mode = OP_REG; 987 } 988 else if (x == -1) 989 { 990 op->reg = 3; 991 op->am = 3; 992 op->ol = 0; 993 op->mode = OP_REG; 994 } 995 else if (x == 4) 996 { 997 #ifdef PUSH_1X_WORKAROUND 998 if (bin == 0x1200) 999 { 1000 /* Remove warning as confusing. 1001 as_warn(_("Hardware push bug workaround")); */ 1002 } 1003 else 1004 #endif 1005 { 1006 op->reg = 2; 1007 op->am = 2; 1008 op->ol = 0; 1009 op->mode = OP_REG; 1010 } 1011 } 1012 else if (x == 8) 1013 { 1014 #ifdef PUSH_1X_WORKAROUND 1015 if (bin == 0x1200) 1016 { 1017 /* Remove warning as confusing. 1018 as_warn(_("Hardware push bug workaround")); */ 1019 } 1020 else 1021 #endif 1022 { 1023 op->reg = 2; 1024 op->am = 3; 1025 op->ol = 0; 1026 op->mode = OP_REG; 1027 } 1028 } 1029 } 1030 else if (op->exp.X_op == O_symbol) 1031 { 1032 op->mode = OP_EXP; 1033 } 1034 else if (op->exp.X_op == O_big) 1035 { 1036 short x; 1037 if (vshift != -1) 1038 { 1039 op->exp.X_op = O_constant; 1040 op->exp.X_add_number = 0xffff & generic_bignum[vshift]; 1041 x = op->exp.X_add_number; 1042 } 1043 else 1044 { 1045 as_bad (_ 1046 ("unknown expression in operand %s. use #llo() #lhi() #hlo() #hhi() "), 1047 l); 1048 return 1; 1049 } 1050 1051 if (x == 0) 1052 { 1053 op->reg = 3; 1054 op->am = 0; 1055 op->ol = 0; 1056 op->mode = OP_REG; 1057 } 1058 else if (x == 1) 1059 { 1060 op->reg = 3; 1061 op->am = 1; 1062 op->ol = 0; 1063 op->mode = OP_REG; 1064 } 1065 else if (x == 2) 1066 { 1067 op->reg = 3; 1068 op->am = 2; 1069 op->ol = 0; 1070 op->mode = OP_REG; 1071 } 1072 else if (x == -1) 1073 { 1074 op->reg = 3; 1075 op->am = 3; 1076 op->ol = 0; 1077 op->mode = OP_REG; 1078 } 1079 else if (x == 4) 1080 { 1081 op->reg = 2; 1082 op->am = 2; 1083 op->ol = 0; 1084 op->mode = OP_REG; 1085 } 1086 else if (x == 8) 1087 { 1088 op->reg = 2; 1089 op->am = 3; 1090 op->ol = 0; 1091 op->mode = OP_REG; 1092 } 1093 } 1094 else 1095 { 1096 as_bad (_("unknown operand %s"), l); 1097 } 1098 return 0; 1099 } 1100 1101 /* Check if absolute &VALUE (assume that we can construct something like ((a&b)<<7 + 25). */ 1102 if (*l == '&') 1103 { 1104 char *h = l; 1105 1106 op->reg = 2; /* reg 2 in absolute addr mode. */ 1107 op->am = 1; /* mode As == 01 bin. */ 1108 op->ol = 1; /* Immediate value followed by instruction. */ 1109 __tl = h + 1; 1110 parse_exp (__tl, &(op->exp)); 1111 op->mode = OP_EXP; 1112 if (op->exp.X_op == O_constant) 1113 { 1114 int x = op->exp.X_add_number; 1115 if (x > 65535 || x < -32768) 1116 { 1117 as_bad (_("value out of range: %d"), x); 1118 return 1; 1119 } 1120 } 1121 else if (op->exp.X_op == O_symbol) 1122 { 1123 } 1124 else 1125 { 1126 as_bad (_("unknown expression in operand %s"), l); 1127 return 1; 1128 } 1129 return 0; 1130 } 1131 1132 /* Check if indirect register mode @Rn / postincrement @Rn+. */ 1133 if (*l == '@') 1134 { 1135 char *t = l; 1136 char *m = strchr (l, '+'); 1137 1138 if (t != l) 1139 { 1140 as_bad (_("unknown addressing mode %s"), l); 1141 return 1; 1142 } 1143 1144 t++; 1145 if (*t != 'r' && *t != 'R') 1146 { 1147 as_bad (_("unknown addressing mode %s"), l); 1148 return 1; 1149 } 1150 1151 t++; /* Points to the reg value. */ 1152 1153 if (check_reg (t)) 1154 { 1155 as_bad (_("Bad register name r%s"), t); 1156 return 1; 1157 } 1158 1159 op->mode = OP_REG; 1160 op->am = m ? 3 : 2; 1161 op->ol = 0; 1162 if (m) 1163 *m = 0; /* strip '+' */ 1164 op->reg = atoi (t); 1165 if (op->reg < 0 || op->reg > 15) 1166 { 1167 as_bad (_("MSP430 does not have %d registers"), op->reg); 1168 return 1; 1169 } 1170 1171 return 0; 1172 } 1173 1174 /* Check if register indexed X(Rn). */ 1175 do 1176 { 1177 char *h = strrchr (l, '('); 1178 char *m = strrchr (l, ')'); 1179 char *t; 1180 1181 *imm_op = 1; 1182 1183 if (!h) 1184 break; 1185 if (!m) 1186 { 1187 as_bad (_("')' required")); 1188 return 1; 1189 } 1190 1191 t = h; 1192 op->am = 1; 1193 op->ol = 1; 1194 /* Extract a register. */ 1195 t++; /* Advance pointer. */ 1196 1197 if (*t != 'r' && *t != 'R') 1198 { 1199 as_bad (_ 1200 ("unknown operator %s. Did you mean X(Rn) or #[hl][hl][oi](CONST) ?"), 1201 l); 1202 return 1; 1203 } 1204 t++; 1205 1206 op->reg = *t - '0'; 1207 if (op->reg > 9 || op->reg < 0) 1208 { 1209 as_bad (_("unknown operator (r%s substituded as a register name"), 1210 t); 1211 return 1; 1212 } 1213 t++; 1214 if (*t != ')') 1215 { 1216 op->reg = op->reg * 10; 1217 op->reg += *t - '0'; 1218 1219 if (op->reg > 15) 1220 { 1221 as_bad (_("unknown operator %s"), l); 1222 return 1; 1223 } 1224 if (op->reg == 2) 1225 { 1226 as_bad (_("r2 should not be used in indexed addressing mode")); 1227 return 1; 1228 } 1229 1230 if (*(t + 1) != ')') 1231 { 1232 as_bad (_("unknown operator %s"), l); 1233 return 1; 1234 } 1235 } 1236 1237 /* Extract constant. */ 1238 __tl = l; 1239 *h = 0; 1240 op->mode = OP_EXP; 1241 parse_exp (__tl, &(op->exp)); 1242 if (op->exp.X_op == O_constant) 1243 { 1244 int x = op->exp.X_add_number; 1245 1246 if (x > 65535 || x < -32768) 1247 { 1248 as_bad (_("value out of range: %d"), x); 1249 return 1; 1250 } 1251 1252 if (x == 0) 1253 { 1254 op->mode = OP_REG; 1255 op->am = 2; 1256 op->ol = 0; 1257 return 0; 1258 } 1259 } 1260 else if (op->exp.X_op == O_symbol) 1261 { 1262 } 1263 else 1264 { 1265 as_bad (_("unknown expression in operand %s"), l); 1266 return 1; 1267 } 1268 1269 return 0; 1270 } 1271 while (0); 1272 1273 /* Register mode 'mov r1,r2'. */ 1274 do 1275 { 1276 char *t = l; 1277 1278 /* Operand should be a register. */ 1279 if (*t == 'r' || *t == 'R') 1280 { 1281 int x = atoi (t + 1); 1282 1283 if (check_reg (t + 1)) 1284 break; 1285 1286 if (x < 0 || x > 15) 1287 break; /* Symbolic mode. */ 1288 1289 op->mode = OP_REG; 1290 op->am = 0; 1291 op->ol = 0; 1292 op->reg = x; 1293 return 0; 1294 } 1295 } 1296 while (0); 1297 1298 /* Symbolic mode 'mov a, b' == 'mov x(pc), y(pc)'. */ 1299 do 1300 { 1301 char *t = l; 1302 1303 __tl = l; 1304 1305 while (*t) 1306 { 1307 /* alpha/number underline dot for labels. */ 1308 if (! ISALNUM (*t) && *t != '_' && *t != '.') 1309 { 1310 as_bad (_("unknown operand %s"), l); 1311 return 1; 1312 } 1313 t++; 1314 } 1315 1316 op->mode = OP_EXP; 1317 op->reg = 0; /* PC relative... be careful. */ 1318 op->am = 1; 1319 op->ol = 1; 1320 __tl = l; 1321 parse_exp (__tl, &(op->exp)); 1322 return 0; 1323 } 1324 while (0); 1325 1326 /* Unreachable. */ 1327 as_bad (_("unknown addressing mode for operand %s"), l); 1328 return 1; 1329 } 1330 1331 1332 /* GAS will call this function for each section at the end of the assembly, 1333 to permit the CPU backend to adjust the alignment of a section. */ 1334 1335 valueT 1336 md_section_align (seg, addr) 1337 asection *seg; 1338 valueT addr; 1339 { 1340 int align = bfd_get_section_alignment (stdoutput, seg); 1341 1342 return ((addr + (1 << align) - 1) & (-1 << align)); 1343 } 1344 1345 /* If you define this macro, it should return the offset between the 1346 address of a PC relative fixup and the position from which the PC 1347 relative adjustment should be made. On many processors, the base 1348 of a PC relative instruction is the next instruction, so this 1349 macro would return the length of an instruction. */ 1350 1351 long 1352 md_pcrel_from_section (fixp, sec) 1353 fixS *fixp; 1354 segT sec; 1355 { 1356 if (fixp->fx_addsy != (symbolS *) NULL 1357 && (!S_IS_DEFINED (fixp->fx_addsy) 1358 || (S_GET_SEGMENT (fixp->fx_addsy) != sec))) 1359 return 0; 1360 1361 return fixp->fx_frag->fr_address + fixp->fx_where; 1362 } 1363 1364 /* GAS will call this for each fixup. It should store the correct 1365 value in the object file. */ 1366 1367 void 1368 md_apply_fix3 (fixp, valuep, seg) 1369 fixS *fixp; 1370 valueT *valuep; 1371 segT seg; 1372 { 1373 unsigned char *where; 1374 unsigned long insn; 1375 long value; 1376 1377 if (fixp->fx_addsy == (symbolS *) NULL) 1378 { 1379 value = *valuep; 1380 fixp->fx_done = 1; 1381 } 1382 else if (fixp->fx_pcrel) 1383 { 1384 segT s = S_GET_SEGMENT (fixp->fx_addsy); 1385 1386 if (fixp->fx_addsy && (s == seg || s == absolute_section)) 1387 { 1388 value = S_GET_VALUE (fixp->fx_addsy) + *valuep; 1389 fixp->fx_done = 1; 1390 } 1391 else 1392 value = *valuep; 1393 } 1394 else 1395 { 1396 value = fixp->fx_offset; 1397 1398 if (fixp->fx_subsy != (symbolS *) NULL) 1399 { 1400 if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section) 1401 { 1402 value -= S_GET_VALUE (fixp->fx_subsy); 1403 fixp->fx_done = 1; 1404 } 1405 else 1406 { 1407 /* We don't actually support subtracting a symbol. */ 1408 as_bad_where (fixp->fx_file, fixp->fx_line, 1409 _("expression too complex")); 1410 } 1411 } 1412 } 1413 1414 switch (fixp->fx_r_type) 1415 { 1416 default: 1417 fixp->fx_no_overflow = 1; 1418 break; 1419 case BFD_RELOC_MSP430_10_PCREL: 1420 break; 1421 } 1422 1423 if (fixp->fx_done) 1424 { 1425 /* Fetch the instruction, insert the fully resolved operand 1426 value, and stuff the instruction back again. */ 1427 1428 where = fixp->fx_frag->fr_literal + fixp->fx_where; 1429 1430 insn = bfd_getl16 (where); 1431 1432 switch (fixp->fx_r_type) 1433 { 1434 case BFD_RELOC_MSP430_10_PCREL: 1435 if (value & 1) 1436 as_bad_where (fixp->fx_file, fixp->fx_line, 1437 _("odd address operand: %ld"), value); 1438 1439 /* Jumps are in words. */ 1440 value >>= 1; 1441 --value; /* Correct PC. */ 1442 1443 if (value < -512 || value > 511) 1444 as_bad_where (fixp->fx_file, fixp->fx_line, 1445 _("operand out of range: %ld"), value); 1446 1447 value &= 0x3ff; /* get rid of extended sign */ 1448 bfd_putl16 ((bfd_vma) (value | insn), where); 1449 break; 1450 1451 case BFD_RELOC_MSP430_16_PCREL: 1452 if (value & 1) 1453 as_bad_where (fixp->fx_file, fixp->fx_line, 1454 _("odd address operand: %ld"), value); 1455 1456 /* Nothing to be corrected here. */ 1457 if (value < -32768 || value > 65536) 1458 as_bad_where (fixp->fx_file, fixp->fx_line, 1459 _("operand out of range: %ld"), value); 1460 1461 value &= 0xffff; /* Get rid of extended sign. */ 1462 bfd_putl16 ((bfd_vma) value, where); 1463 break; 1464 1465 case BFD_RELOC_MSP430_16_PCREL_BYTE: 1466 /* Nothing to be corrected here. */ 1467 if (value < -32768 || value > 65536) 1468 as_bad_where (fixp->fx_file, fixp->fx_line, 1469 _("operand out of range: %ld"), value); 1470 1471 value &= 0xffff; /* Get rid of extended sign. */ 1472 bfd_putl16 ((bfd_vma) value, where); 1473 break; 1474 1475 case BFD_RELOC_32: 1476 bfd_putl16 ((bfd_vma) value, where); 1477 break; 1478 1479 case BFD_RELOC_MSP430_16: 1480 case BFD_RELOC_16: 1481 case BFD_RELOC_MSP430_16_BYTE: 1482 value &= 0xffff; 1483 bfd_putl16 ((bfd_vma) value, where); 1484 break; 1485 1486 default: 1487 as_fatal (_("line %d: unknown relocation type: 0x%x"), 1488 fixp->fx_line, fixp->fx_r_type); 1489 break; 1490 } 1491 } 1492 else 1493 { 1494 fixp->fx_addnumber = value; 1495 } 1496 } 1497 1498 /* A `BFD_ASSEMBLER' GAS will call this to generate a reloc. GAS 1499 will pass the resulting reloc to `bfd_install_relocation'. This 1500 currently works poorly, as `bfd_install_relocation' often does the 1501 wrong thing, and instances of `tc_gen_reloc' have been written to 1502 work around the problems, which in turns makes it difficult to fix 1503 `bfd_install_relocation'. */ 1504 1505 /* If while processing a fixup, a reloc really needs to be created 1506 then it is done here. */ 1507 1508 arelent * 1509 tc_gen_reloc (seg, fixp) 1510 asection *seg ATTRIBUTE_UNUSED; 1511 fixS *fixp; 1512 { 1513 arelent *reloc; 1514 1515 reloc = (arelent *) xmalloc (sizeof (arelent)); 1516 1517 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); 1518 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); 1519 1520 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; 1521 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); 1522 if (reloc->howto == (reloc_howto_type *) NULL) 1523 { 1524 as_bad_where (fixp->fx_file, fixp->fx_line, 1525 _("reloc %d not supported by object file format"), 1526 (int) fixp->fx_r_type); 1527 return NULL; 1528 } 1529 1530 if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT 1531 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) 1532 reloc->address = fixp->fx_offset; 1533 1534 reloc->addend = fixp->fx_offset; 1535 1536 return reloc; 1537 } 1538 1539 /* Parse ordinary expression. */ 1540 1541 static char * 1542 parse_exp (s, op) 1543 char *s; 1544 expressionS *op; 1545 { 1546 input_line_pointer = s; 1547 expression (op); 1548 if (op->X_op == O_absent) 1549 as_bad (_("missing operand")); 1550 return input_line_pointer; 1551 } 1552 1553 1554 int 1555 md_estimate_size_before_relax (fragp, seg) 1556 fragS *fragp ATTRIBUTE_UNUSED; 1557 asection *seg ATTRIBUTE_UNUSED; 1558 { 1559 abort (); 1560 return 0; 1561 } 1562