]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-bfin.c
* output.cc (Output_section::add_input_section): Don't try to
[thirdparty/binutils-gdb.git] / gas / config / tc-bfin.c
CommitLineData
07c1b327 1/* tc-bfin.c -- Assembler for the ADI Blackfin.
ec2655a6 2 Copyright 2005, 2006, 2007
07c1b327
CM
3 Free Software Foundation, Inc.
4
5 This file is part of GAS, the GNU Assembler.
6
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
ec2655a6 9 the Free Software Foundation; either version 3, or (at your option)
07c1b327
CM
10 any later version.
11
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to the Free
19 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20 02110-1301, USA. */
21
22#include "as.h"
23#include "struc-symbol.h"
07c1b327
CM
24#include "bfin-defs.h"
25#include "obstack.h"
26#include "safe-ctype.h"
27#ifdef OBJ_ELF
28#include "dwarf2dbg.h"
29#endif
1ac4baed
BS
30#include "libbfd.h"
31#include "elf/common.h"
32#include "elf/bfin.h"
07c1b327
CM
33
34extern int yyparse (void);
35struct yy_buffer_state;
36typedef struct yy_buffer_state *YY_BUFFER_STATE;
37extern YY_BUFFER_STATE yy_scan_string (const char *yy_str);
38extern void yy_delete_buffer (YY_BUFFER_STATE b);
39static parse_state parse (char *line);
40static void bfin_s_bss PARAMS ((int));
9ba4c445 41static int md_chars_to_number PARAMS ((char *, int));
07c1b327
CM
42
43/* Global variables. */
44struct bfin_insn *insn;
45int last_insn_size;
46
47extern struct obstack mempool;
48FILE *errorf;
49
1ac4baed
BS
50/* Flags to set in the elf header */
51#define DEFAULT_FLAGS 0
52
fe4fa32c
MF
53#ifdef OBJ_FDPIC_ELF
54# define DEFAULT_FDPIC EF_BFIN_FDPIC
55#else
56# define DEFAULT_FDPIC 0
57#endif
58
59static flagword bfin_flags = DEFAULT_FLAGS | DEFAULT_FDPIC;
60static const char *bfin_pic_flag = DEFAULT_FDPIC ? "-mfdpic" : (const char *)0;
1ac4baed 61
07c1b327
CM
62/* Registers list. */
63struct bfin_reg_entry
64{
65 const char *name;
66 int number;
67};
68
69static const struct bfin_reg_entry bfin_reg_info[] = {
70 {"R0.L", REG_RL0},
71 {"R1.L", REG_RL1},
72 {"R2.L", REG_RL2},
73 {"R3.L", REG_RL3},
74 {"R4.L", REG_RL4},
75 {"R5.L", REG_RL5},
76 {"R6.L", REG_RL6},
77 {"R7.L", REG_RL7},
78 {"R0.H", REG_RH0},
79 {"R1.H", REG_RH1},
80 {"R2.H", REG_RH2},
81 {"R3.H", REG_RH3},
82 {"R4.H", REG_RH4},
83 {"R5.H", REG_RH5},
84 {"R6.H", REG_RH6},
85 {"R7.H", REG_RH7},
86 {"R0", REG_R0},
87 {"R1", REG_R1},
88 {"R2", REG_R2},
89 {"R3", REG_R3},
90 {"R4", REG_R4},
91 {"R5", REG_R5},
92 {"R6", REG_R6},
93 {"R7", REG_R7},
94 {"P0", REG_P0},
95 {"P0.H", REG_P0},
96 {"P0.L", REG_P0},
97 {"P1", REG_P1},
98 {"P1.H", REG_P1},
99 {"P1.L", REG_P1},
100 {"P2", REG_P2},
101 {"P2.H", REG_P2},
102 {"P2.L", REG_P2},
103 {"P3", REG_P3},
104 {"P3.H", REG_P3},
105 {"P3.L", REG_P3},
106 {"P4", REG_P4},
107 {"P4.H", REG_P4},
108 {"P4.L", REG_P4},
109 {"P5", REG_P5},
110 {"P5.H", REG_P5},
111 {"P5.L", REG_P5},
112 {"SP", REG_SP},
113 {"SP.L", REG_SP},
114 {"SP.H", REG_SP},
115 {"FP", REG_FP},
116 {"FP.L", REG_FP},
117 {"FP.H", REG_FP},
118 {"A0x", REG_A0x},
119 {"A1x", REG_A1x},
120 {"A0w", REG_A0w},
121 {"A1w", REG_A1w},
122 {"A0.x", REG_A0x},
123 {"A1.x", REG_A1x},
124 {"A0.w", REG_A0w},
125 {"A1.w", REG_A1w},
126 {"A0", REG_A0},
127 {"A0.L", REG_A0},
128 {"A0.H", REG_A0},
129 {"A1", REG_A1},
130 {"A1.L", REG_A1},
131 {"A1.H", REG_A1},
132 {"I0", REG_I0},
133 {"I0.L", REG_I0},
134 {"I0.H", REG_I0},
135 {"I1", REG_I1},
136 {"I1.L", REG_I1},
137 {"I1.H", REG_I1},
138 {"I2", REG_I2},
139 {"I2.L", REG_I2},
140 {"I2.H", REG_I2},
141 {"I3", REG_I3},
142 {"I3.L", REG_I3},
143 {"I3.H", REG_I3},
144 {"M0", REG_M0},
145 {"M0.H", REG_M0},
146 {"M0.L", REG_M0},
147 {"M1", REG_M1},
148 {"M1.H", REG_M1},
149 {"M1.L", REG_M1},
150 {"M2", REG_M2},
151 {"M2.H", REG_M2},
152 {"M2.L", REG_M2},
153 {"M3", REG_M3},
154 {"M3.H", REG_M3},
155 {"M3.L", REG_M3},
156 {"B0", REG_B0},
157 {"B0.H", REG_B0},
158 {"B0.L", REG_B0},
159 {"B1", REG_B1},
160 {"B1.H", REG_B1},
161 {"B1.L", REG_B1},
162 {"B2", REG_B2},
163 {"B2.H", REG_B2},
164 {"B2.L", REG_B2},
165 {"B3", REG_B3},
166 {"B3.H", REG_B3},
167 {"B3.L", REG_B3},
168 {"L0", REG_L0},
169 {"L0.H", REG_L0},
170 {"L0.L", REG_L0},
171 {"L1", REG_L1},
172 {"L1.H", REG_L1},
173 {"L1.L", REG_L1},
174 {"L2", REG_L2},
175 {"L2.H", REG_L2},
176 {"L2.L", REG_L2},
177 {"L3", REG_L3},
178 {"L3.H", REG_L3},
179 {"L3.L", REG_L3},
180 {"AZ", S_AZ},
181 {"AN", S_AN},
182 {"AC0", S_AC0},
183 {"AC1", S_AC1},
184 {"AV0", S_AV0},
185 {"AV0S", S_AV0S},
186 {"AV1", S_AV1},
187 {"AV1S", S_AV1S},
188 {"AQ", S_AQ},
189 {"V", S_V},
190 {"VS", S_VS},
191 {"sftreset", REG_sftreset},
192 {"omode", REG_omode},
193 {"excause", REG_excause},
194 {"emucause", REG_emucause},
195 {"idle_req", REG_idle_req},
196 {"hwerrcause", REG_hwerrcause},
197 {"CC", REG_CC},
198 {"LC0", REG_LC0},
199 {"LC1", REG_LC1},
200 {"ASTAT", REG_ASTAT},
201 {"RETS", REG_RETS},
202 {"LT0", REG_LT0},
203 {"LB0", REG_LB0},
204 {"LT1", REG_LT1},
205 {"LB1", REG_LB1},
206 {"CYCLES", REG_CYCLES},
207 {"CYCLES2", REG_CYCLES2},
208 {"USP", REG_USP},
209 {"SEQSTAT", REG_SEQSTAT},
210 {"SYSCFG", REG_SYSCFG},
211 {"RETI", REG_RETI},
212 {"RETX", REG_RETX},
213 {"RETN", REG_RETN},
214 {"RETE", REG_RETE},
215 {"EMUDAT", REG_EMUDAT},
216 {0, 0}
217};
218
1ac4baed
BS
219/* Blackfin specific function to handle FD-PIC pointer initializations. */
220
221static void
222bfin_pic_ptr (int nbytes)
223{
224 expressionS exp;
225 char *p;
226
227 if (nbytes != 4)
228 abort ();
229
230#ifdef md_flush_pending_output
231 md_flush_pending_output ();
232#endif
233
234 if (is_it_end_of_statement ())
235 {
236 demand_empty_rest_of_line ();
237 return;
238 }
239
240#ifdef md_cons_align
241 md_cons_align (nbytes);
242#endif
243
244 do
245 {
246 bfd_reloc_code_real_type reloc_type = BFD_RELOC_BFIN_FUNCDESC;
247
248 if (strncasecmp (input_line_pointer, "funcdesc(", 9) == 0)
249 {
250 input_line_pointer += 9;
251 expression (&exp);
252 if (*input_line_pointer == ')')
253 input_line_pointer++;
254 else
bd3ba5d1 255 as_bad (_("missing ')'"));
1ac4baed
BS
256 }
257 else
258 error ("missing funcdesc in picptr");
259
260 p = frag_more (4);
261 memset (p, 0, 4);
262 fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &exp, 0,
263 reloc_type);
264 }
265 while (*input_line_pointer++ == ',');
266
267 input_line_pointer--; /* Put terminator back into stream. */
268 demand_empty_rest_of_line ();
269}
270
271static void
272bfin_s_bss (int ignore ATTRIBUTE_UNUSED)
273{
274 register int temp;
275
276 temp = get_absolute_expression ();
277 subseg_set (bss_section, (subsegT) temp);
278 demand_empty_rest_of_line ();
279}
07c1b327
CM
280
281const pseudo_typeS md_pseudo_table[] = {
282 {"align", s_align_bytes, 0},
283 {"byte2", cons, 2},
284 {"byte4", cons, 4},
1ac4baed 285 {"picptr", bfin_pic_ptr, 4},
07c1b327
CM
286 {"code", obj_elf_section, 0},
287 {"db", cons, 1},
288 {"dd", cons, 4},
289 {"dw", cons, 2},
290 {"p", s_ignore, 0},
291 {"pdata", s_ignore, 0},
292 {"var", s_ignore, 0},
293 {"bss", bfin_s_bss, 0},
294 {0, 0, 0}
295};
296
07c1b327
CM
297/* Characters that are used to denote comments and line separators. */
298const char comment_chars[] = "";
299const char line_comment_chars[] = "#";
300const char line_separator_chars[] = ";";
301
302/* Characters that can be used to separate the mantissa from the
303 exponent in floating point numbers. */
304const char EXP_CHARS[] = "eE";
305
306/* Characters that mean this number is a floating point constant.
307 As in 0f12.456 or 0d1.2345e12. */
308const char FLT_CHARS[] = "fFdDxX";
309
310/* Define bfin-specific command-line options (there are none). */
311const char *md_shortopts = "";
312
1ac4baed 313#define OPTION_FDPIC (OPTION_MD_BASE)
fe4fa32c 314#define OPTION_NOPIC (OPTION_MD_BASE + 1)
1ac4baed
BS
315
316struct option md_longopts[] =
317{
fe4fa32c
MF
318 { "mfdpic", no_argument, NULL, OPTION_FDPIC },
319 { "mnopic", no_argument, NULL, OPTION_NOPIC },
320 { "mno-fdpic", no_argument, NULL, OPTION_NOPIC },
1ac4baed 321 { NULL, no_argument, NULL, 0 },
07c1b327 322};
1ac4baed 323
07c1b327
CM
324size_t md_longopts_size = sizeof (md_longopts);
325
326
327int
328md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED)
329{
1ac4baed
BS
330 switch (c)
331 {
332 default:
333 return 0;
334
335 case OPTION_FDPIC:
336 bfin_flags |= EF_BFIN_FDPIC;
337 bfin_pic_flag = "-mfdpic";
338 break;
fe4fa32c
MF
339
340 case OPTION_NOPIC:
341 bfin_flags &= ~(EF_BFIN_FDPIC);
342 bfin_pic_flag = 0;
343 break;
1ac4baed
BS
344 }
345
346 return 1;
07c1b327
CM
347}
348
349void
350md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
351{
352 fprintf (stream, _(" BFIN specific command line options:\n"));
353}
354
355/* Perform machine-specific initializations. */
356void
357md_begin ()
358{
1ac4baed
BS
359 /* Set the ELF flags if desired. */
360 if (bfin_flags)
361 bfd_set_private_flags (stdoutput, bfin_flags);
362
07c1b327
CM
363 /* Set the default machine type. */
364 if (!bfd_set_arch_mach (stdoutput, bfd_arch_bfin, 0))
bd3ba5d1 365 as_warn (_("Could not set architecture and machine."));
07c1b327
CM
366
367 /* Ensure that lines can begin with '(', for multiple
368 register stack pops. */
9f8e671b 369 lex_type ['('] = LEX_BEGIN_NAME;
07c1b327
CM
370
371#ifdef OBJ_ELF
372 record_alignment (text_section, 2);
373 record_alignment (data_section, 2);
374 record_alignment (bss_section, 2);
375#endif
376
377 errorf = stderr;
378 obstack_init (&mempool);
379
380#ifdef DEBUG
381 extern int debug_codeselection;
382 debug_codeselection = 1;
383#endif
384
385 last_insn_size = 0;
386}
387
388/* Perform the main parsing, and assembly of the input here. Also,
389 call the required routines for alignment and fixups here.
390 This is called for every line that contains real assembly code. */
391
392void
393md_assemble (char *line)
394{
395 char *toP = 0;
396 extern char *current_inputline;
397 int size, insn_size;
398 struct bfin_insn *tmp_insn;
399 size_t len;
400 static size_t buffer_len = 0;
401 parse_state state;
402
403 len = strlen (line);
404 if (len + 2 > buffer_len)
405 {
406 if (buffer_len > 0)
407 free (current_inputline);
408 buffer_len = len + 40;
409 current_inputline = xmalloc (buffer_len);
410 }
411 memcpy (current_inputline, line, len);
412 current_inputline[len] = ';';
413 current_inputline[len + 1] = '\0';
414
415 state = parse (current_inputline);
416 if (state == NO_INSN_GENERATED)
417 return;
418
419 for (insn_size = 0, tmp_insn = insn; tmp_insn; tmp_insn = tmp_insn->next)
420 if (!tmp_insn->reloc || !tmp_insn->exp->symbol)
421 insn_size += 2;
422
423 if (insn_size)
424 toP = frag_more (insn_size);
425
426 last_insn_size = insn_size;
427
428#ifdef DEBUG
429 printf ("INS:");
430#endif
431 while (insn)
432 {
433 if (insn->reloc && insn->exp->symbol)
434 {
435 char *prev_toP = toP - 2;
436 switch (insn->reloc)
437 {
438 case BFD_RELOC_BFIN_24_PCREL_JUMP_L:
439 case BFD_RELOC_24_PCREL:
440 case BFD_RELOC_BFIN_16_LOW:
441 case BFD_RELOC_BFIN_16_HIGH:
442 size = 4;
443 break;
444 default:
445 size = 2;
446 }
447
448 /* Following if condition checks for the arithmetic relocations.
449 If the case then it doesn't required to generate the code.
450 It has been assumed that, their ID will be contiguous. */
451 if ((BFD_ARELOC_BFIN_PUSH <= insn->reloc
452 && BFD_ARELOC_BFIN_COMP >= insn->reloc)
453 || insn->reloc == BFD_RELOC_BFIN_16_IMM)
454 {
455 size = 2;
456 }
457 if (insn->reloc == BFD_ARELOC_BFIN_CONST
458 || insn->reloc == BFD_ARELOC_BFIN_PUSH)
459 size = 4;
460
461 fix_new (frag_now,
462 (prev_toP - frag_now->fr_literal),
463 size, insn->exp->symbol, insn->exp->value,
464 insn->pcrel, insn->reloc);
465 }
466 else
467 {
468 md_number_to_chars (toP, insn->value, 2);
469 toP += 2;
470 }
471
472#ifdef DEBUG
473 printf (" reloc :");
474 printf (" %02x%02x", ((unsigned char *) &insn->value)[0],
475 ((unsigned char *) &insn->value)[1]);
476 printf ("\n");
477#endif
478 insn = insn->next;
479 }
480#ifdef OBJ_ELF
481 dwarf2_emit_insn (insn_size);
482#endif
483}
484
485/* Parse one line of instructions, and generate opcode for it.
486 To parse the line, YACC and LEX are used, because the instruction set
487 syntax doesn't confirm to the AT&T assembly syntax.
488 To call a YACC & LEX generated parser, we must provide the input via
489 a FILE stream, otherwise stdin is used by default. Below the input
490 to the function will be put into a temporary file, then the generated
491 parser uses the temporary file for parsing. */
492
493static parse_state
494parse (char *line)
495{
496 parse_state state;
497 YY_BUFFER_STATE buffstate;
498
499 buffstate = yy_scan_string (line);
500
501 /* our lex requires setting the start state to keyword
502 every line as the first word may be a keyword.
503 Fixes a bug where we could not have keywords as labels. */
504 set_start_state ();
505
506 /* Call yyparse here. */
507 state = yyparse ();
508 if (state == SEMANTIC_ERROR)
509 {
bd3ba5d1 510 as_bad (_("Parse failed."));
07c1b327
CM
511 insn = 0;
512 }
513
514 yy_delete_buffer (buffstate);
515 return state;
516}
517
518/* We need to handle various expressions properly.
519 Such as, [SP--] = 34, concerned by md_assemble(). */
520
521void
522md_operand (expressionS * expressionP)
523{
524 if (*input_line_pointer == '[')
525 {
526 as_tsktsk ("We found a '['!");
527 input_line_pointer++;
528 expression (expressionP);
529 }
530}
531
532/* Handle undefined symbols. */
533symbolS *
534md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
535{
536 return (symbolS *) 0;
537}
538
539int
540md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
541 segT segment ATTRIBUTE_UNUSED)
542{
543 return 0;
544}
545
546/* Convert from target byte order to host byte order. */
547
548static int
9ba4c445 549md_chars_to_number (char *val, int n)
07c1b327
CM
550{
551 int retval;
552
553 for (retval = 0; n--;)
554 {
555 retval <<= 8;
556 retval |= val[n];
557 }
558 return retval;
559}
560
561void
562md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED)
563{
564 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
565
566 long value = *valueP;
567 long newval;
568
569 switch (fixP->fx_r_type)
570 {
571 case BFD_RELOC_BFIN_GOT:
1ac4baed
BS
572 case BFD_RELOC_BFIN_GOT17M4:
573 case BFD_RELOC_BFIN_FUNCDESC_GOT17M4:
07c1b327
CM
574 fixP->fx_no_overflow = 1;
575 newval = md_chars_to_number (where, 2);
576 newval |= 0x0 & 0x7f;
577 md_number_to_chars (where, newval, 2);
578 break;
579
580 case BFD_RELOC_BFIN_10_PCREL:
581 if (!value)
582 break;
583 if (value < -1024 || value > 1022)
584 as_bad_where (fixP->fx_file, fixP->fx_line,
bd3ba5d1 585 _("pcrel too far BFD_RELOC_BFIN_10"));
07c1b327
CM
586
587 /* 11 bit offset even numbered, so we remove right bit. */
588 value = value >> 1;
589 newval = md_chars_to_number (where, 2);
590 newval |= value & 0x03ff;
591 md_number_to_chars (where, newval, 2);
592 break;
593
594 case BFD_RELOC_BFIN_12_PCREL_JUMP:
595 case BFD_RELOC_BFIN_12_PCREL_JUMP_S:
596 case BFD_RELOC_12_PCREL:
597 if (!value)
598 break;
599
600 if (value < -4096 || value > 4094)
bd3ba5d1 601 as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far BFD_RELOC_BFIN_12"));
07c1b327
CM
602 /* 13 bit offset even numbered, so we remove right bit. */
603 value = value >> 1;
604 newval = md_chars_to_number (where, 2);
605 newval |= value & 0xfff;
606 md_number_to_chars (where, newval, 2);
607 break;
608
609 case BFD_RELOC_BFIN_16_LOW:
610 case BFD_RELOC_BFIN_16_HIGH:
611 fixP->fx_done = FALSE;
612 break;
613
614 case BFD_RELOC_BFIN_24_PCREL_JUMP_L:
615 case BFD_RELOC_BFIN_24_PCREL_CALL_X:
616 case BFD_RELOC_24_PCREL:
617 if (!value)
618 break;
619
620 if (value < -16777216 || value > 16777214)
bd3ba5d1 621 as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far BFD_RELOC_BFIN_24"));
07c1b327
CM
622
623 /* 25 bit offset even numbered, so we remove right bit. */
624 value = value >> 1;
625 value++;
626
627 md_number_to_chars (where - 2, value >> 16, 1);
628 md_number_to_chars (where, value, 1);
629 md_number_to_chars (where + 1, value >> 8, 1);
630 break;
631
632 case BFD_RELOC_BFIN_5_PCREL: /* LSETUP (a, b) : "a" */
633 if (!value)
634 break;
635 if (value < 4 || value > 30)
bd3ba5d1 636 as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far BFD_RELOC_BFIN_5"));
07c1b327
CM
637 value = value >> 1;
638 newval = md_chars_to_number (where, 1);
639 newval = (newval & 0xf0) | (value & 0xf);
640 md_number_to_chars (where, newval, 1);
641 break;
642
643 case BFD_RELOC_BFIN_11_PCREL: /* LSETUP (a, b) : "b" */
644 if (!value)
645 break;
646 value += 2;
647 if (value < 4 || value > 2046)
bd3ba5d1 648 as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far BFD_RELOC_BFIN_11_PCREL"));
07c1b327
CM
649 /* 11 bit unsigned even, so we remove right bit. */
650 value = value >> 1;
651 newval = md_chars_to_number (where, 2);
652 newval |= value & 0x03ff;
653 md_number_to_chars (where, newval, 2);
654 break;
655
656 case BFD_RELOC_8:
657 if (value < -0x80 || value >= 0x7f)
bd3ba5d1 658 as_bad_where (fixP->fx_file, fixP->fx_line, _("rel too far BFD_RELOC_8"));
07c1b327
CM
659 md_number_to_chars (where, value, 1);
660 break;
661
662 case BFD_RELOC_BFIN_16_IMM:
663 case BFD_RELOC_16:
664 if (value < -0x8000 || value >= 0x7fff)
bd3ba5d1 665 as_bad_where (fixP->fx_file, fixP->fx_line, _("rel too far BFD_RELOC_16"));
07c1b327
CM
666 md_number_to_chars (where, value, 2);
667 break;
668
669 case BFD_RELOC_32:
670 md_number_to_chars (where, value, 4);
671 break;
672
673 case BFD_RELOC_BFIN_PLTPC:
674 md_number_to_chars (where, value, 2);
675 break;
676
1ac4baed 677 case BFD_RELOC_BFIN_FUNCDESC:
07c1b327
CM
678 case BFD_RELOC_VTABLE_INHERIT:
679 case BFD_RELOC_VTABLE_ENTRY:
680 fixP->fx_done = FALSE;
681 break;
682
683 default:
684 if ((BFD_ARELOC_BFIN_PUSH > fixP->fx_r_type) || (BFD_ARELOC_BFIN_COMP < fixP->fx_r_type))
685 {
686 fprintf (stderr, "Relocation %d not handled in gas." " Contact support.\n", fixP->fx_r_type);
687 return;
688 }
689 }
690
691 if (!fixP->fx_addsy)
692 fixP->fx_done = TRUE;
693
694}
695
696/* Round up a section size to the appropriate boundary. */
697valueT
698md_section_align (segment, size)
699 segT segment;
700 valueT size;
701{
702 int boundary = bfd_get_section_alignment (stdoutput, segment);
703 return ((size + (1 << boundary) - 1) & (-1 << boundary));
704}
705
706
07c1b327 707char *
499ac353 708md_atof (int type, char * litP, int * sizeP)
07c1b327 709{
499ac353 710 return ieee_md_atof (type, litP, sizeP, FALSE);
07c1b327
CM
711}
712
713
714/* If while processing a fixup, a reloc really needs to be created
715 then it is done here. */
716
717arelent *
718tc_gen_reloc (seg, fixp)
719 asection *seg ATTRIBUTE_UNUSED;
720 fixS *fixp;
721{
722 arelent *reloc;
723
724 reloc = (arelent *) xmalloc (sizeof (arelent));
725 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
726 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
727 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
728
729 reloc->addend = fixp->fx_offset;
730 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
731
732 if (reloc->howto == (reloc_howto_type *) NULL)
733 {
734 as_bad_where (fixp->fx_file, fixp->fx_line,
735 /* xgettext:c-format. */
736 _("reloc %d not supported by object file format"),
737 (int) fixp->fx_r_type);
738
739 xfree (reloc);
740
741 return NULL;
742 }
743
744 return reloc;
745}
746
747/* The location from which a PC relative jump should be calculated,
748 given a PC relative reloc. */
749
750long
751md_pcrel_from_section (fixP, sec)
752 fixS *fixP;
753 segT sec;
754{
755 if (fixP->fx_addsy != (symbolS *) NULL
756 && (!S_IS_DEFINED (fixP->fx_addsy)
757 || S_GET_SEGMENT (fixP->fx_addsy) != sec))
758 {
759 /* The symbol is undefined (or is defined but not in this section).
760 Let the linker figure it out. */
761 return 0;
762 }
763 return fixP->fx_frag->fr_address + fixP->fx_where;
764}
765
766/* Return true if the fix can be handled by GAS, false if it must
767 be passed through to the linker. */
768
769bfd_boolean
770bfin_fix_adjustable (fixS *fixP)
771{
772 switch (fixP->fx_r_type)
773 {
774 /* Adjust_reloc_syms doesn't know about the GOT. */
1ac4baed
BS
775 case BFD_RELOC_BFIN_GOT:
776 case BFD_RELOC_BFIN_GOT17M4:
777 case BFD_RELOC_BFIN_FUNCDESC_GOT17M4:
778 case BFD_RELOC_BFIN_PLTPC:
07c1b327
CM
779 /* We need the symbol name for the VTABLE entries. */
780 case BFD_RELOC_VTABLE_INHERIT:
781 case BFD_RELOC_VTABLE_ENTRY:
782 return 0;
783
784 default:
785 return 1;
786 }
787}
788
789
790/* Handle the LOOP_BEGIN and LOOP_END statements.
791 Parse the Loop_Begin/Loop_End and create a label. */
792void
793bfin_start_line_hook ()
794{
795 bfd_boolean maybe_begin = FALSE;
796 bfd_boolean maybe_end = FALSE;
797
798 char *c1, *label_name;
799 symbolS *line_label;
800 char *c = input_line_pointer;
8b64503a 801 int cr_num = 0;
07c1b327
CM
802
803 while (ISSPACE (*c))
8b64503a
JZ
804 {
805 if (*c == '\n')
806 cr_num++;
807 c++;
808 }
07c1b327 809
07c1b327
CM
810 /* Look for Loop_Begin or Loop_End statements. */
811
812 if (*c != 'L' && *c != 'l')
813 return;
814
815 c++;
816 if (*c != 'O' && *c != 'o')
817 return;
818
819 c++;
820 if (*c != 'O' && *c != 'o')
821 return;
822
823 c++;
824 if (*c != 'P' && *c != 'p')
825 return;
826
827 c++;
828 if (*c != '_')
829 return;
830
831 c++;
832 if (*c == 'E' || *c == 'e')
833 maybe_end = TRUE;
834 else if (*c == 'B' || *c == 'b')
835 maybe_begin = TRUE;
836 else
837 return;
838
839 if (maybe_end)
840 {
841 c++;
842 if (*c != 'N' && *c != 'n')
843 return;
844
845 c++;
846 if (*c != 'D' && *c != 'd')
847 return;
848 }
849
850 if (maybe_begin)
851 {
852 c++;
853 if (*c != 'E' && *c != 'e')
854 return;
855
856 c++;
857 if (*c != 'G' && *c != 'g')
858 return;
859
860 c++;
861 if (*c != 'I' && *c != 'i')
862 return;
863
864 c++;
865 if (*c != 'N' && *c != 'n')
866 return;
867 }
868
869 c++;
870 while (ISSPACE (*c)) c++;
871 c1 = c;
872 while (ISALPHA (*c) || ISDIGIT (*c) || *c == '_') c++;
873
8b64503a
JZ
874 if (input_line_pointer[-1] == '\n')
875 bump_line_counters ();
876
877 while (cr_num--)
878 bump_line_counters ();
879
07c1b327
CM
880 input_line_pointer = c;
881 if (maybe_end)
882 {
e2c038d3 883 label_name = (char *) xmalloc ((c - c1) + strlen ("__END") + 5);
07c1b327 884 label_name[0] = 0;
e2c038d3 885 strcat (label_name, "L$L$");
07c1b327
CM
886 strncat (label_name, c1, c-c1);
887 strcat (label_name, "__END");
888 }
889 else /* maybe_begin. */
890 {
e2c038d3 891 label_name = (char *) xmalloc ((c - c1) + strlen ("__BEGIN") + 5);
07c1b327 892 label_name[0] = 0;
e2c038d3 893 strcat (label_name, "L$L$");
07c1b327
CM
894 strncat (label_name, c1, c-c1);
895 strcat (label_name, "__BEGIN");
896 }
897
898 line_label = colon (label_name);
899
900 /* Loop_End follows the last instruction in the loop.
901 Adjust label address. */
902 if (maybe_end)
e2c038d3 903 ((struct local_symbol *) line_label)->lsy_value -= last_insn_size;
07c1b327
CM
904}
905
906/* Special extra functions that help bfin-parse.y perform its job. */
907
07c1b327 908#include <assert.h>
07c1b327
CM
909
910struct obstack mempool;
911
912INSTR_T
913conscode (INSTR_T head, INSTR_T tail)
914{
915 if (!head)
916 return tail;
917 head->next = tail;
918 return head;
919}
920
921INSTR_T
922conctcode (INSTR_T head, INSTR_T tail)
923{
924 INSTR_T temp = (head);
925 if (!head)
926 return tail;
927 while (temp->next)
928 temp = temp->next;
929 temp->next = tail;
930
931 return head;
932}
933
934INSTR_T
935note_reloc (INSTR_T code, Expr_Node * symbol, int reloc, int pcrel)
936{
937 /* Assert that the symbol is not an operator. */
938 assert (symbol->type == Expr_Node_Reloc);
939
940 return note_reloc1 (code, symbol->value.s_value, reloc, pcrel);
941
942}
943
944INSTR_T
945note_reloc1 (INSTR_T code, const char *symbol, int reloc, int pcrel)
946{
947 code->reloc = reloc;
948 code->exp = mkexpr (0, symbol_find_or_make (symbol));
949 code->pcrel = pcrel;
950 return code;
951}
952
953INSTR_T
954note_reloc2 (INSTR_T code, const char *symbol, int reloc, int value, int pcrel)
955{
956 code->reloc = reloc;
957 code->exp = mkexpr (value, symbol_find_or_make (symbol));
958 code->pcrel = pcrel;
959 return code;
960}
961
962INSTR_T
963gencode (unsigned long x)
964{
965 INSTR_T cell = (INSTR_T) obstack_alloc (&mempool, sizeof (struct bfin_insn));
966 memset (cell, 0, sizeof (struct bfin_insn));
967 cell->value = (x);
968 return cell;
969}
970
971int reloc;
972int ninsns;
973int count_insns;
974
975static void *
976allocate (int n)
977{
978 return (void *) obstack_alloc (&mempool, n);
979}
980
981Expr_Node *
982Expr_Node_Create (Expr_Node_Type type,
983 Expr_Node_Value value,
984 Expr_Node *Left_Child,
985 Expr_Node *Right_Child)
986{
987
988
989 Expr_Node *node = (Expr_Node *) allocate (sizeof (Expr_Node));
990 node->type = type;
991 node->value = value;
992 node->Left_Child = Left_Child;
993 node->Right_Child = Right_Child;
994 return node;
995}
996
997static const char *con = ".__constant";
998static const char *op = ".__operator";
999static INSTR_T Expr_Node_Gen_Reloc_R (Expr_Node * head);
1000INSTR_T Expr_Node_Gen_Reloc (Expr_Node *head, int parent_reloc);
1001
1002INSTR_T
1003Expr_Node_Gen_Reloc (Expr_Node * head, int parent_reloc)
1004{
1005 /* Top level reloction expression generator VDSP style.
1006 If the relocation is just by itself, generate one item
1007 else generate this convoluted expression. */
1008
1009 INSTR_T note = NULL_CODE;
1010 INSTR_T note1 = NULL_CODE;
1011 int pcrel = 1; /* Is the parent reloc pcrelative?
1012 This calculation here and HOWTO should match. */
1013
1014 if (parent_reloc)
1015 {
1016 /* If it's 32 bit quantity then 16bit code needs to be added. */
1017 int value = 0;
1018
1019 if (head->type == Expr_Node_Constant)
1020 {
1021 /* If note1 is not null code, we have to generate a right
1022 aligned value for the constant. Otherwise the reloc is
1023 a part of the basic command and the yacc file
1024 generates this. */
1025 value = head->value.i_value;
1026 }
1027 switch (parent_reloc)
1028 {
708587a4 1029 /* Some relocations will need to allocate extra words. */
07c1b327
CM
1030 case BFD_RELOC_BFIN_16_IMM:
1031 case BFD_RELOC_BFIN_16_LOW:
1032 case BFD_RELOC_BFIN_16_HIGH:
1033 note1 = conscode (gencode (value), NULL_CODE);
1034 pcrel = 0;
1035 break;
1036 case BFD_RELOC_BFIN_PLTPC:
1037 note1 = conscode (gencode (value), NULL_CODE);
1038 pcrel = 0;
1039 break;
1040 case BFD_RELOC_16:
1041 case BFD_RELOC_BFIN_GOT:
1ac4baed
BS
1042 case BFD_RELOC_BFIN_GOT17M4:
1043 case BFD_RELOC_BFIN_FUNCDESC_GOT17M4:
07c1b327
CM
1044 note1 = conscode (gencode (value), NULL_CODE);
1045 pcrel = 0;
1046 break;
1047 case BFD_RELOC_24_PCREL:
1048 case BFD_RELOC_BFIN_24_PCREL_JUMP_L:
1049 case BFD_RELOC_BFIN_24_PCREL_CALL_X:
1050 /* These offsets are even numbered pcrel. */
1051 note1 = conscode (gencode (value >> 1), NULL_CODE);
1052 break;
1053 default:
1054 note1 = NULL_CODE;
1055 }
1056 }
1057 if (head->type == Expr_Node_Constant)
1058 note = note1;
1059 else if (head->type == Expr_Node_Reloc)
1060 {
1061 note = note_reloc1 (gencode (0), head->value.s_value, parent_reloc, pcrel);
1062 if (note1 != NULL_CODE)
1063 note = conscode (note1, note);
1064 }
beb6bfe8
BS
1065 else if (head->type == Expr_Node_Binop
1066 && (head->value.op_value == Expr_Op_Type_Add
1067 || head->value.op_value == Expr_Op_Type_Sub)
1068 && head->Left_Child->type == Expr_Node_Reloc
1069 && head->Right_Child->type == Expr_Node_Constant)
1070 {
1071 int val = head->Right_Child->value.i_value;
1072 if (head->value.op_value == Expr_Op_Type_Sub)
1073 val = -val;
1074 note = conscode (note_reloc2 (gencode (0), head->Left_Child->value.s_value,
1075 parent_reloc, val, 0),
1076 NULL_CODE);
1077 if (note1 != NULL_CODE)
1078 note = conscode (note1, note);
1079 }
07c1b327
CM
1080 else
1081 {
1082 /* Call the recursive function. */
1083 note = note_reloc1 (gencode (0), op, parent_reloc, pcrel);
1084 if (note1 != NULL_CODE)
1085 note = conscode (note1, note);
1086 note = conctcode (Expr_Node_Gen_Reloc_R (head), note);
1087 }
1088 return note;
1089}
1090
1091static INSTR_T
1092Expr_Node_Gen_Reloc_R (Expr_Node * head)
1093{
1094
1095 INSTR_T note = 0;
1096 INSTR_T note1 = 0;
1097
1098 switch (head->type)
1099 {
1100 case Expr_Node_Constant:
1101 note = conscode (note_reloc2 (gencode (0), con, BFD_ARELOC_BFIN_CONST, head->value.i_value, 0), NULL_CODE);
1102 break;
1103 case Expr_Node_Reloc:
1104 note = conscode (note_reloc (gencode (0), head, BFD_ARELOC_BFIN_PUSH, 0), NULL_CODE);
1105 break;
1106 case Expr_Node_Binop:
1107 note1 = conctcode (Expr_Node_Gen_Reloc_R (head->Left_Child), Expr_Node_Gen_Reloc_R (head->Right_Child));
1108 switch (head->value.op_value)
1109 {
1110 case Expr_Op_Type_Add:
1111 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_ADD, 0), NULL_CODE));
1112 break;
1113 case Expr_Op_Type_Sub:
1114 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_SUB, 0), NULL_CODE));
1115 break;
1116 case Expr_Op_Type_Mult:
1117 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_MULT, 0), NULL_CODE));
1118 break;
1119 case Expr_Op_Type_Div:
1120 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_DIV, 0), NULL_CODE));
1121 break;
1122 case Expr_Op_Type_Mod:
1123 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_MOD, 0), NULL_CODE));
1124 break;
1125 case Expr_Op_Type_Lshift:
1126 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LSHIFT, 0), NULL_CODE));
1127 break;
1128 case Expr_Op_Type_Rshift:
1129 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_RSHIFT, 0), NULL_CODE));
1130 break;
1131 case Expr_Op_Type_BAND:
1132 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_AND, 0), NULL_CODE));
1133 break;
1134 case Expr_Op_Type_BOR:
1135 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_OR, 0), NULL_CODE));
1136 break;
1137 case Expr_Op_Type_BXOR:
1138 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_XOR, 0), NULL_CODE));
1139 break;
1140 case Expr_Op_Type_LAND:
1141 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LAND, 0), NULL_CODE));
1142 break;
1143 case Expr_Op_Type_LOR:
1144 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LOR, 0), NULL_CODE));
1145 break;
1146 default:
df3e8017 1147 fprintf (stderr, "%s:%d:Unknown operator found for arithmetic" " relocation", __FILE__, __LINE__);
07c1b327
CM
1148
1149
1150 }
1151 break;
1152 case Expr_Node_Unop:
1153 note1 = conscode (Expr_Node_Gen_Reloc_R (head->Left_Child), NULL_CODE);
1154 switch (head->value.op_value)
1155 {
1156 case Expr_Op_Type_NEG:
1157 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_NEG, 0), NULL_CODE));
1158 break;
1159 case Expr_Op_Type_COMP:
1160 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_COMP, 0), NULL_CODE));
1161 break;
1162 default:
df3e8017 1163 fprintf (stderr, "%s:%d:Unknown operator found for arithmetic" " relocation", __FILE__, __LINE__);
07c1b327
CM
1164 }
1165 break;
1166 default:
1167 fprintf (stderr, "%s:%d:Unknown node expression found during " "arithmetic relocation generation", __FILE__, __LINE__);
1168 }
1169 return note;
1170}
1171
1172
1173/* Blackfin opcode generation. */
1174
1175/* These functions are called by the generated parser
1176 (from bfin-parse.y), the register type classification
1177 happens in bfin-lex.l. */
1178
1179#include "bfin-aux.h"
1180#include "opcode/bfin.h"
1181
1182#define INIT(t) t c_code = init_##t
1183#define ASSIGN(x) c_code.opcode |= ((x & c_code.mask_##x)<<c_code.bits_##x)
1184#define ASSIGN_R(x) c_code.opcode |= (((x ? (x->regno & CODE_MASK) : 0) & c_code.mask_##x)<<c_code.bits_##x)
1185
1186#define HI(x) ((x >> 16) & 0xffff)
1187#define LO(x) ((x ) & 0xffff)
1188
1189#define GROUP(x) ((x->regno & CLASS_MASK) >> 4)
1190
1191#define GEN_OPCODE32() \
1192 conscode (gencode (HI (c_code.opcode)), \
1193 conscode (gencode (LO (c_code.opcode)), NULL_CODE))
1194
1195#define GEN_OPCODE16() \
1196 conscode (gencode (c_code.opcode), NULL_CODE)
1197
1198
1199/* 32 BIT INSTRUCTIONS. */
1200
1201
1202/* DSP32 instruction generation. */
1203
1204INSTR_T
1205bfin_gen_dsp32mac (int op1, int MM, int mmod, int w1, int P,
1206 int h01, int h11, int h00, int h10, int op0,
1207 REG_T dst, REG_T src0, REG_T src1, int w0)
1208{
1209 INIT (DSP32Mac);
1210
1211 ASSIGN (op0);
1212 ASSIGN (op1);
1213 ASSIGN (MM);
1214 ASSIGN (mmod);
1215 ASSIGN (w0);
1216 ASSIGN (w1);
1217 ASSIGN (h01);
1218 ASSIGN (h11);
1219 ASSIGN (h00);
1220 ASSIGN (h10);
1221 ASSIGN (P);
1222
1223 /* If we have full reg assignments, mask out LSB to encode
1224 single or simultaneous even/odd register moves. */
1225 if (P)
1226 {
1227 dst->regno &= 0x06;
1228 }
1229
1230 ASSIGN_R (dst);
1231 ASSIGN_R (src0);
1232 ASSIGN_R (src1);
1233
1234 return GEN_OPCODE32 ();
1235}
1236
1237INSTR_T
1238bfin_gen_dsp32mult (int op1, int MM, int mmod, int w1, int P,
1239 int h01, int h11, int h00, int h10, int op0,
1240 REG_T dst, REG_T src0, REG_T src1, int w0)
1241{
1242 INIT (DSP32Mult);
1243
1244 ASSIGN (op0);
1245 ASSIGN (op1);
1246 ASSIGN (MM);
1247 ASSIGN (mmod);
1248 ASSIGN (w0);
1249 ASSIGN (w1);
1250 ASSIGN (h01);
1251 ASSIGN (h11);
1252 ASSIGN (h00);
1253 ASSIGN (h10);
1254 ASSIGN (P);
1255
1256 if (P)
1257 {
1258 dst->regno &= 0x06;
1259 }
1260
1261 ASSIGN_R (dst);
1262 ASSIGN_R (src0);
1263 ASSIGN_R (src1);
1264
1265 return GEN_OPCODE32 ();
1266}
1267
1268INSTR_T
1269bfin_gen_dsp32alu (int HL, int aopcde, int aop, int s, int x,
1270 REG_T dst0, REG_T dst1, REG_T src0, REG_T src1)
1271{
1272 INIT (DSP32Alu);
1273
1274 ASSIGN (HL);
1275 ASSIGN (aopcde);
1276 ASSIGN (aop);
1277 ASSIGN (s);
1278 ASSIGN (x);
1279 ASSIGN_R (dst0);
1280 ASSIGN_R (dst1);
1281 ASSIGN_R (src0);
1282 ASSIGN_R (src1);
1283
1284 return GEN_OPCODE32 ();
1285}
1286
1287INSTR_T
1288bfin_gen_dsp32shift (int sopcde, REG_T dst0, REG_T src0,
1289 REG_T src1, int sop, int HLs)
1290{
1291 INIT (DSP32Shift);
1292
1293 ASSIGN (sopcde);
1294 ASSIGN (sop);
1295 ASSIGN (HLs);
1296
1297 ASSIGN_R (dst0);
1298 ASSIGN_R (src0);
1299 ASSIGN_R (src1);
1300
1301 return GEN_OPCODE32 ();
1302}
1303
1304INSTR_T
1305bfin_gen_dsp32shiftimm (int sopcde, REG_T dst0, int immag,
1306 REG_T src1, int sop, int HLs)
1307{
1308 INIT (DSP32ShiftImm);
1309
1310 ASSIGN (sopcde);
1311 ASSIGN (sop);
1312 ASSIGN (HLs);
1313
1314 ASSIGN_R (dst0);
1315 ASSIGN (immag);
1316 ASSIGN_R (src1);
1317
1318 return GEN_OPCODE32 ();
1319}
1320
1321/* LOOP SETUP. */
1322
1323INSTR_T
1324bfin_gen_loopsetup (Expr_Node * psoffset, REG_T c, int rop,
1325 Expr_Node * peoffset, REG_T reg)
1326{
1327 int soffset, eoffset;
1328 INIT (LoopSetup);
1329
1330 soffset = (EXPR_VALUE (psoffset) >> 1);
1331 ASSIGN (soffset);
1332 eoffset = (EXPR_VALUE (peoffset) >> 1);
1333 ASSIGN (eoffset);
1334 ASSIGN (rop);
1335 ASSIGN_R (c);
1336 ASSIGN_R (reg);
1337
1338 return
1339 conscode (gencode (HI (c_code.opcode)),
1340 conctcode (Expr_Node_Gen_Reloc (psoffset, BFD_RELOC_BFIN_5_PCREL),
1341 conctcode (gencode (LO (c_code.opcode)), Expr_Node_Gen_Reloc (peoffset, BFD_RELOC_BFIN_11_PCREL))));
1342
1343}
1344
1345/* Call, Link. */
1346
1347INSTR_T
1348bfin_gen_calla (Expr_Node * addr, int S)
1349{
1350 int val;
1351 int high_val;
1352 int reloc = 0;
1353 INIT (CALLa);
1354
1355 switch(S){
1356 case 0 : reloc = BFD_RELOC_BFIN_24_PCREL_JUMP_L; break;
1357 case 1 : reloc = BFD_RELOC_24_PCREL; break;
1358 case 2 : reloc = BFD_RELOC_BFIN_PLTPC; break;
1359 default : break;
1360 }
1361
1362 ASSIGN (S);
1363
1364 val = EXPR_VALUE (addr) >> 1;
1365 high_val = val >> 16;
1366
1367 return conscode (gencode (HI (c_code.opcode) | (high_val & 0xff)),
1368 Expr_Node_Gen_Reloc (addr, reloc));
1369 }
1370
1371INSTR_T
1372bfin_gen_linkage (int R, int framesize)
1373{
1374 INIT (Linkage);
1375
1376 ASSIGN (R);
1377 ASSIGN (framesize);
1378
1379 return GEN_OPCODE32 ();
1380}
1381
1382
1383/* Load and Store. */
1384
1385INSTR_T
1386bfin_gen_ldimmhalf (REG_T reg, int H, int S, int Z, Expr_Node * phword, int reloc)
1387{
1388 int grp, hword;
1389 unsigned val = EXPR_VALUE (phword);
1390 INIT (LDIMMhalf);
1391
1392 ASSIGN (H);
1393 ASSIGN (S);
1394 ASSIGN (Z);
1395
1396 ASSIGN_R (reg);
1397 grp = (GROUP (reg));
1398 ASSIGN (grp);
1399 if (reloc == 2)
1400 {
1401 return conscode (gencode (HI (c_code.opcode)), Expr_Node_Gen_Reloc (phword, BFD_RELOC_BFIN_16_IMM));
1402 }
1403 else if (reloc == 1)
1404 {
1405 return conscode (gencode (HI (c_code.opcode)), Expr_Node_Gen_Reloc (phword, IS_H (*reg) ? BFD_RELOC_BFIN_16_HIGH : BFD_RELOC_BFIN_16_LOW));
1406 }
1407 else
1408 {
1409 hword = val;
1410 ASSIGN (hword);
1411 }
1412 return GEN_OPCODE32 ();
1413}
1414
1415INSTR_T
1416bfin_gen_ldstidxi (REG_T ptr, REG_T reg, int W, int sz, int Z, Expr_Node * poffset)
1417{
07c1b327
CM
1418 INIT (LDSTidxI);
1419
1420 if (!IS_PREG (*ptr) || (!IS_DREG (*reg) && !Z))
1421 {
1422 fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
1423 return 0;
1424 }
1425
1426 ASSIGN_R (ptr);
1427 ASSIGN_R (reg);
1428 ASSIGN (W);
1429 ASSIGN (sz);
07c1b327
CM
1430
1431 ASSIGN (Z);
1432
1ac4baed
BS
1433 if (poffset->type != Expr_Node_Constant)
1434 {
1435 /* a GOT relocation such as R0 = [P5 + symbol@GOT] */
1436 /* distinguish between R0 = [P5 + symbol@GOT] and
1437 P5 = [P5 + _current_shared_library_p5_offset_]
1438 */
1439 if (poffset->type == Expr_Node_Reloc
1440 && !strcmp (poffset->value.s_value,
1441 "_current_shared_library_p5_offset_"))
1442 {
1443 return conscode (gencode (HI (c_code.opcode)),
1444 Expr_Node_Gen_Reloc(poffset, BFD_RELOC_16));
1445 }
1446 else if (poffset->type != Expr_Node_GOT_Reloc)
1447 abort ();
1448
1449 return conscode (gencode (HI (c_code.opcode)),
1450 Expr_Node_Gen_Reloc(poffset->Left_Child,
1451 poffset->value.i_value));
07c1b327 1452 }
1ac4baed 1453 else
07c1b327 1454 {
1ac4baed
BS
1455 int value, offset;
1456 switch (sz)
1457 { // load/store access size
1458 case 0: // 32 bit
1459 value = EXPR_VALUE (poffset) >> 2;
1460 break;
1461 case 1: // 16 bit
1462 value = EXPR_VALUE (poffset) >> 1;
1463 break;
1464 case 2: // 8 bit
1465 value = EXPR_VALUE (poffset);
1466 break;
1467 default:
1468 abort ();
1469 }
1470
1471 offset = (value & 0xffff);
1472 ASSIGN (offset);
1473 return GEN_OPCODE32 ();
07c1b327 1474 }
07c1b327
CM
1475}
1476
1477
1478INSTR_T
1479bfin_gen_ldst (REG_T ptr, REG_T reg, int aop, int sz, int Z, int W)
1480{
1481 INIT (LDST);
1482
1483 if (!IS_PREG (*ptr) || (!IS_DREG (*reg) && !Z))
1484 {
1485 fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
1486 return 0;
1487 }
1488
1489 ASSIGN_R (ptr);
1490 ASSIGN_R (reg);
1491 ASSIGN (aop);
1492 ASSIGN (sz);
1493 ASSIGN (Z);
1494 ASSIGN (W);
1495
1496 return GEN_OPCODE16 ();
1497}
1498
1499INSTR_T
1500bfin_gen_ldstii (REG_T ptr, REG_T reg, Expr_Node * poffset, int W, int op)
1501{
1502 int offset;
1503 int value = 0;
1504 INIT (LDSTii);
1505
1506
1507 if (!IS_PREG (*ptr))
1508 {
1509 fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
1510 return 0;
1511 }
1512
1513 switch (op)
1514 {
1515 case 1:
1516 case 2:
1517 value = EXPR_VALUE (poffset) >> 1;
1518 break;
1519 case 0:
1520 case 3:
1521 value = EXPR_VALUE (poffset) >> 2;
1522 break;
1523 }
1524
1525 ASSIGN_R (ptr);
1526 ASSIGN_R (reg);
1527
1528 offset = value;
1529 ASSIGN (offset);
1530 ASSIGN (W);
1531 ASSIGN (op);
1532
1533 return GEN_OPCODE16 ();
1534}
1535
1536INSTR_T
1537bfin_gen_ldstiifp (REG_T sreg, Expr_Node * poffset, int W)
1538{
1539 /* Set bit 4 if it's a Preg. */
1540 int reg = (sreg->regno & CODE_MASK) | (IS_PREG (*sreg) ? 0x8 : 0x0);
1541 int offset = ((~(EXPR_VALUE (poffset) >> 2)) & 0x1f) + 1;
1542 INIT (LDSTiiFP);
1543 ASSIGN (reg);
1544 ASSIGN (offset);
1545 ASSIGN (W);
1546
1547 return GEN_OPCODE16 ();
1548}
1549
1550INSTR_T
1551bfin_gen_ldstpmod (REG_T ptr, REG_T reg, int aop, int W, REG_T idx)
1552{
1553 INIT (LDSTpmod);
1554
1555 ASSIGN_R (ptr);
1556 ASSIGN_R (reg);
1557 ASSIGN (aop);
1558 ASSIGN (W);
1559 ASSIGN_R (idx);
1560
1561 return GEN_OPCODE16 ();
1562}
1563
1564INSTR_T
1565bfin_gen_dspldst (REG_T i, REG_T reg, int aop, int W, int m)
1566{
1567 INIT (DspLDST);
1568
1569 ASSIGN_R (i);
1570 ASSIGN_R (reg);
1571 ASSIGN (aop);
1572 ASSIGN (W);
1573 ASSIGN (m);
1574
1575 return GEN_OPCODE16 ();
1576}
1577
1578INSTR_T
1579bfin_gen_logi2op (int opc, int src, int dst)
1580{
1581 INIT (LOGI2op);
1582
1583 ASSIGN (opc);
1584 ASSIGN (src);
1585 ASSIGN (dst);
1586
1587 return GEN_OPCODE16 ();
1588}
1589
1590INSTR_T
1591bfin_gen_brcc (int T, int B, Expr_Node * poffset)
1592{
1593 int offset;
1594 INIT (BRCC);
1595
1596 ASSIGN (T);
1597 ASSIGN (B);
1598 offset = ((EXPR_VALUE (poffset) >> 1));
1599 ASSIGN (offset);
1600 return conscode (gencode (c_code.opcode), Expr_Node_Gen_Reloc (poffset, BFD_RELOC_BFIN_10_PCREL));
1601}
1602
1603INSTR_T
1604bfin_gen_ujump (Expr_Node * poffset)
1605{
1606 int offset;
1607 INIT (UJump);
1608
1609 offset = ((EXPR_VALUE (poffset) >> 1));
1610 ASSIGN (offset);
1611
1612 return conscode (gencode (c_code.opcode),
1613 Expr_Node_Gen_Reloc (
1614 poffset, BFD_RELOC_BFIN_12_PCREL_JUMP_S));
1615}
1616
1617INSTR_T
1618bfin_gen_alu2op (REG_T dst, REG_T src, int opc)
1619{
1620 INIT (ALU2op);
1621
1622 ASSIGN_R (dst);
1623 ASSIGN_R (src);
1624 ASSIGN (opc);
1625
1626 return GEN_OPCODE16 ();
1627}
1628
1629INSTR_T
1630bfin_gen_compi2opd (REG_T dst, int src, int op)
1631{
1632 INIT (COMPI2opD);
1633
1634 ASSIGN_R (dst);
1635 ASSIGN (src);
1636 ASSIGN (op);
1637
1638 return GEN_OPCODE16 ();
1639}
1640
1641INSTR_T
1642bfin_gen_compi2opp (REG_T dst, int src, int op)
1643{
1644 INIT (COMPI2opP);
1645
1646 ASSIGN_R (dst);
1647 ASSIGN (src);
1648 ASSIGN (op);
1649
1650 return GEN_OPCODE16 ();
1651}
1652
1653INSTR_T
1654bfin_gen_dagmodik (REG_T i, int op)
1655{
1656 INIT (DagMODik);
1657
1658 ASSIGN_R (i);
1659 ASSIGN (op);
1660
1661 return GEN_OPCODE16 ();
1662}
1663
1664INSTR_T
1665bfin_gen_dagmodim (REG_T i, REG_T m, int op, int br)
1666{
1667 INIT (DagMODim);
1668
1669 ASSIGN_R (i);
1670 ASSIGN_R (m);
1671 ASSIGN (op);
1672 ASSIGN (br);
1673
1674 return GEN_OPCODE16 ();
1675}
1676
1677INSTR_T
1678bfin_gen_ptr2op (REG_T dst, REG_T src, int opc)
1679{
1680 INIT (PTR2op);
1681
1682 ASSIGN_R (dst);
1683 ASSIGN_R (src);
1684 ASSIGN (opc);
1685
1686 return GEN_OPCODE16 ();
1687}
1688
1689INSTR_T
1690bfin_gen_comp3op (REG_T src0, REG_T src1, REG_T dst, int opc)
1691{
1692 INIT (COMP3op);
1693
1694 ASSIGN_R (src0);
1695 ASSIGN_R (src1);
1696 ASSIGN_R (dst);
1697 ASSIGN (opc);
1698
1699 return GEN_OPCODE16 ();
1700}
1701
1702INSTR_T
1703bfin_gen_ccflag (REG_T x, int y, int opc, int I, int G)
1704{
1705 INIT (CCflag);
1706
1707 ASSIGN_R (x);
1708 ASSIGN (y);
1709 ASSIGN (opc);
1710 ASSIGN (I);
1711 ASSIGN (G);
1712
1713 return GEN_OPCODE16 ();
1714}
1715
1716INSTR_T
1717bfin_gen_ccmv (REG_T src, REG_T dst, int T)
1718{
1719 int s, d;
1720 INIT (CCmv);
1721
1722 ASSIGN_R (src);
1723 ASSIGN_R (dst);
1724 s = (GROUP (src));
1725 ASSIGN (s);
1726 d = (GROUP (dst));
1727 ASSIGN (d);
1728 ASSIGN (T);
1729
1730 return GEN_OPCODE16 ();
1731}
1732
1733INSTR_T
1734bfin_gen_cc2stat (int cbit, int op, int D)
1735{
1736 INIT (CC2stat);
1737
1738 ASSIGN (cbit);
1739 ASSIGN (op);
1740 ASSIGN (D);
1741
1742 return GEN_OPCODE16 ();
1743}
1744
1745INSTR_T
1746bfin_gen_regmv (REG_T src, REG_T dst)
1747{
1748 int gs, gd;
1749 INIT (RegMv);
1750
1751 ASSIGN_R (src);
1752 ASSIGN_R (dst);
1753
1754 gs = (GROUP (src));
1755 ASSIGN (gs);
1756 gd = (GROUP (dst));
1757 ASSIGN (gd);
1758
1759 return GEN_OPCODE16 ();
1760}
1761
1762INSTR_T
1763bfin_gen_cc2dreg (int op, REG_T reg)
1764{
1765 INIT (CC2dreg);
1766
1767 ASSIGN (op);
1768 ASSIGN_R (reg);
1769
1770 return GEN_OPCODE16 ();
1771}
1772
1773INSTR_T
1774bfin_gen_progctrl (int prgfunc, int poprnd)
1775{
1776 INIT (ProgCtrl);
1777
1778 ASSIGN (prgfunc);
1779 ASSIGN (poprnd);
1780
1781 return GEN_OPCODE16 ();
1782}
1783
1784INSTR_T
1785bfin_gen_cactrl (REG_T reg, int a, int op)
1786{
1787 INIT (CaCTRL);
1788
1789 ASSIGN_R (reg);
1790 ASSIGN (a);
1791 ASSIGN (op);
1792
1793 return GEN_OPCODE16 ();
1794}
1795
1796INSTR_T
1797bfin_gen_pushpopmultiple (int dr, int pr, int d, int p, int W)
1798{
1799 INIT (PushPopMultiple);
1800
1801 ASSIGN (dr);
1802 ASSIGN (pr);
1803 ASSIGN (d);
1804 ASSIGN (p);
1805 ASSIGN (W);
1806
1807 return GEN_OPCODE16 ();
1808}
1809
1810INSTR_T
1811bfin_gen_pushpopreg (REG_T reg, int W)
1812{
1813 int grp;
1814 INIT (PushPopReg);
1815
1816 ASSIGN_R (reg);
1817 grp = (GROUP (reg));
1818 ASSIGN (grp);
1819 ASSIGN (W);
1820
1821 return GEN_OPCODE16 ();
1822}
1823
1824/* Pseudo Debugging Support. */
1825
1826INSTR_T
1827bfin_gen_pseudodbg (int fn, int reg, int grp)
1828{
1829 INIT (PseudoDbg);
1830
1831 ASSIGN (fn);
1832 ASSIGN (reg);
1833 ASSIGN (grp);
1834
1835 return GEN_OPCODE16 ();
1836}
1837
1838INSTR_T
1839bfin_gen_pseudodbg_assert (int dbgop, REG_T regtest, int expected)
1840{
1841 INIT (PseudoDbg_Assert);
1842
1843 ASSIGN (dbgop);
1844 ASSIGN_R (regtest);
1845 ASSIGN (expected);
1846
1847 return GEN_OPCODE32 ();
1848}
1849
1850/* Multiple instruction generation. */
1851
1852INSTR_T
1853bfin_gen_multi_instr (INSTR_T dsp32, INSTR_T dsp16_grp1, INSTR_T dsp16_grp2)
1854{
1855 INSTR_T walk;
1856
1857 /* If it's a 0, convert into MNOP. */
1858 if (dsp32)
1859 {
1860 walk = dsp32->next;
1861 SET_MULTI_INSTRUCTION_BIT (dsp32);
1862 }
1863 else
1864 {
1865 dsp32 = gencode (0xc803);
1866 walk = gencode (0x1800);
1867 dsp32->next = walk;
1868 }
1869
1870 if (!dsp16_grp1)
1871 {
1872 dsp16_grp1 = gencode (0x0000);
1873 }
1874
1875 if (!dsp16_grp2)
1876 {
1877 dsp16_grp2 = gencode (0x0000);
1878 }
1879
1880 walk->next = dsp16_grp1;
1881 dsp16_grp1->next = dsp16_grp2;
1882 dsp16_grp2->next = NULL_CODE;
1883
1884 return dsp32;
1885}
1886
1887INSTR_T
1888bfin_gen_loop (Expr_Node *expr, REG_T reg, int rop, REG_T preg)
1889{
1890 const char *loopsym;
1891 char *lbeginsym, *lendsym;
1892 Expr_Node_Value lbeginval, lendval;
1893 Expr_Node *lbegin, *lend;
1894
1895 loopsym = expr->value.s_value;
e2c038d3
BS
1896 lbeginsym = (char *) xmalloc (strlen (loopsym) + strlen ("__BEGIN") + 5);
1897 lendsym = (char *) xmalloc (strlen (loopsym) + strlen ("__END") + 5);
07c1b327
CM
1898
1899 lbeginsym[0] = 0;
1900 lendsym[0] = 0;
1901
e2c038d3 1902 strcat (lbeginsym, "L$L$");
07c1b327
CM
1903 strcat (lbeginsym, loopsym);
1904 strcat (lbeginsym, "__BEGIN");
1905
e2c038d3 1906 strcat (lendsym, "L$L$");
07c1b327
CM
1907 strcat (lendsym, loopsym);
1908 strcat (lendsym, "__END");
1909
1910 lbeginval.s_value = lbeginsym;
1911 lendval.s_value = lendsym;
1912
1913 lbegin = Expr_Node_Create (Expr_Node_Reloc, lbeginval, NULL, NULL);
1914 lend = Expr_Node_Create (Expr_Node_Reloc, lendval, NULL, NULL);
1915 return bfin_gen_loopsetup(lbegin, reg, rop, lend, preg);
1916}
1917
1918bfd_boolean
1919bfin_eol_in_insn (char *line)
1920{
1921 /* Allow a new-line to appear in the middle of a multi-issue instruction. */
1922
1923 char *temp = line;
1924
1925 if (*line != '\n')
1926 return FALSE;
1927
1928 /* A semi-colon followed by a newline is always the end of a line. */
1929 if (line[-1] == ';')
1930 return FALSE;
1931
1932 if (line[-1] == '|')
1933 return TRUE;
1934
1935 /* If the || is on the next line, there might be leading whitespace. */
1936 temp++;
1937 while (*temp == ' ' || *temp == '\t') temp++;
1938
1939 if (*temp == '|')
1940 return TRUE;
1941
1942 return FALSE;
1943}
1944
07c1b327
CM
1945bfd_boolean
1946bfin_start_label (char *ptr)
1947{
1948 ptr--;
1949 while (!ISSPACE (*ptr) && !is_end_of_line[(unsigned char) *ptr])
1950 ptr--;
1951
1952 ptr++;
1953 if (*ptr == '(' || *ptr == '[')
1954 return FALSE;
1955
07c1b327
CM
1956 return TRUE;
1957}
1958
1959int
1960bfin_force_relocation (struct fix *fixp)
1961{
1962 if (fixp->fx_r_type ==BFD_RELOC_BFIN_16_LOW
1963 || fixp->fx_r_type == BFD_RELOC_BFIN_16_HIGH)
1964 return TRUE;
1965
1966 return generic_force_reloc (fixp);
1967}