1 /* tc-loongarch.c -- Assemble for the LoongArch ISA
3 Copyright (C) 2021-2022 Free Software Foundation, Inc.
4 Contributed by Loongson Ltd.
6 This file is part of GAS.
8 GAS is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the license, or
11 (at your option) any later version.
13 GAS is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; see the file COPYING3. If not,
20 see <http://www.gnu.org/licenses/>. */
23 #include "dw2gencfi.h"
24 #include "loongarch-lex.h"
25 #include "elf/loongarch.h"
26 #include "opcode/loongarch.h"
28 #include "bfd/elfxx-loongarch.h"
34 /* All information about an instruction during assemble. */
35 struct loongarch_cl_insn
37 /* First split string. */
39 const char *arg_strs
[MAX_ARG_NUM_PLUS_2
];
42 /* Second analyze name_str and each actual args string to match the insn
43 in 'loongarch-opc.c'. And actual args may need be relocated.
44 We get length of insn. If 'insn_length == 0 && insn_mo->macro != NULL',
45 it's a macro insntruction and we call 'md_assemble' recursively
46 after expanding it. */
50 const struct loongarch_opcode
*insn
;
53 offsetT args
[MAX_ARG_NUM_PLUS_2
];
54 struct reloc_info reloc_info
[MAX_RELOC_NUMBER_A_INSN
];
57 /* For relax reserved. We not support relax now.
58 'insn_length < relax_max_length' means need to relax.
59 And 'insn_length == relax_max_length' means no need to relax. */
60 size_t relax_max_length
;
61 relax_substateT subtype
;
63 /* Then we get the binary representation of insn
64 and write it in to section. */
67 /* The frag that contains the instruction. */
69 /* The offset into FRAG of the first instruction byte. */
71 /* The relocs associated with the instruction, if any. */
72 fixS
*fixp
[MAX_RELOC_NUMBER_A_INSN
];
76 #define DEFAULT_ARCH "loongarch64"
79 /* This array holds the chars that always start a comment. If the
80 pre-processor is disabled, these aren't very useful. */
81 const char comment_chars
[] = "#";
83 /* This array holds the chars that only start a comment at the beginning of
84 a line. If the line seems to have the form '# 123 filename'
85 .line and .file directives will appear in the pre-processed output. */
86 /* Note that input_file.c hand checks for '#' at the beginning of the
87 first line of the input file. This is because the compiler outputs
88 #NO_APP at the beginning of its output. */
89 /* Also note that C style comments are always supported. */
90 const char line_comment_chars
[] = "#";
92 /* This array holds machine specific line separator characters. */
93 const char line_separator_chars
[] = ";";
95 /* Chars that can be used to separate mant from exp in floating point nums. */
96 const char EXP_CHARS
[] = "eE";
98 /* Chars that mean this number is a floating point constant. */
100 /* or 0d1.2345e12. */
101 const char FLT_CHARS
[] = "rRsSfFdDxXpP";
103 const char *md_shortopts
= "O::g::G:";
105 static const char default_arch
[] = DEFAULT_ARCH
;
109 OPTION_IGNORE
= OPTION_MD_BASE
,
116 OPTION_LA_LOCAL_WITH_ABS
,
117 OPTION_LA_GLOBAL_WITH_PCREL
,
118 OPTION_LA_GLOBAL_WITH_ABS
,
123 struct option md_longopts
[] =
125 { "mabi", required_argument
, NULL
, OPTION_ABI
},
127 { "mfpu", required_argument
, NULL
, OPTION_FLOAT_ISA
},
129 { "mla-local-with-abs", no_argument
, NULL
, OPTION_LA_LOCAL_WITH_ABS
},
130 { "mla-global-with-pcrel", no_argument
, NULL
, OPTION_LA_GLOBAL_WITH_PCREL
},
131 { "mla-global-with-abs", no_argument
, NULL
, OPTION_LA_GLOBAL_WITH_ABS
},
133 { NULL
, no_argument
, NULL
, 0 }
136 size_t md_longopts_size
= sizeof (md_longopts
);
139 md_parse_option (int c
, const char *arg
)
143 char ilp32
[256] = "";
144 unsigned char *suf
= (unsigned char *)arg
;
146 lp64
['s'] = lp64
['S'] = EF_LOONGARCH_ABI_LP64_SOFT_FLOAT
;
147 lp64
['f'] = lp64
['F'] = EF_LOONGARCH_ABI_LP64_SINGLE_FLOAT
;
148 lp64
['d'] = lp64
['D'] = EF_LOONGARCH_ABI_LP64_DOUBLE_FLOAT
;
150 ilp32
['s'] = ilp32
['S'] = EF_LOONGARCH_ABI_ILP32_SOFT_FLOAT
;
151 ilp32
['f'] = ilp32
['F'] = EF_LOONGARCH_ABI_ILP32_SINGLE_FLOAT
;
152 ilp32
['d'] = ilp32
['D'] = EF_LOONGARCH_ABI_ILP32_DOUBLE_FLOAT
;
157 if (strncasecmp (arg
, "lp64", 4) == 0 && lp64
[suf
[4]] != 0)
159 LARCH_opts
.ase_ilp32
= 1;
160 LARCH_opts
.ase_lp64
= 1;
161 LARCH_opts
.ase_abi
= lp64
[suf
[4]];
163 else if (strncasecmp (arg
, "ilp32", 5) == 0 && ilp32
[suf
[5]] != 0)
165 LARCH_opts
.ase_abi
= ilp32
[suf
[5]];
166 LARCH_opts
.ase_ilp32
= 1;
172 case OPTION_FLOAT_ISA
:
173 if (strcasecmp (arg
, "soft") == 0)
174 LARCH_opts
.ase_nf
= 1;
175 else if (strcasecmp (arg
, "single") == 0)
176 LARCH_opts
.ase_sf
= 1;
177 else if (strcasecmp (arg
, "double") == 0)
179 LARCH_opts
.ase_sf
= 1;
180 LARCH_opts
.ase_df
= 1;
186 case OPTION_LA_LOCAL_WITH_ABS
:
187 LARCH_opts
.ase_labs
= 1;
190 case OPTION_LA_GLOBAL_WITH_PCREL
:
191 LARCH_opts
.ase_gpcr
= 1;
194 case OPTION_LA_GLOBAL_WITH_ABS
:
195 LARCH_opts
.ase_gabs
= 1;
208 static struct htab
*r_htab
= NULL
;
209 static struct htab
*f_htab
= NULL
;
210 static struct htab
*c_htab
= NULL
;
211 static struct htab
*cr_htab
= NULL
;
212 static struct htab
*v_htab
= NULL
;
213 static struct htab
*x_htab
= NULL
;
216 loongarch_after_parse_args ()
218 /* Set default ABI/ISA LP64D. */
219 if (!EF_LOONGARCH_IS_LP64(LARCH_opts
.ase_abi
)
220 && !EF_LOONGARCH_IS_ILP32(LARCH_opts
.ase_abi
))
222 if (strcmp (default_arch
, "loongarch64") == 0)
224 LARCH_opts
.ase_abi
= EF_LOONGARCH_ABI_LP64_DOUBLE_FLOAT
;
225 LARCH_opts
.ase_ilp32
= 1;
226 LARCH_opts
.ase_lp64
= 1;
228 else if (strcmp (default_arch
, "loongarch32") == 0)
230 LARCH_opts
.ase_abi
= EF_LOONGARCH_ABI_ILP32_DOUBLE_FLOAT
;
231 LARCH_opts
.ase_ilp32
= 1;
234 as_bad ("unknown default architecture `%s'", default_arch
);
237 /* Set default ISA double-float. */
238 if (!LARCH_opts
.ase_nf
239 && !LARCH_opts
.ase_sf
240 && !LARCH_opts
.ase_df
)
242 LARCH_opts
.ase_sf
= 1;
243 LARCH_opts
.ase_df
= 1;
248 assert(LARCH_opts
.ase_ilp32
);
250 /* Init ilp32/lp64 registers names. */
252 r_htab
= str_htab_create (), str_hash_insert (r_htab
, "", 0, 0);
254 for (i
= 0; i
< ARRAY_SIZE (loongarch_r_normal_name
); i
++)
255 str_hash_insert (r_htab
, loongarch_r_normal_name
[i
], (void *) (i
+ 1), 0);
258 cr_htab
= str_htab_create (), str_hash_insert (cr_htab
, "", 0, 0);
260 for (i
= 0; i
< ARRAY_SIZE (loongarch_cr_normal_name
); i
++)
261 str_hash_insert (cr_htab
, loongarch_cr_normal_name
[i
], (void *) (i
+ 1), 0);
263 /* Init single/double float registers names. */
264 if (LARCH_opts
.ase_sf
|| LARCH_opts
.ase_df
)
267 f_htab
= str_htab_create (), str_hash_insert (f_htab
, "", 0, 0);
269 for (i
= 0; i
< ARRAY_SIZE (loongarch_f_normal_name
); i
++)
270 str_hash_insert (f_htab
, loongarch_f_normal_name
[i
], (void *) (i
+ 1),
274 c_htab
= str_htab_create (), str_hash_insert (c_htab
, "", 0, 0);
276 for (i
= 0; i
< ARRAY_SIZE (loongarch_c_normal_name
); i
++)
277 str_hash_insert (c_htab
, loongarch_c_normal_name
[i
], (void *) (i
+ 1),
282 /* Init lsx registers names. */
283 if (LARCH_opts
.ase_lsx
)
286 v_htab
= str_htab_create (), str_hash_insert (v_htab
, "", 0, 0);
287 for (i
= 0; i
< ARRAY_SIZE (loongarch_v_normal_name
); i
++)
288 str_hash_insert (v_htab
, loongarch_v_normal_name
[i
], (void *) (i
+ 1),
292 /* Init lasx registers names. */
293 if (LARCH_opts
.ase_lasx
)
296 x_htab
= str_htab_create (), str_hash_insert (x_htab
, "", 0, 0);
297 for (i
= 0; i
< ARRAY_SIZE (loongarch_x_normal_name
); i
++)
298 str_hash_insert (x_htab
, loongarch_x_normal_name
[i
], (void *) (i
+ 1),
302 /* Init lp64 registers alias. */
303 if (LARCH_opts
.ase_lp64
)
305 for (i
= 0; i
< ARRAY_SIZE (loongarch_r_lp64_name
); i
++)
306 str_hash_insert (r_htab
, loongarch_r_lp64_name
[i
], (void *) (i
+ 1),
308 for (i
= 0; i
< ARRAY_SIZE (loongarch_r_lp64_name1
); i
++)
309 str_hash_insert (r_htab
, loongarch_r_lp64_name1
[i
], (void *) (i
+ 1),
313 /* Init float-lp64 registers alias */
314 if ((LARCH_opts
.ase_sf
|| LARCH_opts
.ase_df
) && LARCH_opts
.ase_lp64
)
316 for (i
= 0; i
< ARRAY_SIZE (loongarch_f_lp64_name
); i
++)
317 str_hash_insert (f_htab
, loongarch_f_lp64_name
[i
],
318 (void *) (i
+ 1), 0);
319 for (i
= 0; i
< ARRAY_SIZE (loongarch_f_lp64_name1
); i
++)
320 str_hash_insert (f_htab
, loongarch_f_lp64_name1
[i
],
321 (void *) (i
+ 1), 0);
326 loongarch_target_format ()
328 return LARCH_opts
.ase_lp64
? "elf64-loongarch" : "elf32-loongarch";
334 const struct loongarch_opcode
*it
;
335 struct loongarch_ase
*ase
;
336 for (ase
= loongarch_ASEs
; ase
->enabled
; ase
++)
337 for (it
= ase
->opcodes
; it
->name
; it
++)
339 if (loongarch_check_format (it
->format
) != 0)
340 as_fatal (_("insn name: %s\tformat: %s\tsyntax error"),
341 it
->name
, it
->format
);
342 if (it
->mask
== 0 && it
->macro
== 0)
343 as_fatal (_("insn name: %s\nformat: %s\nwe want macro but "
345 it
->name
, it
->format
);
347 && loongarch_check_macro (it
->format
, it
->macro
) != 0)
348 as_fatal (_("insn name: %s\nformat: %s\nmacro: %s\tsyntax error"),
349 it
->name
, it
->format
, it
->macro
);
352 /* FIXME: expressionS use 'offsetT' as constant,
353 * we want this is 64-bit type. */
354 assert (8 <= sizeof (offsetT
));
357 static const expressionS const_0
= { .X_op
= O_constant
, .X_add_number
= 0 };
360 my_getExpression (expressionS
*ep
, const char *str
)
363 save_in
= input_line_pointer
;
364 input_line_pointer
= (char *) str
;
366 ret
= input_line_pointer
;
367 input_line_pointer
= save_in
;
372 s_loongarch_align (int arg
)
374 const char *t
= input_line_pointer
;
375 while (!is_end_of_line
[(unsigned char) *t
] && *t
!= ',')
383 /* Handle the .dtprelword and .dtpreldword pseudo-ops. They generate
384 a 32-bit or 64-bit DTP-relative relocation (BYTES says which) for
385 use in DWARF debug information. */
395 if (ex
.X_op
!= O_symbol
)
397 as_bad (_("Unsupported use of %s"),
398 (bytes
== 8 ? ".dtpreldword" : ".dtprelword"));
399 ignore_rest_of_line ();
402 p
= frag_more (bytes
);
403 md_number_to_chars (p
, 0, bytes
);
404 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
, bytes
, &ex
, FALSE
,
406 ? BFD_RELOC_LARCH_TLS_DTPREL64
407 : BFD_RELOC_LARCH_TLS_DTPREL32
));
409 demand_empty_rest_of_line ();
412 static const pseudo_typeS loongarch_pseudo_table
[] =
414 { "align", s_loongarch_align
, -4 },
415 { "dword", cons
, 8 },
418 { "dtprelword", s_dtprel
, 4 },
419 { "dtpreldword", s_dtprel
, 8 },
424 loongarch_pop_insert (void)
426 pop_insert (loongarch_pseudo_table
);
429 #define INTERNAL_LABEL_SPECIAL 10
430 static unsigned long internal_label_count
[INTERNAL_LABEL_SPECIAL
] = { 0 };
433 loongarch_internal_label_name (unsigned long label
, int augend
)
435 static char symbol_name_build
[24];
436 unsigned long want_label
;
439 want_label
= internal_label_count
[label
] + augend
;
441 p
= symbol_name_build
;
442 #ifdef LOCAL_LABEL_PREFIX
443 *p
++ = LOCAL_LABEL_PREFIX
;
446 for (; label
; label
/= 10)
447 *p
++ = label
% 10 + '0';
448 /* Make sure internal label never belong to normal label namespace. */
450 for (; want_label
; want_label
/= 10)
451 *p
++ = want_label
% 10 + '0';
453 return symbol_name_build
;
457 setup_internal_label_here (unsigned long label
)
459 assert (label
< INTERNAL_LABEL_SPECIAL
);
460 internal_label_count
[label
]++;
461 colon (loongarch_internal_label_name (label
, 0));
465 get_internal_label (expressionS
*label_expr
, unsigned long label
,
466 int augend
/* 0 for previous, 1 for next. */)
468 assert (label
< INTERNAL_LABEL_SPECIAL
);
469 if (augend
== 0 && internal_label_count
[label
] == 0)
470 as_fatal (_("internal error: we have no internal label yet"));
471 label_expr
->X_op
= O_symbol
;
472 label_expr
->X_add_symbol
=
473 symbol_find_or_make (loongarch_internal_label_name (label
, augend
));
474 label_expr
->X_add_number
= 0;
477 extern int loongarch_parse_expr (const char *expr
,
478 struct reloc_info
*reloc_stack_top
,
479 size_t max_reloc_num
, size_t *reloc_num
,
480 offsetT
*imm_if_no_reloc
);
483 is_internal_label (const char *c_str
)
490 if (!('0' <= *c_str
&& *c_str
<= '9'))
492 while ('0' <= *c_str
&& *c_str
<= '9')
494 if (*c_str
!= 'b' && *c_str
!= 'f')
497 return *c_str
== '\0';
504 is_label (const char *c_str
)
506 if (is_internal_label (c_str
))
508 else if ('0' <= *c_str
&& *c_str
<= '9')
511 while ('0' <= *c_str
&& *c_str
<= '9')
513 return *c_str
== 'b' || *c_str
== 'f';
515 else if (is_name_beginner (*c_str
))
517 /* [a-zA-Z\._\$][0-9a-zA-Z\._\$]* */
519 while (is_part_of_name (*c_str
))
521 return *c_str
== '\0';
528 is_label_with_addend (const char *c_str
)
530 if (is_internal_label (c_str
))
532 else if ('0' <= *c_str
&& *c_str
<= '9')
535 while ('0' <= *c_str
&& *c_str
<= '9')
537 if (*c_str
== 'b' || *c_str
== 'f')
541 return *c_str
== '\0'
542 || ((*c_str
== '-' || *c_str
== '+')
543 && is_unsigned (c_str
+ 1));
545 else if (is_name_beginner (*c_str
))
547 /* [a-zA-Z\._\$][0-9a-zA-Z\._\$]* */
549 while (is_part_of_name (*c_str
))
551 return *c_str
== '\0'
552 || ((*c_str
== '-' || *c_str
== '+')
553 && is_unsigned (c_str
+ 1));
560 loongarch_args_parser_can_match_arg_helper (char esc_ch1
, char esc_ch2
,
561 const char *bit_field
,
562 const char *arg
, void *context
)
564 struct loongarch_cl_insn
*ip
= context
;
565 offsetT imm
, ret
= 0;
566 size_t reloc_num_we_have
= MAX_RELOC_NUMBER_A_INSN
- ip
->reloc_num
;
567 size_t reloc_num
= 0;
578 ip
->match_now
= is_label (arg
);
579 if (!ip
->match_now
&& is_label_with_addend (arg
))
580 as_fatal (_("This label shouldn't be with addend."));
583 ip
->match_now
= is_label_with_addend (arg
);
590 loongarch_parse_expr (arg
, ip
->reloc_info
+ ip
->reloc_num
,
591 reloc_num_we_have
, &reloc_num
, &imm
) == 0;
600 ip
->match_now
= reloc_num
== 0;
607 ip
->match_now
= reloc_num
== 0 && 0 <= imm
;
617 bfd_reloc_code_real_type reloc_type
= BFD_RELOC_NONE
;
618 reloc_num_we_have
-= reloc_num
;
619 if (reloc_num_we_have
== 0)
620 as_fatal (_("expr too huge") /* Want one more reloc. */);
623 if (strncmp (bit_field
, "10:12", strlen ("10:12")) == 0)
624 reloc_type
= BFD_RELOC_LARCH_SOP_POP_32_U_10_12
;
626 else if (esc_ch1
== 's')
628 if (strncmp (bit_field
, "10:16<<2", strlen ("10:16<<2")) == 0)
629 reloc_type
= BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2
;
630 else if (strncmp (bit_field
, "0:5|10:16<<2",
631 strlen ("0:5|10:16<<2")) == 0)
632 reloc_type
= BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2
;
633 else if (strncmp (bit_field
, "0:10|10:16<<2",
634 strlen ("0:10|10:16<<2")) == 0)
635 reloc_type
= BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2
;
636 else if (strncmp (bit_field
, "10:12", strlen ("10:12")) == 0)
637 reloc_type
= BFD_RELOC_LARCH_SOP_POP_32_S_10_12
;
638 else if (strncmp (bit_field
, "5:20", strlen ("5:20")) == 0)
639 reloc_type
= BFD_RELOC_LARCH_SOP_POP_32_S_5_20
;
640 else if (strncmp (bit_field
, "10:16", strlen ("10:16")) == 0)
641 reloc_type
= BFD_RELOC_LARCH_SOP_POP_32_S_10_16
;
642 else if (strncmp (bit_field
, "10:5", strlen ("10:5")) == 0)
643 reloc_type
= BFD_RELOC_LARCH_SOP_POP_32_S_10_5
;
645 if (reloc_type
== BFD_RELOC_NONE
)
647 _("not support reloc bit-field\nfmt: %c%c %s\nargs: %s"),
648 esc_ch1
, esc_ch2
, bit_field
, arg
);
650 ip
->reloc_num
+= reloc_num
;
651 ip
->reloc_info
[ip
->reloc_num
- 1].type
= reloc_type
;
652 ip
->reloc_info
[ip
->reloc_num
- 1].value
= const_0
;
656 imm
= (intptr_t) str_hash_find (r_htab
, arg
);
657 ip
->match_now
= 0 < imm
;
661 imm
= (intptr_t) str_hash_find (f_htab
, arg
);
662 ip
->match_now
= 0 < imm
;
669 imm
= (intptr_t) str_hash_find (cr_htab
, arg
);
672 imm
= (intptr_t) str_hash_find (c_htab
, arg
);
674 ip
->match_now
= 0 < imm
;
678 imm
= (intptr_t) str_hash_find (v_htab
, arg
);
679 ip
->match_now
= 0 < imm
;
683 imm
= (intptr_t) str_hash_find (x_htab
, arg
);
684 ip
->match_now
= 0 < imm
;
688 ip
->all_match
= ip
->match_now
;
690 ip
->insn
->mask
? loongarch_insn_length (ip
->insn
->match
) : 0;
691 /* FIXME: now we have no relax insn. */
692 ip
->relax_max_length
= ip
->insn_length
;
695 as_fatal (_("unknown escape"));
700 /* Check imm overflow. */
701 int bit_width
, bits_needed_s
, bits_needed_u
;
710 bit_width
= loongarch_get_bit_field_width (bit_field
, &t
);
713 /* No specify bit width. */
717 if (t
[0] == '<' && t
[1] == '<')
719 int i
= strtol (t
+= 2, &t
, 10), j
;
720 for (j
= i
; 0 < j
; j
--, imm
>>= 1)
722 as_fatal (_("require imm low %d bit is 0."), i
);
726 imm
-= strtol (t
, &t
, 10);
728 bits_needed_s
= loongarch_bits_imm_needed (imm
, 1);
729 bits_needed_u
= loongarch_bits_imm_needed (imm
, 0);
731 if ((esc_ch1
== 's' && bit_width
< bits_needed_s
)
732 || (esc_ch1
!= 's' && bit_width
< bits_needed_u
))
733 /* How to do after we detect overflow. */
734 as_fatal (_("Immediate overflow.\n"
737 esc_ch1
, esc_ch2
, bit_field
, arg
);
743 ip
->args
[ip
->arg_num
] = ret
;
750 get_loongarch_opcode (struct loongarch_cl_insn
*insn
)
752 const struct loongarch_opcode
*it
;
753 struct loongarch_ase
*ase
;
754 for (ase
= loongarch_ASEs
; ase
->enabled
; ase
++)
756 if (!*ase
->enabled
|| (ase
->include
&& !*ase
->include
)
757 || (ase
->exclude
&& *ase
->exclude
))
760 if (!ase
->name_hash_entry
)
762 ase
->name_hash_entry
= str_htab_create ();
763 for (it
= ase
->opcodes
; it
->name
; it
++)
764 str_hash_insert (ase
->name_hash_entry
, it
->name
, (void *) it
, 0);
767 if ((it
= str_hash_find (ase
->name_hash_entry
, insn
->name
)) == NULL
)
777 insn
->insn_bin
= (loongarch_foreach_args
778 (it
->format
, insn
->arg_strs
,
779 loongarch_args_parser_can_match_arg_helper
,
781 if (insn
->all_match
&& !(it
->include
&& !*it
->include
)
782 && !(it
->exclude
&& *it
->exclude
))
784 insn
->insn_bin
|= it
->match
;
789 while (it
->name
&& strcasecmp (it
->name
, insn
->name
) == 0);
794 check_this_insn_before_appending (struct loongarch_cl_insn
*ip
)
797 if (strcmp (ip
->name
, "la.abs") == 0)
799 ip
->reloc_info
[ip
->reloc_num
].type
= BFD_RELOC_LARCH_MARK_LA
;
800 my_getExpression (&ip
->reloc_info
[ip
->reloc_num
].value
, ip
->arg_strs
[1]);
803 else if (ip
->insn
->mask
== 0xffff8000
804 /* amswap.w rd, rk, rj */
805 && ((ip
->insn_bin
& 0xfff00000) == 0x38600000
806 /* ammax_db.wu rd, rk, rj */
807 || (ip
->insn_bin
& 0xffff0000) == 0x38700000
808 /* ammin_db.wu rd, rk, rj */
809 || (ip
->insn_bin
& 0xffff0000) == 0x38710000))
811 /* For AMO insn amswap.[wd], amadd.[wd], etc. */
813 && (ip
->args
[0] == ip
->args
[1] || ip
->args
[0] == ip
->args
[2]))
814 as_fatal (_("AMO insns require rd != base && rd != rt"
815 " when rd isn't $r0"));
817 else if ((ip
->insn
->mask
== 0xffe08000
818 /* bstrins.w rd, rj, msbw, lsbw */
819 && (ip
->insn_bin
& 0xffe00000) == 0x00600000)
820 || (ip
->insn
->mask
== 0xffc00000
821 /* bstrins.d rd, rj, msbd, lsbd */
822 && (ip
->insn_bin
& 0xff800000) == 0x00800000))
824 /* For bstr(ins|pick).[wd]. */
825 if (ip
->args
[2] < ip
->args
[3])
826 as_fatal (_("bstr(ins|pick).[wd] require msbd >= lsbd"));
828 else if (ip
->insn
->mask
!= 0 && (ip
->insn_bin
& 0xfe0003c0) == 0x04000000
829 /* csrxchg rd, rj, csr_num */
830 && (strcmp ("csrxchg", ip
->name
) == 0))
831 as_fatal (_("csrxchg require rj != $r0 && rj != $r1"));
837 install_insn (const struct loongarch_cl_insn
*insn
)
839 char *f
= insn
->frag
->fr_literal
+ insn
->where
;
840 if (0 < insn
->insn_length
)
841 md_number_to_chars (f
, insn
->insn_bin
, insn
->insn_length
);
845 move_insn (struct loongarch_cl_insn
*insn
, fragS
*frag
, long where
)
850 for (i
= 0; i
< insn
->reloc_num
; i
++)
852 insn
->fixp
[i
]->fx_frag
= frag
;
853 insn
->fixp
[i
]->fx_where
= where
;
858 /* Add INSN to the end of the output. */
860 append_fixed_insn (struct loongarch_cl_insn
*insn
)
862 char *f
= frag_more (insn
->insn_length
);
863 move_insn (insn
, frag_now
, f
- frag_now
->fr_literal
);
867 append_fixp_and_insn (struct loongarch_cl_insn
*ip
)
869 reloc_howto_type
*howto
;
870 bfd_reloc_code_real_type reloc_type
;
871 struct reloc_info
*reloc_info
= ip
->reloc_info
;
874 dwarf2_emit_insn (0);
876 for (i
= 0; i
< ip
->reloc_num
; i
++)
878 reloc_type
= reloc_info
[i
].type
;
879 howto
= bfd_reloc_type_lookup (stdoutput
, reloc_type
);
881 as_fatal (_("no HOWTO loong relocation number %d"), reloc_type
);
884 fix_new_exp (ip
->frag
, ip
->where
, bfd_get_reloc_size (howto
),
885 &reloc_info
[i
].value
, FALSE
, reloc_type
);
888 if (ip
->insn_length
< ip
->relax_max_length
)
889 as_fatal (_("Internal error: not support relax now"));
891 append_fixed_insn (ip
);
894 /* Ask helper for returning a malloced c_str or NULL. */
896 assember_macro_helper (const char *const args
[], void *context_ptr
)
898 struct loongarch_cl_insn
*insn
= context_ptr
;
900 if ( strcmp (insn
->name
, "li.w") == 0 || strcmp (insn
->name
, "li.d") == 0)
902 char args_buf
[50], insns_buf
[200];
903 const char *arg_strs
[6];
906 /* We pay attention to sign extend beacause it is chance of reduce insn.
907 The exception is 12-bit and hi-12-bit unsigned,
908 we need a 'ori' or a 'lu52i.d' accordingly. */
909 char all0_bit_vec
, sign_bit_vec
, allf_bit_vec
, paritial_is_sext_of_prev
;
911 lo32
= insn
->args
[1] & 0xffffffff;
912 hi32
= insn
->args
[1] >> 32;
914 if (strcmp (insn
->name
, "li.w") == 0)
916 if (hi32
!= 0 && hi32
!= 0xffffffff)
917 as_fatal (_("li overflow: hi32:0x%x lo32:0x%x"), hi32
, lo32
);
918 hi32
= lo32
& 0x80000000 ? 0xffffffff : 0;
921 if (strcmp (insn
->name
, "li.d") == 0 && !LARCH_opts
.ase_lp64
)
922 as_fatal (_("we can't li.d on 32bit-arch"));
924 snprintf (args_buf
, sizeof (args_buf
), "0x%x,0x%x,0x%x,0x%x,%s",
925 (hi32
>> 20) & 0xfff, hi32
& 0xfffff, (lo32
>> 12) & 0xfffff,
926 lo32
& 0xfff, args
[0]);
927 loongarch_split_args_by_comma (args_buf
, arg_strs
);
930 ((((hi32
& 0xfff00000) == 0) << 3) | (((hi32
& 0x000fffff) == 0) << 2)
931 | (((lo32
& 0xfffff000) == 0) << 1) | ((lo32
& 0x00000fff) == 0));
933 ((((hi32
& 0x80000000) != 0) << 3) | (((hi32
& 0x00080000) != 0) << 2)
934 | (((lo32
& 0x80000000) != 0) << 1) | ((lo32
& 0x00000800) != 0));
936 ((((hi32
& 0xfff00000) == 0xfff00000) << 3)
937 | (((hi32
& 0x000fffff) == 0x000fffff) << 2)
938 | (((lo32
& 0xfffff000) == 0xfffff000) << 1)
939 | ((lo32
& 0x00000fff) == 0x00000fff));
940 paritial_is_sext_of_prev
=
941 (all0_bit_vec
^ allf_bit_vec
) & (all0_bit_vec
^ (sign_bit_vec
<< 1));
943 static const char *const li_32bit
[] =
945 "lu12i.w %5,%3&0x80000?%3-0x100000:%3;ori %5,%5,%4;",
946 "lu12i.w %5,%3&0x80000?%3-0x100000:%3;",
947 "addi.w %5,$r0,%4&0x800?%4-0x1000:%4;",
950 static const char *const li_hi_32bit
[] =
952 "lu32i.d %5,%2&0x80000?%2-0x100000:%2;"
953 "lu52i.d %5,%5,%1&0x800?%1-0x1000:%1;",
954 "lu52i.d %5,%5,%1&0x800?%1-0x1000:%1;",
955 "lu32i.d %5,%2&0x80000?%2-0x100000:%2;",
961 if (paritial_is_sext_of_prev
== 0x7)
963 strcat (insns_buf
, "lu52i.d %5,$r0,%1&0x800?%1-0x1000:%1;");
966 if ((all0_bit_vec
& 0x3) == 0x2)
967 strcat (insns_buf
, "ori %5,$r0,%4;");
969 strcat (insns_buf
, li_32bit
[paritial_is_sext_of_prev
& 0x3]);
970 strcat (insns_buf
, li_hi_32bit
[paritial_is_sext_of_prev
>> 2]);
974 ret
= loongarch_expand_macro (insns_buf
, arg_strs
, NULL
, NULL
,
980 /* Accept instructions separated by ';'
981 * assuming 'not starting with space and not ending with space' or pass in
984 loongarch_assemble_INSNs (char *str
)
987 size_t len_str
= strlen(str
);
989 for (rest
= str
; *rest
!= ';' && *rest
!= '\0'; rest
++);
996 setup_internal_label_here (strtol (str
, &str
, 10));
1005 struct loongarch_cl_insn the_one
= { 0 };
1008 for (; *str
&& *str
!= ' '; str
++)
1013 loongarch_split_args_by_comma (str
, the_one
.arg_strs
);
1014 get_loongarch_opcode (&the_one
);
1016 if (!the_one
.all_match
)
1018 char *ss
= loongarch_cat_splited_strs (the_one
.arg_strs
);
1019 as_bad (_("no match insn: %s\t%s"), the_one
.name
, ss
? ss
: "");
1024 if (check_this_insn_before_appending (&the_one
) != 0)
1027 append_fixp_and_insn (&the_one
);
1028 if (the_one
.insn_length
== 0 && the_one
.insn
->macro
)
1030 char *c_str
= loongarch_expand_macro (the_one
.insn
->macro
,
1032 assember_macro_helper
,
1034 loongarch_assemble_INSNs (c_str
);
1041 loongarch_assemble_INSNs (rest
);
1045 md_assemble (char *str
)
1047 loongarch_assemble_INSNs (str
);
1051 md_atof (int type
, char *litP
, int *sizeP
)
1053 return ieee_md_atof (type
, litP
, sizeP
, FALSE
);
1057 md_number_to_chars (char *buf
, valueT val
, int n
)
1059 number_to_chars_littleendian (buf
, val
, n
);
1062 /* The location from which a PC relative jump should be calculated,
1063 given a PC relative reloc. */
1065 md_pcrel_from (fixS
*fixP ATTRIBUTE_UNUSED
)
1070 static void fix_reloc_insn (fixS
*fixP
, bfd_vma reloc_val
, char *buf
)
1072 reloc_howto_type
*howto
;
1074 howto
= bfd_reloc_type_lookup (stdoutput
, fixP
->fx_r_type
);
1076 insn
= bfd_getl32 (buf
);
1078 if (!loongarch_adjust_reloc_bitsfield(howto
, &reloc_val
))
1079 as_warn_where (fixP
->fx_file
, fixP
->fx_line
, "Reloc overflow");
1081 insn
= (insn
& (insn_t
)howto
->src_mask
)
1082 | ((insn
& (~(insn_t
)howto
->dst_mask
)) | reloc_val
);
1084 bfd_putl32 (insn
, buf
);
1088 md_apply_fix (fixS
*fixP
, valueT
*valP
, segT seg ATTRIBUTE_UNUSED
)
1090 static int64_t stack_top
;
1091 static int last_reloc_is_sop_push_pcrel_1
= 0;
1092 int last_reloc_is_sop_push_pcrel
= last_reloc_is_sop_push_pcrel_1
;
1093 last_reloc_is_sop_push_pcrel_1
= 0;
1095 char *buf
= fixP
->fx_frag
->fr_literal
+ fixP
->fx_where
;
1096 switch (fixP
->fx_r_type
)
1098 case BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL
:
1099 case BFD_RELOC_LARCH_SOP_PUSH_TLS_GD
:
1100 case BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT
:
1101 case BFD_RELOC_LARCH_SOP_PUSH_PCREL
:
1102 case BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL
:
1103 if (fixP
->fx_addsy
== NULL
)
1104 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
1105 _("Relocation against a constant"));
1107 if (fixP
->fx_r_type
== BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL
1108 || fixP
->fx_r_type
== BFD_RELOC_LARCH_SOP_PUSH_TLS_GD
1109 || fixP
->fx_r_type
== BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT
)
1110 S_SET_THREAD_LOCAL (fixP
->fx_addsy
);
1112 if (fixP
->fx_r_type
== BFD_RELOC_LARCH_SOP_PUSH_PCREL
)
1114 last_reloc_is_sop_push_pcrel_1
= 1;
1115 if (S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
1116 stack_top
= (S_GET_VALUE (fixP
->fx_addsy
) + fixP
->fx_offset
1117 - (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
));
1123 case BFD_RELOC_LARCH_SOP_POP_32_S_10_5
:
1124 case BFD_RELOC_LARCH_SOP_POP_32_S_10_12
:
1125 case BFD_RELOC_LARCH_SOP_POP_32_U_10_12
:
1126 case BFD_RELOC_LARCH_SOP_POP_32_S_10_16
:
1127 case BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2
:
1128 case BFD_RELOC_LARCH_SOP_POP_32_S_5_20
:
1129 case BFD_RELOC_LARCH_SOP_POP_32_U
:
1130 case BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2
:
1131 case BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2
:
1132 if (!last_reloc_is_sop_push_pcrel
)
1135 fix_reloc_insn (fixP
, (bfd_vma
)stack_top
, buf
);
1145 fixP
->fx_next
= xmemdup (fixP
, sizeof (*fixP
), sizeof (*fixP
));
1146 fixP
->fx_next
->fx_addsy
= fixP
->fx_subsy
;
1147 fixP
->fx_next
->fx_subsy
= NULL
;
1148 fixP
->fx_next
->fx_offset
= 0;
1149 fixP
->fx_subsy
= NULL
;
1151 switch (fixP
->fx_r_type
)
1154 fixP
->fx_r_type
= BFD_RELOC_LARCH_ADD64
;
1155 fixP
->fx_next
->fx_r_type
= BFD_RELOC_LARCH_SUB64
;
1158 fixP
->fx_r_type
= BFD_RELOC_LARCH_ADD32
;
1159 fixP
->fx_next
->fx_r_type
= BFD_RELOC_LARCH_SUB32
;
1162 fixP
->fx_r_type
= BFD_RELOC_LARCH_ADD24
;
1163 fixP
->fx_next
->fx_r_type
= BFD_RELOC_LARCH_SUB24
;
1166 fixP
->fx_r_type
= BFD_RELOC_LARCH_ADD16
;
1167 fixP
->fx_next
->fx_r_type
= BFD_RELOC_LARCH_SUB16
;
1170 fixP
->fx_r_type
= BFD_RELOC_LARCH_ADD8
;
1171 fixP
->fx_next
->fx_r_type
= BFD_RELOC_LARCH_SUB8
;
1176 md_number_to_chars (buf
, 0, fixP
->fx_size
);
1177 if (fixP
->fx_next
->fx_addsy
== NULL
)
1178 fixP
->fx_next
->fx_done
= 1;
1180 if (fixP
->fx_addsy
== NULL
)
1183 md_number_to_chars (buf
, *valP
, fixP
->fx_size
);
1193 loongarch_relax_frag (asection
*sec ATTRIBUTE_UNUSED
,
1194 fragS
*fragp ATTRIBUTE_UNUSED
,
1195 long stretch ATTRIBUTE_UNUSED
)
1201 md_estimate_size_before_relax (fragS
*fragp ATTRIBUTE_UNUSED
,
1202 asection
*segtype ATTRIBUTE_UNUSED
)
1207 /* Translate internal representation of relocation info to BFD target
1210 tc_gen_reloc (asection
*section ATTRIBUTE_UNUSED
, fixS
*fixp
)
1212 arelent
*reloc
= (arelent
*) xmalloc (sizeof (arelent
));
1214 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
1215 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
1216 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
1217 reloc
->addend
= fixp
->fx_offset
;
1219 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, fixp
->fx_r_type
);
1220 if (reloc
->howto
== NULL
)
1222 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
1223 _("cannot represent %s relocation in object file"),
1224 bfd_get_reloc_code_name (fixp
->fx_r_type
));
1231 /* Convert a machine dependent frag. */
1233 md_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
, segT asec ATTRIBUTE_UNUSED
,
1234 fragS
*fragp ATTRIBUTE_UNUSED
)
1236 /* fragp->fr_fix += 8; */
1239 /* Standard calling conventions leave the CFA at SP on entry. */
1241 loongarch_cfi_frame_initial_instructions (void)
1243 cfi_add_CFA_def_cfa_register (3 /* $sp */);
1247 loongarch_dwarf2_addr_size (void)
1249 return LARCH_opts
.ase_lp64
? 8 : 4;
1253 tc_loongarch_parse_to_dw2regnum (expressionS
*exp
)
1255 expression_and_evaluate (exp
);
1259 md_show_usage (FILE *stream
)
1261 fprintf (stream
, _("LARCH options:\n"));
1265 /* Fill in an rs_align_code fragment. We want to fill 'andi $r0,$r0,0'. */
1267 loongarch_handle_align (fragS
*fragp
)
1269 /* char nop_opcode; */
1271 int bytes
, size
, excess
;
1274 if (fragp
->fr_type
!= rs_align_code
)
1277 struct loongarch_cl_insn nop
=
1278 { .name
= "andi", .arg_strs
= { "$r0", "$r0", "0", NULL
} };
1280 get_loongarch_opcode (&nop
);
1281 gas_assert (nop
.all_match
);
1283 p
= fragp
->fr_literal
+ fragp
->fr_fix
;
1284 opcode
= nop
.insn_bin
;
1287 bytes
= fragp
->fr_next
->fr_address
- fragp
->fr_address
- fragp
->fr_fix
;
1288 excess
= bytes
% size
;
1290 gas_assert (excess
< 4);
1291 fragp
->fr_fix
+= excess
;
1293 while (excess
-- != 0)
1296 md_number_to_chars (p
, opcode
, size
);
1297 fragp
->fr_var
= size
;
1301 loongarch_elf_final_processing (void)
1303 elf_elfheader (stdoutput
)->e_flags
= LARCH_opts
.ase_abi
;