1 /* tc-bfin.c -- Assembler for the ADI Blackfin.
3 Free Software Foundation, Inc.
5 This file is part of GAS, the GNU Assembler.
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)
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.
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
23 #include "struc-symbol.h"
25 #include "bfin-defs.h"
27 #include "safe-ctype.h"
29 #include "dwarf2dbg.h"
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));
41 /* Global variables. */
42 struct bfin_insn
*insn
;
45 extern struct obstack mempool
;
55 static const struct bfin_reg_entry bfin_reg_info
[] = {
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
},
186 {"ASTAT", REG_ASTAT
},
192 {"CYCLES", REG_CYCLES
},
193 {"CYCLES2", REG_CYCLES2
},
195 {"SEQSTAT", REG_SEQSTAT
},
196 {"SYSCFG", REG_SYSCFG
},
201 {"EMUDAT", REG_EMUDAT
},
206 const pseudo_typeS md_pseudo_table
[] = {
207 {"align", s_align_bytes
, 0},
210 {"code", obj_elf_section
, 0},
215 {"pdata", s_ignore
, 0},
216 {"var", s_ignore
, 0},
217 {"bss", bfin_s_bss
, 0},
222 bfin_s_bss (int ignore ATTRIBUTE_UNUSED
)
226 temp
= get_absolute_expression ();
227 subseg_set (bss_section
, (subsegT
) temp
);
228 demand_empty_rest_of_line ();
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
[] = ";";
237 /* Characters that can be used to separate the mantissa from the
238 exponent in floating point numbers. */
239 const char EXP_CHARS
[] = "eE";
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";
245 /* Define bfin-specific command-line options (there are none). */
246 const char *md_shortopts
= "";
248 struct option md_longopts
[] = {
249 {NULL
, no_argument
, NULL
, 0}
251 size_t md_longopts_size
= sizeof (md_longopts
);
255 md_parse_option (int c ATTRIBUTE_UNUSED
, char *arg ATTRIBUTE_UNUSED
)
261 md_show_usage (FILE * stream ATTRIBUTE_UNUSED
)
263 fprintf (stream
, _(" BFIN specific command line options:\n"));
266 /* Perform machine-specific initializations. */
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.");
274 /* Ensure that lines can begin with '(', for multiple
275 register stack pops. */
276 lex_type
['('] = LEX_BEGIN_NAME
;
279 record_alignment (text_section
, 2);
280 record_alignment (data_section
, 2);
281 record_alignment (bss_section
, 2);
285 obstack_init (&mempool
);
288 extern int debug_codeselection
;
289 debug_codeselection
= 1;
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. */
300 md_assemble (char *line
)
303 extern char *current_inputline
;
305 struct bfin_insn
*tmp_insn
;
307 static size_t buffer_len
= 0;
311 if (len
+ 2 > buffer_len
)
314 free (current_inputline
);
315 buffer_len
= len
+ 40;
316 current_inputline
= xmalloc (buffer_len
);
318 memcpy (current_inputline
, line
, len
);
319 current_inputline
[len
] = ';';
320 current_inputline
[len
+ 1] = '\0';
322 state
= parse (current_inputline
);
323 if (state
== NO_INSN_GENERATED
)
326 for (insn_size
= 0, tmp_insn
= insn
; tmp_insn
; tmp_insn
= tmp_insn
->next
)
327 if (!tmp_insn
->reloc
|| !tmp_insn
->exp
->symbol
)
331 toP
= frag_more (insn_size
);
333 last_insn_size
= insn_size
;
340 if (insn
->reloc
&& insn
->exp
->symbol
)
342 char *prev_toP
= toP
- 2;
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
:
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
)
364 if (insn
->reloc
== BFD_ARELOC_BFIN_CONST
365 || insn
->reloc
== BFD_ARELOC_BFIN_PUSH
)
369 (prev_toP
- frag_now
->fr_literal
),
370 size
, insn
->exp
->symbol
, insn
->exp
->value
,
371 insn
->pcrel
, insn
->reloc
);
375 md_number_to_chars (toP
, insn
->value
, 2);
381 printf (" %02x%02x", ((unsigned char *) &insn
->value
)[0],
382 ((unsigned char *) &insn
->value
)[1]);
388 dwarf2_emit_insn (insn_size
);
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. */
404 YY_BUFFER_STATE buffstate
;
406 buffstate
= yy_scan_string (line
);
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. */
413 /* Call yyparse here. */
415 if (state
== SEMANTIC_ERROR
)
417 as_bad ("Parse failed.");
421 yy_delete_buffer (buffstate
);
425 /* We need to handle various expressions properly.
426 Such as, [SP--] = 34, concerned by md_assemble(). */
429 md_operand (expressionS
* expressionP
)
431 if (*input_line_pointer
== '[')
433 as_tsktsk ("We found a '['!");
434 input_line_pointer
++;
435 expression (expressionP
);
439 /* Handle undefined symbols. */
441 md_undefined_symbol (char *name ATTRIBUTE_UNUSED
)
443 return (symbolS
*) 0;
447 md_estimate_size_before_relax (fragS
* fragP ATTRIBUTE_UNUSED
,
448 segT segment ATTRIBUTE_UNUSED
)
453 /* Convert from target byte order to host byte order. */
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. */
462 for (retval
= 0; n
--;)
471 md_apply_fix (fixS
*fixP
, valueT
*valueP
, segT seg ATTRIBUTE_UNUSED
)
473 char *where
= fixP
->fx_frag
->fr_literal
+ fixP
->fx_where
;
475 long value
= *valueP
;
478 switch (fixP
->fx_r_type
)
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);
487 case BFD_RELOC_BFIN_10_PCREL
:
490 if (value
< -1024 || value
> 1022)
491 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
492 "pcrel too far BFD_RELOC_BFIN_10");
494 /* 11 bit offset even numbered, so we remove right bit. */
496 newval
= md_chars_to_number (where
, 2);
497 newval
|= value
& 0x03ff;
498 md_number_to_chars (where
, newval
, 2);
501 case BFD_RELOC_BFIN_12_PCREL_JUMP
:
502 case BFD_RELOC_BFIN_12_PCREL_JUMP_S
:
503 case BFD_RELOC_12_PCREL
:
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. */
511 newval
= md_chars_to_number (where
, 2);
512 newval
|= value
& 0xfff;
513 md_number_to_chars (where
, newval
, 2);
516 case BFD_RELOC_BFIN_16_LOW
:
517 case BFD_RELOC_BFIN_16_HIGH
:
518 fixP
->fx_done
= FALSE
;
521 case BFD_RELOC_BFIN_24_PCREL_JUMP_L
:
522 case BFD_RELOC_BFIN_24_PCREL_CALL_X
:
523 case BFD_RELOC_24_PCREL
:
527 if (value
< -16777216 || value
> 16777214)
528 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, "pcrel too far BFD_RELOC_BFIN_24");
530 /* 25 bit offset even numbered, so we remove right bit. */
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);
539 case BFD_RELOC_BFIN_5_PCREL
: /* LSETUP (a, b) : "a" */
542 if (value
< 4 || value
> 30)
543 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, "pcrel too far BFD_RELOC_BFIN_5");
545 newval
= md_chars_to_number (where
, 1);
546 newval
= (newval
& 0xf0) | (value
& 0xf);
547 md_number_to_chars (where
, newval
, 1);
550 case BFD_RELOC_BFIN_11_PCREL
: /* LSETUP (a, b) : "b" */
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. */
558 newval
= md_chars_to_number (where
, 2);
559 newval
|= value
& 0x03ff;
560 md_number_to_chars (where
, newval
, 2);
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);
569 case BFD_RELOC_BFIN_16_IMM
:
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);
577 md_number_to_chars (where
, value
, 4);
580 case BFD_RELOC_BFIN_PLTPC
:
581 md_number_to_chars (where
, value
, 2);
584 case BFD_RELOC_VTABLE_INHERIT
:
585 case BFD_RELOC_VTABLE_ENTRY
:
586 fixP
->fx_done
= FALSE
;
590 if ((BFD_ARELOC_BFIN_PUSH
> fixP
->fx_r_type
) || (BFD_ARELOC_BFIN_COMP
< fixP
->fx_r_type
))
592 fprintf (stderr
, "Relocation %d not handled in gas." " Contact support.\n", fixP
->fx_r_type
);
598 fixP
->fx_done
= TRUE
;
602 /* Round up a section size to the appropriate boundary. */
604 md_section_align (segment
, size
)
608 int boundary
= bfd_get_section_alignment (stdoutput
, segment
);
609 return ((size
+ (1 << boundary
) - 1) & (-1 << boundary
));
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. */
618 /* Equal to MAX_PRECISION in atof-ieee.c. */
619 #define MAX_LITTLENUMS 6
622 md_atof (type
, litP
, sizeP
)
628 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
629 LITTLENUM_TYPE
*wordP
;
644 /* FIXME: Some targets allow other format chars for bigger sizes here. */
648 return _("Bad call to md_atof()");
651 t
= atof_ieee (input_line_pointer
, type
, words
);
653 input_line_pointer
= t
;
654 *sizeP
= prec
* sizeof (LITTLENUM_TYPE
);
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
--;)
661 md_number_to_chars (litP
, (valueT
) (*wordP
--), sizeof (LITTLENUM_TYPE
));
662 litP
+= sizeof (LITTLENUM_TYPE
);
669 /* If while processing a fixup, a reloc really needs to be created
670 then it is done here. */
673 tc_gen_reloc (seg
, fixp
)
674 asection
*seg ATTRIBUTE_UNUSED
;
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
;
684 reloc
->addend
= fixp
->fx_offset
;
685 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, fixp
->fx_r_type
);
687 if (reloc
->howto
== (reloc_howto_type
*) NULL
)
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
);
702 /* The location from which a PC relative jump should be calculated,
703 given a PC relative reloc. */
706 md_pcrel_from_section (fixP
, sec
)
710 if (fixP
->fx_addsy
!= (symbolS
*) NULL
711 && (!S_IS_DEFINED (fixP
->fx_addsy
)
712 || S_GET_SEGMENT (fixP
->fx_addsy
) != sec
))
714 /* The symbol is undefined (or is defined but not in this section).
715 Let the linker figure it out. */
718 return fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
721 /* Return true if the fix can be handled by GAS, false if it must
722 be passed through to the linker. */
725 bfin_fix_adjustable (fixS
*fixP
)
727 switch (fixP
->fx_r_type
)
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
:
743 /* Handle the LOOP_BEGIN and LOOP_END statements.
744 Parse the Loop_Begin/Loop_End and create a label. */
746 bfin_start_line_hook ()
748 bfd_boolean maybe_begin
= FALSE
;
749 bfd_boolean maybe_end
= FALSE
;
751 char *c1
, *label_name
;
753 char *c
= input_line_pointer
;
758 /* Look for Loop_Begin or Loop_End statements. */
760 if (*c
!= 'L' && *c
!= 'l')
764 if (*c
!= 'O' && *c
!= 'o')
768 if (*c
!= 'O' && *c
!= 'o')
772 if (*c
!= 'P' && *c
!= 'p')
780 if (*c
== 'E' || *c
== 'e')
782 else if (*c
== 'B' || *c
== 'b')
790 if (*c
!= 'N' && *c
!= 'n')
794 if (*c
!= 'D' && *c
!= 'd')
801 if (*c
!= 'E' && *c
!= 'e')
805 if (*c
!= 'G' && *c
!= 'g')
809 if (*c
!= 'I' && *c
!= 'i')
813 if (*c
!= 'N' && *c
!= 'n')
818 while (ISSPACE (*c
)) c
++;
820 while (ISALPHA (*c
) || ISDIGIT (*c
) || *c
== '_') c
++;
822 input_line_pointer
= c
;
825 label_name
= (char *) xmalloc ((c
- c1
) + strlen ("__END") + 1);
827 strncat (label_name
, c1
, c
-c1
);
828 strcat (label_name
, "__END");
830 else /* maybe_begin. */
832 label_name
= (char *) xmalloc ((c
- c1
) + strlen ("__BEGIN") + 1);
834 strncat (label_name
, c1
, c
-c1
);
835 strcat (label_name
, "__BEGIN");
838 line_label
= colon (label_name
);
840 /* Loop_End follows the last instruction in the loop.
841 Adjust label address. */
843 line_label
->sy_value
.X_add_number
-= last_insn_size
;
847 /* Special extra functions that help bfin-parse.y perform its job. */
853 #include "bfin-defs.h"
855 struct obstack mempool
;
858 conscode (INSTR_T head
, INSTR_T tail
)
867 conctcode (INSTR_T head
, INSTR_T tail
)
869 INSTR_T temp
= (head
);
880 note_reloc (INSTR_T code
, Expr_Node
* symbol
, int reloc
, int pcrel
)
882 /* Assert that the symbol is not an operator. */
883 assert (symbol
->type
== Expr_Node_Reloc
);
885 return note_reloc1 (code
, symbol
->value
.s_value
, reloc
, pcrel
);
890 note_reloc1 (INSTR_T code
, const char *symbol
, int reloc
, int pcrel
)
893 code
->exp
= mkexpr (0, symbol_find_or_make (symbol
));
899 note_reloc2 (INSTR_T code
, const char *symbol
, int reloc
, int value
, int pcrel
)
902 code
->exp
= mkexpr (value
, symbol_find_or_make (symbol
));
908 gencode (unsigned long x
)
910 INSTR_T cell
= (INSTR_T
) obstack_alloc (&mempool
, sizeof (struct bfin_insn
));
911 memset (cell
, 0, sizeof (struct bfin_insn
));
923 return (void *) obstack_alloc (&mempool
, n
);
927 Expr_Node_Create (Expr_Node_Type type
,
928 Expr_Node_Value value
,
929 Expr_Node
*Left_Child
,
930 Expr_Node
*Right_Child
)
934 Expr_Node
*node
= (Expr_Node
*) allocate (sizeof (Expr_Node
));
937 node
->Left_Child
= Left_Child
;
938 node
->Right_Child
= Right_Child
;
942 static const char *con
= ".__constant";
943 static const char *op
= ".__operator";
944 static INSTR_T
Expr_Node_Gen_Reloc_R (Expr_Node
* head
);
945 INSTR_T
Expr_Node_Gen_Reloc (Expr_Node
*head
, int parent_reloc
);
948 Expr_Node_Gen_Reloc (Expr_Node
* head
, int parent_reloc
)
950 /* Top level reloction expression generator VDSP style.
951 If the relocation is just by itself, generate one item
952 else generate this convoluted expression. */
954 INSTR_T note
= NULL_CODE
;
955 INSTR_T note1
= NULL_CODE
;
956 int pcrel
= 1; /* Is the parent reloc pcrelative?
957 This calculation here and HOWTO should match. */
961 /* If it's 32 bit quantity then 16bit code needs to be added. */
964 if (head
->type
== Expr_Node_Constant
)
966 /* If note1 is not null code, we have to generate a right
967 aligned value for the constant. Otherwise the reloc is
968 a part of the basic command and the yacc file
970 value
= head
->value
.i_value
;
972 switch (parent_reloc
)
974 /* Some reloctions will need to allocate extra words. */
975 case BFD_RELOC_BFIN_16_IMM
:
976 case BFD_RELOC_BFIN_16_LOW
:
977 case BFD_RELOC_BFIN_16_HIGH
:
978 note1
= conscode (gencode (value
), NULL_CODE
);
981 case BFD_RELOC_BFIN_PLTPC
:
982 note1
= conscode (gencode (value
), NULL_CODE
);
986 case BFD_RELOC_BFIN_GOT
:
987 note1
= conscode (gencode (value
), NULL_CODE
);
990 case BFD_RELOC_24_PCREL
:
991 case BFD_RELOC_BFIN_24_PCREL_JUMP_L
:
992 case BFD_RELOC_BFIN_24_PCREL_CALL_X
:
993 /* These offsets are even numbered pcrel. */
994 note1
= conscode (gencode (value
>> 1), NULL_CODE
);
1000 if (head
->type
== Expr_Node_Constant
)
1002 else if (head
->type
== Expr_Node_Reloc
)
1004 note
= note_reloc1 (gencode (0), head
->value
.s_value
, parent_reloc
, pcrel
);
1005 if (note1
!= NULL_CODE
)
1006 note
= conscode (note1
, note
);
1010 /* Call the recursive function. */
1011 note
= note_reloc1 (gencode (0), op
, parent_reloc
, pcrel
);
1012 if (note1
!= NULL_CODE
)
1013 note
= conscode (note1
, note
);
1014 note
= conctcode (Expr_Node_Gen_Reloc_R (head
), note
);
1020 Expr_Node_Gen_Reloc_R (Expr_Node
* head
)
1028 case Expr_Node_Constant
:
1029 note
= conscode (note_reloc2 (gencode (0), con
, BFD_ARELOC_BFIN_CONST
, head
->value
.i_value
, 0), NULL_CODE
);
1031 case Expr_Node_Reloc
:
1032 note
= conscode (note_reloc (gencode (0), head
, BFD_ARELOC_BFIN_PUSH
, 0), NULL_CODE
);
1034 case Expr_Node_Binop
:
1035 note1
= conctcode (Expr_Node_Gen_Reloc_R (head
->Left_Child
), Expr_Node_Gen_Reloc_R (head
->Right_Child
));
1036 switch (head
->value
.op_value
)
1038 case Expr_Op_Type_Add
:
1039 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_ADD
, 0), NULL_CODE
));
1041 case Expr_Op_Type_Sub
:
1042 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_SUB
, 0), NULL_CODE
));
1044 case Expr_Op_Type_Mult
:
1045 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_MULT
, 0), NULL_CODE
));
1047 case Expr_Op_Type_Div
:
1048 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_DIV
, 0), NULL_CODE
));
1050 case Expr_Op_Type_Mod
:
1051 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_MOD
, 0), NULL_CODE
));
1053 case Expr_Op_Type_Lshift
:
1054 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_LSHIFT
, 0), NULL_CODE
));
1056 case Expr_Op_Type_Rshift
:
1057 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_RSHIFT
, 0), NULL_CODE
));
1059 case Expr_Op_Type_BAND
:
1060 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_AND
, 0), NULL_CODE
));
1062 case Expr_Op_Type_BOR
:
1063 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_OR
, 0), NULL_CODE
));
1065 case Expr_Op_Type_BXOR
:
1066 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_XOR
, 0), NULL_CODE
));
1068 case Expr_Op_Type_LAND
:
1069 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_LAND
, 0), NULL_CODE
));
1071 case Expr_Op_Type_LOR
:
1072 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_LOR
, 0), NULL_CODE
));
1075 fprintf (stderr
, "%s:%d:Unkonwn operator found for arithmetic" " relocation", __FILE__
, __LINE__
);
1080 case Expr_Node_Unop
:
1081 note1
= conscode (Expr_Node_Gen_Reloc_R (head
->Left_Child
), NULL_CODE
);
1082 switch (head
->value
.op_value
)
1084 case Expr_Op_Type_NEG
:
1085 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_NEG
, 0), NULL_CODE
));
1087 case Expr_Op_Type_COMP
:
1088 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_COMP
, 0), NULL_CODE
));
1091 fprintf (stderr
, "%s:%d:Unkonwn operator found for arithmetic" " relocation", __FILE__
, __LINE__
);
1095 fprintf (stderr
, "%s:%d:Unknown node expression found during " "arithmetic relocation generation", __FILE__
, __LINE__
);
1101 /* Blackfin opcode generation. */
1103 /* These functions are called by the generated parser
1104 (from bfin-parse.y), the register type classification
1105 happens in bfin-lex.l. */
1107 #include "bfin-aux.h"
1108 #include "opcode/bfin.h"
1110 #define INIT(t) t c_code = init_##t
1111 #define ASSIGN(x) c_code.opcode |= ((x & c_code.mask_##x)<<c_code.bits_##x)
1112 #define ASSIGN_R(x) c_code.opcode |= (((x ? (x->regno & CODE_MASK) : 0) & c_code.mask_##x)<<c_code.bits_##x)
1114 #define HI(x) ((x >> 16) & 0xffff)
1115 #define LO(x) ((x ) & 0xffff)
1117 #define GROUP(x) ((x->regno & CLASS_MASK) >> 4)
1119 #define GEN_OPCODE32() \
1120 conscode (gencode (HI (c_code.opcode)), \
1121 conscode (gencode (LO (c_code.opcode)), NULL_CODE))
1123 #define GEN_OPCODE16() \
1124 conscode (gencode (c_code.opcode), NULL_CODE)
1127 /* 32 BIT INSTRUCTIONS. */
1130 /* DSP32 instruction generation. */
1133 bfin_gen_dsp32mac (int op1
, int MM
, int mmod
, int w1
, int P
,
1134 int h01
, int h11
, int h00
, int h10
, int op0
,
1135 REG_T dst
, REG_T src0
, REG_T src1
, int w0
)
1151 /* If we have full reg assignments, mask out LSB to encode
1152 single or simultaneous even/odd register moves. */
1162 return GEN_OPCODE32 ();
1166 bfin_gen_dsp32mult (int op1
, int MM
, int mmod
, int w1
, int P
,
1167 int h01
, int h11
, int h00
, int h10
, int op0
,
1168 REG_T dst
, REG_T src0
, REG_T src1
, int w0
)
1193 return GEN_OPCODE32 ();
1197 bfin_gen_dsp32alu (int HL
, int aopcde
, int aop
, int s
, int x
,
1198 REG_T dst0
, REG_T dst1
, REG_T src0
, REG_T src1
)
1212 return GEN_OPCODE32 ();
1216 bfin_gen_dsp32shift (int sopcde
, REG_T dst0
, REG_T src0
,
1217 REG_T src1
, int sop
, int HLs
)
1229 return GEN_OPCODE32 ();
1233 bfin_gen_dsp32shiftimm (int sopcde
, REG_T dst0
, int immag
,
1234 REG_T src1
, int sop
, int HLs
)
1236 INIT (DSP32ShiftImm
);
1246 return GEN_OPCODE32 ();
1252 bfin_gen_loopsetup (Expr_Node
* psoffset
, REG_T c
, int rop
,
1253 Expr_Node
* peoffset
, REG_T reg
)
1255 int soffset
, eoffset
;
1258 soffset
= (EXPR_VALUE (psoffset
) >> 1);
1260 eoffset
= (EXPR_VALUE (peoffset
) >> 1);
1267 conscode (gencode (HI (c_code
.opcode
)),
1268 conctcode (Expr_Node_Gen_Reloc (psoffset
, BFD_RELOC_BFIN_5_PCREL
),
1269 conctcode (gencode (LO (c_code
.opcode
)), Expr_Node_Gen_Reloc (peoffset
, BFD_RELOC_BFIN_11_PCREL
))));
1276 bfin_gen_calla (Expr_Node
* addr
, int S
)
1284 case 0 : reloc
= BFD_RELOC_BFIN_24_PCREL_JUMP_L
; break;
1285 case 1 : reloc
= BFD_RELOC_24_PCREL
; break;
1286 case 2 : reloc
= BFD_RELOC_BFIN_PLTPC
; break;
1292 val
= EXPR_VALUE (addr
) >> 1;
1293 high_val
= val
>> 16;
1295 return conscode (gencode (HI (c_code
.opcode
) | (high_val
& 0xff)),
1296 Expr_Node_Gen_Reloc (addr
, reloc
));
1300 bfin_gen_linkage (int R
, int framesize
)
1307 return GEN_OPCODE32 ();
1311 /* Load and Store. */
1314 bfin_gen_ldimmhalf (REG_T reg
, int H
, int S
, int Z
, Expr_Node
* phword
, int reloc
)
1317 unsigned val
= EXPR_VALUE (phword
);
1325 grp
= (GROUP (reg
));
1329 return conscode (gencode (HI (c_code
.opcode
)), Expr_Node_Gen_Reloc (phword
, BFD_RELOC_BFIN_16_IMM
));
1331 else if (reloc
== 1)
1333 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
));
1340 return GEN_OPCODE32 ();
1344 bfin_gen_ldstidxi (REG_T ptr
, REG_T reg
, int W
, int sz
, int Z
, Expr_Node
* poffset
)
1350 if (!IS_PREG (*ptr
) || (!IS_DREG (*reg
) && !Z
))
1352 fprintf (stderr
, "Warning: possible mixup of Preg/Dreg\n");
1363 value
= EXPR_VALUE (poffset
) >> 2;
1366 value
= EXPR_VALUE (poffset
) >> 1;
1369 value
= EXPR_VALUE (poffset
);
1376 offset
= (value
& 0xffff);
1378 /* TODO : test if you need to check this here.
1379 The reloc case should automatically generate instruction
1381 if(poffset
->type
!= Expr_Node_Constant
){
1382 /* A GOT relocation such as R0 = [P5 + symbol@GOT].
1383 Distinguish between R0 = [P5 + symbol@GOT] and
1384 P5 = [P5 + _current_shared_library_p5_offset_]. */
1385 if(!strcmp(poffset
->value
.s_value
, "_current_shared_library_p5_offset_")){
1386 return conscode (gencode (HI (c_code
.opcode
)),
1387 Expr_Node_Gen_Reloc(poffset
, BFD_RELOC_16
));
1391 return conscode (gencode (HI (c_code
.opcode
)),
1392 Expr_Node_Gen_Reloc(poffset
, BFD_RELOC_BFIN_GOT
));
1396 return GEN_OPCODE32 ();
1402 bfin_gen_ldst (REG_T ptr
, REG_T reg
, int aop
, int sz
, int Z
, int W
)
1406 if (!IS_PREG (*ptr
) || (!IS_DREG (*reg
) && !Z
))
1408 fprintf (stderr
, "Warning: possible mixup of Preg/Dreg\n");
1419 return GEN_OPCODE16 ();
1423 bfin_gen_ldstii (REG_T ptr
, REG_T reg
, Expr_Node
* poffset
, int W
, int op
)
1430 if (!IS_PREG (*ptr
))
1432 fprintf (stderr
, "Warning: possible mixup of Preg/Dreg\n");
1440 value
= EXPR_VALUE (poffset
) >> 1;
1444 value
= EXPR_VALUE (poffset
) >> 2;
1456 return GEN_OPCODE16 ();
1460 bfin_gen_ldstiifp (REG_T sreg
, Expr_Node
* poffset
, int W
)
1462 /* Set bit 4 if it's a Preg. */
1463 int reg
= (sreg
->regno
& CODE_MASK
) | (IS_PREG (*sreg
) ? 0x8 : 0x0);
1464 int offset
= ((~(EXPR_VALUE (poffset
) >> 2)) & 0x1f) + 1;
1470 return GEN_OPCODE16 ();
1474 bfin_gen_ldstpmod (REG_T ptr
, REG_T reg
, int aop
, int W
, REG_T idx
)
1484 return GEN_OPCODE16 ();
1488 bfin_gen_dspldst (REG_T i
, REG_T reg
, int aop
, int W
, int m
)
1498 return GEN_OPCODE16 ();
1502 bfin_gen_logi2op (int opc
, int src
, int dst
)
1510 return GEN_OPCODE16 ();
1514 bfin_gen_brcc (int T
, int B
, Expr_Node
* poffset
)
1521 offset
= ((EXPR_VALUE (poffset
) >> 1));
1523 return conscode (gencode (c_code
.opcode
), Expr_Node_Gen_Reloc (poffset
, BFD_RELOC_BFIN_10_PCREL
));
1527 bfin_gen_ujump (Expr_Node
* poffset
)
1532 offset
= ((EXPR_VALUE (poffset
) >> 1));
1535 return conscode (gencode (c_code
.opcode
),
1536 Expr_Node_Gen_Reloc (
1537 poffset
, BFD_RELOC_BFIN_12_PCREL_JUMP_S
));
1541 bfin_gen_alu2op (REG_T dst
, REG_T src
, int opc
)
1549 return GEN_OPCODE16 ();
1553 bfin_gen_compi2opd (REG_T dst
, int src
, int op
)
1561 return GEN_OPCODE16 ();
1565 bfin_gen_compi2opp (REG_T dst
, int src
, int op
)
1573 return GEN_OPCODE16 ();
1577 bfin_gen_dagmodik (REG_T i
, int op
)
1584 return GEN_OPCODE16 ();
1588 bfin_gen_dagmodim (REG_T i
, REG_T m
, int op
, int br
)
1597 return GEN_OPCODE16 ();
1601 bfin_gen_ptr2op (REG_T dst
, REG_T src
, int opc
)
1609 return GEN_OPCODE16 ();
1613 bfin_gen_comp3op (REG_T src0
, REG_T src1
, REG_T dst
, int opc
)
1622 return GEN_OPCODE16 ();
1626 bfin_gen_ccflag (REG_T x
, int y
, int opc
, int I
, int G
)
1636 return GEN_OPCODE16 ();
1640 bfin_gen_ccmv (REG_T src
, REG_T dst
, int T
)
1653 return GEN_OPCODE16 ();
1657 bfin_gen_cc2stat (int cbit
, int op
, int D
)
1665 return GEN_OPCODE16 ();
1669 bfin_gen_regmv (REG_T src
, REG_T dst
)
1682 return GEN_OPCODE16 ();
1686 bfin_gen_cc2dreg (int op
, REG_T reg
)
1693 return GEN_OPCODE16 ();
1697 bfin_gen_progctrl (int prgfunc
, int poprnd
)
1704 return GEN_OPCODE16 ();
1708 bfin_gen_cactrl (REG_T reg
, int a
, int op
)
1716 return GEN_OPCODE16 ();
1720 bfin_gen_pushpopmultiple (int dr
, int pr
, int d
, int p
, int W
)
1722 INIT (PushPopMultiple
);
1730 return GEN_OPCODE16 ();
1734 bfin_gen_pushpopreg (REG_T reg
, int W
)
1740 grp
= (GROUP (reg
));
1744 return GEN_OPCODE16 ();
1747 /* Pseudo Debugging Support. */
1750 bfin_gen_pseudodbg (int fn
, int reg
, int grp
)
1758 return GEN_OPCODE16 ();
1762 bfin_gen_pseudodbg_assert (int dbgop
, REG_T regtest
, int expected
)
1764 INIT (PseudoDbg_Assert
);
1770 return GEN_OPCODE32 ();
1773 /* Multiple instruction generation. */
1776 bfin_gen_multi_instr (INSTR_T dsp32
, INSTR_T dsp16_grp1
, INSTR_T dsp16_grp2
)
1780 /* If it's a 0, convert into MNOP. */
1784 SET_MULTI_INSTRUCTION_BIT (dsp32
);
1788 dsp32
= gencode (0xc803);
1789 walk
= gencode (0x1800);
1795 dsp16_grp1
= gencode (0x0000);
1800 dsp16_grp2
= gencode (0x0000);
1803 walk
->next
= dsp16_grp1
;
1804 dsp16_grp1
->next
= dsp16_grp2
;
1805 dsp16_grp2
->next
= NULL_CODE
;
1811 bfin_gen_loop (Expr_Node
*expr
, REG_T reg
, int rop
, REG_T preg
)
1813 const char *loopsym
;
1814 char *lbeginsym
, *lendsym
;
1815 Expr_Node_Value lbeginval
, lendval
;
1816 Expr_Node
*lbegin
, *lend
;
1818 loopsym
= expr
->value
.s_value
;
1819 lbeginsym
= (char *) xmalloc (strlen (loopsym
) + strlen ("__BEGIN") + 1);
1820 lendsym
= (char *) xmalloc (strlen (loopsym
) + strlen ("__END") + 1);
1825 strcat (lbeginsym
, loopsym
);
1826 strcat (lbeginsym
, "__BEGIN");
1828 strcat (lendsym
, loopsym
);
1829 strcat (lendsym
, "__END");
1831 lbeginval
.s_value
= lbeginsym
;
1832 lendval
.s_value
= lendsym
;
1834 lbegin
= Expr_Node_Create (Expr_Node_Reloc
, lbeginval
, NULL
, NULL
);
1835 lend
= Expr_Node_Create (Expr_Node_Reloc
, lendval
, NULL
, NULL
);
1836 return bfin_gen_loopsetup(lbegin
, reg
, rop
, lend
, preg
);
1840 bfin_eol_in_insn (char *line
)
1842 /* Allow a new-line to appear in the middle of a multi-issue instruction. */
1849 /* A semi-colon followed by a newline is always the end of a line. */
1850 if (line
[-1] == ';')
1853 if (line
[-1] == '|')
1856 /* If the || is on the next line, there might be leading whitespace. */
1858 while (*temp
== ' ' || *temp
== '\t') temp
++;
1867 bfin_name_is_register (char *name
)
1871 if (*name
== '[' || *name
== '(')
1874 if ((name
[0] == 'W' || name
[0] == 'w') && name
[1] == '[')
1877 if ((name
[0] == 'B' || name
[0] == 'b') && name
[1] == '[')
1880 for (i
=0; bfin_reg_info
[i
].name
!= 0; i
++)
1882 if (!strcasecmp (bfin_reg_info
[i
].name
, name
))
1889 bfin_equals (Expr_Node
*sym
)
1893 c
= input_line_pointer
;
1897 input_line_pointer
= c
;
1899 equals ((char *) sym
->value
.s_value
, 1);
1903 bfin_start_label (char *ptr
)
1906 while (!ISSPACE (*ptr
) && !is_end_of_line
[(unsigned char) *ptr
])
1910 if (*ptr
== '(' || *ptr
== '[')
1917 bfin_force_relocation (struct fix
*fixp
)
1919 if (fixp
->fx_r_type
==BFD_RELOC_BFIN_16_LOW
1920 || fixp
->fx_r_type
== BFD_RELOC_BFIN_16_HIGH
)
1923 return generic_force_reloc (fixp
);