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