1 /* tc-ft32.c -- Assemble code for ft32
2 Copyright (C) 2008-2023 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 51 Franklin Street - Fifth Floor,
19 Boston, MA 02110-1301, USA. */
21 /* Contributed by Anthony Green <green@spindazzle.org>. */
24 #include "safe-ctype.h"
25 #include "opcode/ft32.h"
27 extern const ft32_opc_info_t ft32_opc_info
[128];
29 /* See md_parse_option() for meanings of these options. */
30 static char norelax
; /* True if -norelax switch seen. */
32 const char comment_chars
[] = "#";
33 const char line_separator_chars
[] = ";";
34 const char line_comment_chars
[] = "#";
36 static int pending_reloc
;
37 static htab_t opcode_hash_control
;
39 static valueT
md_chars_to_number (char * buf
, int n
);
41 const pseudo_typeS md_pseudo_table
[] =
46 const char FLT_CHARS
[] = "rRsSfFdDxXpP";
47 const char EXP_CHARS
[] = "eE";
49 /* This function is called once, at assembler startup time. It sets
50 up the hash table with all the opcodes in it, and also initializes
51 some aliases for compatibility with other assemblers. */
56 const ft32_opc_info_t
*opcode
;
57 opcode_hash_control
= str_htab_create ();
59 /* Insert names into hash table. */
60 for (opcode
= ft32_opc_info
; opcode
->name
; opcode
++)
61 str_hash_insert (opcode_hash_control
, opcode
->name
, opcode
, 0);
63 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, 0);
68 /* Parse an expression and then restore the input line pointer. */
71 parse_exp_save_ilp (char *s
, expressionS
*op
)
73 char *save
= input_line_pointer
;
75 input_line_pointer
= s
;
77 s
= input_line_pointer
;
78 input_line_pointer
= save
;
83 parse_condition (char **ptr
)
93 { "gt," , (2 << FT32_FLD_CR_BIT
) | (5 << FT32_FLD_CB_BIT
) | (1 << FT32_FLD_CV_BIT
)},
94 { "gte," , (2 << FT32_FLD_CR_BIT
) | (4 << FT32_FLD_CB_BIT
) | (1 << FT32_FLD_CV_BIT
)},
95 { "lt," , (2 << FT32_FLD_CR_BIT
) | (4 << FT32_FLD_CB_BIT
) | (0 << FT32_FLD_CV_BIT
)},
96 { "lte," , (2 << FT32_FLD_CR_BIT
) | (5 << FT32_FLD_CB_BIT
) | (0 << FT32_FLD_CV_BIT
)},
97 { "a," , (2 << FT32_FLD_CR_BIT
) | (6 << FT32_FLD_CB_BIT
) | (1 << FT32_FLD_CV_BIT
)},
98 { "ae," , (2 << FT32_FLD_CR_BIT
) | (1 << FT32_FLD_CB_BIT
) | (0 << FT32_FLD_CV_BIT
)},
99 { "be," , (2 << FT32_FLD_CR_BIT
) | (6 << FT32_FLD_CB_BIT
) | (0 << FT32_FLD_CV_BIT
)},
100 { "b," , (2 << FT32_FLD_CR_BIT
) | (1 << FT32_FLD_CB_BIT
) | (1 << FT32_FLD_CV_BIT
)},
101 { "nz," , (2 << FT32_FLD_CR_BIT
) | (0 << FT32_FLD_CB_BIT
) | (0 << FT32_FLD_CV_BIT
)},
102 { "z," , (2 << FT32_FLD_CR_BIT
) | (0 << FT32_FLD_CB_BIT
) | (1 << FT32_FLD_CV_BIT
)},
103 { "nc," , (2 << FT32_FLD_CR_BIT
) | (1 << FT32_FLD_CB_BIT
) | (0 << FT32_FLD_CV_BIT
)},
104 { "c," , (2 << FT32_FLD_CR_BIT
) | (1 << FT32_FLD_CB_BIT
) | (1 << FT32_FLD_CV_BIT
)},
105 { "no," , (2 << FT32_FLD_CR_BIT
) | (2 << FT32_FLD_CB_BIT
) | (0 << FT32_FLD_CV_BIT
)},
106 { "o," , (2 << FT32_FLD_CR_BIT
) | (2 << FT32_FLD_CB_BIT
) | (1 << FT32_FLD_CV_BIT
)},
107 { "ns," , (2 << FT32_FLD_CR_BIT
) | (3 << FT32_FLD_CB_BIT
) | (0 << FT32_FLD_CV_BIT
)},
108 { "s," , (2 << FT32_FLD_CR_BIT
) | (3 << FT32_FLD_CB_BIT
) | (1 << FT32_FLD_CV_BIT
)},
112 for (pc
= ccs
; pc
->name
; pc
++)
114 if (memcmp(pc
->name
, s
, strlen(pc
->name
)) == 0)
116 *ptr
+= strlen(pc
->name
) - 1;
124 parse_decimal (char **ptr
)
129 while (('0' <= *s
) && (*s
<= '9'))
139 parse_register_operand (char **ptr
)
146 as_bad (_("expecting register"));
147 ignore_rest_of_line ();
150 if ((s
[1] == 's') && (s
[2] == 'p'))
154 else if ((s
[1] == 'c') && (s
[2] == 'c'))
158 else if ((s
[1] == 'f') && (s
[2] == 'p'))
162 else if (s
[1] == 'r')
165 if ((reg
< 0) || (reg
> 9))
167 as_bad (_("illegal register number"));
168 ignore_rest_of_line ();
171 if ((reg
== 1) || (reg
== 2) || (reg
== 3))
174 if ((r2
>= 0) && (r2
<= 9))
176 reg
= (reg
* 10) + r2
;
183 as_bad (_("illegal register number"));
184 ignore_rest_of_line ();
193 /* This is the guts of the machine-dependent assembler. STR points to
194 a machine dependent instruction. This function is supposed to emit
195 the frags/bytes it assembles to. */
198 md_assemble (char *str
)
202 ft32_opc_info_t
*opcode
;
214 /* Drop leading whitespace. */
218 /* Find the op code end. */
222 && !is_end_of_line
[*op_end
& 0xff]
232 as_bad (_("can't find opcode "));
234 opcode
= (ft32_opc_info_t
*) str_hash_find (opcode_hash_control
, op_start
);
239 as_bad (_("unknown opcode %s"), op_start
);
264 as_bad (_("unknown width specifier '.%c'"), op_end
[1]);
271 dw
= 2; /* default is ".l" */
273 b
|= dw
<< FT32_FLD_DW_BIT
;
276 while (ISSPACE (*op_end
))
279 output
= frag_more (4);
289 case FT32_FLD_CBCRCV
:
290 b
|= parse_condition( &op_end
);
293 b
|= parse_decimal (&op_end
) << FT32_FLD_CB_BIT
;
296 b
|= parse_register_operand (&op_end
) << FT32_FLD_R_D_BIT
;
299 b
|= (parse_register_operand (&op_end
) - 28) << FT32_FLD_CR_BIT
;
302 b
|= parse_decimal (&op_end
) << FT32_FLD_CV_BIT
;
305 b
|= parse_register_operand (&op_end
) << FT32_FLD_R_1_BIT
;
310 b
|= parse_register_operand (&op_end
) << FT32_FLD_RIMM_BIT
;
314 b
|= 0x400 << FT32_FLD_RIMM_BIT
;
315 op_end
= parse_exp_save_ilp (op_end
, &arg
);
317 fix_new_exp (frag_now
,
318 (output
- frag_now
->fr_literal
),
326 b
|= parse_register_operand (&op_end
) << FT32_FLD_R_2_BIT
;
329 op_end
= parse_exp_save_ilp (op_end
, &arg
);
331 fix_new_exp (frag_now
,
332 (output
- frag_now
->fr_literal
),
339 op_end
= parse_exp_save_ilp (op_end
, &arg
);
341 fix_new_exp (frag_now
,
342 (output
- frag_now
->fr_literal
),
349 op_end
= parse_exp_save_ilp (op_end
, &arg
);
351 fix_new_exp (frag_now
,
352 (output
- frag_now
->fr_literal
),
359 op_end
= parse_exp_save_ilp (op_end
, &arg
);
361 fix_new_exp (frag_now
,
362 (output
- frag_now
->fr_literal
),
369 op_end
= parse_exp_save_ilp (op_end
, &arg
);
370 if (arg
.X_add_number
& 0x80)
371 arg
.X_add_number
^= 0x7f00;
373 fix_new_exp (frag_now
,
374 (output
- frag_now
->fr_literal
),
380 case FT32_FLD_R_D_POST
:
381 b
|= parse_register_operand (&op_end
) << FT32_FLD_R_D_BIT
;
383 case FT32_FLD_R_1_POST
:
384 b
|= parse_register_operand (&op_end
) << FT32_FLD_R_1_BIT
;
387 as_bad (_("internal error in argument parsing"));
395 while (ISSPACE (*op_end
))
400 as_bad (_("expected comma separator"));
401 ignore_rest_of_line ();
405 while (ISSPACE (*op_end
))
412 as_warn (_("extra stuff on line ignored"));
414 can_sc
= ft32_shortcode (b
, &sc
);
416 if (!fixed
&& can_sc
)
418 arg
.X_op
= O_constant
;
419 arg
.X_add_number
= 0;
420 arg
.X_add_symbol
= NULL
;
421 arg
.X_op_symbol
= NULL
;
422 fix_new_exp (frag_now
,
423 (output
- frag_now
->fr_literal
),
427 BFD_RELOC_FT32_RELAX
);
430 output
[idx
++] = 0xff & (b
>> 0);
431 output
[idx
++] = 0xff & (b
>> 8);
432 output
[idx
++] = 0xff & (b
>> 16);
433 output
[idx
++] = 0xff & (b
>> 24);
435 dwarf2_emit_insn (4);
437 while (ISSPACE (*op_end
))
441 as_warn ("extra stuff on line ignored");
444 as_bad ("Something forgot to clean up\n");
447 /* Turn a string in input_line_pointer into a floating point constant
448 of type type, and store the appropriate bytes in *LITP. The number
449 of LITTLENUMS emitted is stored in *SIZEP . An error message is
450 returned, or NULL on OK. */
453 md_atof (int type
, char *litP
, int *sizeP
)
456 LITTLENUM_TYPE words
[4];
472 return _("bad call to md_atof");
475 t
= atof_ieee (input_line_pointer
, type
, words
);
477 input_line_pointer
= t
;
481 for (i
= prec
- 1; i
>= 0; i
--)
483 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
490 const char *md_shortopts
= "";
492 struct option md_longopts
[] =
494 #define OPTION_NORELAX (OPTION_MD_BASE)
495 {"norelax", no_argument
, NULL
, OPTION_NORELAX
},
496 {"no-relax", no_argument
, NULL
, OPTION_NORELAX
},
497 {NULL
, no_argument
, NULL
, 0}
499 size_t md_longopts_size
= sizeof (md_longopts
);
501 /* We have no target specific options yet, so these next
502 two functions are empty. */
504 md_parse_option (int c ATTRIBUTE_UNUSED
, const char *arg ATTRIBUTE_UNUSED
)
520 md_show_usage (FILE *stream ATTRIBUTE_UNUSED
)
522 fprintf (stream
, _("FT32 options:\n"));
523 fprintf (stream
, _("\n\
524 -no-relax don't relax relocations\n\
528 /* Convert from target byte order to host byte order. */
531 md_chars_to_number (char * buf
, int n
)
534 unsigned char * where
= (unsigned char *) buf
;
539 result
|= (where
[n
] & 255);
545 /* Apply a fixup to the object file. */
548 md_apply_fix (fixS
*fixP ATTRIBUTE_UNUSED
,
549 valueT
* valP ATTRIBUTE_UNUSED
, segT seg ATTRIBUTE_UNUSED
)
551 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
555 if (linkrelax
&& fixP
->fx_subsy
)
557 /* For a subtraction relocation expression, generate one
558 of the DIFF relocs, with the value being the difference.
559 Note that a sym1 - sym2 expression is adjusted into a
560 section_start_sym + sym4_offset_from_section_start - sym1
561 expression. fixP->fx_addsy holds the section start symbol,
562 fixP->fx_offset holds sym2's offset, and fixP->fx_subsy
563 holds sym1. Calculate the current difference and write value,
564 but leave fx_offset as is - during relaxation,
565 fx_offset - value gives sym1's value. */
567 switch (fixP
->fx_r_type
)
570 fixP
->fx_r_type
= BFD_RELOC_FT32_DIFF32
;
573 as_bad_subtract (fixP
);
577 val
= S_GET_VALUE (fixP
->fx_addsy
) +
578 fixP
->fx_offset
- S_GET_VALUE (fixP
->fx_subsy
);
581 fixP
->fx_subsy
= NULL
;
584 /* We don't actually support subtracting a symbol. */
585 if (fixP
->fx_subsy
!= (symbolS
*) NULL
)
586 as_bad_subtract (fixP
);
588 switch (fixP
->fx_r_type
)
590 case BFD_RELOC_FT32_DIFF32
:
607 case BFD_RELOC_FT32_10
:
610 newval
= md_chars_to_number (buf
, 2);
611 newval
|= (val
& ((1 << 10) - 1)) << FT32_FLD_RIMM_BIT
;
612 md_number_to_chars (buf
, newval
, 2);
615 case BFD_RELOC_FT32_20
:
618 newval
= md_chars_to_number (buf
, 3);
619 newval
|= val
& ((1 << 20) - 1);
620 md_number_to_chars (buf
, newval
, 3);
623 case BFD_RELOC_FT32_15
:
626 newval
= md_chars_to_number (buf
, 2);
627 newval
|= val
& ((1 << 15) - 1);
628 md_number_to_chars (buf
, newval
, 2);
631 case BFD_RELOC_FT32_17
:
634 newval
= md_chars_to_number (buf
, 3);
635 newval
|= val
& ((1 << 17) - 1);
636 md_number_to_chars (buf
, newval
, 3);
639 case BFD_RELOC_FT32_18
:
642 newval
= md_chars_to_number (buf
, 4);
643 newval
|= (val
>> 2) & ((1 << 18) - 1);
644 md_number_to_chars (buf
, newval
, 4);
647 case BFD_RELOC_FT32_RELAX
:
654 if (fixP
->fx_addsy
== NULL
&& fixP
->fx_pcrel
== 0)
659 md_number_to_chars (char *ptr
, valueT use
, int nbytes
)
661 number_to_chars_littleendian (ptr
, use
, nbytes
);
664 /* Generate a machine-dependent relocation. */
667 tc_gen_reloc (asection
*section ATTRIBUTE_UNUSED
, fixS
*fixP
)
670 bfd_reloc_code_real_type code
;
672 switch (fixP
->fx_r_type
)
677 case BFD_RELOC_FT32_10
:
678 case BFD_RELOC_FT32_20
:
679 case BFD_RELOC_FT32_15
:
680 case BFD_RELOC_FT32_17
:
681 case BFD_RELOC_FT32_18
:
682 case BFD_RELOC_FT32_RELAX
:
683 case BFD_RELOC_FT32_DIFF32
:
684 code
= fixP
->fx_r_type
;
687 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
688 _("Semantics error. This type of operand can not be "
689 "relocated, it must be an assembly-time constant"));
693 relP
= XNEW (arelent
);
694 gas_assert (relP
!= 0);
695 relP
->sym_ptr_ptr
= XNEW (asymbol
*);
696 *relP
->sym_ptr_ptr
= symbol_get_bfdsym (fixP
->fx_addsy
);
697 relP
->address
= fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
699 relP
->addend
= fixP
->fx_offset
;
701 relP
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
706 name
= S_GET_NAME (fixP
->fx_addsy
);
708 name
= _("<unknown>");
709 as_fatal (_("Cannot generate relocation type for symbol %s, code %s"),
710 name
, bfd_get_reloc_code_name (code
));
716 /* TC_FORCE_RELOCATION hook */
719 relaxable_section (asection
*sec
)
721 return ((sec
->flags
& SEC_DEBUGGING
) == 0
722 && (sec
->flags
& SEC_CODE
) != 0
723 && (sec
->flags
& SEC_ALLOC
) != 0);
726 /* Does whatever the xtensa port does. */
729 ft32_validate_fix_sub (fixS
*fix
)
731 segT add_symbol_segment
, sub_symbol_segment
;
733 /* The difference of two symbols should be resolved by the assembler when
734 linkrelax is not set. If the linker may relax the section containing
735 the symbols, then an Xtensa DIFF relocation must be generated so that
736 the linker knows to adjust the difference value. */
737 if (!linkrelax
|| fix
->fx_addsy
== NULL
)
740 /* Make sure both symbols are in the same segment, and that segment is
741 "normal" and relaxable. If the segment is not "normal", then the
742 fix is not valid. If the segment is not "relaxable", then the fix
743 should have been handled earlier. */
744 add_symbol_segment
= S_GET_SEGMENT (fix
->fx_addsy
);
745 if (! SEG_NORMAL (add_symbol_segment
) ||
746 ! relaxable_section (add_symbol_segment
))
749 sub_symbol_segment
= S_GET_SEGMENT (fix
->fx_subsy
);
750 return (sub_symbol_segment
== add_symbol_segment
);
753 /* TC_FORCE_RELOCATION hook */
755 /* If linkrelax is turned on, and the symbol to relocate
756 against is in a relaxable segment, don't compute the value -
757 generate a relocation instead. */
760 ft32_force_relocation (fixS
*fix
)
762 if (linkrelax
&& fix
->fx_addsy
763 && relaxable_section (S_GET_SEGMENT (fix
->fx_addsy
)))
768 return generic_force_reloc (fix
);
772 ft32_allow_local_subtract (expressionS
* left
,
776 /* If we are not in relaxation mode, subtraction is OK. */
780 /* If the symbols are not in a code section then they are OK. */
781 if ((section
->flags
& SEC_CODE
) == 0)
784 if (left
->X_add_symbol
== right
->X_add_symbol
)
787 /* We have to assume that there may be instructions between the
788 two symbols and that relaxation may increase the distance between