* lib/ld-lib.exp (run_dump_test): For options "warning" and
[deliverable/binutils-gdb.git] / gas / config / tc-msp430.c
CommitLineData
2469cfa2
NC
1/* tc-msp430.c -- Assembler code for the Texas Instruments MSP430
2
87975d2a 3 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010
20ee54e8 4 Free Software Foundation, Inc.
2469cfa2
NC
5 Contributed by Dmitry Diky <diwil@mail.ru>
6
7 This file is part of GAS, the GNU Assembler.
8
9 GAS is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
ec2655a6 11 the Free Software Foundation; either version 3, or (at your option)
2469cfa2
NC
12 any later version.
13
14 GAS is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GAS; see the file COPYING. If not, write to
4b4da160
NC
21 the Free Software Foundation, 51 Franklin Street - Fifth Floor,
22 Boston, MA 02110-1301, USA. */
2469cfa2 23
2469cfa2
NC
24#include <limits.h>
25
26#define PUSH_1X_WORKAROUND
27#include "as.h"
28#include "subsegs.h"
29#include "opcode/msp430.h"
30#include "safe-ctype.h"
2a9a06c1 31#include "dwarf2dbg.h"
2469cfa2 32
79cf5950 33/* We will disable polymorphs by default because it is dangerous.
708587a4 34 The potential problem here is the following: assume we got the
77592908
DD
35 following code:
36
37 jump .l1
38 nop
39 jump subroutine ; external symbol
40 .l1:
41 nop
42 ret
43
44 In case of assembly time relaxation we'll get:
45 0: jmp .l1 <.text +0x08> (reloc deleted)
46 2: nop
47 4: br subroutine
48 .l1:
49 8: nop
50 10: ret
51
79cf5950
NC
52 If the 'subroutine' is within +-1024 bytes range then linker
53 will produce:
77592908
DD
54 0: jmp .text +0x08
55 2: nop
56 4: jmp subroutine
57 .l1:
58 6: nop
59 8: ret ; 'jmp .text +0x08' will land here. WRONG!!!
60
77592908 61 The workaround is the following:
79cf5950 62 1. Declare global var enable_polymorphs which set to 1 via option -mp.
77592908
DD
63 2. Declare global var enable_relax which set to 1 via option -mQ.
64
65 If polymorphs are enabled, and relax isn't, treat all jumps as long jumps,
66 do not delete any relocs and leave them for linker.
67
79cf5950 68 If relax is enabled, relax at assembly time and kill relocs as necessary. */
77592908
DD
69
70int msp430_enable_relax;
71int msp430_enable_polys;
72
f5c7edf4
AM
73/* GCC uses the some condition codes which we'll
74 implement as new polymorph instructions.
75
76 COND EXPL SHORT JUMP LONG JUMP
77 ===============================================
78 eq == jeq jne +4; br lab
79 ne != jne jeq +4; br lab
80
81 ltn honours no-overflow flag
82 ltn < jn jn +2; jmp +4; br lab
83
84 lt < jl jge +4; br lab
85 ltu < jlo lhs +4; br lab
86 le <= see below
87 leu <= see below
88
89 gt > see below
90 gtu > see below
91 ge >= jge jl +4; br lab
92 geu >= jhs jlo +4; br lab
93 ===============================================
94
95 Therefore, new opcodes are (BranchEQ -> beq; and so on...)
96 beq,bne,blt,bltn,bltu,bge,bgeu
97 'u' means unsigned compares
98
99 Also, we add 'jump' instruction:
100 jump UNCOND -> jmp br lab
101
102 They will have fmt == 4, and insn_opnumb == number of instruction. */
103
104struct rcodes_s
105{
106 char * name;
107 int index; /* Corresponding insn_opnumb. */
108 int sop; /* Opcode if jump length is short. */
109 long lpos; /* Label position. */
110 long lop0; /* Opcode 1 _word_ (16 bits). */
111 long lop1; /* Opcode second word. */
112 long lop2; /* Opcode third word. */
113};
114
115#define MSP430_RLC(n,i,sop,o1) \
116 {#n, i, sop, 2, (o1 + 2), 0x4010, 0}
117
118static struct rcodes_s msp430_rcodes[] =
119{
120 MSP430_RLC (beq, 0, 0x2400, 0x2000),
121 MSP430_RLC (bne, 1, 0x2000, 0x2400),
122 MSP430_RLC (blt, 2, 0x3800, 0x3400),
123 MSP430_RLC (bltu, 3, 0x2800, 0x2c00),
124 MSP430_RLC (bge, 4, 0x3400, 0x3800),
125 MSP430_RLC (bgeu, 5, 0x2c00, 0x2800),
126 {"bltn", 6, 0x3000, 3, 0x3000 + 1, 0x3c00 + 2,0x4010},
127 {"jump", 7, 0x3c00, 1, 0x4010, 0, 0},
128 {0,0,0,0,0,0,0}
129};
130#undef MSP430_RLC
131
132
133/* More difficult than above and they have format 5.
134
135 COND EXPL SHORT LONG
136 =================================================================
137 gt > jeq +2; jge label jeq +6; jl +4; br label
138 gtu > jeq +2; jhs label jeq +6; jlo +4; br label
139 leu <= jeq label; jlo label jeq +2; jhs +4; br label
140 le <= jeq label; jl label jeq +2; jge +4; br label
141 ================================================================= */
142
143struct hcodes_s
144{
145 char * name;
146 int index; /* Corresponding insn_opnumb. */
147 int tlab; /* Number of labels in short mode. */
148 int op0; /* Opcode for first word of short jump. */
149 int op1; /* Opcode for second word of short jump. */
150 int lop0; /* Opcodes for long jump mode. */
151 int lop1;
152 int lop2;
153};
154
155static struct hcodes_s msp430_hcodes[] =
156{
157 {"bgt", 0, 1, 0x2401, 0x3400, 0x2403, 0x3802, 0x4010 },
158 {"bgtu", 1, 1, 0x2401, 0x2c00, 0x2403, 0x2802, 0x4010 },
159 {"bleu", 2, 2, 0x2400, 0x2800, 0x2401, 0x2c02, 0x4010 },
160 {"ble", 3, 2, 0x2400, 0x3800, 0x2401, 0x3402, 0x4010 },
161 {0,0,0,0,0,0,0,0}
162};
163
2469cfa2
NC
164const char comment_chars[] = ";";
165const char line_comment_chars[] = "#";
870074dd 166const char line_separator_chars[] = "{";
2469cfa2
NC
167const char EXP_CHARS[] = "eE";
168const char FLT_CHARS[] = "dD";
169
170/* Handle long expressions. */
171extern LITTLENUM_TYPE generic_bignum[];
172
173static struct hash_control *msp430_hash;
174
b18c562e
NC
175/* Relaxations. */
176#define STATE_UNCOND_BRANCH 1 /* jump */
177#define STATE_NOOV_BRANCH 3 /* bltn */
178#define STATE_SIMPLE_BRANCH 2 /* bne, beq, etc... */
179#define STATE_EMUL_BRANCH 4
180
181#define CNRL 2
182#define CUBL 4
183#define CNOL 8
184#define CSBL 6
185#define CEBL 4
186
187/* Length. */
188#define STATE_BITS10 1 /* wild guess. short jump */
189#define STATE_WORD 2 /* 2 bytes pc rel. addr. more */
190#define STATE_UNDEF 3 /* cannot handle this yet. convert to word mode */
191
192#define ENCODE_RELAX(what,length) (((what) << 2) + (length))
193#define RELAX_STATE(s) ((s) & 3)
194#define RELAX_LEN(s) ((s) >> 2)
195#define RELAX_NEXT(a,b) ENCODE_RELAX (a, b + 1)
196
197relax_typeS md_relax_table[] =
198{
199 /* Unused. */
200 {1, 1, 0, 0},
201 {1, 1, 0, 0},
202 {1, 1, 0, 0},
203 {1, 1, 0, 0},
204
205 /* Unconditional jump. */
206 {1, 1, 8, 5},
207 {1024, -1024, CNRL, RELAX_NEXT (STATE_UNCOND_BRANCH, STATE_BITS10)}, /* state 10 bits displ */
208 {0, 0, CUBL, RELAX_NEXT (STATE_UNCOND_BRANCH, STATE_WORD)}, /* state word */
209 {1, 1, CUBL, 0}, /* state undef */
210
211 /* Simple branches. */
212 {0, 0, 8, 9},
213 {1024, -1024, CNRL, RELAX_NEXT (STATE_SIMPLE_BRANCH, STATE_BITS10)}, /* state 10 bits displ */
214 {0, 0, CSBL, RELAX_NEXT (STATE_SIMPLE_BRANCH, STATE_WORD)}, /* state word */
215 {1, 1, CSBL, 0},
216
217 /* blt no overflow branch. */
218 {1, 1, 8, 13},
219 {1024, -1024, CNRL, RELAX_NEXT (STATE_NOOV_BRANCH, STATE_BITS10)}, /* state 10 bits displ */
220 {0, 0, CNOL, RELAX_NEXT (STATE_NOOV_BRANCH, STATE_WORD)}, /* state word */
221 {1, 1, CNOL, 0},
222
223 /* Emulated branches. */
224 {1, 1, 8, 17},
225 {1020, -1020, CEBL, RELAX_NEXT (STATE_EMUL_BRANCH, STATE_BITS10)}, /* state 10 bits displ */
226 {0, 0, CNOL, RELAX_NEXT (STATE_EMUL_BRANCH, STATE_WORD)}, /* state word */
227 {1, 1, CNOL, 0}
228};
229
2469cfa2 230
8cd5b113 231#define MAX_OP_LEN 256
2469cfa2
NC
232
233struct mcu_type_s
234{
b18c562e 235 char * name;
2469cfa2
NC
236 int isa;
237 int mach;
238};
239
240#define MSP430_ISA_11 11
3b260895 241#define MSP430_ISA_110 110
2469cfa2
NC
242#define MSP430_ISA_12 12
243#define MSP430_ISA_13 13
244#define MSP430_ISA_14 14
3b260895
NC
245#define MSP430_ISA_15 15
246#define MSP430_ISA_16 16
44c86e8c 247#define MSP430_ISA_21 21
2469cfa2
NC
248#define MSP430_ISA_31 31
249#define MSP430_ISA_32 32
250#define MSP430_ISA_33 33
3b260895
NC
251#define MSP430_ISA_41 41
252#define MSP430_ISA_42 42
2469cfa2
NC
253#define MSP430_ISA_43 43
254#define MSP430_ISA_44 44
2469cfa2
NC
255
256#define CHECK_RELOC_MSP430 ((imm_op || byte_op)?BFD_RELOC_MSP430_16_BYTE:BFD_RELOC_MSP430_16)
257#define CHECK_RELOC_MSP430_PCREL ((imm_op || byte_op)?BFD_RELOC_MSP430_16_PCREL_BYTE:BFD_RELOC_MSP430_16_PCREL)
258
259static struct mcu_type_s mcu_types[] =
260{
b18c562e
NC
261 {"msp1", MSP430_ISA_11, bfd_mach_msp11},
262 {"msp2", MSP430_ISA_14, bfd_mach_msp14},
263 {"msp430x110", MSP430_ISA_11, bfd_mach_msp11},
264 {"msp430x112", MSP430_ISA_11, bfd_mach_msp11},
265 {"msp430x1101", MSP430_ISA_110, bfd_mach_msp110},
266 {"msp430x1111", MSP430_ISA_110, bfd_mach_msp110},
267 {"msp430x1121", MSP430_ISA_110, bfd_mach_msp110},
268 {"msp430x1122", MSP430_ISA_11, bfd_mach_msp110},
269 {"msp430x1132", MSP430_ISA_11, bfd_mach_msp110},
270
271 {"msp430x122", MSP430_ISA_12, bfd_mach_msp12},
272 {"msp430x123", MSP430_ISA_12, bfd_mach_msp12},
273 {"msp430x1222", MSP430_ISA_12, bfd_mach_msp12},
274 {"msp430x1232", MSP430_ISA_12, bfd_mach_msp12},
275
276 {"msp430x133", MSP430_ISA_13, bfd_mach_msp13},
277 {"msp430x135", MSP430_ISA_13, bfd_mach_msp13},
278 {"msp430x1331", MSP430_ISA_13, bfd_mach_msp13},
279 {"msp430x1351", MSP430_ISA_13, bfd_mach_msp13},
280 {"msp430x147", MSP430_ISA_14, bfd_mach_msp14},
281 {"msp430x148", MSP430_ISA_14, bfd_mach_msp14},
282 {"msp430x149", MSP430_ISA_14, bfd_mach_msp14},
283
284 {"msp430x155", MSP430_ISA_15, bfd_mach_msp15},
285 {"msp430x156", MSP430_ISA_15, bfd_mach_msp15},
286 {"msp430x157", MSP430_ISA_15, bfd_mach_msp15},
287 {"msp430x167", MSP430_ISA_16, bfd_mach_msp16},
288 {"msp430x168", MSP430_ISA_16, bfd_mach_msp16},
289 {"msp430x169", MSP430_ISA_16, bfd_mach_msp16},
c05e9f04
NC
290 {"msp430x1610", MSP430_ISA_16, bfd_mach_msp16},
291 {"msp430x1611", MSP430_ISA_16, bfd_mach_msp16},
292 {"msp430x1612", MSP430_ISA_16, bfd_mach_msp16},
3b260895 293
44c86e8c
NC
294 {"msp430x2101", MSP430_ISA_21, bfd_mach_msp21},
295 {"msp430x2111", MSP430_ISA_21, bfd_mach_msp21},
296 {"msp430x2121", MSP430_ISA_21, bfd_mach_msp21},
297 {"msp430x2131", MSP430_ISA_21, bfd_mach_msp21},
298
b18c562e
NC
299 {"msp430x311", MSP430_ISA_31, bfd_mach_msp31},
300 {"msp430x312", MSP430_ISA_31, bfd_mach_msp31},
301 {"msp430x313", MSP430_ISA_31, bfd_mach_msp31},
302 {"msp430x314", MSP430_ISA_31, bfd_mach_msp31},
303 {"msp430x315", MSP430_ISA_31, bfd_mach_msp31},
304 {"msp430x323", MSP430_ISA_32, bfd_mach_msp32},
305 {"msp430x325", MSP430_ISA_32, bfd_mach_msp32},
306 {"msp430x336", MSP430_ISA_33, bfd_mach_msp33},
307 {"msp430x337", MSP430_ISA_33, bfd_mach_msp33},
308
309 {"msp430x412", MSP430_ISA_41, bfd_mach_msp41},
310 {"msp430x413", MSP430_ISA_41, bfd_mach_msp41},
311 {"msp430x415", MSP430_ISA_41, bfd_mach_msp41},
312 {"msp430x417", MSP430_ISA_41, bfd_mach_msp41},
3b260895
NC
313
314 {"msp430xE423", MSP430_ISA_42, bfd_mach_msp42},
315 {"msp430xE425", MSP430_ISA_42, bfd_mach_msp42},
316 {"msp430xE427", MSP430_ISA_42, bfd_mach_msp42},
c05e9f04 317
3b260895
NC
318 {"msp430xW423", MSP430_ISA_42, bfd_mach_msp42},
319 {"msp430xW425", MSP430_ISA_42, bfd_mach_msp42},
320 {"msp430xW427", MSP430_ISA_42, bfd_mach_msp42},
321
c05e9f04
NC
322 {"msp430xG437", MSP430_ISA_43, bfd_mach_msp43},
323 {"msp430xG438", MSP430_ISA_43, bfd_mach_msp43},
324 {"msp430xG439", MSP430_ISA_43, bfd_mach_msp43},
325
b18c562e
NC
326 {"msp430x435", MSP430_ISA_43, bfd_mach_msp43},
327 {"msp430x436", MSP430_ISA_43, bfd_mach_msp43},
328 {"msp430x437", MSP430_ISA_43, bfd_mach_msp43},
329 {"msp430x447", MSP430_ISA_44, bfd_mach_msp44},
330 {"msp430x448", MSP430_ISA_44, bfd_mach_msp44},
331 {"msp430x449", MSP430_ISA_44, bfd_mach_msp44},
2469cfa2
NC
332
333 {NULL, 0, 0}
334};
335
336
337static struct mcu_type_s default_mcu =
338 { "msp430x11", MSP430_ISA_11, bfd_mach_msp11 };
339
b18c562e
NC
340static struct mcu_type_s * msp430_mcu = & default_mcu;
341
342/* Profiling capability:
343 It is a performance hit to use gcc's profiling approach for this tiny target.
344 Even more -- jtag hardware facility does not perform any profiling functions.
345 However we've got gdb's built-in simulator where we can do anything.
346 Therefore my suggestion is:
347
348 We define new section ".profiler" which holds all profiling information.
349 We define new pseudo operation .profiler which will instruct assembler to
350 add new profile entry to the object file. Profile should take place at the
351 present address.
352
353 Pseudo-op format:
354
355 .profiler flags,function_to_profile [, cycle_corrector, extra]
356
357 where 'flags' is a combination of the following chars:
358 s - function Start
359 x - function eXit
360 i - function is in Init section
361 f - function is in Fini section
362 l - Library call
363 c - libC standard call
364 d - stack value Demand (saved at run-time in simulator)
365 I - Interrupt service routine
366 P - Prologue start
367 p - Prologue end
368 E - Epilogue start
369 e - Epilogue end
370 j - long Jump/ sjlj unwind
371 a - an Arbitrary code fragment
372 t - exTra parameter saved (constant value like frame size)
373 '""' optional: "sil" == sil
374
375 function_to_profile - function's address
376 cycle_corrector - a value which should be added to the cycle
377 counter, zero if omitted
378 extra - some extra parameter, zero if omitted.
379
380 For example:
381 ------------------------------
382 .global fxx
383 .type fxx,@function
384 fxx:
385 .LFrameOffset_fxx=0x08
386 .profiler "scdP", fxx ; function entry.
387 ; we also demand stack value to be displayed
388 push r11
389 push r10
390 push r9
391 push r8
392 .profiler "cdp",fxx,0, .LFrameOffset_fxx ; check stack value at this point
393 ; (this is a prologue end)
79cf5950 394 ; note, that spare var filled with the frame size
b18c562e
NC
395 mov r15,r8
396 ....
397 .profiler cdE,fxx ; check stack
398 pop r8
399 pop r9
400 pop r10
401 pop r11
402 .profiler xcde,fxx,3 ; exit adds 3 to the cycle counter
403 ret ; cause 'ret' insn takes 3 cycles
404 -------------------------------
405
406 This profiling approach does not produce any overhead and
407 absolutely harmless.
408 So, even profiled code can be uploaded to the MCU. */
409#define MSP430_PROFILER_FLAG_ENTRY 1 /* s */
410#define MSP430_PROFILER_FLAG_EXIT 2 /* x */
411#define MSP430_PROFILER_FLAG_INITSECT 4 /* i */
412#define MSP430_PROFILER_FLAG_FINISECT 8 /* f */
413#define MSP430_PROFILER_FLAG_LIBCALL 0x10 /* l */
414#define MSP430_PROFILER_FLAG_STDCALL 0x20 /* c */
415#define MSP430_PROFILER_FLAG_STACKDMD 0x40 /* d */
416#define MSP430_PROFILER_FLAG_ISR 0x80 /* I */
417#define MSP430_PROFILER_FLAG_PROLSTART 0x100 /* P */
418#define MSP430_PROFILER_FLAG_PROLEND 0x200 /* p */
419#define MSP430_PROFILER_FLAG_EPISTART 0x400 /* E */
420#define MSP430_PROFILER_FLAG_EPIEND 0x800 /* e */
421#define MSP430_PROFILER_FLAG_JUMP 0x1000 /* j */
422#define MSP430_PROFILER_FLAG_FRAGMENT 0x2000 /* a */
423#define MSP430_PROFILER_FLAG_EXTRA 0x4000 /* t */
424#define MSP430_PROFILER_FLAG_notyet 0x8000 /* ? */
2469cfa2 425
b18c562e
NC
426static int
427pow2value (int y)
2469cfa2 428{
b18c562e
NC
429 int n = 0;
430 unsigned int x;
2469cfa2 431
b18c562e 432 x = y;
2469cfa2 433
b18c562e
NC
434 if (!x)
435 return 1;
2469cfa2 436
b18c562e
NC
437 for (; x; x = x >> 1)
438 if (x & 1)
439 n++;
440
441 return n == 1;
442}
443
444/* Parse ordinary expression. */
445
446static char *
447parse_exp (char * s, expressionS * op)
2469cfa2 448{
b18c562e
NC
449 input_line_pointer = s;
450 expression (op);
451 if (op->X_op == O_absent)
452 as_bad (_("missing operand"));
453 return input_line_pointer;
454}
2469cfa2 455
b18c562e
NC
456
457/* Delete spaces from s: X ( r 1 2) => X(r12). */
2469cfa2
NC
458
459static void
b18c562e 460del_spaces (char * s)
2469cfa2 461{
b18c562e
NC
462 while (*s)
463 {
464 if (ISSPACE (*s))
465 {
466 char *m = s + 1;
2469cfa2 467
b18c562e
NC
468 while (ISSPACE (*m) && *m)
469 m++;
470 memmove (s, m, strlen (m) + 1);
471 }
472 else
473 s++;
474 }
475}
2469cfa2 476
b18c562e
NC
477static inline char *
478skip_space (char * s)
479{
480 while (ISSPACE (*s))
481 ++s;
482 return s;
483}
2469cfa2 484
708587a4 485/* Extract one word from FROM and copy it to TO. Delimiters are ",;\n" */
b18c562e
NC
486
487static char *
488extract_operand (char * from, char * to, int limit)
489{
490 int size = 0;
491
492 /* Drop leading whitespace. */
493 from = skip_space (from);
494
495 while (size < limit && *from)
496 {
497 *(to + size) = *from;
498 if (*from == ',' || *from == ';' || *from == '\n')
499 break;
500 from++;
501 size++;
502 }
503
504 *(to + size) = 0;
505 del_spaces (to);
506
507 from++;
508
509 return from;
2469cfa2
NC
510}
511
b18c562e
NC
512static void
513msp430_profiler (int dummy ATTRIBUTE_UNUSED)
2469cfa2 514{
b18c562e
NC
515 char buffer[1024];
516 char f[32];
517 char * str = buffer;
518 char * flags = f;
519 int p_flags = 0;
520 char * halt;
521 int ops = 0;
522 int left;
523 char * s;
524 segT seg;
525 int subseg;
526 char * end = 0;
527 expressionS exp;
528 expressionS exp1;
529
530 s = input_line_pointer;
531 end = input_line_pointer;
532
533 while (*end && *end != '\n')
534 end++;
535
536 while (*s && *s != '\n')
537 {
538 if (*s == ',')
539 ops++;
540 s++;
541 }
2469cfa2 542
b18c562e
NC
543 left = 3 - ops;
544
545 if (ops < 1)
546 {
547 as_bad (_(".profiler pseudo requires at least two operands."));
548 input_line_pointer = end;
549 return;
550 }
551
552 input_line_pointer = extract_operand (input_line_pointer, flags, 32);
553
554 while (*flags)
555 {
556 switch (*flags)
557 {
558 case '"':
559 break;
560 case 'a':
561 p_flags |= MSP430_PROFILER_FLAG_FRAGMENT;
562 break;
563 case 'j':
564 p_flags |= MSP430_PROFILER_FLAG_JUMP;
565 break;
566 case 'P':
567 p_flags |= MSP430_PROFILER_FLAG_PROLSTART;
568 break;
569 case 'p':
570 p_flags |= MSP430_PROFILER_FLAG_PROLEND;
571 break;
572 case 'E':
573 p_flags |= MSP430_PROFILER_FLAG_EPISTART;
574 break;
575 case 'e':
576 p_flags |= MSP430_PROFILER_FLAG_EPIEND;
577 break;
578 case 's':
579 p_flags |= MSP430_PROFILER_FLAG_ENTRY;
580 break;
581 case 'x':
582 p_flags |= MSP430_PROFILER_FLAG_EXIT;
583 break;
584 case 'i':
585 p_flags |= MSP430_PROFILER_FLAG_INITSECT;
586 break;
587 case 'f':
588 p_flags |= MSP430_PROFILER_FLAG_FINISECT;
589 break;
590 case 'l':
591 p_flags |= MSP430_PROFILER_FLAG_LIBCALL;
592 break;
593 case 'c':
594 p_flags |= MSP430_PROFILER_FLAG_STDCALL;
595 break;
596 case 'd':
597 p_flags |= MSP430_PROFILER_FLAG_STACKDMD;
598 break;
599 case 'I':
600 p_flags |= MSP430_PROFILER_FLAG_ISR;
601 break;
602 case 't':
603 p_flags |= MSP430_PROFILER_FLAG_EXTRA;
604 break;
605 default:
606 as_warn (_("unknown profiling flag - ignored."));
607 break;
608 }
609 flags++;
610 }
611
612 if (p_flags
613 && ( ! pow2value (p_flags & ( MSP430_PROFILER_FLAG_ENTRY
614 | MSP430_PROFILER_FLAG_EXIT))
615 || ! pow2value (p_flags & ( MSP430_PROFILER_FLAG_PROLSTART
616 | MSP430_PROFILER_FLAG_PROLEND
617 | MSP430_PROFILER_FLAG_EPISTART
618 | MSP430_PROFILER_FLAG_EPIEND))
619 || ! pow2value (p_flags & ( MSP430_PROFILER_FLAG_INITSECT
620 | MSP430_PROFILER_FLAG_FINISECT))))
621 {
79cf5950 622 as_bad (_("ambiguous flags combination - '.profiler' directive ignored."));
b18c562e
NC
623 input_line_pointer = end;
624 return;
625 }
626
627 /* Generate temp symbol which denotes current location. */
79cf5950 628 if (now_seg == absolute_section) /* Paranoia ? */
b18c562e
NC
629 {
630 exp1.X_op = O_constant;
631 exp1.X_add_number = abs_section_offset;
79cf5950 632 as_warn (_("profiling in absolute section?"));
b18c562e
NC
633 }
634 else
635 {
636 exp1.X_op = O_symbol;
637 exp1.X_add_symbol = symbol_temp_new_now ();
638 exp1.X_add_number = 0;
639 }
640
641 /* Generate a symbol which holds flags value. */
642 exp.X_op = O_constant;
643 exp.X_add_number = p_flags;
644
645 /* Save current section. */
646 seg = now_seg;
647 subseg = now_subseg;
648
649 /* Now go to .profiler section. */
650 obj_elf_change_section (".profiler", SHT_PROGBITS, 0, 0, 0, 0, 0);
651
652 /* Save flags. */
653 emit_expr (& exp, 2);
654
655 /* Save label value. */
656 emit_expr (& exp1, 2);
657
658 while (ops--)
659 {
660 /* Now get profiling info. */
661 halt = extract_operand (input_line_pointer, str, 1024);
662 /* Process like ".word xxx" directive. */
663 parse_exp (str, & exp);
664 emit_expr (& exp, 2);
665 input_line_pointer = halt;
666 }
667
668 /* Fill the rest with zeros. */
669 exp.X_op = O_constant;
670 exp.X_add_number = 0;
671 while (left--)
672 emit_expr (& exp, 2);
673
674 /* Return to current section. */
675 subseg_set (seg, subseg);
2469cfa2
NC
676}
677
678static char *
b18c562e 679extract_word (char * from, char * to, int limit)
2469cfa2 680{
2469cfa2
NC
681 char *op_end;
682 int size = 0;
683
684 /* Drop leading whitespace. */
685 from = skip_space (from);
686 *to = 0;
687
688 /* Find the op code end. */
87975d2a 689 for (op_end = from; *op_end != 0 && is_part_of_name (*op_end);)
2469cfa2
NC
690 {
691 to[size++] = *op_end++;
692 if (size + 1 >= limit)
693 break;
694 }
695
696 to[size] = 0;
697 return op_end;
698}
699
b18c562e 700#define OPTION_MMCU 'm'
77592908
DD
701#define OPTION_RELAX 'Q'
702#define OPTION_POLYMORPHS 'P'
b18c562e 703
2469cfa2 704static void
b18c562e 705msp430_set_arch (int dummy ATTRIBUTE_UNUSED)
2469cfa2
NC
706{
707 char *str = (char *) alloca (32); /* 32 for good measure. */
708
709 input_line_pointer = extract_word (input_line_pointer, str, 32);
710
711 md_parse_option (OPTION_MMCU, str);
712 bfd_set_arch_mach (stdoutput, TARGET_ARCH, msp430_mcu->mach);
713}
714
b18c562e
NC
715static void
716show_mcu_list (FILE * stream)
717{
718 int i;
719
720 fprintf (stream, _("Known MCU names:\n"));
721
722 for (i = 0; mcu_types[i].name; i++)
723 fprintf (stream, _("\t %s\n"), mcu_types[i].name);
724
725 fprintf (stream, "\n");
726}
727
2469cfa2 728int
b18c562e 729md_parse_option (int c, char * arg)
2469cfa2
NC
730{
731 int i;
732
733 switch (c)
734 {
735 case OPTION_MMCU:
736 for (i = 0; mcu_types[i].name; ++i)
737 if (strcmp (mcu_types[i].name, arg) == 0)
738 break;
739
740 if (!mcu_types[i].name)
741 {
742 show_mcu_list (stderr);
743 as_fatal (_("unknown MCU: %s\n"), arg);
744 }
745
746 if (msp430_mcu == &default_mcu || msp430_mcu->mach == mcu_types[i].mach)
747 msp430_mcu = &mcu_types[i];
748 else
749 as_fatal (_("redefinition of mcu type %s' to %s'"),
750 msp430_mcu->name, mcu_types[i].name);
751 return 1;
77592908
DD
752 break;
753
754 case OPTION_RELAX:
755 msp430_enable_relax = 1;
756 return 1;
757 break;
758
759 case OPTION_POLYMORPHS:
760 msp430_enable_polys = 1;
761 return 1;
762 break;
2469cfa2
NC
763 }
764
765 return 0;
766}
767
2469cfa2 768
b18c562e 769const pseudo_typeS md_pseudo_table[] =
2469cfa2 770{
b18c562e
NC
771 {"arch", msp430_set_arch, 0},
772 {"profiler", msp430_profiler, 0},
773 {NULL, NULL, 0}
774};
2469cfa2 775
b18c562e 776const char *md_shortopts = "m:";
2469cfa2 777
b18c562e 778struct option md_longopts[] =
2469cfa2 779{
b18c562e 780 {"mmcu", required_argument, NULL, OPTION_MMCU},
77592908
DD
781 {"mP", no_argument, NULL, OPTION_POLYMORPHS},
782 {"mQ", no_argument, NULL, OPTION_RELAX},
b18c562e
NC
783 {NULL, no_argument, NULL, 0}
784};
2469cfa2 785
b18c562e 786size_t md_longopts_size = sizeof (md_longopts);
2469cfa2 787
b18c562e
NC
788void
789md_show_usage (FILE * stream)
2469cfa2 790{
b18c562e
NC
791 fprintf (stream,
792 _("MSP430 options:\n"
793 " -mmcu=[msp430-name] select microcontroller type\n"
794 " msp430x110 msp430x112\n"
795 " msp430x1101 msp430x1111\n"
796 " msp430x1121 msp430x1122 msp430x1132\n"
797 " msp430x122 msp430x123\n"
798 " msp430x1222 msp430x1232\n"
799 " msp430x133 msp430x135\n"
800 " msp430x1331 msp430x1351\n"
801 " msp430x147 msp430x148 msp430x149\n"
802 " msp430x155 msp430x156 msp430x157\n"
803 " msp430x167 msp430x168 msp430x169\n"
804 " msp430x1610 msp430x1611 msp430x1612\n"
805 " msp430x311 msp430x312 msp430x313 msp430x314 msp430x315\n"
806 " msp430x323 msp430x325\n"
807 " msp430x336 msp430x337\n"
808 " msp430x412 msp430x413 msp430x415 msp430x417\n"
809 " msp430xE423 msp430xE425 msp430E427\n"
810 " msp430xW423 msp430xW425 msp430W427\n"
811 " msp430xG437 msp430xG438 msp430G439\n"
812 " msp430x435 msp430x436 msp430x437\n"
813 " msp430x447 msp430x448 msp430x449\n"));
77592908
DD
814 fprintf (stream,
815 _(" -mQ - enable relaxation at assembly time. DANGEROUS!\n"
816 " -mP - enable polymorph instructions\n"));
2469cfa2 817
b18c562e
NC
818 show_mcu_list (stream);
819}
2469cfa2 820
b18c562e
NC
821symbolS *
822md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
823{
824 return 0;
2469cfa2
NC
825}
826
827static char *
b18c562e 828extract_cmd (char * from, char * to, int limit)
2469cfa2
NC
829{
830 int size = 0;
831
832 while (*from && ! ISSPACE (*from) && *from != '.' && limit > size)
833 {
834 *(to + size) = *from;
835 from++;
836 size++;
837 }
838
839 *(to + size) = 0;
840
841 return from;
842}
843
2469cfa2 844char *
b18c562e 845md_atof (int type, char * litP, int * sizeP)
2469cfa2 846{
499ac353 847 return ieee_md_atof (type, litP, sizeP, FALSE);
2469cfa2
NC
848}
849
850void
b18c562e 851md_begin (void)
2469cfa2 852{
b18c562e 853 struct msp430_opcode_s * opcode;
2469cfa2
NC
854 msp430_hash = hash_new ();
855
856 for (opcode = msp430_opcodes; opcode->name; opcode++)
857 hash_insert (msp430_hash, opcode->name, (char *) opcode);
858
859 bfd_set_arch_mach (stdoutput, TARGET_ARCH, msp430_mcu->mach);
860}
861
b18c562e
NC
862static int
863check_reg (char * t)
2469cfa2 864{
b18c562e 865 /* If this is a reg numb, str 't' must be a number from 0 - 15. */
2469cfa2 866
b18c562e
NC
867 if (strlen (t) > 2 && *(t + 2) != '+')
868 return 1;
2469cfa2 869
b18c562e 870 while (*t)
2469cfa2 871 {
b18c562e
NC
872 if ((*t < '0' || *t > '9') && *t != '+')
873 break;
874 t++;
2469cfa2
NC
875 }
876
b18c562e
NC
877 if (*t)
878 return 1;
2469cfa2 879
b18c562e 880 return 0;
2469cfa2
NC
881}
882
2469cfa2 883
b18c562e
NC
884static int
885msp430_srcoperand (struct msp430_operand_s * op,
886 char * l, int bin, int * imm_op)
2469cfa2 887{
b18c562e 888 char *__tl = l;
2469cfa2 889
b18c562e
NC
890 /* Check if an immediate #VALUE. The hash sign should be only at the beginning! */
891 if (*l == '#')
2469cfa2 892 {
b18c562e
NC
893 char *h = l;
894 int vshift = -1;
895 int rval = 0;
2469cfa2 896
b18c562e
NC
897 /* Check if there is:
898 llo(x) - least significant 16 bits, x &= 0xffff
899 lhi(x) - x = (x >> 16) & 0xffff,
900 hlo(x) - x = (x >> 32) & 0xffff,
901 hhi(x) - x = (x >> 48) & 0xffff
902 The value _MUST_ be constant expression: #hlo(1231231231). */
2469cfa2 903
b18c562e 904 *imm_op = 1;
2469cfa2 905
b18c562e
NC
906 if (strncasecmp (h, "#llo(", 5) == 0)
907 {
908 vshift = 0;
909 rval = 3;
910 }
911 else if (strncasecmp (h, "#lhi(", 5) == 0)
912 {
913 vshift = 1;
914 rval = 3;
915 }
916 else if (strncasecmp (h, "#hlo(", 5) == 0)
917 {
918 vshift = 2;
919 rval = 3;
920 }
921 else if (strncasecmp (h, "#hhi(", 5) == 0)
922 {
923 vshift = 3;
924 rval = 3;
925 }
926 else if (strncasecmp (h, "#lo(", 4) == 0)
927 {
928 vshift = 0;
929 rval = 2;
930 }
931 else if (strncasecmp (h, "#hi(", 4) == 0)
932 {
933 vshift = 1;
934 rval = 2;
935 }
2469cfa2 936
b18c562e
NC
937 op->reg = 0; /* Reg PC. */
938 op->am = 3;
939 op->ol = 1; /* Immediate will follow an instruction. */
940 __tl = h + 1 + rval;
941 op->mode = OP_EXP;
2469cfa2 942
b18c562e
NC
943 parse_exp (__tl, &(op->exp));
944 if (op->exp.X_op == O_constant)
2469cfa2 945 {
b18c562e 946 int x = op->exp.X_add_number;
2469cfa2 947
b18c562e 948 if (vshift == 0)
2469cfa2 949 {
b18c562e
NC
950 x = x & 0xffff;
951 op->exp.X_add_number = x;
952 }
953 else if (vshift == 1)
954 {
955 x = (x >> 16) & 0xffff;
956 op->exp.X_add_number = x;
957 }
958 else if (vshift > 1)
959 {
960 if (x < 0)
961 op->exp.X_add_number = -1;
2469cfa2 962 else
b18c562e
NC
963 op->exp.X_add_number = 0; /* Nothing left. */
964 x = op->exp.X_add_number;
2469cfa2 965 }
2469cfa2 966
b18c562e
NC
967 if (op->exp.X_add_number > 65535 || op->exp.X_add_number < -32768)
968 {
969 as_bad (_("value %d out of range. Use #lo() or #hi()"), x);
970 return 1;
971 }
2469cfa2 972
b18c562e
NC
973 /* Now check constants. */
974 /* Substitute register mode with a constant generator if applicable. */
2469cfa2 975
b18c562e 976 x = (short) x; /* Extend sign. */
2469cfa2 977
b18c562e 978 if (x == 0)
2469cfa2 979 {
b18c562e
NC
980 op->reg = 3;
981 op->am = 0;
982 op->ol = 0;
983 op->mode = OP_REG;
984 }
985 else if (x == 1)
986 {
987 op->reg = 3;
988 op->am = 1;
989 op->ol = 0;
990 op->mode = OP_REG;
991 }
992 else if (x == 2)
993 {
994 op->reg = 3;
995 op->am = 2;
996 op->ol = 0;
997 op->mode = OP_REG;
998 }
999 else if (x == -1)
1000 {
1001 op->reg = 3;
1002 op->am = 3;
1003 op->ol = 0;
1004 op->mode = OP_REG;
1005 }
1006 else if (x == 4)
1007 {
1008#ifdef PUSH_1X_WORKAROUND
1009 if (bin == 0x1200)
1010 {
1011 /* Remove warning as confusing.
20203fb9 1012 as_warn (_("Hardware push bug workaround")); */
b18c562e
NC
1013 }
1014 else
1015#endif
1016 {
1017 op->reg = 2;
1018 op->am = 2;
1019 op->ol = 0;
1020 op->mode = OP_REG;
1021 }
1022 }
1023 else if (x == 8)
1024 {
1025#ifdef PUSH_1X_WORKAROUND
1026 if (bin == 0x1200)
1027 {
1028 /* Remove warning as confusing.
20203fb9 1029 as_warn (_("Hardware push bug workaround")); */
b18c562e
NC
1030 }
1031 else
1032#endif
1033 {
1034 op->reg = 2;
1035 op->am = 3;
1036 op->ol = 0;
1037 op->mode = OP_REG;
1038 }
2469cfa2 1039 }
2469cfa2 1040 }
b18c562e
NC
1041 else if (op->exp.X_op == O_symbol)
1042 {
1043 op->mode = OP_EXP;
1044 }
1045 else if (op->exp.X_op == O_big)
1046 {
1047 short x;
1048 if (vshift != -1)
1049 {
1050 op->exp.X_op = O_constant;
1051 op->exp.X_add_number = 0xffff & generic_bignum[vshift];
1052 x = op->exp.X_add_number;
1053 }
1054 else
1055 {
1056 as_bad (_
1057 ("unknown expression in operand %s. use #llo() #lhi() #hlo() #hhi() "),
1058 l);
1059 return 1;
1060 }
2469cfa2 1061
b18c562e
NC
1062 if (x == 0)
1063 {
1064 op->reg = 3;
1065 op->am = 0;
1066 op->ol = 0;
1067 op->mode = OP_REG;
1068 }
1069 else if (x == 1)
1070 {
1071 op->reg = 3;
1072 op->am = 1;
1073 op->ol = 0;
1074 op->mode = OP_REG;
1075 }
1076 else if (x == 2)
1077 {
1078 op->reg = 3;
1079 op->am = 2;
1080 op->ol = 0;
1081 op->mode = OP_REG;
1082 }
1083 else if (x == -1)
1084 {
1085 op->reg = 3;
1086 op->am = 3;
1087 op->ol = 0;
1088 op->mode = OP_REG;
1089 }
1090 else if (x == 4)
1091 {
1092 op->reg = 2;
1093 op->am = 2;
1094 op->ol = 0;
1095 op->mode = OP_REG;
1096 }
1097 else if (x == 8)
1098 {
1099 op->reg = 2;
1100 op->am = 3;
1101 op->ol = 0;
1102 op->mode = OP_REG;
1103 }
1104 }
79cf5950 1105 /* Redundant (yet) check. */
b18c562e
NC
1106 else if (op->exp.X_op == O_register)
1107 as_bad
1108 (_("Registers cannot be used within immediate expression [%s]"), l);
1109 else
1110 as_bad (_("unknown operand %s"), l);
2469cfa2 1111
b18c562e
NC
1112 return 0;
1113 }
2469cfa2 1114
b18c562e
NC
1115 /* Check if absolute &VALUE (assume that we can construct something like ((a&b)<<7 + 25). */
1116 if (*l == '&')
1117 {
1118 char *h = l;
2469cfa2 1119
b18c562e
NC
1120 op->reg = 2; /* reg 2 in absolute addr mode. */
1121 op->am = 1; /* mode As == 01 bin. */
1122 op->ol = 1; /* Immediate value followed by instruction. */
1123 __tl = h + 1;
1124 parse_exp (__tl, &(op->exp));
1125 op->mode = OP_EXP;
1126 if (op->exp.X_op == O_constant)
2469cfa2 1127 {
b18c562e 1128 int x = op->exp.X_add_number;
2469cfa2 1129
b18c562e
NC
1130 if (x > 65535 || x < -32768)
1131 {
1132 as_bad (_("value out of range: %d"), x);
1133 return 1;
1134 }
2469cfa2 1135 }
b18c562e
NC
1136 else if (op->exp.X_op == O_symbol)
1137 ;
1138 else
2469cfa2 1139 {
79cf5950 1140 /* Redundant (yet) check. */
b18c562e
NC
1141 if (op->exp.X_op == O_register)
1142 as_bad
1143 (_("Registers cannot be used within absolute expression [%s]"), l);
2469cfa2 1144 else
b18c562e
NC
1145 as_bad (_("unknown expression in operand %s"), l);
1146 return 1;
2469cfa2 1147 }
b18c562e
NC
1148 return 0;
1149 }
2469cfa2 1150
b18c562e
NC
1151 /* Check if indirect register mode @Rn / postincrement @Rn+. */
1152 if (*l == '@')
1153 {
1154 char *t = l;
1155 char *m = strchr (l, '+');
1156
1157 if (t != l)
2469cfa2 1158 {
b18c562e
NC
1159 as_bad (_("unknown addressing mode %s"), l);
1160 return 1;
2469cfa2
NC
1161 }
1162
b18c562e
NC
1163 t++;
1164 if (*t != 'r' && *t != 'R')
1165 {
1166 as_bad (_("unknown addressing mode %s"), l);
1167 return 1;
1168 }
2469cfa2 1169
b18c562e 1170 t++; /* Points to the reg value. */
2469cfa2 1171
b18c562e 1172 if (check_reg (t))
2469cfa2 1173 {
b18c562e
NC
1174 as_bad (_("Bad register name r%s"), t);
1175 return 1;
2469cfa2 1176 }
2469cfa2 1177
b18c562e
NC
1178 op->mode = OP_REG;
1179 op->am = m ? 3 : 2;
1180 op->ol = 0;
1181 if (m)
1182 *m = 0; /* strip '+' */
1183 op->reg = atoi (t);
1184 if (op->reg < 0 || op->reg > 15)
2469cfa2 1185 {
b18c562e
NC
1186 as_bad (_("MSP430 does not have %d registers"), op->reg);
1187 return 1;
1188 }
2469cfa2 1189
b18c562e
NC
1190 return 0;
1191 }
2469cfa2 1192
b18c562e
NC
1193 /* Check if register indexed X(Rn). */
1194 do
1195 {
1196 char *h = strrchr (l, '(');
1197 char *m = strrchr (l, ')');
1198 char *t;
2469cfa2 1199
b18c562e 1200 *imm_op = 1;
2469cfa2 1201
b18c562e
NC
1202 if (!h)
1203 break;
1204 if (!m)
1205 {
1206 as_bad (_("')' required"));
1207 return 1;
1208 }
2469cfa2 1209
b18c562e
NC
1210 t = h;
1211 op->am = 1;
1212 op->ol = 1;
1213 /* Extract a register. */
1214 t++; /* Advance pointer. */
2469cfa2 1215
b18c562e
NC
1216 if (*t != 'r' && *t != 'R')
1217 {
1218 as_bad (_
1219 ("unknown operator %s. Did you mean X(Rn) or #[hl][hl][oi](CONST) ?"),
1220 l);
1221 return 1;
1222 }
1223 t++;
2469cfa2 1224
b18c562e
NC
1225 op->reg = *t - '0';
1226 if (op->reg > 9 || op->reg < 0)
1227 {
79cf5950 1228 as_bad (_("unknown operator (r%s substituted as a register name"),
b18c562e
NC
1229 t);
1230 return 1;
1231 }
1232 t++;
1233 if (*t != ')')
1234 {
1235 op->reg = op->reg * 10;
1236 op->reg += *t - '0';
2469cfa2 1237
b18c562e 1238 if (op->reg > 15)
2469cfa2 1239 {
b18c562e
NC
1240 as_bad (_("unknown operator %s"), l);
1241 return 1;
2469cfa2 1242 }
b18c562e 1243 if (op->reg == 2)
2469cfa2 1244 {
b18c562e
NC
1245 as_bad (_("r2 should not be used in indexed addressing mode"));
1246 return 1;
1247 }
2469cfa2 1248
b18c562e
NC
1249 if (*(t + 1) != ')')
1250 {
1251 as_bad (_("unknown operator %s"), l);
1252 return 1;
2469cfa2 1253 }
b18c562e
NC
1254 }
1255
1256 /* Extract constant. */
1257 __tl = l;
1258 *h = 0;
1259 op->mode = OP_EXP;
1260 parse_exp (__tl, &(op->exp));
1261 if (op->exp.X_op == O_constant)
1262 {
1263 int x = op->exp.X_add_number;
1264
1265 if (x > 65535 || x < -32768)
2469cfa2 1266 {
b18c562e
NC
1267 as_bad (_("value out of range: %d"), x);
1268 return 1;
2469cfa2 1269 }
b18c562e
NC
1270
1271 if (x == 0)
2469cfa2 1272 {
b18c562e
NC
1273 op->mode = OP_REG;
1274 op->am = 2;
1275 op->ol = 0;
1276 return 0;
2469cfa2
NC
1277 }
1278 }
b18c562e
NC
1279 else if (op->exp.X_op == O_symbol)
1280 ;
2469cfa2
NC
1281 else
1282 {
79cf5950 1283 /* Redundant (yet) check. */
b18c562e
NC
1284 if (op->exp.X_op == O_register)
1285 as_bad
1286 (_("Registers cannot be used as a prefix of indexed expression [%s]"), l);
1287 else
1288 as_bad (_("unknown expression in operand %s"), l);
1289 return 1;
2469cfa2 1290 }
2469cfa2 1291
b18c562e 1292 return 0;
2469cfa2 1293 }
b18c562e 1294 while (0);
2469cfa2 1295
b18c562e
NC
1296 /* Register mode 'mov r1,r2'. */
1297 do
1298 {
1299 char *t = l;
1300
1301 /* Operand should be a register. */
1302 if (*t == 'r' || *t == 'R')
1303 {
1304 int x = atoi (t + 1);
1305
1306 if (check_reg (t + 1))
1307 break;
1308
1309 if (x < 0 || x > 15)
1310 break; /* Symbolic mode. */
1311
1312 op->mode = OP_REG;
1313 op->am = 0;
1314 op->ol = 0;
1315 op->reg = x;
1316 return 0;
1317 }
1318 }
1319 while (0);
1320
1321 /* Symbolic mode 'mov a, b' == 'mov x(pc), y(pc)'. */
1322 do
1323 {
b18c562e
NC
1324 op->mode = OP_EXP;
1325 op->reg = 0; /* PC relative... be careful. */
1326 op->am = 1;
1327 op->ol = 1;
1328 __tl = l;
1329 parse_exp (__tl, &(op->exp));
1330 return 0;
1331 }
1332 while (0);
1333
1334 /* Unreachable. */
1335 as_bad (_("unknown addressing mode for operand %s"), l);
1336 return 1;
2469cfa2
NC
1337}
1338
b18c562e 1339
2469cfa2 1340static int
b18c562e 1341msp430_dstoperand (struct msp430_operand_s * op, char * l, int bin)
2469cfa2
NC
1342{
1343 int dummy;
b18c562e
NC
1344 int ret = msp430_srcoperand (op, l, bin, & dummy);
1345
2469cfa2
NC
1346 if (ret)
1347 return ret;
1348
1349 if (op->am == 2)
1350 {
1351 char *__tl = "0";
1352
1353 op->mode = OP_EXP;
1354 op->am = 1;
1355 op->ol = 1;
1356 parse_exp (__tl, &(op->exp));
b18c562e 1357
2469cfa2
NC
1358 if (op->exp.X_op != O_constant || op->exp.X_add_number != 0)
1359 {
1360 as_bad (_("Internal bug. Try to use 0(r%d) instead of @r%d"),
1361 op->reg, op->reg);
1362 return 1;
1363 }
1364 return 0;
1365 }
1366
1367 if (op->am > 1)
1368 {
1369 as_bad (_
1370 ("this addressing mode is not applicable for destination operand"));
1371 return 1;
1372 }
1373 return 0;
1374}
1375
1376
b18c562e
NC
1377/* Parse instruction operands.
1378 Return binary opcode. */
1379
1380static unsigned int
1381msp430_operands (struct msp430_opcode_s * opcode, char * line)
2469cfa2 1382{
b18c562e 1383 int bin = opcode->bin_opcode; /* Opcode mask. */
2a9a06c1 1384 int __is = 0;
b18c562e
NC
1385 char l1[MAX_OP_LEN], l2[MAX_OP_LEN];
1386 char *frag;
1387 int where;
1388 struct msp430_operand_s op1, op2;
1389 int res = 0;
1390 static short ZEROS = 0;
1391 int byte_op, imm_op;
2469cfa2 1392
b18c562e
NC
1393 /* Opcode is the one from opcodes table
1394 line contains something like
1395 [.w] @r2+, 5(R1)
1396 or
1397 .b @r2+, 5(R1). */
2469cfa2 1398
b18c562e
NC
1399 /* Check if byte or word operation. */
1400 if (*line == '.' && TOLOWER (*(line + 1)) == 'b')
2469cfa2 1401 {
b18c562e
NC
1402 bin |= BYTE_OPERATION;
1403 byte_op = 1;
2469cfa2 1404 }
b18c562e
NC
1405 else
1406 byte_op = 0;
2469cfa2 1407
b18c562e
NC
1408 /* skip .[bwBW]. */
1409 while (! ISSPACE (*line) && *line)
1410 line++;
2469cfa2 1411
b18c562e 1412 if (opcode->insn_opnumb && (!*line || *line == '\n'))
2469cfa2 1413 {
b18c562e
NC
1414 as_bad (_("instruction %s requires %d operand(s)"),
1415 opcode->name, opcode->insn_opnumb);
1416 return 0;
1417 }
2469cfa2 1418
b18c562e
NC
1419 memset (l1, 0, sizeof (l1));
1420 memset (l2, 0, sizeof (l2));
1421 memset (&op1, 0, sizeof (op1));
1422 memset (&op2, 0, sizeof (op2));
2469cfa2 1423
b18c562e 1424 imm_op = 0;
2469cfa2 1425
b18c562e
NC
1426 switch (opcode->fmt)
1427 {
1428 case 0: /* Emulated. */
1429 switch (opcode->insn_opnumb)
2469cfa2 1430 {
b18c562e
NC
1431 case 0:
1432 /* Set/clear bits instructions. */
1433 __is = 2;
1434 frag = frag_more (__is);
1435 bfd_putl16 ((bfd_vma) bin, frag);
2a9a06c1 1436 dwarf2_emit_insn (__is);
b18c562e
NC
1437 break;
1438 case 1:
1439 /* Something which works with destination operand. */
1440 line = extract_operand (line, l1, sizeof (l1));
1441 res = msp430_dstoperand (&op1, l1, opcode->bin_opcode);
1442 if (res)
1443 break;
2469cfa2 1444
b18c562e
NC
1445 bin |= (op1.reg | (op1.am << 7));
1446 __is = 1 + op1.ol;
1447 frag = frag_more (2 * __is);
1448 where = frag - frag_now->fr_literal;
1449 bfd_putl16 ((bfd_vma) bin, frag);
2a9a06c1 1450 dwarf2_emit_insn (2 * __is);
2469cfa2 1451
b18c562e 1452 if (op1.mode == OP_EXP)
2469cfa2 1453 {
b18c562e
NC
1454 where += 2;
1455 bfd_putl16 ((bfd_vma) ZEROS, frag + 2);
1456
1457 if (op1.reg)
1458 fix_new_exp (frag_now, where, 2,
1459 &(op1.exp), FALSE, CHECK_RELOC_MSP430);
2469cfa2 1460 else
b18c562e
NC
1461 fix_new_exp (frag_now, where, 2,
1462 &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
2469cfa2 1463 }
b18c562e 1464 break;
2469cfa2 1465
b18c562e
NC
1466 case 2:
1467 {
1468 /* Shift instruction. */
1469 line = extract_operand (line, l1, sizeof (l1));
1470 strncpy (l2, l1, sizeof (l2));
1471 l2[sizeof (l2) - 1] = '\0';
1472 res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op);
1473 res += msp430_dstoperand (&op2, l2, opcode->bin_opcode);
2469cfa2 1474
b18c562e
NC
1475 if (res)
1476 break; /* An error occurred. All warnings were done before. */
2469cfa2 1477
b18c562e 1478 bin |= (op2.reg | (op1.reg << 8) | (op1.am << 4) | (op2.am << 7));
2469cfa2 1479
b18c562e
NC
1480 __is = 1 + op1.ol + op2.ol; /* insn size in words. */
1481 frag = frag_more (2 * __is);
1482 where = frag - frag_now->fr_literal;
1483 bfd_putl16 ((bfd_vma) bin, frag);
2a9a06c1
DD
1484 dwarf2_emit_insn (2 * __is);
1485
b18c562e
NC
1486 if (op1.mode == OP_EXP)
1487 {
1488 where += 2; /* Advance 'where' as we do not know _where_. */
1489 bfd_putl16 ((bfd_vma) ZEROS, frag + 2);
1490
1491 if (op1.reg || (op1.reg == 0 && op1.am == 3)) /* Not PC relative. */
1492 fix_new_exp (frag_now, where, 2,
1493 &(op1.exp), FALSE, CHECK_RELOC_MSP430);
1494 else
1495 fix_new_exp (frag_now, where, 2,
1496 &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
1497 }
1498
1499 if (op2.mode == OP_EXP)
1500 {
1501 imm_op = 0;
1502 bfd_putl16 ((bfd_vma) ZEROS, frag + 2 + ((__is == 3) ? 2 : 0));
1503
1504 if (op2.reg) /* Not PC relative. */
1505 fix_new_exp (frag_now, where + 2, 2,
1506 &(op2.exp), FALSE, CHECK_RELOC_MSP430);
1507 else
1508 fix_new_exp (frag_now, where + 2, 2,
1509 &(op2.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
1510 }
1511 break;
1512 }
1513 case 3:
1514 /* Branch instruction => mov dst, r0. */
1515 line = extract_operand (line, l1, sizeof (l1));
1516
1517 res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op);
1518 if (res)
1519 break;
1520
1521 byte_op = 0;
1522 imm_op = 0;
1523
1524 bin |= ((op1.reg << 8) | (op1.am << 4));
1525 __is = 1 + op1.ol;
1526 frag = frag_more (2 * __is);
1527 where = frag - frag_now->fr_literal;
1528 bfd_putl16 ((bfd_vma) bin, frag);
2a9a06c1 1529 dwarf2_emit_insn (2 * __is);
b18c562e
NC
1530
1531 if (op1.mode == OP_EXP)
2469cfa2 1532 {
b18c562e
NC
1533 where += 2;
1534 bfd_putl16 ((bfd_vma) ZEROS, frag + 2);
1535
1536 if (op1.reg || (op1.reg == 0 && op1.am == 3))
1537 fix_new_exp (frag_now, where, 2,
1538 &(op1.exp), FALSE, CHECK_RELOC_MSP430);
2469cfa2 1539 else
b18c562e
NC
1540 fix_new_exp (frag_now, where, 2,
1541 &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
2469cfa2 1542 }
b18c562e 1543 break;
2469cfa2 1544 }
b18c562e 1545 break;
2469cfa2 1546
b18c562e
NC
1547 case 1: /* Format 1, double operand. */
1548 line = extract_operand (line, l1, sizeof (l1));
1549 line = extract_operand (line, l2, sizeof (l2));
1550 res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op);
1551 res += msp430_dstoperand (&op2, l2, opcode->bin_opcode);
2469cfa2 1552
b18c562e
NC
1553 if (res)
1554 break; /* Error occurred. All warnings were done before. */
2469cfa2 1555
b18c562e
NC
1556 bin |= (op2.reg | (op1.reg << 8) | (op1.am << 4) | (op2.am << 7));
1557
1558 __is = 1 + op1.ol + op2.ol; /* insn size in words. */
1559 frag = frag_more (2 * __is);
1560 where = frag - frag_now->fr_literal;
1561 bfd_putl16 ((bfd_vma) bin, frag);
2a9a06c1 1562 dwarf2_emit_insn (2 * __is);
b18c562e
NC
1563
1564 if (op1.mode == OP_EXP)
2469cfa2 1565 {
b18c562e
NC
1566 where += 2; /* Advance where as we do not know _where_. */
1567 bfd_putl16 ((bfd_vma) ZEROS, frag + 2);
1568
1569 if (op1.reg || (op1.reg == 0 && op1.am == 3)) /* Not PC relative. */
1570 fix_new_exp (frag_now, where, 2,
1571 &(op1.exp), FALSE, CHECK_RELOC_MSP430);
1572 else
1573 fix_new_exp (frag_now, where, 2,
1574 &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
2469cfa2 1575 }
b18c562e
NC
1576
1577 if (op2.mode == OP_EXP)
2469cfa2 1578 {
b18c562e
NC
1579 imm_op = 0;
1580 bfd_putl16 ((bfd_vma) ZEROS, frag + 2 + ((__is == 3) ? 2 : 0));
1581
1582 if (op2.reg) /* Not PC relative. */
1583 fix_new_exp (frag_now, where + 2, 2,
1584 &(op2.exp), FALSE, CHECK_RELOC_MSP430);
1585 else
1586 fix_new_exp (frag_now, where + 2, 2,
1587 &(op2.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
2469cfa2 1588 }
b18c562e
NC
1589 break;
1590
1591 case 2: /* Single-operand mostly instr. */
1592 if (opcode->insn_opnumb == 0)
2469cfa2 1593 {
b18c562e
NC
1594 /* reti instruction. */
1595 frag = frag_more (2);
1596 bfd_putl16 ((bfd_vma) bin, frag);
2a9a06c1 1597 dwarf2_emit_insn (2);
b18c562e 1598 break;
2469cfa2 1599 }
2469cfa2 1600
b18c562e
NC
1601 line = extract_operand (line, l1, sizeof (l1));
1602 res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op);
1603 if (res)
1604 break; /* Error in operand. */
2469cfa2 1605
b18c562e
NC
1606 bin |= op1.reg | (op1.am << 4);
1607 __is = 1 + op1.ol;
1608 frag = frag_more (2 * __is);
1609 where = frag - frag_now->fr_literal;
1610 bfd_putl16 ((bfd_vma) bin, frag);
2a9a06c1 1611 dwarf2_emit_insn (2 * __is);
b18c562e
NC
1612
1613 if (op1.mode == OP_EXP)
2469cfa2 1614 {
b18c562e
NC
1615 bfd_putl16 ((bfd_vma) ZEROS, frag + 2);
1616
1617 if (op1.reg || (op1.reg == 0 && op1.am == 3)) /* Not PC relative. */
1618 fix_new_exp (frag_now, where + 2, 2,
1619 &(op1.exp), FALSE, CHECK_RELOC_MSP430);
1620 else
1621 fix_new_exp (frag_now, where + 2, 2,
1622 &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
2469cfa2 1623 }
b18c562e 1624 break;
2469cfa2 1625
b18c562e
NC
1626 case 3: /* Conditional jumps instructions. */
1627 line = extract_operand (line, l1, sizeof (l1));
1628 /* l1 is a label. */
1629 if (l1[0])
2469cfa2 1630 {
b18c562e
NC
1631 char *m = l1;
1632 expressionS exp;
2469cfa2 1633
b18c562e
NC
1634 if (*m == '$')
1635 m++;
2469cfa2 1636
b18c562e
NC
1637 parse_exp (m, &exp);
1638 frag = frag_more (2); /* Instr size is 1 word. */
2469cfa2 1639
b18c562e 1640 /* In order to handle something like:
2469cfa2 1641
b18c562e
NC
1642 and #0x8000, r5
1643 tst r5
1644 jz 4 ; skip next 4 bytes
1645 inv r5
1646 inc r5
1647 nop ; will jump here if r5 positive or zero
2469cfa2 1648
b18c562e 1649 jCOND -n ;assumes jump n bytes backward:
2469cfa2 1650
b18c562e
NC
1651 mov r5,r6
1652 jmp -2
2469cfa2 1653
b18c562e
NC
1654 is equal to:
1655 lab:
1656 mov r5,r6
1657 jmp lab
1658
1659 jCOND $n ; jump from PC in either direction. */
2469cfa2 1660
b18c562e
NC
1661 if (exp.X_op == O_constant)
1662 {
1663 int x = exp.X_add_number;
2469cfa2 1664
b18c562e
NC
1665 if (x & 1)
1666 {
1667 as_warn (_("Even number required. Rounded to %d"), x + 1);
1668 x++;
1669 }
2469cfa2 1670
b18c562e
NC
1671 if ((*l1 == '$' && x > 0) || x < 0)
1672 x -= 2;
2469cfa2 1673
b18c562e
NC
1674 x >>= 1;
1675
1676 if (x > 512 || x < -511)
1677 {
1678 as_bad (_("Wrong displacement %d"), x << 1);
1679 break;
1680 }
1681
1682 bin |= x & 0x3ff;
1683 bfd_putl16 ((bfd_vma) bin, frag);
1684 }
1685 else if (exp.X_op == O_symbol && *l1 != '$')
2469cfa2 1686 {
b18c562e
NC
1687 where = frag - frag_now->fr_literal;
1688 fix_new_exp (frag_now, where, 2,
1689 &exp, TRUE, BFD_RELOC_MSP430_10_PCREL);
1690
1691 bfd_putl16 ((bfd_vma) bin, frag);
2469cfa2 1692 }
b18c562e 1693 else if (*l1 == '$')
2469cfa2 1694 {
b18c562e 1695 as_bad (_("instruction requires label sans '$'"));
2469cfa2 1696 }
b18c562e 1697 else
2469cfa2 1698 {
b18c562e
NC
1699 as_bad (_
1700 ("instruction requires label or value in range -511:512"));
2469cfa2 1701 }
2a9a06c1
DD
1702 dwarf2_emit_insn (2 * __is);
1703 break;
2469cfa2 1704 }
b18c562e
NC
1705 else
1706 {
1707 as_bad (_("instruction requires label"));
1708 break;
1709 }
1710 break;
2469cfa2 1711
b18c562e 1712 case 4: /* Extended jumps. */
77592908
DD
1713 if (!msp430_enable_polys)
1714 {
20203fb9 1715 as_bad (_("polymorphs are not enabled. Use -mP option to enable."));
77592908
DD
1716 break;
1717 }
1718
b18c562e
NC
1719 line = extract_operand (line, l1, sizeof (l1));
1720 if (l1[0])
2469cfa2 1721 {
b18c562e
NC
1722 char *m = l1;
1723 expressionS exp;
2469cfa2 1724
b18c562e
NC
1725 /* Ignore absolute addressing. make it PC relative anyway. */
1726 if (*m == '#' || *m == '$')
1727 m++;
2469cfa2 1728
b18c562e
NC
1729 parse_exp (m, & exp);
1730 if (exp.X_op == O_symbol)
2469cfa2 1731 {
b18c562e
NC
1732 /* Relaxation required. */
1733 struct rcodes_s rc = msp430_rcodes[opcode->insn_opnumb];
1734
2a9a06c1
DD
1735 /* The parameter to dwarf2_emit_insn is actually the offset to the start
1736 of the insn from the fix piece of instruction that was emitted.
1737 Since next fragments may have variable size we tie debug info
1738 to the beginning of the instruction. */
3e470ab5 1739 frag = frag_more (8);
2a9a06c1 1740 dwarf2_emit_insn (0);
3e470ab5
DD
1741 bfd_putl16 ((bfd_vma) rc.sop, frag);
1742 frag = frag_variant (rs_machine_dependent, 8, 2,
b18c562e
NC
1743 ENCODE_RELAX (rc.lpos, STATE_BITS10), /* Wild guess. */
1744 exp.X_add_symbol,
1745 0, /* Offset is zero if jump dist less than 1K. */
1746 (char *) frag);
1747 break;
2469cfa2
NC
1748 }
1749 }
b18c562e
NC
1750
1751 as_bad (_("instruction requires label"));
1752 break;
1753
1754 case 5: /* Emulated extended branches. */
77592908
DD
1755 if (!msp430_enable_polys)
1756 {
20203fb9 1757 as_bad (_("polymorphs are not enabled. Use -mP option to enable."));
77592908
DD
1758 break;
1759 }
b18c562e
NC
1760 line = extract_operand (line, l1, sizeof (l1));
1761 if (l1[0])
2469cfa2 1762 {
b18c562e
NC
1763 char * m = l1;
1764 expressionS exp;
1765
1766 /* Ignore absolute addressing. make it PC relative anyway. */
1767 if (*m == '#' || *m == '$')
1768 m++;
1769
1770 parse_exp (m, & exp);
1771 if (exp.X_op == O_symbol)
1772 {
1773 /* Relaxation required. */
1774 struct hcodes_s hc = msp430_hcodes[opcode->insn_opnumb];
1775
3e470ab5 1776 frag = frag_more (8);
2a9a06c1 1777 dwarf2_emit_insn (0);
3e470ab5
DD
1778 bfd_putl16 ((bfd_vma) hc.op0, frag);
1779 bfd_putl16 ((bfd_vma) hc.op1, frag+2);
1780
1781 frag = frag_variant (rs_machine_dependent, 8, 2,
b18c562e
NC
1782 ENCODE_RELAX (STATE_EMUL_BRANCH, STATE_BITS10), /* Wild guess. */
1783 exp.X_add_symbol,
1784 0, /* Offset is zero if jump dist less than 1K. */
1785 (char *) frag);
1786 break;
1787 }
2469cfa2
NC
1788 }
1789
b18c562e
NC
1790 as_bad (_("instruction requires label"));
1791 break;
2469cfa2 1792
b18c562e 1793 default:
79cf5950 1794 as_bad (_("Illegal instruction or not implemented opcode."));
b18c562e 1795 }
2469cfa2 1796
b18c562e
NC
1797 input_line_pointer = line;
1798 return 0;
1799}
2469cfa2 1800
b18c562e
NC
1801void
1802md_assemble (char * str)
1803{
1804 struct msp430_opcode_s * opcode;
1805 char cmd[32];
1806 unsigned int i = 0;
2469cfa2 1807
b18c562e
NC
1808 str = skip_space (str); /* Skip leading spaces. */
1809 str = extract_cmd (str, cmd, sizeof (cmd));
2469cfa2 1810
b18c562e
NC
1811 while (cmd[i] && i < sizeof (cmd))
1812 {
1813 char a = TOLOWER (cmd[i]);
1814 cmd[i] = a;
1815 i++;
2469cfa2 1816 }
2469cfa2 1817
b18c562e 1818 if (!cmd[0])
2469cfa2 1819 {
b18c562e
NC
1820 as_bad (_("can't find opcode "));
1821 return;
1822 }
2469cfa2 1823
b18c562e 1824 opcode = (struct msp430_opcode_s *) hash_find (msp430_hash, cmd);
2469cfa2 1825
b18c562e
NC
1826 if (opcode == NULL)
1827 {
1828 as_bad (_("unknown opcode `%s'"), cmd);
1829 return;
2469cfa2 1830 }
2469cfa2 1831
b18c562e
NC
1832 {
1833 char *__t = input_line_pointer;
2469cfa2 1834
b18c562e
NC
1835 msp430_operands (opcode, str);
1836 input_line_pointer = __t;
1837 }
1838}
2469cfa2
NC
1839
1840/* GAS will call this function for each section at the end of the assembly,
1841 to permit the CPU backend to adjust the alignment of a section. */
1842
1843valueT
b18c562e 1844md_section_align (asection * seg, valueT addr)
2469cfa2
NC
1845{
1846 int align = bfd_get_section_alignment (stdoutput, seg);
1847
1848 return ((addr + (1 << align) - 1) & (-1 << align));
1849}
1850
1851/* If you define this macro, it should return the offset between the
1852 address of a PC relative fixup and the position from which the PC
1853 relative adjustment should be made. On many processors, the base
1854 of a PC relative instruction is the next instruction, so this
1855 macro would return the length of an instruction. */
1856
1857long
b18c562e 1858md_pcrel_from_section (fixS * fixp, segT sec)
2469cfa2
NC
1859{
1860 if (fixp->fx_addsy != (symbolS *) NULL
1861 && (!S_IS_DEFINED (fixp->fx_addsy)
1862 || (S_GET_SEGMENT (fixp->fx_addsy) != sec)))
1863 return 0;
1864
1865 return fixp->fx_frag->fr_address + fixp->fx_where;
1866}
1867
77592908
DD
1868/* Replaces standard TC_FORCE_RELOCATION_LOCAL.
1869 Now it handles the situation when relocations
1870 have to be passed to linker. */
1871int
1872msp430_force_relocation_local(fixS *fixp)
1873{
1874 if (msp430_enable_polys
1875 && !msp430_enable_relax)
1876 return 1;
1877 else
1878 return (!fixp->fx_pcrel
77592908
DD
1879 || generic_force_reloc(fixp));
1880}
1881
1882
2469cfa2
NC
1883/* GAS will call this for each fixup. It should store the correct
1884 value in the object file. */
2469cfa2 1885void
55cf6793 1886md_apply_fix (fixS * fixp, valueT * valuep, segT seg)
2469cfa2 1887{
b18c562e 1888 unsigned char * where;
2469cfa2
NC
1889 unsigned long insn;
1890 long value;
1891
1892 if (fixp->fx_addsy == (symbolS *) NULL)
1893 {
1894 value = *valuep;
1895 fixp->fx_done = 1;
1896 }
1897 else if (fixp->fx_pcrel)
1898 {
1899 segT s = S_GET_SEGMENT (fixp->fx_addsy);
1900
1901 if (fixp->fx_addsy && (s == seg || s == absolute_section))
1902 {
18af0b39
NC
1903 /* FIXME: We can appear here only in case if we perform a pc
1904 relative jump to the label which is i) global, ii) locally
1905 defined or this is a jump to an absolute symbol.
1906 If this is an absolute symbol -- everything is OK.
1907 If this is a global label, we've got a symbol value defined
1908 twice:
1909 1. S_GET_VALUE (fixp->fx_addsy) will contain a symbol offset
1910 from this section start
1911 2. *valuep will contain the real offset from jump insn to the
1912 label
1913 So, the result of S_GET_VALUE (fixp->fx_addsy) + (* valuep);
1914 will be incorrect. Therefore remove s_get_value. */
1915 value = /* S_GET_VALUE (fixp->fx_addsy) + */ * valuep;
2469cfa2
NC
1916 fixp->fx_done = 1;
1917 }
1918 else
1919 value = *valuep;
1920 }
1921 else
1922 {
1923 value = fixp->fx_offset;
1924
1925 if (fixp->fx_subsy != (symbolS *) NULL)
1926 {
1927 if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
1928 {
1929 value -= S_GET_VALUE (fixp->fx_subsy);
1930 fixp->fx_done = 1;
1931 }
1932 else
1933 {
1934 /* We don't actually support subtracting a symbol. */
1935 as_bad_where (fixp->fx_file, fixp->fx_line,
1936 _("expression too complex"));
1937 }
1938 }
1939 }
1940
77592908
DD
1941 fixp->fx_no_overflow = 1;
1942
1943 /* if polymorphs are enabled and relax disabled.
1944 do not kill any relocs and pass them to linker. */
1945 if (msp430_enable_polys
1946 && !msp430_enable_relax)
2469cfa2 1947 {
77592908
DD
1948 if (!fixp->fx_addsy || (fixp->fx_addsy
1949 && S_GET_SEGMENT (fixp->fx_addsy) == absolute_section))
79cf5950 1950 fixp->fx_done = 1; /* It is ok to kill 'abs' reloc. */
77592908
DD
1951 else
1952 fixp->fx_done = 0;
2469cfa2
NC
1953 }
1954
1955 if (fixp->fx_done)
1956 {
1957 /* Fetch the instruction, insert the fully resolved operand
8cd5b113 1958 value, and stuff the instruction back again. */
2469cfa2 1959
2132e3a3 1960 where = (unsigned char *) fixp->fx_frag->fr_literal + fixp->fx_where;
2469cfa2
NC
1961
1962 insn = bfd_getl16 (where);
1963
1964 switch (fixp->fx_r_type)
1965 {
1966 case BFD_RELOC_MSP430_10_PCREL:
1967 if (value & 1)
1968 as_bad_where (fixp->fx_file, fixp->fx_line,
1969 _("odd address operand: %ld"), value);
1970
1971 /* Jumps are in words. */
1972 value >>= 1;
1973 --value; /* Correct PC. */
1974
1975 if (value < -512 || value > 511)
1976 as_bad_where (fixp->fx_file, fixp->fx_line,
1977 _("operand out of range: %ld"), value);
1978
1979 value &= 0x3ff; /* get rid of extended sign */
1980 bfd_putl16 ((bfd_vma) (value | insn), where);
1981 break;
1982
b18c562e 1983 case BFD_RELOC_MSP430_RL_PCREL:
2469cfa2
NC
1984 case BFD_RELOC_MSP430_16_PCREL:
1985 if (value & 1)
1986 as_bad_where (fixp->fx_file, fixp->fx_line,
1987 _("odd address operand: %ld"), value);
1988
1989 /* Nothing to be corrected here. */
1990 if (value < -32768 || value > 65536)
1991 as_bad_where (fixp->fx_file, fixp->fx_line,
1992 _("operand out of range: %ld"), value);
1993
1994 value &= 0xffff; /* Get rid of extended sign. */
1995 bfd_putl16 ((bfd_vma) value, where);
1996 break;
1997
1998 case BFD_RELOC_MSP430_16_PCREL_BYTE:
1999 /* Nothing to be corrected here. */
2000 if (value < -32768 || value > 65536)
2001 as_bad_where (fixp->fx_file, fixp->fx_line,
2002 _("operand out of range: %ld"), value);
2003
2004 value &= 0xffff; /* Get rid of extended sign. */
2005 bfd_putl16 ((bfd_vma) value, where);
2006 break;
2007
2008 case BFD_RELOC_32:
2009 bfd_putl16 ((bfd_vma) value, where);
2010 break;
2011
2012 case BFD_RELOC_MSP430_16:
2013 case BFD_RELOC_16:
2014 case BFD_RELOC_MSP430_16_BYTE:
2015 value &= 0xffff;
2016 bfd_putl16 ((bfd_vma) value, where);
2017 break;
2018
2019 default:
2020 as_fatal (_("line %d: unknown relocation type: 0x%x"),
2021 fixp->fx_line, fixp->fx_r_type);
2022 break;
2023 }
2024 }
2025 else
2026 {
2027 fixp->fx_addnumber = value;
2028 }
2469cfa2
NC
2029}
2030
7be1c489
AM
2031/* GAS will call this to generate a reloc, passing the resulting reloc
2032 to `bfd_install_relocation'. This currently works poorly, as
2033 `bfd_install_relocation' often does the wrong thing, and instances of
2034 `tc_gen_reloc' have been written to work around the problems, which
2035 in turns makes it difficult to fix `bfd_install_relocation'. */
2469cfa2
NC
2036
2037/* If while processing a fixup, a reloc really needs to be created
2038 then it is done here. */
2039
2040arelent *
b18c562e 2041tc_gen_reloc (asection * seg ATTRIBUTE_UNUSED, fixS * fixp)
2469cfa2 2042{
b18c562e 2043 arelent * reloc;
2469cfa2 2044
b18c562e 2045 reloc = xmalloc (sizeof (arelent));
2469cfa2 2046
b18c562e 2047 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
2469cfa2
NC
2048 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
2049
2050 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
2051 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
2052 if (reloc->howto == (reloc_howto_type *) NULL)
2053 {
2054 as_bad_where (fixp->fx_file, fixp->fx_line,
2055 _("reloc %d not supported by object file format"),
2056 (int) fixp->fx_r_type);
2057 return NULL;
2058 }
2059
2060 if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
2061 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
2062 reloc->address = fixp->fx_offset;
2063
2064 reloc->addend = fixp->fx_offset;
2065
2066 return reloc;
2067}
2068
b18c562e
NC
2069int
2070md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
2071 asection * segment_type ATTRIBUTE_UNUSED)
2072{
2073 if (fragP->fr_symbol && S_GET_SEGMENT (fragP->fr_symbol) == segment_type)
2074 {
2075 /* This is a jump -> pcrel mode. Nothing to do much here.
2076 Return value == 2. */
2077 fragP->fr_subtype =
2078 ENCODE_RELAX (RELAX_LEN (fragP->fr_subtype), STATE_BITS10);
2079 }
2080 else if (fragP->fr_symbol)
2081 {
2082 /* Its got a segment, but its not ours. Even if fr_symbol is in
79cf5950 2083 an absolute segment, we don't know a displacement until we link
b18c562e
NC
2084 object files. So it will always be long. This also applies to
2085 labels in a subsegment of current. Liker may relax it to short
2086 jump later. Return value == 8. */
2087 fragP->fr_subtype =
2088 ENCODE_RELAX (RELAX_LEN (fragP->fr_subtype), STATE_WORD);
2089 }
2090 else
2091 {
2092 /* We know the abs value. may be it is a jump to fixed address.
79cf5950 2093 Impossible in our case, cause all constants already handled. */
b18c562e
NC
2094 fragP->fr_subtype =
2095 ENCODE_RELAX (RELAX_LEN (fragP->fr_subtype), STATE_UNDEF);
2096 }
2469cfa2 2097
b18c562e
NC
2098 return md_relax_table[fragP->fr_subtype].rlx_length;
2099}
2100
2101void
2102md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
2103 asection * sec ATTRIBUTE_UNUSED,
2104 fragS * fragP)
2469cfa2 2105{
b18c562e
NC
2106 char * where = 0;
2107 int rela = -1;
2108 int i;
2109 struct rcodes_s * cc = NULL;
2110 struct hcodes_s * hc = NULL;
2111
2112 switch (fragP->fr_subtype)
2113 {
2114 case ENCODE_RELAX (STATE_UNCOND_BRANCH, STATE_BITS10):
2115 case ENCODE_RELAX (STATE_SIMPLE_BRANCH, STATE_BITS10):
2116 case ENCODE_RELAX (STATE_NOOV_BRANCH, STATE_BITS10):
2117 /* We do not have to convert anything here.
2118 Just apply a fix. */
2119 rela = BFD_RELOC_MSP430_10_PCREL;
2120 break;
2121
2122 case ENCODE_RELAX (STATE_UNCOND_BRANCH, STATE_WORD):
2123 case ENCODE_RELAX (STATE_UNCOND_BRANCH, STATE_UNDEF):
2124 /* Convert uncond branch jmp lab -> br lab. */
2125 cc = & msp430_rcodes[7];
2126 where = fragP->fr_literal + fragP->fr_fix;
2127 bfd_putl16 (cc->lop0, where);
2128 rela = BFD_RELOC_MSP430_RL_PCREL;
2129 fragP->fr_fix += 2;
2130 break;
2131
2132 case ENCODE_RELAX (STATE_SIMPLE_BRANCH, STATE_WORD):
2133 case ENCODE_RELAX (STATE_SIMPLE_BRANCH, STATE_UNDEF):
2134 {
2135 /* Other simple branches. */
2136 int insn = bfd_getl16 (fragP->fr_opcode);
2137
2138 insn &= 0xffff;
2139 /* Find actual instruction. */
2140 for (i = 0; i < 7 && !cc; i++)
2141 if (msp430_rcodes[i].sop == insn)
2142 cc = & msp430_rcodes[i];
2143 if (!cc || !cc->name)
2144 as_fatal (_("internal inconsistency problem in %s: insn %04lx"),
2145 __FUNCTION__, (long) insn);
2146 where = fragP->fr_literal + fragP->fr_fix;
2147 bfd_putl16 (cc->lop0, where);
2148 bfd_putl16 (cc->lop1, where + 2);
2149 rela = BFD_RELOC_MSP430_RL_PCREL;
2150 fragP->fr_fix += 4;
2151 }
2152 break;
2153
2154 case ENCODE_RELAX (STATE_NOOV_BRANCH, STATE_WORD):
2155 case ENCODE_RELAX (STATE_NOOV_BRANCH, STATE_UNDEF):
2156 cc = & msp430_rcodes[6];
2157 where = fragP->fr_literal + fragP->fr_fix;
2158 bfd_putl16 (cc->lop0, where);
2159 bfd_putl16 (cc->lop1, where + 2);
2160 bfd_putl16 (cc->lop2, where + 4);
2161 rela = BFD_RELOC_MSP430_RL_PCREL;
2162 fragP->fr_fix += 6;
2163 break;
2164
2165 case ENCODE_RELAX (STATE_EMUL_BRANCH, STATE_BITS10):
2166 {
2167 int insn = bfd_getl16 (fragP->fr_opcode + 2);
2168
2169 insn &= 0xffff;
2170 for (i = 0; i < 4 && !hc; i++)
2171 if (msp430_hcodes[i].op1 == insn)
2172 hc = &msp430_hcodes[i];
2173 if (!hc || !hc->name)
2174 as_fatal (_("internal inconsistency problem in %s: ext. insn %04lx"),
2175 __FUNCTION__, (long) insn);
2176 rela = BFD_RELOC_MSP430_10_PCREL;
2177 /* Apply a fix for a first label if necessary.
2178 another fix will be applied to the next word of insn anyway. */
2179 if (hc->tlab == 2)
2180 fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
2181 fragP->fr_offset, TRUE, rela);
2182 fragP->fr_fix += 2;
2183 }
2184
2185 break;
2186
2187 case ENCODE_RELAX (STATE_EMUL_BRANCH, STATE_WORD):
2188 case ENCODE_RELAX (STATE_EMUL_BRANCH, STATE_UNDEF):
2189 {
2190 int insn = bfd_getl16 (fragP->fr_opcode + 2);
2191
2192 insn &= 0xffff;
2193 for (i = 0; i < 4 && !hc; i++)
2194 if (msp430_hcodes[i].op1 == insn)
2195 hc = & msp430_hcodes[i];
2196 if (!hc || !hc->name)
2197 as_fatal (_("internal inconsistency problem in %s: ext. insn %04lx"),
2198 __FUNCTION__, (long) insn);
2199 rela = BFD_RELOC_MSP430_RL_PCREL;
2200 where = fragP->fr_literal + fragP->fr_fix;
2201 bfd_putl16 (hc->lop0, where);
2202 bfd_putl16 (hc->lop1, where + 2);
2203 bfd_putl16 (hc->lop2, where + 4);
2204 fragP->fr_fix += 6;
2205 }
2206 break;
2207
2208 default:
2209 as_fatal (_("internal inconsistency problem in %s: %lx"),
2210 __FUNCTION__, (long) fragP->fr_subtype);
2211 break;
2212 }
2213
2214 /* Now apply fix. */
2215 fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
2216 fragP->fr_offset, TRUE, rela);
2217 /* Just fixed 2 bytes. */
2218 fragP->fr_fix += 2;
2469cfa2
NC
2219}
2220
b18c562e
NC
2221/* Relax fragment. Mostly stolen from hc11 and mcore
2222 which arches I think I know. */
2469cfa2 2223
b18c562e
NC
2224long
2225msp430_relax_frag (segT seg ATTRIBUTE_UNUSED, fragS * fragP,
2226 long stretch ATTRIBUTE_UNUSED)
2469cfa2 2227{
b18c562e
NC
2228 long growth;
2229 offsetT aim = 0;
2230 symbolS *symbolP;
2231 const relax_typeS *this_type;
2232 const relax_typeS *start_type;
2233 relax_substateT next_state;
2234 relax_substateT this_state;
2235 const relax_typeS *table = md_relax_table;
2236
2237 /* Nothing to be done if the frag has already max size. */
2238 if (RELAX_STATE (fragP->fr_subtype) == STATE_UNDEF
2239 || RELAX_STATE (fragP->fr_subtype) == STATE_WORD)
2240 return 0;
2241
2242 if (RELAX_STATE (fragP->fr_subtype) == STATE_BITS10)
2243 {
2244 symbolP = fragP->fr_symbol;
2245 if (symbol_resolved_p (symbolP))
2246 as_fatal (_("internal inconsistency problem in %s: resolved symbol"),
2247 __FUNCTION__);
2248 /* We know the offset. calculate a distance. */
2249 aim = S_GET_VALUE (symbolP) - fragP->fr_address - fragP->fr_fix;
2250 }
2251
77592908
DD
2252 if (!msp430_enable_relax)
2253 {
2254 /* Relaxation is not enabled. So, make all jump as long ones
2255 by setting 'aim' to quite high value. */
2256 aim = 0x7fff;
2257 }
2258
b18c562e
NC
2259 this_state = fragP->fr_subtype;
2260 start_type = this_type = table + this_state;
2261
2262 if (aim < 0)
2263 {
2264 /* Look backwards. */
2265 for (next_state = this_type->rlx_more; next_state;)
3e470ab5 2266 if (aim >= this_type->rlx_backward || !this_type->rlx_backward)
b18c562e
NC
2267 next_state = 0;
2268 else
2269 {
2270 /* Grow to next state. */
2271 this_state = next_state;
2272 this_type = table + this_state;
2273 next_state = this_type->rlx_more;
2274 }
2275 }
2276 else
2277 {
2278 /* Look forwards. */
2279 for (next_state = this_type->rlx_more; next_state;)
3e470ab5 2280 if (aim <= this_type->rlx_forward || !this_type->rlx_forward)
b18c562e
NC
2281 next_state = 0;
2282 else
2283 {
2284 /* Grow to next state. */
2285 this_state = next_state;
2286 this_type = table + this_state;
2287 next_state = this_type->rlx_more;
2288 }
2289 }
2290
2291 growth = this_type->rlx_length - start_type->rlx_length;
2292 if (growth != 0)
2293 fragP->fr_subtype = this_state;
2294 return growth;
2469cfa2 2295}
This page took 0.569413 seconds and 4 git commands to generate.