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 ((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 (char *val
, int n
)
460 for (retval
= 0; n
--;)
469 md_apply_fix (fixS
*fixP
, valueT
*valueP
, segT seg ATTRIBUTE_UNUSED
)
471 char *where
= fixP
->fx_frag
->fr_literal
+ fixP
->fx_where
;
473 long value
= *valueP
;
476 switch (fixP
->fx_r_type
)
478 case BFD_RELOC_BFIN_GOT
:
479 fixP
->fx_no_overflow
= 1;
480 newval
= md_chars_to_number (where
, 2);
481 newval
|= 0x0 & 0x7f;
482 md_number_to_chars (where
, newval
, 2);
485 case BFD_RELOC_BFIN_10_PCREL
:
488 if (value
< -1024 || value
> 1022)
489 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
490 "pcrel too far BFD_RELOC_BFIN_10");
492 /* 11 bit offset even numbered, so we remove right bit. */
494 newval
= md_chars_to_number (where
, 2);
495 newval
|= value
& 0x03ff;
496 md_number_to_chars (where
, newval
, 2);
499 case BFD_RELOC_BFIN_12_PCREL_JUMP
:
500 case BFD_RELOC_BFIN_12_PCREL_JUMP_S
:
501 case BFD_RELOC_12_PCREL
:
505 if (value
< -4096 || value
> 4094)
506 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, "pcrel too far BFD_RELOC_BFIN_12");
507 /* 13 bit offset even numbered, so we remove right bit. */
509 newval
= md_chars_to_number (where
, 2);
510 newval
|= value
& 0xfff;
511 md_number_to_chars (where
, newval
, 2);
514 case BFD_RELOC_BFIN_16_LOW
:
515 case BFD_RELOC_BFIN_16_HIGH
:
516 fixP
->fx_done
= FALSE
;
519 case BFD_RELOC_BFIN_24_PCREL_JUMP_L
:
520 case BFD_RELOC_BFIN_24_PCREL_CALL_X
:
521 case BFD_RELOC_24_PCREL
:
525 if (value
< -16777216 || value
> 16777214)
526 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, "pcrel too far BFD_RELOC_BFIN_24");
528 /* 25 bit offset even numbered, so we remove right bit. */
532 md_number_to_chars (where
- 2, value
>> 16, 1);
533 md_number_to_chars (where
, value
, 1);
534 md_number_to_chars (where
+ 1, value
>> 8, 1);
537 case BFD_RELOC_BFIN_5_PCREL
: /* LSETUP (a, b) : "a" */
540 if (value
< 4 || value
> 30)
541 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, "pcrel too far BFD_RELOC_BFIN_5");
543 newval
= md_chars_to_number (where
, 1);
544 newval
= (newval
& 0xf0) | (value
& 0xf);
545 md_number_to_chars (where
, newval
, 1);
548 case BFD_RELOC_BFIN_11_PCREL
: /* LSETUP (a, b) : "b" */
552 if (value
< 4 || value
> 2046)
553 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, "pcrel too far BFD_RELOC_BFIN_11_PCREL");
554 /* 11 bit unsigned even, so we remove right bit. */
556 newval
= md_chars_to_number (where
, 2);
557 newval
|= value
& 0x03ff;
558 md_number_to_chars (where
, newval
, 2);
562 if (value
< -0x80 || value
>= 0x7f)
563 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, "rel too far BFD_RELOC_8");
564 md_number_to_chars (where
, value
, 1);
567 case BFD_RELOC_BFIN_16_IMM
:
569 if (value
< -0x8000 || value
>= 0x7fff)
570 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, "rel too far BFD_RELOC_8");
571 md_number_to_chars (where
, value
, 2);
575 md_number_to_chars (where
, value
, 4);
578 case BFD_RELOC_BFIN_PLTPC
:
579 md_number_to_chars (where
, value
, 2);
582 case BFD_RELOC_VTABLE_INHERIT
:
583 case BFD_RELOC_VTABLE_ENTRY
:
584 fixP
->fx_done
= FALSE
;
588 if ((BFD_ARELOC_BFIN_PUSH
> fixP
->fx_r_type
) || (BFD_ARELOC_BFIN_COMP
< fixP
->fx_r_type
))
590 fprintf (stderr
, "Relocation %d not handled in gas." " Contact support.\n", fixP
->fx_r_type
);
596 fixP
->fx_done
= TRUE
;
600 /* Round up a section size to the appropriate boundary. */
602 md_section_align (segment
, size
)
606 int boundary
= bfd_get_section_alignment (stdoutput
, segment
);
607 return ((size
+ (1 << boundary
) - 1) & (-1 << boundary
));
611 /* Turn a string in input_line_pointer into a floating point
612 constant of type type, and store the appropriate bytes in
613 *litP. The number of LITTLENUMS emitted is stored in *sizeP.
614 An error message is returned, or NULL on OK. */
616 /* Equal to MAX_PRECISION in atof-ieee.c. */
617 #define MAX_LITTLENUMS 6
620 md_atof (type
, litP
, sizeP
)
626 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
627 LITTLENUM_TYPE
*wordP
;
642 /* FIXME: Some targets allow other format chars for bigger sizes here. */
646 return _("Bad call to md_atof()");
649 t
= atof_ieee (input_line_pointer
, type
, words
);
651 input_line_pointer
= t
;
652 *sizeP
= prec
* sizeof (LITTLENUM_TYPE
);
654 *sizeP
= prec
* sizeof (LITTLENUM_TYPE
);
655 /* This loops outputs the LITTLENUMs in REVERSE order; in accord with
656 the littleendianness of the processor. */
657 for (wordP
= words
+ prec
- 1; prec
--;)
659 md_number_to_chars (litP
, (valueT
) (*wordP
--), sizeof (LITTLENUM_TYPE
));
660 litP
+= sizeof (LITTLENUM_TYPE
);
667 /* If while processing a fixup, a reloc really needs to be created
668 then it is done here. */
671 tc_gen_reloc (seg
, fixp
)
672 asection
*seg ATTRIBUTE_UNUSED
;
677 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
678 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
679 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
680 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
682 reloc
->addend
= fixp
->fx_offset
;
683 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, fixp
->fx_r_type
);
685 if (reloc
->howto
== (reloc_howto_type
*) NULL
)
687 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
688 /* xgettext:c-format. */
689 _("reloc %d not supported by object file format"),
690 (int) fixp
->fx_r_type
);
700 /* The location from which a PC relative jump should be calculated,
701 given a PC relative reloc. */
704 md_pcrel_from_section (fixP
, sec
)
708 if (fixP
->fx_addsy
!= (symbolS
*) NULL
709 && (!S_IS_DEFINED (fixP
->fx_addsy
)
710 || S_GET_SEGMENT (fixP
->fx_addsy
) != sec
))
712 /* The symbol is undefined (or is defined but not in this section).
713 Let the linker figure it out. */
716 return fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
719 /* Return true if the fix can be handled by GAS, false if it must
720 be passed through to the linker. */
723 bfin_fix_adjustable (fixS
*fixP
)
725 switch (fixP
->fx_r_type
)
727 /* Adjust_reloc_syms doesn't know about the GOT. */
728 case BFD_RELOC_BFIN_GOT
:
729 case BFD_RELOC_BFIN_PLTPC
:
730 /* We need the symbol name for the VTABLE entries. */
731 case BFD_RELOC_VTABLE_INHERIT
:
732 case BFD_RELOC_VTABLE_ENTRY
:
741 /* Handle the LOOP_BEGIN and LOOP_END statements.
742 Parse the Loop_Begin/Loop_End and create a label. */
744 bfin_start_line_hook ()
746 bfd_boolean maybe_begin
= FALSE
;
747 bfd_boolean maybe_end
= FALSE
;
749 char *c1
, *label_name
;
751 char *c
= input_line_pointer
;
756 /* Look for Loop_Begin or Loop_End statements. */
758 if (*c
!= 'L' && *c
!= 'l')
762 if (*c
!= 'O' && *c
!= 'o')
766 if (*c
!= 'O' && *c
!= 'o')
770 if (*c
!= 'P' && *c
!= 'p')
778 if (*c
== 'E' || *c
== 'e')
780 else if (*c
== 'B' || *c
== 'b')
788 if (*c
!= 'N' && *c
!= 'n')
792 if (*c
!= 'D' && *c
!= 'd')
799 if (*c
!= 'E' && *c
!= 'e')
803 if (*c
!= 'G' && *c
!= 'g')
807 if (*c
!= 'I' && *c
!= 'i')
811 if (*c
!= 'N' && *c
!= 'n')
816 while (ISSPACE (*c
)) c
++;
818 while (ISALPHA (*c
) || ISDIGIT (*c
) || *c
== '_') c
++;
820 input_line_pointer
= c
;
823 label_name
= (char *) xmalloc ((c
- c1
) + strlen ("__END") + 1);
825 strncat (label_name
, c1
, c
-c1
);
826 strcat (label_name
, "__END");
828 else /* maybe_begin. */
830 label_name
= (char *) xmalloc ((c
- c1
) + strlen ("__BEGIN") + 1);
832 strncat (label_name
, c1
, c
-c1
);
833 strcat (label_name
, "__BEGIN");
836 line_label
= colon (label_name
);
838 /* Loop_End follows the last instruction in the loop.
839 Adjust label address. */
841 line_label
->sy_value
.X_add_number
-= last_insn_size
;
845 /* Special extra functions that help bfin-parse.y perform its job. */
851 #include "bfin-defs.h"
853 struct obstack mempool
;
856 conscode (INSTR_T head
, INSTR_T tail
)
865 conctcode (INSTR_T head
, INSTR_T tail
)
867 INSTR_T temp
= (head
);
878 note_reloc (INSTR_T code
, Expr_Node
* symbol
, int reloc
, int pcrel
)
880 /* Assert that the symbol is not an operator. */
881 assert (symbol
->type
== Expr_Node_Reloc
);
883 return note_reloc1 (code
, symbol
->value
.s_value
, reloc
, pcrel
);
888 note_reloc1 (INSTR_T code
, const char *symbol
, int reloc
, int pcrel
)
891 code
->exp
= mkexpr (0, symbol_find_or_make (symbol
));
897 note_reloc2 (INSTR_T code
, const char *symbol
, int reloc
, int value
, int pcrel
)
900 code
->exp
= mkexpr (value
, symbol_find_or_make (symbol
));
906 gencode (unsigned long x
)
908 INSTR_T cell
= (INSTR_T
) obstack_alloc (&mempool
, sizeof (struct bfin_insn
));
909 memset (cell
, 0, sizeof (struct bfin_insn
));
921 return (void *) obstack_alloc (&mempool
, n
);
925 Expr_Node_Create (Expr_Node_Type type
,
926 Expr_Node_Value value
,
927 Expr_Node
*Left_Child
,
928 Expr_Node
*Right_Child
)
932 Expr_Node
*node
= (Expr_Node
*) allocate (sizeof (Expr_Node
));
935 node
->Left_Child
= Left_Child
;
936 node
->Right_Child
= Right_Child
;
940 static const char *con
= ".__constant";
941 static const char *op
= ".__operator";
942 static INSTR_T
Expr_Node_Gen_Reloc_R (Expr_Node
* head
);
943 INSTR_T
Expr_Node_Gen_Reloc (Expr_Node
*head
, int parent_reloc
);
946 Expr_Node_Gen_Reloc (Expr_Node
* head
, int parent_reloc
)
948 /* Top level reloction expression generator VDSP style.
949 If the relocation is just by itself, generate one item
950 else generate this convoluted expression. */
952 INSTR_T note
= NULL_CODE
;
953 INSTR_T note1
= NULL_CODE
;
954 int pcrel
= 1; /* Is the parent reloc pcrelative?
955 This calculation here and HOWTO should match. */
959 /* If it's 32 bit quantity then 16bit code needs to be added. */
962 if (head
->type
== Expr_Node_Constant
)
964 /* If note1 is not null code, we have to generate a right
965 aligned value for the constant. Otherwise the reloc is
966 a part of the basic command and the yacc file
968 value
= head
->value
.i_value
;
970 switch (parent_reloc
)
972 /* Some reloctions will need to allocate extra words. */
973 case BFD_RELOC_BFIN_16_IMM
:
974 case BFD_RELOC_BFIN_16_LOW
:
975 case BFD_RELOC_BFIN_16_HIGH
:
976 note1
= conscode (gencode (value
), NULL_CODE
);
979 case BFD_RELOC_BFIN_PLTPC
:
980 note1
= conscode (gencode (value
), NULL_CODE
);
984 case BFD_RELOC_BFIN_GOT
:
985 note1
= conscode (gencode (value
), NULL_CODE
);
988 case BFD_RELOC_24_PCREL
:
989 case BFD_RELOC_BFIN_24_PCREL_JUMP_L
:
990 case BFD_RELOC_BFIN_24_PCREL_CALL_X
:
991 /* These offsets are even numbered pcrel. */
992 note1
= conscode (gencode (value
>> 1), NULL_CODE
);
998 if (head
->type
== Expr_Node_Constant
)
1000 else if (head
->type
== Expr_Node_Reloc
)
1002 note
= note_reloc1 (gencode (0), head
->value
.s_value
, parent_reloc
, pcrel
);
1003 if (note1
!= NULL_CODE
)
1004 note
= conscode (note1
, note
);
1008 /* Call the recursive function. */
1009 note
= note_reloc1 (gencode (0), op
, parent_reloc
, pcrel
);
1010 if (note1
!= NULL_CODE
)
1011 note
= conscode (note1
, note
);
1012 note
= conctcode (Expr_Node_Gen_Reloc_R (head
), note
);
1018 Expr_Node_Gen_Reloc_R (Expr_Node
* head
)
1026 case Expr_Node_Constant
:
1027 note
= conscode (note_reloc2 (gencode (0), con
, BFD_ARELOC_BFIN_CONST
, head
->value
.i_value
, 0), NULL_CODE
);
1029 case Expr_Node_Reloc
:
1030 note
= conscode (note_reloc (gencode (0), head
, BFD_ARELOC_BFIN_PUSH
, 0), NULL_CODE
);
1032 case Expr_Node_Binop
:
1033 note1
= conctcode (Expr_Node_Gen_Reloc_R (head
->Left_Child
), Expr_Node_Gen_Reloc_R (head
->Right_Child
));
1034 switch (head
->value
.op_value
)
1036 case Expr_Op_Type_Add
:
1037 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_ADD
, 0), NULL_CODE
));
1039 case Expr_Op_Type_Sub
:
1040 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_SUB
, 0), NULL_CODE
));
1042 case Expr_Op_Type_Mult
:
1043 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_MULT
, 0), NULL_CODE
));
1045 case Expr_Op_Type_Div
:
1046 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_DIV
, 0), NULL_CODE
));
1048 case Expr_Op_Type_Mod
:
1049 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_MOD
, 0), NULL_CODE
));
1051 case Expr_Op_Type_Lshift
:
1052 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_LSHIFT
, 0), NULL_CODE
));
1054 case Expr_Op_Type_Rshift
:
1055 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_RSHIFT
, 0), NULL_CODE
));
1057 case Expr_Op_Type_BAND
:
1058 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_AND
, 0), NULL_CODE
));
1060 case Expr_Op_Type_BOR
:
1061 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_OR
, 0), NULL_CODE
));
1063 case Expr_Op_Type_BXOR
:
1064 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_XOR
, 0), NULL_CODE
));
1066 case Expr_Op_Type_LAND
:
1067 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_LAND
, 0), NULL_CODE
));
1069 case Expr_Op_Type_LOR
:
1070 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_LOR
, 0), NULL_CODE
));
1073 fprintf (stderr
, "%s:%d:Unkonwn operator found for arithmetic" " relocation", __FILE__
, __LINE__
);
1078 case Expr_Node_Unop
:
1079 note1
= conscode (Expr_Node_Gen_Reloc_R (head
->Left_Child
), NULL_CODE
);
1080 switch (head
->value
.op_value
)
1082 case Expr_Op_Type_NEG
:
1083 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_NEG
, 0), NULL_CODE
));
1085 case Expr_Op_Type_COMP
:
1086 note
= conctcode (note1
, conscode (note_reloc1 (gencode (0), op
, BFD_ARELOC_BFIN_COMP
, 0), NULL_CODE
));
1089 fprintf (stderr
, "%s:%d:Unkonwn operator found for arithmetic" " relocation", __FILE__
, __LINE__
);
1093 fprintf (stderr
, "%s:%d:Unknown node expression found during " "arithmetic relocation generation", __FILE__
, __LINE__
);
1099 /* Blackfin opcode generation. */
1101 /* These functions are called by the generated parser
1102 (from bfin-parse.y), the register type classification
1103 happens in bfin-lex.l. */
1105 #include "bfin-aux.h"
1106 #include "opcode/bfin.h"
1108 #define INIT(t) t c_code = init_##t
1109 #define ASSIGN(x) c_code.opcode |= ((x & c_code.mask_##x)<<c_code.bits_##x)
1110 #define ASSIGN_R(x) c_code.opcode |= (((x ? (x->regno & CODE_MASK) : 0) & c_code.mask_##x)<<c_code.bits_##x)
1112 #define HI(x) ((x >> 16) & 0xffff)
1113 #define LO(x) ((x ) & 0xffff)
1115 #define GROUP(x) ((x->regno & CLASS_MASK) >> 4)
1117 #define GEN_OPCODE32() \
1118 conscode (gencode (HI (c_code.opcode)), \
1119 conscode (gencode (LO (c_code.opcode)), NULL_CODE))
1121 #define GEN_OPCODE16() \
1122 conscode (gencode (c_code.opcode), NULL_CODE)
1125 /* 32 BIT INSTRUCTIONS. */
1128 /* DSP32 instruction generation. */
1131 bfin_gen_dsp32mac (int op1
, int MM
, int mmod
, int w1
, int P
,
1132 int h01
, int h11
, int h00
, int h10
, int op0
,
1133 REG_T dst
, REG_T src0
, REG_T src1
, int w0
)
1149 /* If we have full reg assignments, mask out LSB to encode
1150 single or simultaneous even/odd register moves. */
1160 return GEN_OPCODE32 ();
1164 bfin_gen_dsp32mult (int op1
, int MM
, int mmod
, int w1
, int P
,
1165 int h01
, int h11
, int h00
, int h10
, int op0
,
1166 REG_T dst
, REG_T src0
, REG_T src1
, int w0
)
1191 return GEN_OPCODE32 ();
1195 bfin_gen_dsp32alu (int HL
, int aopcde
, int aop
, int s
, int x
,
1196 REG_T dst0
, REG_T dst1
, REG_T src0
, REG_T src1
)
1210 return GEN_OPCODE32 ();
1214 bfin_gen_dsp32shift (int sopcde
, REG_T dst0
, REG_T src0
,
1215 REG_T src1
, int sop
, int HLs
)
1227 return GEN_OPCODE32 ();
1231 bfin_gen_dsp32shiftimm (int sopcde
, REG_T dst0
, int immag
,
1232 REG_T src1
, int sop
, int HLs
)
1234 INIT (DSP32ShiftImm
);
1244 return GEN_OPCODE32 ();
1250 bfin_gen_loopsetup (Expr_Node
* psoffset
, REG_T c
, int rop
,
1251 Expr_Node
* peoffset
, REG_T reg
)
1253 int soffset
, eoffset
;
1256 soffset
= (EXPR_VALUE (psoffset
) >> 1);
1258 eoffset
= (EXPR_VALUE (peoffset
) >> 1);
1265 conscode (gencode (HI (c_code
.opcode
)),
1266 conctcode (Expr_Node_Gen_Reloc (psoffset
, BFD_RELOC_BFIN_5_PCREL
),
1267 conctcode (gencode (LO (c_code
.opcode
)), Expr_Node_Gen_Reloc (peoffset
, BFD_RELOC_BFIN_11_PCREL
))));
1274 bfin_gen_calla (Expr_Node
* addr
, int S
)
1282 case 0 : reloc
= BFD_RELOC_BFIN_24_PCREL_JUMP_L
; break;
1283 case 1 : reloc
= BFD_RELOC_24_PCREL
; break;
1284 case 2 : reloc
= BFD_RELOC_BFIN_PLTPC
; break;
1290 val
= EXPR_VALUE (addr
) >> 1;
1291 high_val
= val
>> 16;
1293 return conscode (gencode (HI (c_code
.opcode
) | (high_val
& 0xff)),
1294 Expr_Node_Gen_Reloc (addr
, reloc
));
1298 bfin_gen_linkage (int R
, int framesize
)
1305 return GEN_OPCODE32 ();
1309 /* Load and Store. */
1312 bfin_gen_ldimmhalf (REG_T reg
, int H
, int S
, int Z
, Expr_Node
* phword
, int reloc
)
1315 unsigned val
= EXPR_VALUE (phword
);
1323 grp
= (GROUP (reg
));
1327 return conscode (gencode (HI (c_code
.opcode
)), Expr_Node_Gen_Reloc (phword
, BFD_RELOC_BFIN_16_IMM
));
1329 else if (reloc
== 1)
1331 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
));
1338 return GEN_OPCODE32 ();
1342 bfin_gen_ldstidxi (REG_T ptr
, REG_T reg
, int W
, int sz
, int Z
, Expr_Node
* poffset
)
1348 if (!IS_PREG (*ptr
) || (!IS_DREG (*reg
) && !Z
))
1350 fprintf (stderr
, "Warning: possible mixup of Preg/Dreg\n");
1361 value
= EXPR_VALUE (poffset
) >> 2;
1364 value
= EXPR_VALUE (poffset
) >> 1;
1367 value
= EXPR_VALUE (poffset
);
1374 offset
= (value
& 0xffff);
1376 /* TODO : test if you need to check this here.
1377 The reloc case should automatically generate instruction
1379 if(poffset
->type
!= Expr_Node_Constant
){
1380 /* A GOT relocation such as R0 = [P5 + symbol@GOT].
1381 Distinguish between R0 = [P5 + symbol@GOT] and
1382 P5 = [P5 + _current_shared_library_p5_offset_]. */
1383 if(!strcmp(poffset
->value
.s_value
, "_current_shared_library_p5_offset_")){
1384 return conscode (gencode (HI (c_code
.opcode
)),
1385 Expr_Node_Gen_Reloc(poffset
, BFD_RELOC_16
));
1389 return conscode (gencode (HI (c_code
.opcode
)),
1390 Expr_Node_Gen_Reloc(poffset
, BFD_RELOC_BFIN_GOT
));
1394 return GEN_OPCODE32 ();
1400 bfin_gen_ldst (REG_T ptr
, REG_T reg
, int aop
, int sz
, int Z
, int W
)
1404 if (!IS_PREG (*ptr
) || (!IS_DREG (*reg
) && !Z
))
1406 fprintf (stderr
, "Warning: possible mixup of Preg/Dreg\n");
1417 return GEN_OPCODE16 ();
1421 bfin_gen_ldstii (REG_T ptr
, REG_T reg
, Expr_Node
* poffset
, int W
, int op
)
1428 if (!IS_PREG (*ptr
))
1430 fprintf (stderr
, "Warning: possible mixup of Preg/Dreg\n");
1438 value
= EXPR_VALUE (poffset
) >> 1;
1442 value
= EXPR_VALUE (poffset
) >> 2;
1454 return GEN_OPCODE16 ();
1458 bfin_gen_ldstiifp (REG_T sreg
, Expr_Node
* poffset
, int W
)
1460 /* Set bit 4 if it's a Preg. */
1461 int reg
= (sreg
->regno
& CODE_MASK
) | (IS_PREG (*sreg
) ? 0x8 : 0x0);
1462 int offset
= ((~(EXPR_VALUE (poffset
) >> 2)) & 0x1f) + 1;
1468 return GEN_OPCODE16 ();
1472 bfin_gen_ldstpmod (REG_T ptr
, REG_T reg
, int aop
, int W
, REG_T idx
)
1482 return GEN_OPCODE16 ();
1486 bfin_gen_dspldst (REG_T i
, REG_T reg
, int aop
, int W
, int m
)
1496 return GEN_OPCODE16 ();
1500 bfin_gen_logi2op (int opc
, int src
, int dst
)
1508 return GEN_OPCODE16 ();
1512 bfin_gen_brcc (int T
, int B
, Expr_Node
* poffset
)
1519 offset
= ((EXPR_VALUE (poffset
) >> 1));
1521 return conscode (gencode (c_code
.opcode
), Expr_Node_Gen_Reloc (poffset
, BFD_RELOC_BFIN_10_PCREL
));
1525 bfin_gen_ujump (Expr_Node
* poffset
)
1530 offset
= ((EXPR_VALUE (poffset
) >> 1));
1533 return conscode (gencode (c_code
.opcode
),
1534 Expr_Node_Gen_Reloc (
1535 poffset
, BFD_RELOC_BFIN_12_PCREL_JUMP_S
));
1539 bfin_gen_alu2op (REG_T dst
, REG_T src
, int opc
)
1547 return GEN_OPCODE16 ();
1551 bfin_gen_compi2opd (REG_T dst
, int src
, int op
)
1559 return GEN_OPCODE16 ();
1563 bfin_gen_compi2opp (REG_T dst
, int src
, int op
)
1571 return GEN_OPCODE16 ();
1575 bfin_gen_dagmodik (REG_T i
, int op
)
1582 return GEN_OPCODE16 ();
1586 bfin_gen_dagmodim (REG_T i
, REG_T m
, int op
, int br
)
1595 return GEN_OPCODE16 ();
1599 bfin_gen_ptr2op (REG_T dst
, REG_T src
, int opc
)
1607 return GEN_OPCODE16 ();
1611 bfin_gen_comp3op (REG_T src0
, REG_T src1
, REG_T dst
, int opc
)
1620 return GEN_OPCODE16 ();
1624 bfin_gen_ccflag (REG_T x
, int y
, int opc
, int I
, int G
)
1634 return GEN_OPCODE16 ();
1638 bfin_gen_ccmv (REG_T src
, REG_T dst
, int T
)
1651 return GEN_OPCODE16 ();
1655 bfin_gen_cc2stat (int cbit
, int op
, int D
)
1663 return GEN_OPCODE16 ();
1667 bfin_gen_regmv (REG_T src
, REG_T dst
)
1680 return GEN_OPCODE16 ();
1684 bfin_gen_cc2dreg (int op
, REG_T reg
)
1691 return GEN_OPCODE16 ();
1695 bfin_gen_progctrl (int prgfunc
, int poprnd
)
1702 return GEN_OPCODE16 ();
1706 bfin_gen_cactrl (REG_T reg
, int a
, int op
)
1714 return GEN_OPCODE16 ();
1718 bfin_gen_pushpopmultiple (int dr
, int pr
, int d
, int p
, int W
)
1720 INIT (PushPopMultiple
);
1728 return GEN_OPCODE16 ();
1732 bfin_gen_pushpopreg (REG_T reg
, int W
)
1738 grp
= (GROUP (reg
));
1742 return GEN_OPCODE16 ();
1745 /* Pseudo Debugging Support. */
1748 bfin_gen_pseudodbg (int fn
, int reg
, int grp
)
1756 return GEN_OPCODE16 ();
1760 bfin_gen_pseudodbg_assert (int dbgop
, REG_T regtest
, int expected
)
1762 INIT (PseudoDbg_Assert
);
1768 return GEN_OPCODE32 ();
1771 /* Multiple instruction generation. */
1774 bfin_gen_multi_instr (INSTR_T dsp32
, INSTR_T dsp16_grp1
, INSTR_T dsp16_grp2
)
1778 /* If it's a 0, convert into MNOP. */
1782 SET_MULTI_INSTRUCTION_BIT (dsp32
);
1786 dsp32
= gencode (0xc803);
1787 walk
= gencode (0x1800);
1793 dsp16_grp1
= gencode (0x0000);
1798 dsp16_grp2
= gencode (0x0000);
1801 walk
->next
= dsp16_grp1
;
1802 dsp16_grp1
->next
= dsp16_grp2
;
1803 dsp16_grp2
->next
= NULL_CODE
;
1809 bfin_gen_loop (Expr_Node
*expr
, REG_T reg
, int rop
, REG_T preg
)
1811 const char *loopsym
;
1812 char *lbeginsym
, *lendsym
;
1813 Expr_Node_Value lbeginval
, lendval
;
1814 Expr_Node
*lbegin
, *lend
;
1816 loopsym
= expr
->value
.s_value
;
1817 lbeginsym
= (char *) xmalloc (strlen (loopsym
) + strlen ("__BEGIN") + 1);
1818 lendsym
= (char *) xmalloc (strlen (loopsym
) + strlen ("__END") + 1);
1823 strcat (lbeginsym
, loopsym
);
1824 strcat (lbeginsym
, "__BEGIN");
1826 strcat (lendsym
, loopsym
);
1827 strcat (lendsym
, "__END");
1829 lbeginval
.s_value
= lbeginsym
;
1830 lendval
.s_value
= lendsym
;
1832 lbegin
= Expr_Node_Create (Expr_Node_Reloc
, lbeginval
, NULL
, NULL
);
1833 lend
= Expr_Node_Create (Expr_Node_Reloc
, lendval
, NULL
, NULL
);
1834 return bfin_gen_loopsetup(lbegin
, reg
, rop
, lend
, preg
);
1838 bfin_eol_in_insn (char *line
)
1840 /* Allow a new-line to appear in the middle of a multi-issue instruction. */
1847 /* A semi-colon followed by a newline is always the end of a line. */
1848 if (line
[-1] == ';')
1851 if (line
[-1] == '|')
1854 /* If the || is on the next line, there might be leading whitespace. */
1856 while (*temp
== ' ' || *temp
== '\t') temp
++;
1865 bfin_name_is_register (char *name
)
1869 if (*name
== '[' || *name
== '(')
1872 if ((name
[0] == 'W' || name
[0] == 'w') && name
[1] == '[')
1875 if ((name
[0] == 'B' || name
[0] == 'b') && name
[1] == '[')
1878 for (i
=0; bfin_reg_info
[i
].name
!= 0; i
++)
1880 if (!strcasecmp (bfin_reg_info
[i
].name
, name
))
1887 bfin_equals (Expr_Node
*sym
)
1891 c
= input_line_pointer
;
1895 input_line_pointer
= c
;
1897 equals ((char *) sym
->value
.s_value
, 1);
1901 bfin_start_label (char *ptr
)
1904 while (!ISSPACE (*ptr
) && !is_end_of_line
[(unsigned char) *ptr
])
1908 if (*ptr
== '(' || *ptr
== '[')
1915 bfin_force_relocation (struct fix
*fixp
)
1917 if (fixp
->fx_r_type
==BFD_RELOC_BFIN_16_LOW
1918 || fixp
->fx_r_type
== BFD_RELOC_BFIN_16_HIGH
)
1921 return generic_force_reloc (fixp
);