1 /* tc-loongarch.c -- Assemble for the LoongArch ISA
3 Copyright (C) 2021-2023 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/>. */
24 #include "dw2gencfi.h"
25 #include "loongarch-lex.h"
26 #include "elf/loongarch.h"
27 #include "opcode/loongarch.h"
29 #include "bfd/elfxx-loongarch.h"
35 /* All information about an instruction during assemble. */
36 struct loongarch_cl_insn
38 /* First split string. */
40 const char *arg_strs
[MAX_ARG_NUM_PLUS_2
];
43 /* Second analyze name_str and each actual args string to match the insn
44 in 'loongarch-opc.c'. And actual args may need be relocated.
45 We get length of insn. If 'insn_length == 0 && insn_mo->macro != NULL',
46 it's a macro insntruction and we call 'md_assemble' recursively
47 after expanding it. */
51 const struct loongarch_opcode
*insn
;
54 offsetT args
[MAX_ARG_NUM_PLUS_2
];
55 struct reloc_info reloc_info
[MAX_RELOC_NUMBER_A_INSN
];
58 /* For relax reserved. We not support relax now.
59 'insn_length < relax_max_length' means need to relax.
60 And 'insn_length == relax_max_length' means no need to relax. */
61 size_t relax_max_length
;
62 relax_substateT subtype
;
64 /* Then we get the binary representation of insn
65 and write it in to section. */
68 /* The frag that contains the instruction. */
70 /* The offset into FRAG of the first instruction byte. */
72 /* The relocs associated with the instruction, if any. */
73 fixS
*fixp
[MAX_RELOC_NUMBER_A_INSN
];
78 #define DEFAULT_ARCH "loongarch64"
81 /* This array holds the chars that always start a comment. If the
82 pre-processor is disabled, these aren't very useful. */
83 const char comment_chars
[] = "#";
85 /* This array holds the chars that only start a comment at the beginning of
86 a line. If the line seems to have the form '# 123 filename'
87 .line and .file directives will appear in the pre-processed output. */
88 /* Note that input_file.c hand checks for '#' at the beginning of the
89 first line of the input file. This is because the compiler outputs
90 #NO_APP at the beginning of its output. */
91 /* Also note that C style comments are always supported. */
92 const char line_comment_chars
[] = "#";
94 /* This array holds machine specific line separator characters. */
95 const char line_separator_chars
[] = ";";
97 /* Chars that can be used to separate mant from exp in floating point nums. */
98 const char EXP_CHARS
[] = "eE";
100 /* Chars that mean this number is a floating point constant. */
101 /* As in 0f12.456. */
102 /* or 0d1.2345e12. */
103 const char FLT_CHARS
[] = "rRsSfFdDxXpP";
105 const char *md_shortopts
= "O::g::G:";
107 static const char default_arch
[] = DEFAULT_ARCH
;
109 /* The lowest 4-bit is the bytes of instructions. */
110 #define RELAX_BRANCH_16 0xc0000014
111 #define RELAX_BRANCH_21 0xc0000024
112 #define RELAX_BRANCH_26 0xc0000048
114 #define RELAX_BRANCH(x) \
115 (((x) & 0xf0000000) == 0xc0000000)
116 #define RELAX_BRANCH_ENCODE(x) \
117 (BFD_RELOC_LARCH_B16 == (x) ? RELAX_BRANCH_16 : RELAX_BRANCH_21)
121 OPTION_IGNORE
= OPTION_MD_BASE
,
128 OPTION_LA_LOCAL_WITH_ABS
,
129 OPTION_LA_GLOBAL_WITH_PCREL
,
130 OPTION_LA_GLOBAL_WITH_ABS
,
138 struct option md_longopts
[] =
140 { "mabi", required_argument
, NULL
, OPTION_ABI
},
142 { "mfpu", required_argument
, NULL
, OPTION_FLOAT_ISA
},
144 { "mla-local-with-abs", no_argument
, NULL
, OPTION_LA_LOCAL_WITH_ABS
},
145 { "mla-global-with-pcrel", no_argument
, NULL
, OPTION_LA_GLOBAL_WITH_PCREL
},
146 { "mla-global-with-abs", no_argument
, NULL
, OPTION_LA_GLOBAL_WITH_ABS
},
148 { "mrelax", no_argument
, NULL
, OPTION_RELAX
},
149 { "mno-relax", no_argument
, NULL
, OPTION_NO_RELAX
},
150 { "mthin-add-sub", no_argument
, NULL
, OPTION_THIN_ADD_SUB
},
152 { NULL
, no_argument
, NULL
, 0 }
155 size_t md_longopts_size
= sizeof (md_longopts
);
158 md_parse_option (int c
, const char *arg
)
162 char ilp32
[256] = "";
163 unsigned char *suf
= (unsigned char *)arg
;
165 lp64
['s'] = lp64
['S'] = EF_LOONGARCH_ABI_SOFT_FLOAT
;
166 lp64
['f'] = lp64
['F'] = EF_LOONGARCH_ABI_SINGLE_FLOAT
;
167 lp64
['d'] = lp64
['D'] = EF_LOONGARCH_ABI_DOUBLE_FLOAT
;
169 ilp32
['s'] = ilp32
['S'] = EF_LOONGARCH_ABI_SOFT_FLOAT
;
170 ilp32
['f'] = ilp32
['F'] = EF_LOONGARCH_ABI_SINGLE_FLOAT
;
171 ilp32
['d'] = ilp32
['D'] = EF_LOONGARCH_ABI_DOUBLE_FLOAT
;
176 if (strncasecmp (arg
, "lp64", 4) == 0 && lp64
[suf
[4]] != 0)
178 LARCH_opts
.ase_ilp32
= 1;
179 LARCH_opts
.ase_lp64
= 1;
180 LARCH_opts
.ase_lsx
= 1;
181 LARCH_opts
.ase_lasx
= 1;
182 LARCH_opts
.ase_lvz
= 1;
183 LARCH_opts
.ase_lbt
= 1;
184 LARCH_opts
.ase_abi
= lp64
[suf
[4]];
186 else if (strncasecmp (arg
, "ilp32", 5) == 0 && ilp32
[suf
[5]] != 0)
188 LARCH_opts
.ase_abi
= ilp32
[suf
[5]];
189 LARCH_opts
.ase_ilp32
= 1;
195 case OPTION_FLOAT_ISA
:
196 if (strcasecmp (arg
, "soft") == 0)
197 LARCH_opts
.ase_nf
= 1;
198 else if (strcasecmp (arg
, "single") == 0)
199 LARCH_opts
.ase_sf
= 1;
200 else if (strcasecmp (arg
, "double") == 0)
202 LARCH_opts
.ase_sf
= 1;
203 LARCH_opts
.ase_df
= 1;
209 case OPTION_LA_LOCAL_WITH_ABS
:
210 LARCH_opts
.ase_labs
= 1;
213 case OPTION_LA_GLOBAL_WITH_PCREL
:
214 LARCH_opts
.ase_gpcr
= 1;
217 case OPTION_LA_GLOBAL_WITH_ABS
:
218 LARCH_opts
.ase_gabs
= 1;
222 LARCH_opts
.relax
= 1;
225 case OPTION_NO_RELAX
:
226 LARCH_opts
.relax
= 0;
229 case OPTION_THIN_ADD_SUB
:
230 LARCH_opts
.thin_add_sub
= 1;
243 static const char *const *r_abi_names
= NULL
;
244 static const char *const *f_abi_names
= NULL
;
245 static struct htab
*r_htab
= NULL
;
246 static struct htab
*r_deprecated_htab
= NULL
;
247 static struct htab
*f_htab
= NULL
;
248 static struct htab
*f_deprecated_htab
= NULL
;
249 static struct htab
*fc_htab
= NULL
;
250 static struct htab
*fcn_htab
= NULL
;
251 static struct htab
*c_htab
= NULL
;
252 static struct htab
*cr_htab
= NULL
;
253 static struct htab
*v_htab
= NULL
;
254 static struct htab
*x_htab
= NULL
;
257 loongarch_after_parse_args ()
259 /* Set default ABI/ISA LP64D. */
260 if (!LARCH_opts
.ase_ilp32
)
262 if (strcmp (default_arch
, "loongarch64") == 0)
264 LARCH_opts
.ase_abi
= EF_LOONGARCH_ABI_DOUBLE_FLOAT
;
265 LARCH_opts
.ase_ilp32
= 1;
266 LARCH_opts
.ase_lp64
= 1;
267 LARCH_opts
.ase_lsx
= 1;
268 LARCH_opts
.ase_lasx
= 1;
269 LARCH_opts
.ase_lvz
= 1;
270 LARCH_opts
.ase_lbt
= 1;
272 else if (strcmp (default_arch
, "loongarch32") == 0)
274 LARCH_opts
.ase_abi
= EF_LOONGARCH_ABI_DOUBLE_FLOAT
;
275 LARCH_opts
.ase_ilp32
= 1;
278 as_bad ("unknown default architecture `%s'", default_arch
);
281 LARCH_opts
.ase_abi
|= EF_LOONGARCH_OBJABI_V1
;
282 /* Set default ISA double-float. */
283 if (!LARCH_opts
.ase_nf
284 && !LARCH_opts
.ase_sf
285 && !LARCH_opts
.ase_df
)
287 LARCH_opts
.ase_sf
= 1;
288 LARCH_opts
.ase_df
= 1;
293 assert(LARCH_opts
.ase_ilp32
);
295 /* Init ilp32/lp64 registers names. */
297 r_htab
= str_htab_create (), str_hash_insert (r_htab
, "", 0, 0);
298 if (!r_deprecated_htab
)
299 r_deprecated_htab
= str_htab_create (),
300 str_hash_insert (r_deprecated_htab
, "", 0, 0);
302 r_abi_names
= loongarch_r_normal_name
;
303 for (i
= 0; i
< ARRAY_SIZE (loongarch_r_normal_name
); i
++)
304 str_hash_insert (r_htab
, loongarch_r_normal_name
[i
], (void *) (i
+ 1), 0);
307 cr_htab
= str_htab_create (), str_hash_insert (cr_htab
, "", 0, 0);
309 for (i
= 0; i
< ARRAY_SIZE (loongarch_cr_normal_name
); i
++)
310 str_hash_insert (cr_htab
, loongarch_cr_normal_name
[i
], (void *) (i
+ 1), 0);
312 /* Init single/double float registers names. */
313 if (LARCH_opts
.ase_sf
|| LARCH_opts
.ase_df
)
316 f_htab
= str_htab_create (), str_hash_insert (f_htab
, "", 0, 0);
317 if (!f_deprecated_htab
)
318 f_deprecated_htab
= str_htab_create (),
319 str_hash_insert (f_deprecated_htab
, "", 0, 0);
321 f_abi_names
= loongarch_f_normal_name
;
322 for (i
= 0; i
< ARRAY_SIZE (loongarch_f_normal_name
); i
++)
323 str_hash_insert (f_htab
, loongarch_f_normal_name
[i
], (void *) (i
+ 1),
327 fc_htab
= str_htab_create (), str_hash_insert (fc_htab
, "", 0, 0);
329 for (i
= 0; i
< ARRAY_SIZE (loongarch_fc_normal_name
); i
++)
330 str_hash_insert (fc_htab
, loongarch_fc_normal_name
[i
], (void *) (i
+ 1),
334 fcn_htab
= str_htab_create (), str_hash_insert (fcn_htab
, "", 0, 0);
336 for (i
= 0; i
< ARRAY_SIZE (loongarch_fc_numeric_name
); i
++)
337 str_hash_insert (fcn_htab
, loongarch_fc_numeric_name
[i
], (void *) (i
+ 1),
341 c_htab
= str_htab_create (), str_hash_insert (c_htab
, "", 0, 0);
343 for (i
= 0; i
< ARRAY_SIZE (loongarch_c_normal_name
); i
++)
344 str_hash_insert (c_htab
, loongarch_c_normal_name
[i
], (void *) (i
+ 1),
349 /* Init lsx registers names. */
350 if (LARCH_opts
.ase_lsx
)
353 v_htab
= str_htab_create (), str_hash_insert (v_htab
, "", 0, 0);
354 for (i
= 0; i
< ARRAY_SIZE (loongarch_v_normal_name
); i
++)
355 str_hash_insert (v_htab
, loongarch_v_normal_name
[i
], (void *) (i
+ 1),
359 /* Init lasx registers names. */
360 if (LARCH_opts
.ase_lasx
)
363 x_htab
= str_htab_create (), str_hash_insert (x_htab
, "", 0, 0);
364 for (i
= 0; i
< ARRAY_SIZE (loongarch_x_normal_name
); i
++)
365 str_hash_insert (x_htab
, loongarch_x_normal_name
[i
], (void *) (i
+ 1),
369 /* Init lp64 registers alias. */
370 if (LARCH_opts
.ase_lp64
)
372 r_abi_names
= loongarch_r_lp64_name
;
373 for (i
= 0; i
< ARRAY_SIZE (loongarch_r_lp64_name
); i
++)
374 str_hash_insert (r_htab
, loongarch_r_lp64_name
[i
], (void *) (i
+ 1),
376 for (i
= 0; i
< ARRAY_SIZE (loongarch_r_lp64_name_deprecated
); i
++)
377 str_hash_insert (r_deprecated_htab
, loongarch_r_lp64_name_deprecated
[i
],
378 (void *) (i
+ 1), 0);
381 /* Init float-lp64 registers alias */
382 if ((LARCH_opts
.ase_sf
|| LARCH_opts
.ase_df
) && LARCH_opts
.ase_lp64
)
384 f_abi_names
= loongarch_f_lp64_name
;
385 for (i
= 0; i
< ARRAY_SIZE (loongarch_f_lp64_name
); i
++)
386 str_hash_insert (f_htab
, loongarch_f_lp64_name
[i
],
387 (void *) (i
+ 1), 0);
388 for (i
= 0; i
< ARRAY_SIZE (loongarch_f_lp64_name_deprecated
); i
++)
389 str_hash_insert (f_deprecated_htab
, loongarch_f_lp64_name_deprecated
[i
],
390 (void *) (i
+ 1), 0);
395 loongarch_target_format ()
397 return LARCH_opts
.ase_lp64
? "elf64-loongarch" : "elf32-loongarch";
403 const struct loongarch_opcode
*it
;
404 struct loongarch_ase
*ase
;
405 for (ase
= loongarch_ASEs
; ase
->enabled
; ase
++)
406 for (it
= ase
->opcodes
; it
->name
; it
++)
408 if (loongarch_check_format (it
->format
) != 0)
409 as_fatal (_("insn name: %s\tformat: %s\tsyntax error"),
410 it
->name
, it
->format
);
411 if (it
->mask
== 0 && it
->macro
== 0)
412 as_fatal (_("insn name: %s\nformat: %s\nwe want macro but "
414 it
->name
, it
->format
);
416 && loongarch_check_macro (it
->format
, it
->macro
) != 0)
417 as_fatal (_("insn name: %s\nformat: %s\nmacro: %s\tsyntax error"),
418 it
->name
, it
->format
, it
->macro
);
421 /* FIXME: expressionS use 'offsetT' as constant,
422 * we want this is 64-bit type. */
423 assert (8 <= sizeof (offsetT
));
427 loongarch_mach (void)
429 return LARCH_opts
.ase_lp64
? bfd_mach_loongarch64
: bfd_mach_loongarch32
;
432 static const expressionS const_0
= { .X_op
= O_constant
, .X_add_number
= 0 };
435 s_loongarch_align (int arg
)
437 const char *t
= input_line_pointer
;
438 while (!is_end_of_line
[(unsigned char) *t
] && *t
!= ',')
446 /* Handle the .dtprelword and .dtpreldword pseudo-ops. They generate
447 a 32-bit or 64-bit DTP-relative relocation (BYTES says which) for
448 use in DWARF debug information. */
458 if (ex
.X_op
!= O_symbol
)
460 as_bad (_("Unsupported use of %s"),
461 (bytes
== 8 ? ".dtpreldword" : ".dtprelword"));
462 ignore_rest_of_line ();
465 p
= frag_more (bytes
);
466 md_number_to_chars (p
, 0, bytes
);
467 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
, bytes
, &ex
, FALSE
,
469 ? BFD_RELOC_LARCH_TLS_DTPREL64
470 : BFD_RELOC_LARCH_TLS_DTPREL32
));
472 demand_empty_rest_of_line ();
475 static const pseudo_typeS loongarch_pseudo_table
[] =
477 { "align", s_loongarch_align
, -4 },
478 { "dword", cons
, 8 },
481 { "dtprelword", s_dtprel
, 4 },
482 { "dtpreldword", s_dtprel
, 8 },
487 loongarch_pop_insert (void)
489 pop_insert (loongarch_pseudo_table
);
492 #define INTERNAL_LABEL_SPECIAL 10
493 static unsigned long internal_label_count
[INTERNAL_LABEL_SPECIAL
] = { 0 };
496 loongarch_internal_label_name (unsigned long label
, int augend
)
498 static char symbol_name_build
[24];
499 unsigned long want_label
;
502 want_label
= internal_label_count
[label
] + augend
;
504 p
= symbol_name_build
;
505 #ifdef LOCAL_LABEL_PREFIX
506 *p
++ = LOCAL_LABEL_PREFIX
;
509 for (; label
; label
/= 10)
510 *p
++ = label
% 10 + '0';
511 /* Make sure internal label never belong to normal label namespace. */
513 for (; want_label
; want_label
/= 10)
514 *p
++ = want_label
% 10 + '0';
516 return symbol_name_build
;
520 setup_internal_label_here (unsigned long label
)
522 assert (label
< INTERNAL_LABEL_SPECIAL
);
523 internal_label_count
[label
]++;
524 colon (loongarch_internal_label_name (label
, 0));
528 get_internal_label (expressionS
*label_expr
, unsigned long label
,
529 int augend
/* 0 for previous, 1 for next. */)
531 assert (label
< INTERNAL_LABEL_SPECIAL
);
532 as_fatal (_("internal error: we have no internal label yet"));
533 label_expr
->X_op
= O_symbol
;
534 label_expr
->X_add_symbol
=
535 symbol_find_or_make (loongarch_internal_label_name (label
, augend
));
536 label_expr
->X_add_number
= 0;
540 is_internal_label (const char *c_str
)
547 if (!('0' <= *c_str
&& *c_str
<= '9'))
549 while ('0' <= *c_str
&& *c_str
<= '9')
551 if (*c_str
!= 'b' && *c_str
!= 'f')
554 return *c_str
== '\0';
561 is_label (const char *c_str
)
563 if (is_internal_label (c_str
))
565 else if ('0' <= *c_str
&& *c_str
<= '9')
568 while ('0' <= *c_str
&& *c_str
<= '9')
570 return *c_str
== 'b' || *c_str
== 'f';
572 else if (is_name_beginner (*c_str
))
574 /* [a-zA-Z\._\$][0-9a-zA-Z\._\$]* */
576 while (is_part_of_name (*c_str
))
578 return *c_str
== '\0';
585 is_label_with_addend (const char *c_str
)
587 if (is_internal_label (c_str
))
589 else if ('0' <= *c_str
&& *c_str
<= '9')
592 while ('0' <= *c_str
&& *c_str
<= '9')
594 if (*c_str
== 'b' || *c_str
== 'f')
598 return *c_str
== '\0'
599 || ((*c_str
== '-' || *c_str
== '+')
600 && is_unsigned (c_str
+ 1));
602 else if (is_name_beginner (*c_str
))
604 /* [a-zA-Z\._\$][0-9a-zA-Z\._\$]* */
606 while (is_part_of_name (*c_str
))
608 return *c_str
== '\0'
609 || ((*c_str
== '-' || *c_str
== '+')
610 && is_unsigned (c_str
+ 1));
617 loongarch_args_parser_can_match_arg_helper (char esc_ch1
, char esc_ch2
,
618 const char *bit_field
,
619 const char *arg
, void *context
)
621 struct loongarch_cl_insn
*ip
= context
;
622 offsetT imm
, ret
= 0;
623 size_t reloc_num_we_have
= MAX_RELOC_NUMBER_A_INSN
- ip
->reloc_num
;
624 size_t reloc_num
= 0;
635 ip
->match_now
= is_label (arg
);
636 if (!ip
->match_now
&& is_label_with_addend (arg
))
637 as_fatal (_("This label shouldn't be with addend."));
640 ip
->match_now
= is_label_with_addend (arg
);
647 loongarch_parse_expr (arg
, ip
->reloc_info
+ ip
->reloc_num
,
648 reloc_num_we_have
, &reloc_num
, &imm
) == 0;
656 bfd_reloc_code_real_type reloc_type
= BFD_RELOC_NONE
;
657 reloc_num_we_have
-= reloc_num
;
658 if (reloc_num_we_have
== 0)
659 as_fatal (_("expr too huge") /* Want one more reloc. */);
662 if (strncmp (bit_field
, "10:12", strlen ("10:12")) == 0)
663 reloc_type
= BFD_RELOC_LARCH_SOP_POP_32_U_10_12
;
665 else if (esc_ch1
== 's')
667 if (strncmp (bit_field
, "10:16<<2", strlen ("10:16<<2")) == 0)
668 reloc_type
= BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2
;
669 else if (strncmp (bit_field
, "0:5|10:16<<2",
670 strlen ("0:5|10:16<<2")) == 0)
671 reloc_type
= BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2
;
672 else if (strncmp (bit_field
, "0:10|10:16<<2",
673 strlen ("0:10|10:16<<2")) == 0)
674 reloc_type
= BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2
;
675 else if (strncmp (bit_field
, "10:12", strlen ("10:12")) == 0)
676 reloc_type
= BFD_RELOC_LARCH_SOP_POP_32_S_10_12
;
677 else if (strncmp (bit_field
, "5:20", strlen ("5:20")) == 0)
678 reloc_type
= BFD_RELOC_LARCH_SOP_POP_32_S_5_20
;
679 else if (strncmp (bit_field
, "10:16", strlen ("10:16")) == 0)
680 reloc_type
= BFD_RELOC_LARCH_SOP_POP_32_S_10_16
;
681 else if (strncmp (bit_field
, "10:5", strlen ("10:5")) == 0)
682 reloc_type
= BFD_RELOC_LARCH_SOP_POP_32_S_10_5
;
684 if (reloc_type
== BFD_RELOC_NONE
)
686 _("not support reloc bit-field\nfmt: %c%c %s\nargs: %s"),
687 esc_ch1
, esc_ch2
, bit_field
, arg
);
689 if (ip
->reloc_info
[0].type
>= BFD_RELOC_LARCH_B16
690 && ip
->reloc_info
[0].type
< BFD_RELOC_LARCH_64_PCREL
)
692 /* As we compact stack-relocs, it is no need for pop operation.
693 But break out until here in order to check the imm field.
694 May be reloc_num > 1 if implement relax? */
695 ip
->reloc_num
+= reloc_num
;
696 reloc_type
= ip
->reloc_info
[0].type
;
698 if (LARCH_opts
.relax
&& ip
->macro_id
699 && (BFD_RELOC_LARCH_PCALA_HI20
== reloc_type
700 || BFD_RELOC_LARCH_PCALA_LO12
== reloc_type
701 || BFD_RELOC_LARCH_GOT_PC_HI20
== reloc_type
702 || BFD_RELOC_LARCH_GOT_PC_LO12
== reloc_type
))
704 ip
->reloc_info
[ip
->reloc_num
].type
= BFD_RELOC_LARCH_RELAX
;
705 ip
->reloc_info
[ip
->reloc_num
].value
= const_0
;
711 ip
->reloc_num
+= reloc_num
;
712 ip
->reloc_info
[ip
->reloc_num
- 1].type
= reloc_type
;
713 ip
->reloc_info
[ip
->reloc_num
- 1].value
= const_0
;
717 imm
= (intptr_t) str_hash_find (r_htab
, arg
);
718 ip
->match_now
= 0 < imm
;
722 /* Handle potential usage of deprecated register aliases. */
723 imm
= (intptr_t) str_hash_find (r_deprecated_htab
, arg
);
724 ip
->match_now
= 0 < imm
;
726 if (ip
->match_now
&& !ip
->macro_id
)
727 as_warn (_("register alias %s is deprecated, use %s instead"),
728 arg
, r_abi_names
[ret
]);
734 imm
= (intptr_t) str_hash_find (fc_htab
, arg
);
737 imm
= (intptr_t) str_hash_find (fcn_htab
, arg
);
741 imm
= (intptr_t) str_hash_find (f_htab
, arg
);
743 ip
->match_now
= 0 < imm
;
745 if (ip
->match_now
&& !ip
->macro_id
)
747 /* Handle potential usage of deprecated register aliases. */
748 imm
= (intptr_t) str_hash_find (f_deprecated_htab
, arg
);
749 ip
->match_now
= 0 < imm
;
752 as_warn (_("register alias %s is deprecated, use %s instead"),
753 arg
, f_abi_names
[ret
]);
759 imm
= (intptr_t) str_hash_find (cr_htab
, arg
);
762 imm
= (intptr_t) str_hash_find (c_htab
, arg
);
764 ip
->match_now
= 0 < imm
;
768 imm
= (intptr_t) str_hash_find (v_htab
, arg
);
769 ip
->match_now
= 0 < imm
;
773 imm
= (intptr_t) str_hash_find (x_htab
, arg
);
774 ip
->match_now
= 0 < imm
;
778 ip
->all_match
= ip
->match_now
;
780 ip
->insn
->mask
? loongarch_insn_length (ip
->insn
->match
) : 0;
781 /* FIXME: now we have no relax insn. */
782 ip
->relax_max_length
= ip
->insn_length
;
785 as_fatal (_("unknown escape"));
790 /* Check imm overflow. */
791 int bit_width
, bits_needed_s
, bits_needed_u
;
800 bit_width
= loongarch_get_bit_field_width (bit_field
, &t
);
803 /* No specify bit width. */
807 if (t
[0] == '<' && t
[1] == '<')
809 int i
= strtol (t
+= 2, &t
, 10), j
;
810 for (j
= i
; 0 < j
; j
--, imm
>>= 1)
812 as_fatal (_("require imm low %d bit is 0."), i
);
816 imm
-= strtol (t
, &t
, 10);
818 bits_needed_s
= loongarch_bits_imm_needed (imm
, 1);
819 bits_needed_u
= loongarch_bits_imm_needed (imm
, 0);
821 if ((esc_ch1
== 's' && bit_width
< bits_needed_s
)
822 || (esc_ch1
!= 's' && bit_width
< bits_needed_u
))
823 /* How to do after we detect overflow. */
824 as_fatal (_("Immediate overflow.\n"
827 esc_ch1
, esc_ch2
, bit_field
, arg
);
833 ip
->args
[ip
->arg_num
] = ret
;
840 get_loongarch_opcode (struct loongarch_cl_insn
*insn
)
842 const struct loongarch_opcode
*it
;
843 struct loongarch_ase
*ase
;
844 for (ase
= loongarch_ASEs
; ase
->enabled
; ase
++)
846 if (!*ase
->enabled
|| (ase
->include
&& !*ase
->include
)
847 || (ase
->exclude
&& *ase
->exclude
))
850 if (!ase
->name_hash_entry
)
852 ase
->name_hash_entry
= str_htab_create ();
853 for (it
= ase
->opcodes
; it
->name
; it
++)
855 if ((!it
->include
|| (it
->include
&& *it
->include
))
856 && (!it
->exclude
|| (it
->exclude
&& !(*it
->exclude
)))
857 && !(it
->pinfo
& INSN_DIS_ALIAS
))
858 str_hash_insert (ase
->name_hash_entry
, it
->name
,
863 if ((it
= str_hash_find (ase
->name_hash_entry
, insn
->name
)) == NULL
)
873 insn
->insn_bin
= (loongarch_foreach_args
874 (it
->format
, insn
->arg_strs
,
875 loongarch_args_parser_can_match_arg_helper
,
877 if (insn
->all_match
&& !(it
->include
&& !*it
->include
)
878 && !(it
->exclude
&& *it
->exclude
))
880 insn
->insn_bin
|= it
->match
;
885 while (it
->name
&& strcasecmp (it
->name
, insn
->name
) == 0);
890 check_this_insn_before_appending (struct loongarch_cl_insn
*ip
)
894 if (strncmp (ip
->name
, "la.abs", 6) == 0)
896 ip
->reloc_info
[ip
->reloc_num
].type
= BFD_RELOC_LARCH_MARK_LA
;
897 ip
->reloc_info
[ip
->reloc_num
].value
= const_0
;
900 else if (ip
->insn
->mask
== 0xffff8000
901 /* amswap.w rd, rk, rj */
902 && ((ip
->insn_bin
& 0xfff00000) == 0x38600000
903 /* ammax_db.wu rd, rk, rj */
904 || (ip
->insn_bin
& 0xffff0000) == 0x38700000
905 /* ammin_db.wu rd, rk, rj */
906 || (ip
->insn_bin
& 0xffff0000) == 0x38710000))
908 /* For AMO insn amswap.[wd], amadd.[wd], etc. */
910 && (ip
->args
[0] == ip
->args
[1] || ip
->args
[0] == ip
->args
[2]))
911 as_fatal (_("AMO insns require rd != base && rd != rt"
912 " when rd isn't $r0"));
914 else if ((ip
->insn
->mask
== 0xffe08000
915 /* bstrins.w rd, rj, msbw, lsbw */
916 && (ip
->insn_bin
& 0xffe00000) == 0x00600000)
917 || (ip
->insn
->mask
== 0xffc00000
918 /* bstrins.d rd, rj, msbd, lsbd */
919 && (ip
->insn_bin
& 0xff800000) == 0x00800000))
921 /* For bstr(ins|pick).[wd]. */
922 if (ip
->args
[2] < ip
->args
[3])
923 as_fatal (_("bstr(ins|pick).[wd] require msbd >= lsbd"));
925 else if (ip
->insn
->mask
!= 0 && (ip
->insn_bin
& 0xfe0003c0) == 0x04000000
926 /* csrxchg rd, rj, csr_num */
927 && (strcmp ("csrxchg", ip
->name
) == 0))
928 as_fatal (_("csrxchg require rj != $r0 && rj != $r1"));
934 install_insn (const struct loongarch_cl_insn
*insn
)
936 char *f
= insn
->frag
->fr_literal
+ insn
->where
;
937 if (0 < insn
->insn_length
)
938 md_number_to_chars (f
, insn
->insn_bin
, insn
->insn_length
);
942 move_insn (struct loongarch_cl_insn
*insn
, fragS
*frag
, long where
)
947 for (i
= 0; i
< insn
->reloc_num
; i
++)
951 insn
->fixp
[i
]->fx_frag
= frag
;
952 insn
->fixp
[i
]->fx_where
= where
;
958 /* Add INSN to the end of the output. */
960 append_fixed_insn (struct loongarch_cl_insn
*insn
)
962 char *f
= frag_more (insn
->insn_length
);
963 move_insn (insn
, frag_now
, f
- frag_now
->fr_literal
);
966 /* Add instructions based on the worst-case scenario firstly. */
968 append_relaxed_branch_insn (struct loongarch_cl_insn
*insn
, int max_chars
,
969 int var
, relax_substateT subtype
, symbolS
*symbol
, offsetT offset
)
971 frag_grow (max_chars
);
972 move_insn (insn
, frag_now
, frag_more (0) - frag_now
->fr_literal
);
973 frag_var (rs_machine_dependent
, max_chars
, var
,
974 subtype
, symbol
, offset
, NULL
);
978 append_fixp_and_insn (struct loongarch_cl_insn
*ip
)
980 reloc_howto_type
*howto
;
981 bfd_reloc_code_real_type r_type
;
982 struct reloc_info
*reloc_info
= ip
->reloc_info
;
985 dwarf2_emit_insn (0);
987 for (i
= 0; i
< ip
->reloc_num
; i
++)
989 r_type
= reloc_info
[i
].type
;
991 if (r_type
!= BFD_RELOC_UNUSED
)
994 gas_assert (&(reloc_info
[i
].value
));
995 if (BFD_RELOC_LARCH_B16
== r_type
|| BFD_RELOC_LARCH_B21
== r_type
)
997 int min_bytes
= 4; /* One branch instruction. */
998 unsigned max_bytes
= 8; /* Branch and jump instructions. */
1000 if (now_seg
== absolute_section
)
1002 as_bad (_("relaxable branches not supported in absolute section"));
1006 append_relaxed_branch_insn (ip
, max_bytes
, min_bytes
,
1007 RELAX_BRANCH_ENCODE (r_type
),
1008 reloc_info
[i
].value
.X_add_symbol
,
1009 reloc_info
[i
].value
.X_add_number
);
1014 howto
= bfd_reloc_type_lookup (stdoutput
, r_type
);
1016 as_fatal (_("no HOWTO loong relocation number %d"), r_type
);
1018 ip
->fixp
[i
] = fix_new_exp (ip
->frag
, ip
->where
,
1019 bfd_get_reloc_size (howto
),
1020 &reloc_info
[i
].value
, FALSE
, r_type
);
1025 if (ip
->insn_length
< ip
->relax_max_length
)
1026 as_fatal (_("Internal error: not support relax now"));
1028 append_fixed_insn (ip
);
1030 /* We need to start a new frag after any instruction that can be
1031 optimized away or compressed by the linker during relaxation, to prevent
1032 the assembler from computing static offsets across such an instruction.
1034 This is necessary to get correct .eh_frame cfa info. If one cfa's two
1035 symbol is not in the same frag, it will generate relocs to calculate
1036 symbol subtraction. (gas/dw2gencfi.c:output_cfi_insn:
1037 if (symbol_get_frag (to) == symbol_get_frag (from))) */
1038 if (LARCH_opts
.relax
1039 && (BFD_RELOC_LARCH_PCALA_HI20
== reloc_info
[0].type
1040 || BFD_RELOC_LARCH_GOT_PC_HI20
== reloc_info
[0].type
))
1042 frag_wane (frag_now
);
1047 /* Ask helper for returning a malloced c_str or NULL. */
1049 assember_macro_helper (const char *const args
[], void *context_ptr
)
1051 struct loongarch_cl_insn
*insn
= context_ptr
;
1053 if ( strcmp (insn
->name
, "li.w") == 0 || strcmp (insn
->name
, "li.d") == 0)
1055 char args_buf
[50], insns_buf
[200];
1056 const char *arg_strs
[6];
1057 uint32_t hi32
, lo32
;
1059 /* We pay attention to sign extend beacause it is chance of reduce insn.
1060 The exception is 12-bit and hi-12-bit unsigned,
1061 we need a 'ori' or a 'lu52i.d' accordingly. */
1062 char all0_bit_vec
, sign_bit_vec
, allf_bit_vec
, paritial_is_sext_of_prev
;
1064 lo32
= insn
->args
[1] & 0xffffffff;
1065 hi32
= insn
->args
[1] >> 32;
1067 if (strcmp (insn
->name
, "li.w") == 0)
1069 if (hi32
!= 0 && hi32
!= 0xffffffff)
1070 as_fatal (_("li overflow: hi32:0x%x lo32:0x%x"), hi32
, lo32
);
1071 hi32
= lo32
& 0x80000000 ? 0xffffffff : 0;
1074 if (strcmp (insn
->name
, "li.d") == 0 && !LARCH_opts
.ase_lp64
)
1075 as_fatal (_("we can't li.d on 32bit-arch"));
1077 snprintf (args_buf
, sizeof (args_buf
), "0x%x,0x%x,0x%x,0x%x,%s",
1078 (hi32
>> 20) & 0xfff, hi32
& 0xfffff, (lo32
>> 12) & 0xfffff,
1079 lo32
& 0xfff, args
[0]);
1080 loongarch_split_args_by_comma (args_buf
, arg_strs
);
1083 ((((hi32
& 0xfff00000) == 0) << 3) | (((hi32
& 0x000fffff) == 0) << 2)
1084 | (((lo32
& 0xfffff000) == 0) << 1) | ((lo32
& 0x00000fff) == 0));
1086 ((((hi32
& 0x80000000) != 0) << 3) | (((hi32
& 0x00080000) != 0) << 2)
1087 | (((lo32
& 0x80000000) != 0) << 1) | ((lo32
& 0x00000800) != 0));
1089 ((((hi32
& 0xfff00000) == 0xfff00000) << 3)
1090 | (((hi32
& 0x000fffff) == 0x000fffff) << 2)
1091 | (((lo32
& 0xfffff000) == 0xfffff000) << 1)
1092 | ((lo32
& 0x00000fff) == 0x00000fff));
1093 paritial_is_sext_of_prev
=
1094 (all0_bit_vec
^ allf_bit_vec
) & (all0_bit_vec
^ (sign_bit_vec
<< 1));
1096 static const char *const li_32bit
[] =
1098 "lu12i.w %5,%3&0x80000?%3-0x100000:%3;ori %5,%5,%4;",
1099 "lu12i.w %5,%3&0x80000?%3-0x100000:%3;",
1100 "addi.w %5,$r0,%4&0x800?%4-0x1000:%4;",
1103 static const char *const li_hi_32bit
[] =
1105 "lu32i.d %5,%2&0x80000?%2-0x100000:%2;"
1106 "lu52i.d %5,%5,%1&0x800?%1-0x1000:%1;",
1107 "lu52i.d %5,%5,%1&0x800?%1-0x1000:%1;",
1108 "lu32i.d %5,%2&0x80000?%2-0x100000:%2;",
1113 insns_buf
[0] = '\0';
1114 if (paritial_is_sext_of_prev
== 0x7)
1116 strcat (insns_buf
, "lu52i.d %5,$r0,%1&0x800?%1-0x1000:%1;");
1119 if ((all0_bit_vec
& 0x3) == 0x2)
1120 strcat (insns_buf
, "ori %5,$r0,%4;");
1122 strcat (insns_buf
, li_32bit
[paritial_is_sext_of_prev
& 0x3]);
1123 strcat (insns_buf
, li_hi_32bit
[paritial_is_sext_of_prev
>> 2]);
1127 ret
= loongarch_expand_macro (insns_buf
, arg_strs
, NULL
, NULL
,
1134 /* Accept instructions separated by ';'
1135 * assuming 'not starting with space and not ending with space' or pass in
1138 loongarch_assemble_INSNs (char *str
, struct loongarch_cl_insn
*ctx
)
1141 size_t len_str
= strlen(str
);
1143 for (rest
= str
; *rest
!= ';' && *rest
!= '\0'; rest
++);
1150 setup_internal_label_here (strtol (str
, &str
, 10));
1159 struct loongarch_cl_insn the_one
= { 0 };
1161 the_one
.macro_id
= ctx
->macro_id
;
1163 for (; *str
&& *str
!= ' '; str
++)
1168 loongarch_split_args_by_comma (str
, the_one
.arg_strs
);
1169 get_loongarch_opcode (&the_one
);
1171 if (!the_one
.all_match
)
1173 char *ss
= loongarch_cat_splited_strs (the_one
.arg_strs
);
1174 as_bad (_("no match insn: %s\t%s"), the_one
.name
, ss
? ss
: "");
1179 if (check_this_insn_before_appending (&the_one
) != 0)
1182 append_fixp_and_insn (&the_one
);
1183 if (the_one
.insn_length
== 0 && the_one
.insn
->macro
)
1185 the_one
.macro_id
= 1;
1187 char *c_str
= loongarch_expand_macro (the_one
.insn
->macro
,
1189 assember_macro_helper
,
1191 loongarch_assemble_INSNs (c_str
, &the_one
);
1198 loongarch_assemble_INSNs (rest
, ctx
);
1202 md_assemble (char *str
)
1204 struct loongarch_cl_insn the_one
= { 0 };
1205 loongarch_assemble_INSNs (str
, &the_one
);
1209 md_atof (int type
, char *litP
, int *sizeP
)
1211 return ieee_md_atof (type
, litP
, sizeP
, FALSE
);
1215 md_number_to_chars (char *buf
, valueT val
, int n
)
1217 number_to_chars_littleendian (buf
, val
, n
);
1220 /* The location from which a PC relative jump should be calculated,
1221 given a PC relative reloc. */
1223 md_pcrel_from (fixS
*fixP ATTRIBUTE_UNUSED
)
1228 static void fix_reloc_insn (fixS
*fixP
, bfd_vma reloc_val
, char *buf
)
1230 reloc_howto_type
*howto
;
1232 howto
= bfd_reloc_type_lookup (stdoutput
, fixP
->fx_r_type
);
1234 insn
= bfd_getl32 (buf
);
1236 if (!loongarch_adjust_reloc_bitsfield (NULL
, howto
, &reloc_val
))
1237 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, "Reloc overflow");
1239 insn
= (insn
& (insn_t
)howto
->src_mask
)
1240 | ((insn
& (~(insn_t
)howto
->dst_mask
)) | reloc_val
);
1242 bfd_putl32 (insn
, buf
);
1246 md_apply_fix (fixS
*fixP
, valueT
*valP
, segT seg ATTRIBUTE_UNUSED
)
1248 static int64_t stack_top
;
1249 static int last_reloc_is_sop_push_pcrel_1
= 0;
1250 int last_reloc_is_sop_push_pcrel
= last_reloc_is_sop_push_pcrel_1
;
1252 last_reloc_is_sop_push_pcrel_1
= 0;
1254 char *buf
= fixP
->fx_frag
->fr_literal
+ fixP
->fx_where
;
1255 switch (fixP
->fx_r_type
)
1257 case BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL
:
1258 case BFD_RELOC_LARCH_SOP_PUSH_TLS_GD
:
1259 case BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT
:
1260 case BFD_RELOC_LARCH_TLS_LE_HI20
:
1261 case BFD_RELOC_LARCH_TLS_LE_LO12
:
1262 case BFD_RELOC_LARCH_TLS_LE64_LO20
:
1263 case BFD_RELOC_LARCH_TLS_LE64_HI12
:
1264 case BFD_RELOC_LARCH_TLS_IE_PC_HI20
:
1265 case BFD_RELOC_LARCH_TLS_IE_PC_LO12
:
1266 case BFD_RELOC_LARCH_TLS_IE64_PC_LO20
:
1267 case BFD_RELOC_LARCH_TLS_IE64_PC_HI12
:
1268 case BFD_RELOC_LARCH_TLS_IE_HI20
:
1269 case BFD_RELOC_LARCH_TLS_IE_LO12
:
1270 case BFD_RELOC_LARCH_TLS_IE64_LO20
:
1271 case BFD_RELOC_LARCH_TLS_IE64_HI12
:
1272 case BFD_RELOC_LARCH_TLS_LD_PC_HI20
:
1273 case BFD_RELOC_LARCH_TLS_LD_HI20
:
1274 case BFD_RELOC_LARCH_TLS_GD_PC_HI20
:
1275 case BFD_RELOC_LARCH_TLS_GD_HI20
:
1276 /* Add tls lo (got_lo reloc type). */
1277 if (fixP
->fx_addsy
== NULL
)
1278 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
1279 _("Relocation against a constant"));
1280 S_SET_THREAD_LOCAL (fixP
->fx_addsy
);
1283 case BFD_RELOC_LARCH_SOP_PUSH_PCREL
:
1284 if (fixP
->fx_addsy
== NULL
)
1285 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
1286 _("Relocation against a constant"));
1288 last_reloc_is_sop_push_pcrel_1
= 1;
1289 if (S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
1290 stack_top
= (S_GET_VALUE (fixP
->fx_addsy
) + fixP
->fx_offset
1291 - (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
));
1296 case BFD_RELOC_LARCH_SOP_POP_32_S_10_5
:
1297 case BFD_RELOC_LARCH_SOP_POP_32_S_10_12
:
1298 case BFD_RELOC_LARCH_SOP_POP_32_U_10_12
:
1299 case BFD_RELOC_LARCH_SOP_POP_32_S_10_16
:
1300 case BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2
:
1301 case BFD_RELOC_LARCH_SOP_POP_32_S_5_20
:
1302 case BFD_RELOC_LARCH_SOP_POP_32_U
:
1303 case BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2
:
1304 case BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2
:
1305 if (!last_reloc_is_sop_push_pcrel
)
1308 fix_reloc_insn (fixP
, (bfd_vma
)stack_top
, buf
);
1311 /* LARCH only has R_LARCH_64/32, not has R_LARCH_24/16/8.
1312 For BFD_RELOC_64/32, if fx_addsy and fx_subsy not null, wer need
1313 generate BFD_RELOC_LARCH_ADD64/32 and BFD_RELOC_LARCH_SUB64/32 here.
1314 Then will parse howto table bfd_reloc_code_real_type to generate
1315 R_LARCH_ADD64/32 and R_LARCH_SUB64/32 reloc at tc_gen_reloc function.
1316 If only fx_addsy not null, skip here directly, then generate
1319 For BFD_RELOC_24/16/8, if fx_addsy and fx_subsy not null, wer need
1320 generate BFD_RELOC_LARCH_ADD24/16/8 and BFD_RELOC_LARCH_SUB24/16/8 here.
1321 Then will parse howto table bfd_reloc_code_real_type to generate
1322 R_LARCH_ADD24/16/8 and R_LARCH_SUB24/16/8 reloc at tc_gen_reloc
1323 function. If only fx_addsy not null, we generate
1324 BFD_RELOC_LARCH_ADD24/16/8 only, then generate R_LARCH_24/16/8.
1325 To avoid R_LARCH_ADDxx add extra value, we write 0 first
1326 (use md_number_to_chars (buf, 0, fixP->fx_size)). */
1331 switch (fixP
->fx_r_type
)
1334 fixP
->fx_r_type
= BFD_RELOC_LARCH_64_PCREL
;
1337 fixP
->fx_r_type
= BFD_RELOC_LARCH_32_PCREL
;
1344 /* If symbol in .eh_frame the address may be adjusted, and contents of
1345 .eh_frame will be adjusted, so use pc-relative relocation for FDE
1347 The Option of mthin-add-sub does not affect the generation of
1348 R_LARCH_32_PCREL relocation in .eh_frame. */
1349 if (fixP
->fx_r_type
== BFD_RELOC_32
1350 && fixP
->fx_addsy
&& fixP
->fx_subsy
1351 && (sub_segment
= S_GET_SEGMENT (fixP
->fx_subsy
))
1352 && strcmp (sub_segment
->name
, ".eh_frame") == 0
1353 && S_GET_VALUE (fixP
->fx_subsy
)
1354 == fixP
->fx_frag
->fr_address
+ fixP
->fx_where
)
1356 fixP
->fx_r_type
= BFD_RELOC_LARCH_32_PCREL
;
1357 fixP
->fx_subsy
= NULL
;
1361 if (fixP
->fx_addsy
&& fixP
->fx_subsy
)
1363 fixP
->fx_next
= xmemdup (fixP
, sizeof (*fixP
), sizeof (*fixP
));
1364 fixP
->fx_next
->fx_addsy
= fixP
->fx_subsy
;
1365 fixP
->fx_next
->fx_subsy
= NULL
;
1366 fixP
->fx_next
->fx_offset
= 0;
1367 fixP
->fx_subsy
= NULL
;
1369 switch (fixP
->fx_r_type
)
1372 fixP
->fx_r_type
= BFD_RELOC_LARCH_ADD64
;
1373 fixP
->fx_next
->fx_r_type
= BFD_RELOC_LARCH_SUB64
;
1376 fixP
->fx_r_type
= BFD_RELOC_LARCH_ADD32
;
1377 fixP
->fx_next
->fx_r_type
= BFD_RELOC_LARCH_SUB32
;
1383 md_number_to_chars (buf
, 0, fixP
->fx_size
);
1386 if (fixP
->fx_addsy
== NULL
)
1389 md_number_to_chars (buf
, *valP
, fixP
->fx_size
);
1398 fixP
->fx_next
= xmemdup (fixP
, sizeof (*fixP
), sizeof (*fixP
));
1399 fixP
->fx_next
->fx_addsy
= fixP
->fx_subsy
;
1400 fixP
->fx_next
->fx_subsy
= NULL
;
1401 fixP
->fx_next
->fx_offset
= 0;
1402 fixP
->fx_subsy
= NULL
;
1404 switch (fixP
->fx_r_type
)
1407 fixP
->fx_r_type
= BFD_RELOC_LARCH_ADD24
;
1408 fixP
->fx_next
->fx_r_type
= BFD_RELOC_LARCH_SUB24
;
1411 fixP
->fx_r_type
= BFD_RELOC_LARCH_ADD16
;
1412 fixP
->fx_next
->fx_r_type
= BFD_RELOC_LARCH_SUB16
;
1415 fixP
->fx_r_type
= BFD_RELOC_LARCH_ADD8
;
1416 fixP
->fx_next
->fx_r_type
= BFD_RELOC_LARCH_SUB8
;
1422 md_number_to_chars (buf
, 0, fixP
->fx_size
);
1424 if (fixP
->fx_next
->fx_addsy
== NULL
)
1425 fixP
->fx_next
->fx_done
= 1;
1428 if (fixP
->fx_addsy
== NULL
)
1431 md_number_to_chars (buf
, *valP
, fixP
->fx_size
);
1435 case BFD_RELOC_LARCH_CFA
:
1436 if (fixP
->fx_addsy
&& fixP
->fx_subsy
)
1438 fixP
->fx_next
= xmemdup (fixP
, sizeof (*fixP
), sizeof (*fixP
));
1439 fixP
->fx_next
->fx_addsy
= fixP
->fx_subsy
;
1440 fixP
->fx_next
->fx_subsy
= NULL
;
1441 fixP
->fx_next
->fx_offset
= 0;
1442 fixP
->fx_subsy
= NULL
;
1444 unsigned int subtype
;
1446 subtype
= bfd_get_8 (NULL
, &((fragS
*)
1447 (fixP
->fx_frag
->fr_opcode
))->fr_literal
[fixP
->fx_where
]);
1448 loc
= fixP
->fx_frag
->fr_fix
- (subtype
& 7);
1451 case DW_CFA_advance_loc1
:
1452 fixP
->fx_where
= loc
+ 1;
1453 fixP
->fx_next
->fx_where
= loc
+ 1;
1454 fixP
->fx_r_type
= BFD_RELOC_LARCH_ADD8
;
1455 fixP
->fx_next
->fx_r_type
= BFD_RELOC_LARCH_SUB8
;
1456 md_number_to_chars (buf
+1, 0, fixP
->fx_size
);
1459 case DW_CFA_advance_loc2
:
1461 fixP
->fx_next
->fx_size
= 2;
1462 fixP
->fx_where
= loc
+ 1;
1463 fixP
->fx_next
->fx_where
= loc
+ 1;
1464 fixP
->fx_r_type
= BFD_RELOC_LARCH_ADD16
;
1465 fixP
->fx_next
->fx_r_type
= BFD_RELOC_LARCH_SUB16
;
1466 md_number_to_chars (buf
+1, 0, fixP
->fx_size
);
1469 case DW_CFA_advance_loc4
:
1471 fixP
->fx_next
->fx_size
= 4;
1472 fixP
->fx_where
= loc
;
1473 fixP
->fx_next
->fx_where
= loc
;
1474 fixP
->fx_r_type
= BFD_RELOC_LARCH_ADD32
;
1475 fixP
->fx_next
->fx_r_type
= BFD_RELOC_LARCH_SUB32
;
1476 md_number_to_chars (buf
+1, 0, fixP
->fx_size
);
1480 if (subtype
< 0x80 && (subtype
& 0x40))
1482 /* DW_CFA_advance_loc. */
1483 fixP
->fx_frag
= (fragS
*) fixP
->fx_frag
->fr_opcode
;
1484 fixP
->fx_next
->fx_frag
= fixP
->fx_frag
;
1485 fixP
->fx_r_type
= BFD_RELOC_LARCH_ADD6
;
1486 fixP
->fx_next
->fx_r_type
= BFD_RELOC_LARCH_SUB6
;
1487 md_number_to_chars (buf
, 0x40, fixP
->fx_size
);
1490 as_fatal (_("internal: bad CFA value #%d"), subtype
);
1496 case BFD_RELOC_LARCH_B16
:
1497 case BFD_RELOC_LARCH_B21
:
1498 case BFD_RELOC_LARCH_B26
:
1499 if (fixP
->fx_addsy
== NULL
)
1501 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
1502 _ ("Relocation against a constant."));
1504 if (S_GET_SEGMENT (fixP
->fx_addsy
) == seg
1505 && !S_FORCE_RELOC (fixP
->fx_addsy
, 1))
1507 int64_t sym_addend
= S_GET_VALUE (fixP
->fx_addsy
) + fixP
->fx_offset
;
1508 int64_t pc
= fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
1509 fix_reloc_insn (fixP
, sym_addend
- pc
, buf
);
1511 /* If relax, symbol value may change at link time, so reloc need to
1513 if (!LARCH_opts
.relax
)
1518 /* Because ADD_ULEB128/SUB_ULEB128 always occur in pairs.
1519 So just deal with one is ok.
1520 case BFD_RELOC_LARCH_ADD_ULEB128: */
1521 case BFD_RELOC_LARCH_SUB_ULEB128
:
1523 unsigned int len
= 0;
1524 len
= loongarch_get_uleb128_length ((bfd_byte
*)buf
);
1525 bfd_byte
*endp
= (bfd_byte
*) buf
+ len
-1;
1526 /* Clean the uleb128 value to 0. Do not reduce the length. */
1527 memset (buf
, 0x80, len
- 1);
1538 md_estimate_size_before_relax (fragS
*fragp ATTRIBUTE_UNUSED
,
1539 asection
*segtype ATTRIBUTE_UNUSED
)
1541 return (fragp
->fr_var
= 4);
1544 /* Translate internal representation of relocation info to BFD target
1547 tc_gen_reloc (asection
*section ATTRIBUTE_UNUSED
, fixS
*fixp
)
1549 arelent
*reloc
= (arelent
*) xmalloc (sizeof (arelent
));
1551 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
1552 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
1553 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
1554 reloc
->addend
= fixp
->fx_offset
;
1556 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, fixp
->fx_r_type
);
1557 if (reloc
->howto
== NULL
)
1559 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
1560 _("cannot represent %s relocation in object file"),
1561 bfd_get_reloc_code_name (fixp
->fx_r_type
));
1568 /* Standard calling conventions leave the CFA at SP on entry. */
1570 loongarch_cfi_frame_initial_instructions (void)
1572 cfi_add_CFA_def_cfa_register (3 /* $sp */);
1576 loongarch_pre_output_hook (void)
1578 const frchainS
*frch
;
1581 if (!LARCH_opts
.relax
)
1584 /* Save the current segment info. */
1586 subsegT subseg
= now_subseg
;
1588 for (s
= stdoutput
->sections
; s
; s
= s
->next
)
1589 for (frch
= seg_info (s
)->frchainP
; frch
; frch
= frch
->frch_next
)
1593 for (frag
= frch
->frch_root
; frag
; frag
= frag
->fr_next
)
1595 if (frag
->fr_type
== rs_cfa
)
1598 expressionS
*symval
;
1600 symval
= symbol_get_value_expression (frag
->fr_symbol
);
1601 exp
.X_op
= O_subtract
;
1602 exp
.X_add_symbol
= symval
->X_add_symbol
;
1603 exp
.X_add_number
= 0;
1604 exp
.X_op_symbol
= symval
->X_op_symbol
;
1606 /* We must set the segment before creating a frag after all
1607 frag chains have been chained together. */
1608 subseg_set (s
, frch
->frch_subseg
);
1610 fix_new_exp (frag
, (int) frag
->fr_offset
, 1, &exp
, 0,
1611 BFD_RELOC_LARCH_CFA
);
1616 /* Restore the original segment info. */
1617 subseg_set (seg
, subseg
);
1621 tc_loongarch_parse_to_dw2regnum (expressionS
*exp
)
1623 expression_and_evaluate (exp
);
1627 md_show_usage (FILE *stream
)
1629 fprintf (stream
, _("LARCH options:\n"));
1631 fprintf (stream
, _("\
1632 -mthin-add-sub Convert a pair of R_LARCH_ADD32/64 and R_LARCH_SUB32/64 to\n\
1633 R_LARCH_32/64_PCREL as much as possible\n\
1634 The option does not affect the generation of R_LARCH_32_PCREL\n\
1635 relocations in .eh_frame\n"));
1639 loongarch_make_nops (char *buf
, bfd_vma bytes
)
1643 /* Fill with 4-byte NOPs. */
1644 for ( ; i
< bytes
; i
+= 4)
1645 number_to_chars_littleendian (buf
+ i
, LARCH_NOP
, 4);
1648 /* Called from md_do_align. Used to create an alignment frag in a
1649 code section by emitting a worst-case NOP sequence that the linker
1650 will later relax to the correct number of NOPs. We can't compute
1651 the correct alignment now because of other linker relaxations. */
1654 loongarch_frag_align_code (int n
)
1656 bfd_vma bytes
= (bfd_vma
) 1 << n
;
1657 bfd_vma insn_alignment
= 4;
1658 bfd_vma worst_case_bytes
= bytes
- insn_alignment
;
1662 /* If we are moving to a smaller alignment than the instruction size, then no
1663 alignment is required. */
1664 if (bytes
<= insn_alignment
)
1667 /* When not relaxing, loongarch_handle_align handles code alignment. */
1668 if (!LARCH_opts
.relax
)
1671 nops
= frag_more (worst_case_bytes
);
1673 ex
.X_op
= O_constant
;
1674 ex
.X_add_number
= worst_case_bytes
;
1676 loongarch_make_nops (nops
, worst_case_bytes
);
1678 fix_new_exp (frag_now
, nops
- frag_now
->fr_literal
, 0,
1679 &ex
, false, BFD_RELOC_LARCH_ALIGN
);
1681 /* We need to start a new frag after the alignment which may be removed by
1682 the linker, to prevent the assembler from computing static offsets.
1683 This is necessary to get correct EH info. */
1684 frag_wane (frag_now
);
1690 /* Fill in an rs_align_code fragment. We want to fill 'andi $r0,$r0,0'. */
1692 loongarch_handle_align (fragS
*fragp
)
1694 /* char nop_opcode; */
1696 int bytes
, size
, excess
;
1699 if (fragp
->fr_type
!= rs_align_code
)
1702 struct loongarch_cl_insn nop
=
1703 { .name
= "andi", .arg_strs
= { "$r0", "$r0", "0", NULL
} };
1705 get_loongarch_opcode (&nop
);
1706 gas_assert (nop
.all_match
);
1708 p
= fragp
->fr_literal
+ fragp
->fr_fix
;
1709 opcode
= nop
.insn_bin
;
1712 bytes
= fragp
->fr_next
->fr_address
- fragp
->fr_address
- fragp
->fr_fix
;
1713 excess
= bytes
% size
;
1715 gas_assert (excess
< 4);
1716 fragp
->fr_fix
+= excess
;
1718 while (excess
-- != 0)
1721 md_number_to_chars (p
, opcode
, size
);
1722 fragp
->fr_var
= size
;
1725 /* Scan uleb128 subtraction expressions and insert fixups for them.
1726 e.g., .uleb128 .L1 - .L0
1727 Because relaxation may change the value of the subtraction, we
1728 must resolve them at link-time. */
1731 loongarch_insert_uleb128_fixes (bfd
*abfd ATTRIBUTE_UNUSED
,
1732 asection
*sec
, void *xxx ATTRIBUTE_UNUSED
)
1734 segment_info_type
*seginfo
= seg_info (sec
);
1737 subseg_set (sec
, 0);
1739 for (fragP
= seginfo
->frchainP
->frch_root
;
1740 fragP
; fragP
= fragP
->fr_next
)
1742 expressionS
*exp
, *exp_dup
;
1744 if (fragP
->fr_type
!= rs_leb128
|| fragP
->fr_symbol
== NULL
)
1747 exp
= symbol_get_value_expression (fragP
->fr_symbol
);
1749 if (exp
->X_op
!= O_subtract
)
1752 /* FIXME: Skip for .sleb128. */
1753 if (fragP
->fr_subtype
!= 0)
1756 exp_dup
= xmemdup (exp
, sizeof (*exp
), sizeof (*exp
));
1757 exp_dup
->X_op
= O_symbol
;
1758 exp_dup
->X_op_symbol
= NULL
;
1760 exp_dup
->X_add_symbol
= exp
->X_add_symbol
;
1761 fix_new_exp (fragP
, fragP
->fr_fix
, 0,
1762 exp_dup
, 0, BFD_RELOC_LARCH_ADD_ULEB128
);
1764 /* From binutils/testsuite/binutils-all/dw5.S
1765 section .debug_rnglists
1766 .uleb128 .Letext0-.Ltext0 Range length (*.LLRL2)
1767 Offset Info Type Symbol's Value Symbol's Name + Addend
1768 0000000000000015 0000000200000079 R_LARCH_ADD_ULEB128 0000000000000000 .text + 2
1769 0000000000000015 000000020000007a R_LARCH_SUB_ULEB128 0000000000000000 .text + 0. */
1771 /* Only the ADD_ULEB128 has X_add_number (Addend)? */
1772 exp_dup
->X_add_number
= 0;
1773 exp_dup
->X_add_symbol
= exp
->X_op_symbol
;
1774 fix_new_exp (fragP
, fragP
->fr_fix
, 0,
1775 exp_dup
, 0, BFD_RELOC_LARCH_SUB_ULEB128
);
1780 loongarch_md_finish (void)
1782 /* Insert relocations for uleb128 directives, so the values can be recomputed
1784 if (LARCH_opts
.relax
)
1785 bfd_map_over_sections (stdoutput
, loongarch_insert_uleb128_fixes
, NULL
);
1789 loongarch_elf_final_processing (void)
1791 elf_elfheader (stdoutput
)->e_flags
= LARCH_opts
.ase_abi
;
1794 /* Compute the length of a branch sequence, and adjust the stored length
1795 accordingly. If FRAGP is NULL, the worst-case length is returned. */
1797 loongarch_relaxed_branch_length (fragS
*fragp
, asection
*sec
, int update
)
1804 if (fragp
->fr_symbol
!= NULL
1805 && S_IS_DEFINED (fragp
->fr_symbol
)
1806 && !S_IS_WEAK (fragp
->fr_symbol
)
1807 && sec
== S_GET_SEGMENT (fragp
->fr_symbol
))
1809 offsetT val
= S_GET_VALUE (fragp
->fr_symbol
) + fragp
->fr_offset
;
1811 val
-= fragp
->fr_address
+ fragp
->fr_fix
;
1813 if (RELAX_BRANCH_16
== fragp
->fr_subtype
1814 && OUT_OF_RANGE (val
, 16, 2))
1818 fragp
->fr_subtype
= RELAX_BRANCH_26
;
1821 if (RELAX_BRANCH_21
== fragp
->fr_subtype
1822 && OUT_OF_RANGE (val
, 21, 2))
1826 fragp
->fr_subtype
= RELAX_BRANCH_26
;
1829 if (RELAX_BRANCH_26
== fragp
->fr_subtype
)
1837 loongarch_relax_frag (asection
*sec ATTRIBUTE_UNUSED
,
1838 fragS
*fragp ATTRIBUTE_UNUSED
,
1839 long stretch ATTRIBUTE_UNUSED
)
1841 if (RELAX_BRANCH (fragp
->fr_subtype
))
1843 offsetT old_var
= fragp
->fr_var
;
1844 fragp
->fr_var
= loongarch_relaxed_branch_length (fragp
, sec
, true);
1845 return fragp
->fr_var
- old_var
;
1850 /* Expand far branches to multi-instruction sequences.
1851 Branch instructions:
1852 beq, bne, blt, bgt, bltz, bgtz, ble, bge, blez, bgez
1853 bltu, bgtu, bleu, bgeu
1854 beqz, bnez, bceqz, bcnez. */
1857 loongarch_convert_frag_branch (fragS
*fragp
)
1864 buf
= (bfd_byte
*)fragp
->fr_literal
+ fragp
->fr_fix
;
1866 exp
.X_op
= O_symbol
;
1867 exp
.X_add_symbol
= fragp
->fr_symbol
;
1868 exp
.X_add_number
= fragp
->fr_offset
;
1870 gas_assert ((fragp
->fr_subtype
& 0xf) == fragp
->fr_var
);
1872 /* blt $t0, $t1, .L1
1879 switch (fragp
->fr_subtype
)
1881 case RELAX_BRANCH_26
:
1882 insn
= bfd_getl32 (buf
);
1883 /* Invert the branch condition. */
1884 if (LARCH_FLOAT_BRANCH
== (insn
& LARCH_BRANCH_OPCODE_MASK
))
1885 insn
^= LARCH_FLOAT_BRANCH_INVERT_BIT
;
1887 insn
^= LARCH_BRANCH_INVERT_BIT
;
1888 insn
|= ENCODE_BRANCH16_IMM (8); /* Set target to PC + 8. */
1889 bfd_putl32 (insn
, buf
);
1892 /* Add the B instruction and jump to the original target. */
1893 bfd_putl32 (LARCH_B
, buf
);
1894 fixp
= fix_new_exp (fragp
, buf
- (bfd_byte
*)fragp
->fr_literal
,
1895 4, &exp
, false, BFD_RELOC_LARCH_B26
);
1898 case RELAX_BRANCH_21
:
1899 fixp
= fix_new_exp (fragp
, buf
- (bfd_byte
*)fragp
->fr_literal
,
1900 4, &exp
, false, BFD_RELOC_LARCH_B21
);
1903 case RELAX_BRANCH_16
:
1904 fixp
= fix_new_exp (fragp
, buf
- (bfd_byte
*)fragp
->fr_literal
,
1905 4, &exp
, false, BFD_RELOC_LARCH_B16
);
1913 fixp
->fx_file
= fragp
->fr_file
;
1914 fixp
->fx_line
= fragp
->fr_line
;
1916 gas_assert (buf
== (bfd_byte
*)fragp
->fr_literal
1917 + fragp
->fr_fix
+ fragp
->fr_var
);
1919 fragp
->fr_fix
+= fragp
->fr_var
;
1922 /* Relax a machine dependent frag. This returns the amount by which
1923 the current size of the frag should change. */
1926 md_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
, segT asec ATTRIBUTE_UNUSED
,
1929 gas_assert (RELAX_BRANCH (fragp
->fr_subtype
));
1930 loongarch_convert_frag_branch (fragp
);