]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-bfin.c
opcodes/
[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
693/* Turn a string in input_line_pointer into a floating point
694 constant of type type, and store the appropriate bytes in
695 *litP. The number of LITTLENUMS emitted is stored in *sizeP.
696 An error message is returned, or NULL on OK. */
697
698/* Equal to MAX_PRECISION in atof-ieee.c. */
699#define MAX_LITTLENUMS 6
700
701char *
702md_atof (type, litP, sizeP)
703 char type;
704 char * litP;
705 int * sizeP;
706{
707 int prec;
708 LITTLENUM_TYPE words [MAX_LITTLENUMS];
709 LITTLENUM_TYPE *wordP;
710 char * t;
711
712 switch (type)
713 {
714 case 'f':
715 case 'F':
716 prec = 2;
717 break;
718
719 case 'd':
720 case 'D':
721 prec = 4;
722 break;
723
724 /* FIXME: Some targets allow other format chars for bigger sizes here. */
725
726 default:
727 *sizeP = 0;
728 return _("Bad call to md_atof()");
729 }
730
731 t = atof_ieee (input_line_pointer, type, words);
732 if (t)
733 input_line_pointer = t;
734 *sizeP = prec * sizeof (LITTLENUM_TYPE);
735
736 *sizeP = prec * sizeof (LITTLENUM_TYPE);
737 /* This loops outputs the LITTLENUMs in REVERSE order; in accord with
738 the littleendianness of the processor. */
739 for (wordP = words + prec - 1; prec--;)
740 {
741 md_number_to_chars (litP, (valueT) (*wordP--), sizeof (LITTLENUM_TYPE));
742 litP += sizeof (LITTLENUM_TYPE);
743 }
744
745 return 0;
746}
747
748
749/* If while processing a fixup, a reloc really needs to be created
750 then it is done here. */
751
752arelent *
753tc_gen_reloc (seg, fixp)
754 asection *seg ATTRIBUTE_UNUSED;
755 fixS *fixp;
756{
757 arelent *reloc;
758
759 reloc = (arelent *) xmalloc (sizeof (arelent));
760 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
761 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
762 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
763
764 reloc->addend = fixp->fx_offset;
765 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
766
767 if (reloc->howto == (reloc_howto_type *) NULL)
768 {
769 as_bad_where (fixp->fx_file, fixp->fx_line,
770 /* xgettext:c-format. */
771 _("reloc %d not supported by object file format"),
772 (int) fixp->fx_r_type);
773
774 xfree (reloc);
775
776 return NULL;
777 }
778
779 return reloc;
780}
781
782/* The location from which a PC relative jump should be calculated,
783 given a PC relative reloc. */
784
785long
786md_pcrel_from_section (fixP, sec)
787 fixS *fixP;
788 segT sec;
789{
790 if (fixP->fx_addsy != (symbolS *) NULL
791 && (!S_IS_DEFINED (fixP->fx_addsy)
792 || S_GET_SEGMENT (fixP->fx_addsy) != sec))
793 {
794 /* The symbol is undefined (or is defined but not in this section).
795 Let the linker figure it out. */
796 return 0;
797 }
798 return fixP->fx_frag->fr_address + fixP->fx_where;
799}
800
801/* Return true if the fix can be handled by GAS, false if it must
802 be passed through to the linker. */
803
804bfd_boolean
805bfin_fix_adjustable (fixS *fixP)
806{
807 switch (fixP->fx_r_type)
808 {
809 /* Adjust_reloc_syms doesn't know about the GOT. */
1ac4baed
BS
810 case BFD_RELOC_BFIN_GOT:
811 case BFD_RELOC_BFIN_GOT17M4:
812 case BFD_RELOC_BFIN_FUNCDESC_GOT17M4:
813 case BFD_RELOC_BFIN_PLTPC:
07c1b327
CM
814 /* We need the symbol name for the VTABLE entries. */
815 case BFD_RELOC_VTABLE_INHERIT:
816 case BFD_RELOC_VTABLE_ENTRY:
817 return 0;
818
819 default:
820 return 1;
821 }
822}
823
824
825/* Handle the LOOP_BEGIN and LOOP_END statements.
826 Parse the Loop_Begin/Loop_End and create a label. */
827void
828bfin_start_line_hook ()
829{
830 bfd_boolean maybe_begin = FALSE;
831 bfd_boolean maybe_end = FALSE;
832
833 char *c1, *label_name;
834 symbolS *line_label;
835 char *c = input_line_pointer;
8b64503a 836 int cr_num = 0;
07c1b327
CM
837
838 while (ISSPACE (*c))
8b64503a
JZ
839 {
840 if (*c == '\n')
841 cr_num++;
842 c++;
843 }
07c1b327 844
07c1b327
CM
845 /* Look for Loop_Begin or Loop_End statements. */
846
847 if (*c != 'L' && *c != 'l')
848 return;
849
850 c++;
851 if (*c != 'O' && *c != 'o')
852 return;
853
854 c++;
855 if (*c != 'O' && *c != 'o')
856 return;
857
858 c++;
859 if (*c != 'P' && *c != 'p')
860 return;
861
862 c++;
863 if (*c != '_')
864 return;
865
866 c++;
867 if (*c == 'E' || *c == 'e')
868 maybe_end = TRUE;
869 else if (*c == 'B' || *c == 'b')
870 maybe_begin = TRUE;
871 else
872 return;
873
874 if (maybe_end)
875 {
876 c++;
877 if (*c != 'N' && *c != 'n')
878 return;
879
880 c++;
881 if (*c != 'D' && *c != 'd')
882 return;
883 }
884
885 if (maybe_begin)
886 {
887 c++;
888 if (*c != 'E' && *c != 'e')
889 return;
890
891 c++;
892 if (*c != 'G' && *c != 'g')
893 return;
894
895 c++;
896 if (*c != 'I' && *c != 'i')
897 return;
898
899 c++;
900 if (*c != 'N' && *c != 'n')
901 return;
902 }
903
904 c++;
905 while (ISSPACE (*c)) c++;
906 c1 = c;
907 while (ISALPHA (*c) || ISDIGIT (*c) || *c == '_') c++;
908
8b64503a
JZ
909 if (input_line_pointer[-1] == '\n')
910 bump_line_counters ();
911
912 while (cr_num--)
913 bump_line_counters ();
914
07c1b327
CM
915 input_line_pointer = c;
916 if (maybe_end)
917 {
918 label_name = (char *) xmalloc ((c - c1) + strlen ("__END") + 1);
919 label_name[0] = 0;
920 strncat (label_name, c1, c-c1);
921 strcat (label_name, "__END");
922 }
923 else /* maybe_begin. */
924 {
925 label_name = (char *) xmalloc ((c - c1) + strlen ("__BEGIN") + 1);
926 label_name[0] = 0;
927 strncat (label_name, c1, c-c1);
928 strcat (label_name, "__BEGIN");
929 }
930
931 line_label = colon (label_name);
932
933 /* Loop_End follows the last instruction in the loop.
934 Adjust label address. */
935 if (maybe_end)
936 line_label->sy_value.X_add_number -= last_insn_size;
937
938}
939
940/* Special extra functions that help bfin-parse.y perform its job. */
941
07c1b327 942#include <assert.h>
07c1b327
CM
943
944struct obstack mempool;
945
946INSTR_T
947conscode (INSTR_T head, INSTR_T tail)
948{
949 if (!head)
950 return tail;
951 head->next = tail;
952 return head;
953}
954
955INSTR_T
956conctcode (INSTR_T head, INSTR_T tail)
957{
958 INSTR_T temp = (head);
959 if (!head)
960 return tail;
961 while (temp->next)
962 temp = temp->next;
963 temp->next = tail;
964
965 return head;
966}
967
968INSTR_T
969note_reloc (INSTR_T code, Expr_Node * symbol, int reloc, int pcrel)
970{
971 /* Assert that the symbol is not an operator. */
972 assert (symbol->type == Expr_Node_Reloc);
973
974 return note_reloc1 (code, symbol->value.s_value, reloc, pcrel);
975
976}
977
978INSTR_T
979note_reloc1 (INSTR_T code, const char *symbol, int reloc, int pcrel)
980{
981 code->reloc = reloc;
982 code->exp = mkexpr (0, symbol_find_or_make (symbol));
983 code->pcrel = pcrel;
984 return code;
985}
986
987INSTR_T
988note_reloc2 (INSTR_T code, const char *symbol, int reloc, int value, int pcrel)
989{
990 code->reloc = reloc;
991 code->exp = mkexpr (value, symbol_find_or_make (symbol));
992 code->pcrel = pcrel;
993 return code;
994}
995
996INSTR_T
997gencode (unsigned long x)
998{
999 INSTR_T cell = (INSTR_T) obstack_alloc (&mempool, sizeof (struct bfin_insn));
1000 memset (cell, 0, sizeof (struct bfin_insn));
1001 cell->value = (x);
1002 return cell;
1003}
1004
1005int reloc;
1006int ninsns;
1007int count_insns;
1008
1009static void *
1010allocate (int n)
1011{
1012 return (void *) obstack_alloc (&mempool, n);
1013}
1014
1015Expr_Node *
1016Expr_Node_Create (Expr_Node_Type type,
1017 Expr_Node_Value value,
1018 Expr_Node *Left_Child,
1019 Expr_Node *Right_Child)
1020{
1021
1022
1023 Expr_Node *node = (Expr_Node *) allocate (sizeof (Expr_Node));
1024 node->type = type;
1025 node->value = value;
1026 node->Left_Child = Left_Child;
1027 node->Right_Child = Right_Child;
1028 return node;
1029}
1030
1031static const char *con = ".__constant";
1032static const char *op = ".__operator";
1033static INSTR_T Expr_Node_Gen_Reloc_R (Expr_Node * head);
1034INSTR_T Expr_Node_Gen_Reloc (Expr_Node *head, int parent_reloc);
1035
1036INSTR_T
1037Expr_Node_Gen_Reloc (Expr_Node * head, int parent_reloc)
1038{
1039 /* Top level reloction expression generator VDSP style.
1040 If the relocation is just by itself, generate one item
1041 else generate this convoluted expression. */
1042
1043 INSTR_T note = NULL_CODE;
1044 INSTR_T note1 = NULL_CODE;
1045 int pcrel = 1; /* Is the parent reloc pcrelative?
1046 This calculation here and HOWTO should match. */
1047
1048 if (parent_reloc)
1049 {
1050 /* If it's 32 bit quantity then 16bit code needs to be added. */
1051 int value = 0;
1052
1053 if (head->type == Expr_Node_Constant)
1054 {
1055 /* If note1 is not null code, we have to generate a right
1056 aligned value for the constant. Otherwise the reloc is
1057 a part of the basic command and the yacc file
1058 generates this. */
1059 value = head->value.i_value;
1060 }
1061 switch (parent_reloc)
1062 {
708587a4 1063 /* Some relocations will need to allocate extra words. */
07c1b327
CM
1064 case BFD_RELOC_BFIN_16_IMM:
1065 case BFD_RELOC_BFIN_16_LOW:
1066 case BFD_RELOC_BFIN_16_HIGH:
1067 note1 = conscode (gencode (value), NULL_CODE);
1068 pcrel = 0;
1069 break;
1070 case BFD_RELOC_BFIN_PLTPC:
1071 note1 = conscode (gencode (value), NULL_CODE);
1072 pcrel = 0;
1073 break;
1074 case BFD_RELOC_16:
1075 case BFD_RELOC_BFIN_GOT:
1ac4baed
BS
1076 case BFD_RELOC_BFIN_GOT17M4:
1077 case BFD_RELOC_BFIN_FUNCDESC_GOT17M4:
07c1b327
CM
1078 note1 = conscode (gencode (value), NULL_CODE);
1079 pcrel = 0;
1080 break;
1081 case BFD_RELOC_24_PCREL:
1082 case BFD_RELOC_BFIN_24_PCREL_JUMP_L:
1083 case BFD_RELOC_BFIN_24_PCREL_CALL_X:
1084 /* These offsets are even numbered pcrel. */
1085 note1 = conscode (gencode (value >> 1), NULL_CODE);
1086 break;
1087 default:
1088 note1 = NULL_CODE;
1089 }
1090 }
1091 if (head->type == Expr_Node_Constant)
1092 note = note1;
1093 else if (head->type == Expr_Node_Reloc)
1094 {
1095 note = note_reloc1 (gencode (0), head->value.s_value, parent_reloc, pcrel);
1096 if (note1 != NULL_CODE)
1097 note = conscode (note1, note);
1098 }
beb6bfe8
BS
1099 else if (head->type == Expr_Node_Binop
1100 && (head->value.op_value == Expr_Op_Type_Add
1101 || head->value.op_value == Expr_Op_Type_Sub)
1102 && head->Left_Child->type == Expr_Node_Reloc
1103 && head->Right_Child->type == Expr_Node_Constant)
1104 {
1105 int val = head->Right_Child->value.i_value;
1106 if (head->value.op_value == Expr_Op_Type_Sub)
1107 val = -val;
1108 note = conscode (note_reloc2 (gencode (0), head->Left_Child->value.s_value,
1109 parent_reloc, val, 0),
1110 NULL_CODE);
1111 if (note1 != NULL_CODE)
1112 note = conscode (note1, note);
1113 }
07c1b327
CM
1114 else
1115 {
1116 /* Call the recursive function. */
1117 note = note_reloc1 (gencode (0), op, parent_reloc, pcrel);
1118 if (note1 != NULL_CODE)
1119 note = conscode (note1, note);
1120 note = conctcode (Expr_Node_Gen_Reloc_R (head), note);
1121 }
1122 return note;
1123}
1124
1125static INSTR_T
1126Expr_Node_Gen_Reloc_R (Expr_Node * head)
1127{
1128
1129 INSTR_T note = 0;
1130 INSTR_T note1 = 0;
1131
1132 switch (head->type)
1133 {
1134 case Expr_Node_Constant:
1135 note = conscode (note_reloc2 (gencode (0), con, BFD_ARELOC_BFIN_CONST, head->value.i_value, 0), NULL_CODE);
1136 break;
1137 case Expr_Node_Reloc:
1138 note = conscode (note_reloc (gencode (0), head, BFD_ARELOC_BFIN_PUSH, 0), NULL_CODE);
1139 break;
1140 case Expr_Node_Binop:
1141 note1 = conctcode (Expr_Node_Gen_Reloc_R (head->Left_Child), Expr_Node_Gen_Reloc_R (head->Right_Child));
1142 switch (head->value.op_value)
1143 {
1144 case Expr_Op_Type_Add:
1145 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_ADD, 0), NULL_CODE));
1146 break;
1147 case Expr_Op_Type_Sub:
1148 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_SUB, 0), NULL_CODE));
1149 break;
1150 case Expr_Op_Type_Mult:
1151 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_MULT, 0), NULL_CODE));
1152 break;
1153 case Expr_Op_Type_Div:
1154 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_DIV, 0), NULL_CODE));
1155 break;
1156 case Expr_Op_Type_Mod:
1157 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_MOD, 0), NULL_CODE));
1158 break;
1159 case Expr_Op_Type_Lshift:
1160 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LSHIFT, 0), NULL_CODE));
1161 break;
1162 case Expr_Op_Type_Rshift:
1163 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_RSHIFT, 0), NULL_CODE));
1164 break;
1165 case Expr_Op_Type_BAND:
1166 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_AND, 0), NULL_CODE));
1167 break;
1168 case Expr_Op_Type_BOR:
1169 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_OR, 0), NULL_CODE));
1170 break;
1171 case Expr_Op_Type_BXOR:
1172 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_XOR, 0), NULL_CODE));
1173 break;
1174 case Expr_Op_Type_LAND:
1175 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LAND, 0), NULL_CODE));
1176 break;
1177 case Expr_Op_Type_LOR:
1178 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LOR, 0), NULL_CODE));
1179 break;
1180 default:
df3e8017 1181 fprintf (stderr, "%s:%d:Unknown operator found for arithmetic" " relocation", __FILE__, __LINE__);
07c1b327
CM
1182
1183
1184 }
1185 break;
1186 case Expr_Node_Unop:
1187 note1 = conscode (Expr_Node_Gen_Reloc_R (head->Left_Child), NULL_CODE);
1188 switch (head->value.op_value)
1189 {
1190 case Expr_Op_Type_NEG:
1191 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_NEG, 0), NULL_CODE));
1192 break;
1193 case Expr_Op_Type_COMP:
1194 note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_COMP, 0), NULL_CODE));
1195 break;
1196 default:
df3e8017 1197 fprintf (stderr, "%s:%d:Unknown operator found for arithmetic" " relocation", __FILE__, __LINE__);
07c1b327
CM
1198 }
1199 break;
1200 default:
1201 fprintf (stderr, "%s:%d:Unknown node expression found during " "arithmetic relocation generation", __FILE__, __LINE__);
1202 }
1203 return note;
1204}
1205
1206
1207/* Blackfin opcode generation. */
1208
1209/* These functions are called by the generated parser
1210 (from bfin-parse.y), the register type classification
1211 happens in bfin-lex.l. */
1212
1213#include "bfin-aux.h"
1214#include "opcode/bfin.h"
1215
1216#define INIT(t) t c_code = init_##t
1217#define ASSIGN(x) c_code.opcode |= ((x & c_code.mask_##x)<<c_code.bits_##x)
1218#define ASSIGN_R(x) c_code.opcode |= (((x ? (x->regno & CODE_MASK) : 0) & c_code.mask_##x)<<c_code.bits_##x)
1219
1220#define HI(x) ((x >> 16) & 0xffff)
1221#define LO(x) ((x ) & 0xffff)
1222
1223#define GROUP(x) ((x->regno & CLASS_MASK) >> 4)
1224
1225#define GEN_OPCODE32() \
1226 conscode (gencode (HI (c_code.opcode)), \
1227 conscode (gencode (LO (c_code.opcode)), NULL_CODE))
1228
1229#define GEN_OPCODE16() \
1230 conscode (gencode (c_code.opcode), NULL_CODE)
1231
1232
1233/* 32 BIT INSTRUCTIONS. */
1234
1235
1236/* DSP32 instruction generation. */
1237
1238INSTR_T
1239bfin_gen_dsp32mac (int op1, int MM, int mmod, int w1, int P,
1240 int h01, int h11, int h00, int h10, int op0,
1241 REG_T dst, REG_T src0, REG_T src1, int w0)
1242{
1243 INIT (DSP32Mac);
1244
1245 ASSIGN (op0);
1246 ASSIGN (op1);
1247 ASSIGN (MM);
1248 ASSIGN (mmod);
1249 ASSIGN (w0);
1250 ASSIGN (w1);
1251 ASSIGN (h01);
1252 ASSIGN (h11);
1253 ASSIGN (h00);
1254 ASSIGN (h10);
1255 ASSIGN (P);
1256
1257 /* If we have full reg assignments, mask out LSB to encode
1258 single or simultaneous even/odd register moves. */
1259 if (P)
1260 {
1261 dst->regno &= 0x06;
1262 }
1263
1264 ASSIGN_R (dst);
1265 ASSIGN_R (src0);
1266 ASSIGN_R (src1);
1267
1268 return GEN_OPCODE32 ();
1269}
1270
1271INSTR_T
1272bfin_gen_dsp32mult (int op1, int MM, int mmod, int w1, int P,
1273 int h01, int h11, int h00, int h10, int op0,
1274 REG_T dst, REG_T src0, REG_T src1, int w0)
1275{
1276 INIT (DSP32Mult);
1277
1278 ASSIGN (op0);
1279 ASSIGN (op1);
1280 ASSIGN (MM);
1281 ASSIGN (mmod);
1282 ASSIGN (w0);
1283 ASSIGN (w1);
1284 ASSIGN (h01);
1285 ASSIGN (h11);
1286 ASSIGN (h00);
1287 ASSIGN (h10);
1288 ASSIGN (P);
1289
1290 if (P)
1291 {
1292 dst->regno &= 0x06;
1293 }
1294
1295 ASSIGN_R (dst);
1296 ASSIGN_R (src0);
1297 ASSIGN_R (src1);
1298
1299 return GEN_OPCODE32 ();
1300}
1301
1302INSTR_T
1303bfin_gen_dsp32alu (int HL, int aopcde, int aop, int s, int x,
1304 REG_T dst0, REG_T dst1, REG_T src0, REG_T src1)
1305{
1306 INIT (DSP32Alu);
1307
1308 ASSIGN (HL);
1309 ASSIGN (aopcde);
1310 ASSIGN (aop);
1311 ASSIGN (s);
1312 ASSIGN (x);
1313 ASSIGN_R (dst0);
1314 ASSIGN_R (dst1);
1315 ASSIGN_R (src0);
1316 ASSIGN_R (src1);
1317
1318 return GEN_OPCODE32 ();
1319}
1320
1321INSTR_T
1322bfin_gen_dsp32shift (int sopcde, REG_T dst0, REG_T src0,
1323 REG_T src1, int sop, int HLs)
1324{
1325 INIT (DSP32Shift);
1326
1327 ASSIGN (sopcde);
1328 ASSIGN (sop);
1329 ASSIGN (HLs);
1330
1331 ASSIGN_R (dst0);
1332 ASSIGN_R (src0);
1333 ASSIGN_R (src1);
1334
1335 return GEN_OPCODE32 ();
1336}
1337
1338INSTR_T
1339bfin_gen_dsp32shiftimm (int sopcde, REG_T dst0, int immag,
1340 REG_T src1, int sop, int HLs)
1341{
1342 INIT (DSP32ShiftImm);
1343
1344 ASSIGN (sopcde);
1345 ASSIGN (sop);
1346 ASSIGN (HLs);
1347
1348 ASSIGN_R (dst0);
1349 ASSIGN (immag);
1350 ASSIGN_R (src1);
1351
1352 return GEN_OPCODE32 ();
1353}
1354
1355/* LOOP SETUP. */
1356
1357INSTR_T
1358bfin_gen_loopsetup (Expr_Node * psoffset, REG_T c, int rop,
1359 Expr_Node * peoffset, REG_T reg)
1360{
1361 int soffset, eoffset;
1362 INIT (LoopSetup);
1363
1364 soffset = (EXPR_VALUE (psoffset) >> 1);
1365 ASSIGN (soffset);
1366 eoffset = (EXPR_VALUE (peoffset) >> 1);
1367 ASSIGN (eoffset);
1368 ASSIGN (rop);
1369 ASSIGN_R (c);
1370 ASSIGN_R (reg);
1371
1372 return
1373 conscode (gencode (HI (c_code.opcode)),
1374 conctcode (Expr_Node_Gen_Reloc (psoffset, BFD_RELOC_BFIN_5_PCREL),
1375 conctcode (gencode (LO (c_code.opcode)), Expr_Node_Gen_Reloc (peoffset, BFD_RELOC_BFIN_11_PCREL))));
1376
1377}
1378
1379/* Call, Link. */
1380
1381INSTR_T
1382bfin_gen_calla (Expr_Node * addr, int S)
1383{
1384 int val;
1385 int high_val;
1386 int reloc = 0;
1387 INIT (CALLa);
1388
1389 switch(S){
1390 case 0 : reloc = BFD_RELOC_BFIN_24_PCREL_JUMP_L; break;
1391 case 1 : reloc = BFD_RELOC_24_PCREL; break;
1392 case 2 : reloc = BFD_RELOC_BFIN_PLTPC; break;
1393 default : break;
1394 }
1395
1396 ASSIGN (S);
1397
1398 val = EXPR_VALUE (addr) >> 1;
1399 high_val = val >> 16;
1400
1401 return conscode (gencode (HI (c_code.opcode) | (high_val & 0xff)),
1402 Expr_Node_Gen_Reloc (addr, reloc));
1403 }
1404
1405INSTR_T
1406bfin_gen_linkage (int R, int framesize)
1407{
1408 INIT (Linkage);
1409
1410 ASSIGN (R);
1411 ASSIGN (framesize);
1412
1413 return GEN_OPCODE32 ();
1414}
1415
1416
1417/* Load and Store. */
1418
1419INSTR_T
1420bfin_gen_ldimmhalf (REG_T reg, int H, int S, int Z, Expr_Node * phword, int reloc)
1421{
1422 int grp, hword;
1423 unsigned val = EXPR_VALUE (phword);
1424 INIT (LDIMMhalf);
1425
1426 ASSIGN (H);
1427 ASSIGN (S);
1428 ASSIGN (Z);
1429
1430 ASSIGN_R (reg);
1431 grp = (GROUP (reg));
1432 ASSIGN (grp);
1433 if (reloc == 2)
1434 {
1435 return conscode (gencode (HI (c_code.opcode)), Expr_Node_Gen_Reloc (phword, BFD_RELOC_BFIN_16_IMM));
1436 }
1437 else if (reloc == 1)
1438 {
1439 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));
1440 }
1441 else
1442 {
1443 hword = val;
1444 ASSIGN (hword);
1445 }
1446 return GEN_OPCODE32 ();
1447}
1448
1449INSTR_T
1450bfin_gen_ldstidxi (REG_T ptr, REG_T reg, int W, int sz, int Z, Expr_Node * poffset)
1451{
07c1b327
CM
1452 INIT (LDSTidxI);
1453
1454 if (!IS_PREG (*ptr) || (!IS_DREG (*reg) && !Z))
1455 {
1456 fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
1457 return 0;
1458 }
1459
1460 ASSIGN_R (ptr);
1461 ASSIGN_R (reg);
1462 ASSIGN (W);
1463 ASSIGN (sz);
07c1b327
CM
1464
1465 ASSIGN (Z);
1466
1ac4baed
BS
1467 if (poffset->type != Expr_Node_Constant)
1468 {
1469 /* a GOT relocation such as R0 = [P5 + symbol@GOT] */
1470 /* distinguish between R0 = [P5 + symbol@GOT] and
1471 P5 = [P5 + _current_shared_library_p5_offset_]
1472 */
1473 if (poffset->type == Expr_Node_Reloc
1474 && !strcmp (poffset->value.s_value,
1475 "_current_shared_library_p5_offset_"))
1476 {
1477 return conscode (gencode (HI (c_code.opcode)),
1478 Expr_Node_Gen_Reloc(poffset, BFD_RELOC_16));
1479 }
1480 else if (poffset->type != Expr_Node_GOT_Reloc)
1481 abort ();
1482
1483 return conscode (gencode (HI (c_code.opcode)),
1484 Expr_Node_Gen_Reloc(poffset->Left_Child,
1485 poffset->value.i_value));
07c1b327 1486 }
1ac4baed 1487 else
07c1b327 1488 {
1ac4baed
BS
1489 int value, offset;
1490 switch (sz)
1491 { // load/store access size
1492 case 0: // 32 bit
1493 value = EXPR_VALUE (poffset) >> 2;
1494 break;
1495 case 1: // 16 bit
1496 value = EXPR_VALUE (poffset) >> 1;
1497 break;
1498 case 2: // 8 bit
1499 value = EXPR_VALUE (poffset);
1500 break;
1501 default:
1502 abort ();
1503 }
1504
1505 offset = (value & 0xffff);
1506 ASSIGN (offset);
1507 return GEN_OPCODE32 ();
07c1b327 1508 }
07c1b327
CM
1509}
1510
1511
1512INSTR_T
1513bfin_gen_ldst (REG_T ptr, REG_T reg, int aop, int sz, int Z, int W)
1514{
1515 INIT (LDST);
1516
1517 if (!IS_PREG (*ptr) || (!IS_DREG (*reg) && !Z))
1518 {
1519 fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
1520 return 0;
1521 }
1522
1523 ASSIGN_R (ptr);
1524 ASSIGN_R (reg);
1525 ASSIGN (aop);
1526 ASSIGN (sz);
1527 ASSIGN (Z);
1528 ASSIGN (W);
1529
1530 return GEN_OPCODE16 ();
1531}
1532
1533INSTR_T
1534bfin_gen_ldstii (REG_T ptr, REG_T reg, Expr_Node * poffset, int W, int op)
1535{
1536 int offset;
1537 int value = 0;
1538 INIT (LDSTii);
1539
1540
1541 if (!IS_PREG (*ptr))
1542 {
1543 fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
1544 return 0;
1545 }
1546
1547 switch (op)
1548 {
1549 case 1:
1550 case 2:
1551 value = EXPR_VALUE (poffset) >> 1;
1552 break;
1553 case 0:
1554 case 3:
1555 value = EXPR_VALUE (poffset) >> 2;
1556 break;
1557 }
1558
1559 ASSIGN_R (ptr);
1560 ASSIGN_R (reg);
1561
1562 offset = value;
1563 ASSIGN (offset);
1564 ASSIGN (W);
1565 ASSIGN (op);
1566
1567 return GEN_OPCODE16 ();
1568}
1569
1570INSTR_T
1571bfin_gen_ldstiifp (REG_T sreg, Expr_Node * poffset, int W)
1572{
1573 /* Set bit 4 if it's a Preg. */
1574 int reg = (sreg->regno & CODE_MASK) | (IS_PREG (*sreg) ? 0x8 : 0x0);
1575 int offset = ((~(EXPR_VALUE (poffset) >> 2)) & 0x1f) + 1;
1576 INIT (LDSTiiFP);
1577 ASSIGN (reg);
1578 ASSIGN (offset);
1579 ASSIGN (W);
1580
1581 return GEN_OPCODE16 ();
1582}
1583
1584INSTR_T
1585bfin_gen_ldstpmod (REG_T ptr, REG_T reg, int aop, int W, REG_T idx)
1586{
1587 INIT (LDSTpmod);
1588
1589 ASSIGN_R (ptr);
1590 ASSIGN_R (reg);
1591 ASSIGN (aop);
1592 ASSIGN (W);
1593 ASSIGN_R (idx);
1594
1595 return GEN_OPCODE16 ();
1596}
1597
1598INSTR_T
1599bfin_gen_dspldst (REG_T i, REG_T reg, int aop, int W, int m)
1600{
1601 INIT (DspLDST);
1602
1603 ASSIGN_R (i);
1604 ASSIGN_R (reg);
1605 ASSIGN (aop);
1606 ASSIGN (W);
1607 ASSIGN (m);
1608
1609 return GEN_OPCODE16 ();
1610}
1611
1612INSTR_T
1613bfin_gen_logi2op (int opc, int src, int dst)
1614{
1615 INIT (LOGI2op);
1616
1617 ASSIGN (opc);
1618 ASSIGN (src);
1619 ASSIGN (dst);
1620
1621 return GEN_OPCODE16 ();
1622}
1623
1624INSTR_T
1625bfin_gen_brcc (int T, int B, Expr_Node * poffset)
1626{
1627 int offset;
1628 INIT (BRCC);
1629
1630 ASSIGN (T);
1631 ASSIGN (B);
1632 offset = ((EXPR_VALUE (poffset) >> 1));
1633 ASSIGN (offset);
1634 return conscode (gencode (c_code.opcode), Expr_Node_Gen_Reloc (poffset, BFD_RELOC_BFIN_10_PCREL));
1635}
1636
1637INSTR_T
1638bfin_gen_ujump (Expr_Node * poffset)
1639{
1640 int offset;
1641 INIT (UJump);
1642
1643 offset = ((EXPR_VALUE (poffset) >> 1));
1644 ASSIGN (offset);
1645
1646 return conscode (gencode (c_code.opcode),
1647 Expr_Node_Gen_Reloc (
1648 poffset, BFD_RELOC_BFIN_12_PCREL_JUMP_S));
1649}
1650
1651INSTR_T
1652bfin_gen_alu2op (REG_T dst, REG_T src, int opc)
1653{
1654 INIT (ALU2op);
1655
1656 ASSIGN_R (dst);
1657 ASSIGN_R (src);
1658 ASSIGN (opc);
1659
1660 return GEN_OPCODE16 ();
1661}
1662
1663INSTR_T
1664bfin_gen_compi2opd (REG_T dst, int src, int op)
1665{
1666 INIT (COMPI2opD);
1667
1668 ASSIGN_R (dst);
1669 ASSIGN (src);
1670 ASSIGN (op);
1671
1672 return GEN_OPCODE16 ();
1673}
1674
1675INSTR_T
1676bfin_gen_compi2opp (REG_T dst, int src, int op)
1677{
1678 INIT (COMPI2opP);
1679
1680 ASSIGN_R (dst);
1681 ASSIGN (src);
1682 ASSIGN (op);
1683
1684 return GEN_OPCODE16 ();
1685}
1686
1687INSTR_T
1688bfin_gen_dagmodik (REG_T i, int op)
1689{
1690 INIT (DagMODik);
1691
1692 ASSIGN_R (i);
1693 ASSIGN (op);
1694
1695 return GEN_OPCODE16 ();
1696}
1697
1698INSTR_T
1699bfin_gen_dagmodim (REG_T i, REG_T m, int op, int br)
1700{
1701 INIT (DagMODim);
1702
1703 ASSIGN_R (i);
1704 ASSIGN_R (m);
1705 ASSIGN (op);
1706 ASSIGN (br);
1707
1708 return GEN_OPCODE16 ();
1709}
1710
1711INSTR_T
1712bfin_gen_ptr2op (REG_T dst, REG_T src, int opc)
1713{
1714 INIT (PTR2op);
1715
1716 ASSIGN_R (dst);
1717 ASSIGN_R (src);
1718 ASSIGN (opc);
1719
1720 return GEN_OPCODE16 ();
1721}
1722
1723INSTR_T
1724bfin_gen_comp3op (REG_T src0, REG_T src1, REG_T dst, int opc)
1725{
1726 INIT (COMP3op);
1727
1728 ASSIGN_R (src0);
1729 ASSIGN_R (src1);
1730 ASSIGN_R (dst);
1731 ASSIGN (opc);
1732
1733 return GEN_OPCODE16 ();
1734}
1735
1736INSTR_T
1737bfin_gen_ccflag (REG_T x, int y, int opc, int I, int G)
1738{
1739 INIT (CCflag);
1740
1741 ASSIGN_R (x);
1742 ASSIGN (y);
1743 ASSIGN (opc);
1744 ASSIGN (I);
1745 ASSIGN (G);
1746
1747 return GEN_OPCODE16 ();
1748}
1749
1750INSTR_T
1751bfin_gen_ccmv (REG_T src, REG_T dst, int T)
1752{
1753 int s, d;
1754 INIT (CCmv);
1755
1756 ASSIGN_R (src);
1757 ASSIGN_R (dst);
1758 s = (GROUP (src));
1759 ASSIGN (s);
1760 d = (GROUP (dst));
1761 ASSIGN (d);
1762 ASSIGN (T);
1763
1764 return GEN_OPCODE16 ();
1765}
1766
1767INSTR_T
1768bfin_gen_cc2stat (int cbit, int op, int D)
1769{
1770 INIT (CC2stat);
1771
1772 ASSIGN (cbit);
1773 ASSIGN (op);
1774 ASSIGN (D);
1775
1776 return GEN_OPCODE16 ();
1777}
1778
1779INSTR_T
1780bfin_gen_regmv (REG_T src, REG_T dst)
1781{
1782 int gs, gd;
1783 INIT (RegMv);
1784
1785 ASSIGN_R (src);
1786 ASSIGN_R (dst);
1787
1788 gs = (GROUP (src));
1789 ASSIGN (gs);
1790 gd = (GROUP (dst));
1791 ASSIGN (gd);
1792
1793 return GEN_OPCODE16 ();
1794}
1795
1796INSTR_T
1797bfin_gen_cc2dreg (int op, REG_T reg)
1798{
1799 INIT (CC2dreg);
1800
1801 ASSIGN (op);
1802 ASSIGN_R (reg);
1803
1804 return GEN_OPCODE16 ();
1805}
1806
1807INSTR_T
1808bfin_gen_progctrl (int prgfunc, int poprnd)
1809{
1810 INIT (ProgCtrl);
1811
1812 ASSIGN (prgfunc);
1813 ASSIGN (poprnd);
1814
1815 return GEN_OPCODE16 ();
1816}
1817
1818INSTR_T
1819bfin_gen_cactrl (REG_T reg, int a, int op)
1820{
1821 INIT (CaCTRL);
1822
1823 ASSIGN_R (reg);
1824 ASSIGN (a);
1825 ASSIGN (op);
1826
1827 return GEN_OPCODE16 ();
1828}
1829
1830INSTR_T
1831bfin_gen_pushpopmultiple (int dr, int pr, int d, int p, int W)
1832{
1833 INIT (PushPopMultiple);
1834
1835 ASSIGN (dr);
1836 ASSIGN (pr);
1837 ASSIGN (d);
1838 ASSIGN (p);
1839 ASSIGN (W);
1840
1841 return GEN_OPCODE16 ();
1842}
1843
1844INSTR_T
1845bfin_gen_pushpopreg (REG_T reg, int W)
1846{
1847 int grp;
1848 INIT (PushPopReg);
1849
1850 ASSIGN_R (reg);
1851 grp = (GROUP (reg));
1852 ASSIGN (grp);
1853 ASSIGN (W);
1854
1855 return GEN_OPCODE16 ();
1856}
1857
1858/* Pseudo Debugging Support. */
1859
1860INSTR_T
1861bfin_gen_pseudodbg (int fn, int reg, int grp)
1862{
1863 INIT (PseudoDbg);
1864
1865 ASSIGN (fn);
1866 ASSIGN (reg);
1867 ASSIGN (grp);
1868
1869 return GEN_OPCODE16 ();
1870}
1871
1872INSTR_T
1873bfin_gen_pseudodbg_assert (int dbgop, REG_T regtest, int expected)
1874{
1875 INIT (PseudoDbg_Assert);
1876
1877 ASSIGN (dbgop);
1878 ASSIGN_R (regtest);
1879 ASSIGN (expected);
1880
1881 return GEN_OPCODE32 ();
1882}
1883
1884/* Multiple instruction generation. */
1885
1886INSTR_T
1887bfin_gen_multi_instr (INSTR_T dsp32, INSTR_T dsp16_grp1, INSTR_T dsp16_grp2)
1888{
1889 INSTR_T walk;
1890
1891 /* If it's a 0, convert into MNOP. */
1892 if (dsp32)
1893 {
1894 walk = dsp32->next;
1895 SET_MULTI_INSTRUCTION_BIT (dsp32);
1896 }
1897 else
1898 {
1899 dsp32 = gencode (0xc803);
1900 walk = gencode (0x1800);
1901 dsp32->next = walk;
1902 }
1903
1904 if (!dsp16_grp1)
1905 {
1906 dsp16_grp1 = gencode (0x0000);
1907 }
1908
1909 if (!dsp16_grp2)
1910 {
1911 dsp16_grp2 = gencode (0x0000);
1912 }
1913
1914 walk->next = dsp16_grp1;
1915 dsp16_grp1->next = dsp16_grp2;
1916 dsp16_grp2->next = NULL_CODE;
1917
1918 return dsp32;
1919}
1920
1921INSTR_T
1922bfin_gen_loop (Expr_Node *expr, REG_T reg, int rop, REG_T preg)
1923{
1924 const char *loopsym;
1925 char *lbeginsym, *lendsym;
1926 Expr_Node_Value lbeginval, lendval;
1927 Expr_Node *lbegin, *lend;
1928
1929 loopsym = expr->value.s_value;
1930 lbeginsym = (char *) xmalloc (strlen (loopsym) + strlen ("__BEGIN") + 1);
1931 lendsym = (char *) xmalloc (strlen (loopsym) + strlen ("__END") + 1);
1932
1933 lbeginsym[0] = 0;
1934 lendsym[0] = 0;
1935
1936 strcat (lbeginsym, loopsym);
1937 strcat (lbeginsym, "__BEGIN");
1938
1939 strcat (lendsym, loopsym);
1940 strcat (lendsym, "__END");
1941
1942 lbeginval.s_value = lbeginsym;
1943 lendval.s_value = lendsym;
1944
1945 lbegin = Expr_Node_Create (Expr_Node_Reloc, lbeginval, NULL, NULL);
1946 lend = Expr_Node_Create (Expr_Node_Reloc, lendval, NULL, NULL);
1947 return bfin_gen_loopsetup(lbegin, reg, rop, lend, preg);
1948}
1949
1950bfd_boolean
1951bfin_eol_in_insn (char *line)
1952{
1953 /* Allow a new-line to appear in the middle of a multi-issue instruction. */
1954
1955 char *temp = line;
1956
1957 if (*line != '\n')
1958 return FALSE;
1959
1960 /* A semi-colon followed by a newline is always the end of a line. */
1961 if (line[-1] == ';')
1962 return FALSE;
1963
1964 if (line[-1] == '|')
1965 return TRUE;
1966
1967 /* If the || is on the next line, there might be leading whitespace. */
1968 temp++;
1969 while (*temp == ' ' || *temp == '\t') temp++;
1970
1971 if (*temp == '|')
1972 return TRUE;
1973
1974 return FALSE;
1975}
1976
07c1b327
CM
1977bfd_boolean
1978bfin_start_label (char *ptr)
1979{
1980 ptr--;
1981 while (!ISSPACE (*ptr) && !is_end_of_line[(unsigned char) *ptr])
1982 ptr--;
1983
1984 ptr++;
1985 if (*ptr == '(' || *ptr == '[')
1986 return FALSE;
1987
07c1b327
CM
1988 return TRUE;
1989}
1990
1991int
1992bfin_force_relocation (struct fix *fixp)
1993{
1994 if (fixp->fx_r_type ==BFD_RELOC_BFIN_16_LOW
1995 || fixp->fx_r_type == BFD_RELOC_BFIN_16_HIGH)
1996 return TRUE;
1997
1998 return generic_force_reloc (fixp);
1999}