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