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