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