1 /* tc-loongarch.c -- Assemble for the LoongArch ISA
2
3 Copyright (C) 2021-2024 Free Software Foundation, Inc.
4 Contributed by Loongson Ltd.
5
6 This file is part of GAS.
7
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.
12
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.
17
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/>. */
21
22 #include "as.h"
23 #include "subsegs.h"
24 #include "dw2gencfi.h"
25 #include "loongarch-lex.h"
26 #include "elf/loongarch.h"
27 #include "opcode/loongarch.h"
28 #include "obj-elf.h"
29 #include "bfd/elfxx-loongarch.h"
30 #include <stdlib.h>
31 #include <string.h>
32 #include <stdio.h>
33 #include <assert.h>
34
35 /* All information about an instruction during assemble. */
36 struct loongarch_cl_insn
37 {
38 /* First split string. */
39 const char *name;
40 const char *arg_strs[MAX_ARG_NUM_PLUS_2];
41 size_t arg_num;
42
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. */
48 int match_now;
49 int all_match;
50
51 const struct loongarch_opcode *insn;
52 size_t insn_length;
53
54 offsetT args[MAX_ARG_NUM_PLUS_2];
55 struct reloc_info reloc_info[MAX_RELOC_NUMBER_A_INSN];
56 size_t reloc_num;
57
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;
63
64 /* Then we get the binary representation of insn
65 and write it in to section. */
66 insn_t insn_bin;
67
68 /* The frag that contains the instruction. */
69 struct frag *frag;
70 /* The offset into FRAG of the first instruction byte. */
71 long where;
72 /* The relocs associated with the instruction, if any. */
73 fixS *fixp[MAX_RELOC_NUMBER_A_INSN];
74 /* Represents macros or instructions expanded from macro.
75 For la.local -> la.pcrel or la.pcrel -> pcalau12i + addi.d, la.pcrel,
76 pcalau12i and addi.d are expanded from macro.
77 The first bit represents expanded from one register macro (e.g.
78 la.local $t0, symbol) and emit R_LARCH_RELAX relocations.
79 The second bit represents expanded from two registers macro (e.g.
80 la.local $t0, $t1, symbol) and not emit R_LARCH_RELAX relocations.
81
82 The macros or instructions expanded from macros do not output register
83 deprecated warning. */
84 unsigned int expand_from_macro;
85 };
86
87 #ifndef DEFAULT_ARCH
88 #define DEFAULT_ARCH "loongarch64"
89 #endif
90
91 /* This array holds the chars that always start a comment. If the
92 pre-processor is disabled, these aren't very useful. */
93 const char comment_chars[] = "#";
94
95 /* This array holds the chars that only start a comment at the beginning of
96 a line. If the line seems to have the form '# 123 filename'
97 .line and .file directives will appear in the pre-processed output. */
98 /* Note that input_file.c hand checks for '#' at the beginning of the
99 first line of the input file. This is because the compiler outputs
100 #NO_APP at the beginning of its output. */
101 /* Also note that C style comments are always supported. */
102 const char line_comment_chars[] = "#";
103
104 /* This array holds machine specific line separator characters. */
105 const char line_separator_chars[] = ";";
106
107 /* Chars that can be used to separate mant from exp in floating point nums. */
108 const char EXP_CHARS[] = "eE";
109
110 /* Chars that mean this number is a floating point constant. */
111 /* As in 0f12.456. */
112 /* or 0d1.2345e12. */
113 const char FLT_CHARS[] = "rRsSfFdDxXpP";
114
115 const char *md_shortopts = "O::g::G:";
116
117 static const char default_arch[] = DEFAULT_ARCH;
118
119 /* The lowest 4-bit is the bytes of instructions. */
120 #define RELAX_BRANCH_16 0xc0000014
121 #define RELAX_BRANCH_21 0xc0000024
122 #define RELAX_BRANCH_26 0xc0000048
123
124 #define RELAX_BRANCH(x) \
125 (((x) & 0xf0000000) == 0xc0000000)
126 #define RELAX_BRANCH_ENCODE(x) \
127 (BFD_RELOC_LARCH_B16 == (x) ? RELAX_BRANCH_16 : RELAX_BRANCH_21)
128
129 enum options
130 {
131 OPTION_IGNORE = OPTION_MD_BASE,
132
133 OPTION_ABI,
134 OPTION_FLOAT_ABI,
135
136 OPTION_FLOAT_ISA,
137
138 OPTION_LA_LOCAL_WITH_ABS,
139 OPTION_LA_GLOBAL_WITH_PCREL,
140 OPTION_LA_GLOBAL_WITH_ABS,
141 OPTION_RELAX,
142 OPTION_NO_RELAX,
143 OPTION_THIN_ADD_SUB,
144
145 OPTION_END_OF_ENUM,
146 };
147
148 struct option md_longopts[] =
149 {
150 { "mabi", required_argument, NULL, OPTION_ABI },
151
152 { "mfpu", required_argument, NULL, OPTION_FLOAT_ISA },
153
154 { "mla-local-with-abs", no_argument, NULL, OPTION_LA_LOCAL_WITH_ABS },
155 { "mla-global-with-pcrel", no_argument, NULL, OPTION_LA_GLOBAL_WITH_PCREL },
156 { "mla-global-with-abs", no_argument, NULL, OPTION_LA_GLOBAL_WITH_ABS },
157
158 { "mrelax", no_argument, NULL, OPTION_RELAX },
159 { "mno-relax", no_argument, NULL, OPTION_NO_RELAX },
160 { "mthin-add-sub", no_argument, NULL, OPTION_THIN_ADD_SUB},
161
162 { NULL, no_argument, NULL, 0 }
163 };
164
165 size_t md_longopts_size = sizeof (md_longopts);
166
167 int
md_parse_option(int c,const char * arg)168 md_parse_option (int c, const char *arg)
169 {
170 int ret = 1;
171 char lp64[256] = "";
172 char ilp32[256] = "";
173 unsigned char *suf = (unsigned char *)arg;
174
175 lp64['s'] = lp64['S'] = EF_LOONGARCH_ABI_SOFT_FLOAT;
176 lp64['f'] = lp64['F'] = EF_LOONGARCH_ABI_SINGLE_FLOAT;
177 lp64['d'] = lp64['D'] = EF_LOONGARCH_ABI_DOUBLE_FLOAT;
178
179 ilp32['s'] = ilp32['S'] = EF_LOONGARCH_ABI_SOFT_FLOAT;
180 ilp32['f'] = ilp32['F'] = EF_LOONGARCH_ABI_SINGLE_FLOAT;
181 ilp32['d'] = ilp32['D'] = EF_LOONGARCH_ABI_DOUBLE_FLOAT;
182
183 switch (c)
184 {
185 case OPTION_ABI:
186 if (strncasecmp (arg, "lp64", 4) == 0 && lp64[suf[4]] != 0)
187 {
188 LARCH_opts.ase_ilp32 = 1;
189 LARCH_opts.ase_lp64 = 1;
190 LARCH_opts.ase_lsx = 1;
191 LARCH_opts.ase_lasx = 1;
192 LARCH_opts.ase_lvz = 1;
193 LARCH_opts.ase_lbt = 1;
194 LARCH_opts.ase_abi = lp64[suf[4]];
195 }
196 else if (strncasecmp (arg, "ilp32", 5) == 0 && ilp32[suf[5]] != 0)
197 {
198 LARCH_opts.ase_abi = ilp32[suf[5]];
199 LARCH_opts.ase_ilp32 = 1;
200 }
201 else
202 ret = 0;
203 break;
204
205 case OPTION_FLOAT_ISA:
206 if (strcasecmp (arg, "soft") == 0)
207 LARCH_opts.ase_nf = 1;
208 else if (strcasecmp (arg, "single") == 0)
209 LARCH_opts.ase_sf = 1;
210 else if (strcasecmp (arg, "double") == 0)
211 {
212 LARCH_opts.ase_sf = 1;
213 LARCH_opts.ase_df = 1;
214 }
215 else
216 ret = 0;
217 break;
218
219 case OPTION_LA_LOCAL_WITH_ABS:
220 LARCH_opts.ase_labs = 1;
221 break;
222
223 case OPTION_LA_GLOBAL_WITH_PCREL:
224 LARCH_opts.ase_gpcr = 1;
225 break;
226
227 case OPTION_LA_GLOBAL_WITH_ABS:
228 LARCH_opts.ase_gabs = 1;
229 break;
230
231 case OPTION_RELAX:
232 LARCH_opts.relax = 1;
233 break;
234
235 case OPTION_NO_RELAX:
236 LARCH_opts.relax = 0;
237 break;
238
239 case OPTION_THIN_ADD_SUB:
240 LARCH_opts.thin_add_sub = 1;
241 break;
242
243 case OPTION_IGNORE:
244 break;
245
246 default:
247 ret = 0;
248 break;
249 }
250 return ret;
251 }
252
253 static const char *const *r_abi_names = NULL;
254 static const char *const *f_abi_names = NULL;
255 static struct htab *r_htab = NULL;
256 static struct htab *r_deprecated_htab = NULL;
257 static struct htab *f_htab = NULL;
258 static struct htab *f_deprecated_htab = NULL;
259 static struct htab *fc_htab = NULL;
260 static struct htab *fcn_htab = NULL;
261 static struct htab *c_htab = NULL;
262 static struct htab *cr_htab = NULL;
263 static struct htab *v_htab = NULL;
264 static struct htab *x_htab = NULL;
265
266 void
loongarch_after_parse_args()267 loongarch_after_parse_args ()
268 {
269 /* Set default ABI/ISA LP64D. */
270 if (!LARCH_opts.ase_ilp32)
271 {
272 if (strcmp (default_arch, "loongarch64") == 0)
273 {
274 LARCH_opts.ase_abi = EF_LOONGARCH_ABI_DOUBLE_FLOAT;
275 LARCH_opts.ase_ilp32 = 1;
276 LARCH_opts.ase_lp64 = 1;
277 LARCH_opts.ase_lsx = 1;
278 LARCH_opts.ase_lasx = 1;
279 LARCH_opts.ase_lvz = 1;
280 LARCH_opts.ase_lbt = 1;
281 }
282 else if (strcmp (default_arch, "loongarch32") == 0)
283 {
284 LARCH_opts.ase_abi = EF_LOONGARCH_ABI_DOUBLE_FLOAT;
285 LARCH_opts.ase_ilp32 = 1;
286 }
287 else
288 as_bad ("unknown default architecture `%s'", default_arch);
289 }
290
291 LARCH_opts.ase_abi |= EF_LOONGARCH_OBJABI_V1;
292 /* Set default ISA double-float. */
293 if (!LARCH_opts.ase_nf
294 && !LARCH_opts.ase_sf
295 && !LARCH_opts.ase_df)
296 {
297 LARCH_opts.ase_sf = 1;
298 LARCH_opts.ase_df = 1;
299 }
300
301 size_t i;
302
303 assert(LARCH_opts.ase_ilp32);
304
305 /* Init ilp32/lp64 registers names. */
306 if (!r_htab)
307 r_htab = str_htab_create (), str_hash_insert (r_htab, "", 0, 0);
308 if (!r_deprecated_htab)
309 r_deprecated_htab = str_htab_create (),
310 str_hash_insert (r_deprecated_htab, "", 0, 0);
311
312 r_abi_names = loongarch_r_normal_name;
313 for (i = 0; i < ARRAY_SIZE (loongarch_r_normal_name); i++)
314 str_hash_insert (r_htab, loongarch_r_normal_name[i], (void *) (i + 1), 0);
315
316 /* Init ilp32/lp64 registers alias. */
317 r_abi_names = loongarch_r_alias;
318 for (i = 0; i < ARRAY_SIZE (loongarch_r_alias); i++)
319 str_hash_insert (r_htab, loongarch_r_alias[i], (void *) (i + 1), 0);
320
321 for (i = 0; i < ARRAY_SIZE (loongarch_r_alias_1); i++)
322 str_hash_insert (r_htab, loongarch_r_alias_1[i], (void *) (i + 1), 0);
323
324 for (i = 0; i < ARRAY_SIZE (loongarch_r_alias_deprecated); i++)
325 str_hash_insert (r_deprecated_htab, loongarch_r_alias_deprecated[i],
326 (void *) (i + 1), 0);
327
328 if (!cr_htab)
329 cr_htab = str_htab_create (), str_hash_insert (cr_htab, "", 0, 0);
330
331 for (i = 0; i < ARRAY_SIZE (loongarch_cr_normal_name); i++)
332 str_hash_insert (cr_htab, loongarch_cr_normal_name[i], (void *) (i + 1), 0);
333
334 /* Init single/double float registers names. */
335 if (LARCH_opts.ase_sf || LARCH_opts.ase_df)
336 {
337 if (!f_htab)
338 f_htab = str_htab_create (), str_hash_insert (f_htab, "", 0, 0);
339 if (!f_deprecated_htab)
340 f_deprecated_htab = str_htab_create (),
341 str_hash_insert (f_deprecated_htab, "", 0, 0);
342
343 f_abi_names = loongarch_f_normal_name;
344 for (i = 0; i < ARRAY_SIZE (loongarch_f_normal_name); i++)
345 str_hash_insert (f_htab, loongarch_f_normal_name[i], (void *) (i + 1),
346 0);
347
348 /* Init float-ilp32/lp64 registers alias. */
349 f_abi_names = loongarch_f_alias;
350 for (i = 0; i < ARRAY_SIZE (loongarch_f_alias); i++)
351 str_hash_insert (f_htab, loongarch_f_alias[i],
352 (void *) (i + 1), 0);
353 for (i = 0; i < ARRAY_SIZE (loongarch_f_alias_deprecated); i++)
354 str_hash_insert (f_deprecated_htab, loongarch_f_alias_deprecated[i],
355 (void *) (i + 1), 0);
356
357 if (!fc_htab)
358 fc_htab = str_htab_create (), str_hash_insert (fc_htab, "", 0, 0);
359
360 for (i = 0; i < ARRAY_SIZE (loongarch_fc_normal_name); i++)
361 str_hash_insert (fc_htab, loongarch_fc_normal_name[i], (void *) (i + 1),
362 0);
363
364 if (!fcn_htab)
365 fcn_htab = str_htab_create (), str_hash_insert (fcn_htab, "", 0, 0);
366
367 for (i = 0; i < ARRAY_SIZE (loongarch_fc_numeric_name); i++)
368 str_hash_insert (fcn_htab, loongarch_fc_numeric_name[i], (void *) (i + 1),
369 0);
370
371 if (!c_htab)
372 c_htab = str_htab_create (), str_hash_insert (c_htab, "", 0, 0);
373
374 for (i = 0; i < ARRAY_SIZE (loongarch_c_normal_name); i++)
375 str_hash_insert (c_htab, loongarch_c_normal_name[i], (void *) (i + 1),
376 0);
377
378 }
379
380 /* Init lsx registers names. */
381 if (LARCH_opts.ase_lsx)
382 {
383 if (!v_htab)
384 v_htab = str_htab_create (), str_hash_insert (v_htab, "", 0, 0);
385 for (i = 0; i < ARRAY_SIZE (loongarch_v_normal_name); i++)
386 str_hash_insert (v_htab, loongarch_v_normal_name[i], (void *) (i + 1),
387 0);
388 }
389
390 /* Init lasx registers names. */
391 if (LARCH_opts.ase_lasx)
392 {
393 if (!x_htab)
394 x_htab = str_htab_create (), str_hash_insert (x_htab, "", 0, 0);
395 for (i = 0; i < ARRAY_SIZE (loongarch_x_normal_name); i++)
396 str_hash_insert (x_htab, loongarch_x_normal_name[i], (void *) (i + 1),
397 0);
398 }
399
400 }
401
402 const char *
loongarch_target_format()403 loongarch_target_format ()
404 {
405 return LARCH_opts.ase_lp64 ? "elf64-loongarch" : "elf32-loongarch";
406 }
407
408 void
md_begin()409 md_begin ()
410 {
411 const struct loongarch_opcode *it;
412 struct loongarch_ase *ase;
413 for (ase = loongarch_ASEs; ase->enabled; ase++)
414 for (it = ase->opcodes; it->name; it++)
415 {
416 if (loongarch_check_format (it->format) != 0)
417 as_fatal (_("insn name: %s\tformat: %s\tsyntax error"),
418 it->name, it->format);
419 if (it->mask == 0 && it->macro == 0)
420 as_fatal (_("insn name: %s\nformat: %s\nwe want macro but "
421 "macro is NULL"),
422 it->name, it->format);
423 if (it->macro
424 && loongarch_check_macro (it->format, it->macro) != 0)
425 as_fatal (_("insn name: %s\nformat: %s\nmacro: %s\tsyntax error"),
426 it->name, it->format, it->macro);
427 }
428
429 /* FIXME: expressionS use 'offsetT' as constant,
430 * we want this is 64-bit type. */
431 assert (8 <= sizeof (offsetT));
432 }
433
434 unsigned long
loongarch_mach(void)435 loongarch_mach (void)
436 {
437 return LARCH_opts.ase_lp64 ? bfd_mach_loongarch64 : bfd_mach_loongarch32;
438 }
439
440 static const expressionS const_0 = { .X_op = O_constant, .X_add_number = 0 };
441
442 /* Handle the .dtprelword and .dtpreldword pseudo-ops. They generate
443 a 32-bit or 64-bit DTP-relative relocation (BYTES says which) for
444 use in DWARF debug information. */
445
446 static void
s_dtprel(int bytes)447 s_dtprel (int bytes)
448 {
449 expressionS ex;
450 char *p;
451
452 expression (&ex);
453
454 if (ex.X_op != O_symbol)
455 {
456 as_bad (_("Unsupported use of %s"),
457 (bytes == 8 ? ".dtpreldword" : ".dtprelword"));
458 ignore_rest_of_line ();
459 }
460
461 p = frag_more (bytes);
462 md_number_to_chars (p, 0, bytes);
463 fix_new_exp (frag_now, p - frag_now->fr_literal, bytes, &ex, FALSE,
464 (bytes == 8
465 ? BFD_RELOC_LARCH_TLS_DTPREL64
466 : BFD_RELOC_LARCH_TLS_DTPREL32));
467
468 demand_empty_rest_of_line ();
469 }
470
471 static const pseudo_typeS loongarch_pseudo_table[] =
472 {
473 { "dword", cons, 8 },
474 { "word", cons, 4 },
475 { "half", cons, 2 },
476 { "dtprelword", s_dtprel, 4 },
477 { "dtpreldword", s_dtprel, 8 },
478 { NULL, NULL, 0 },
479 };
480
481 void
loongarch_pop_insert(void)482 loongarch_pop_insert (void)
483 {
484 pop_insert (loongarch_pseudo_table);
485 }
486
487 #define INTERNAL_LABEL_SPECIAL 10
488 static unsigned long internal_label_count[INTERNAL_LABEL_SPECIAL] = { 0 };
489
490 static const char *
loongarch_internal_label_name(unsigned long label,int augend)491 loongarch_internal_label_name (unsigned long label, int augend)
492 {
493 static char symbol_name_build[24];
494 unsigned long want_label;
495 char *p;
496
497 want_label = internal_label_count[label] + augend;
498
499 p = symbol_name_build;
500 #ifdef LOCAL_LABEL_PREFIX
501 *p++ = LOCAL_LABEL_PREFIX;
502 #endif
503 *p++ = 'L';
504 for (; label; label /= 10)
505 *p++ = label % 10 + '0';
506 /* Make sure internal label never belong to normal label namespace. */
507 *p++ = ':';
508 for (; want_label; want_label /= 10)
509 *p++ = want_label % 10 + '0';
510 *p++ = '\0';
511 return symbol_name_build;
512 }
513
514 static void
setup_internal_label_here(unsigned long label)515 setup_internal_label_here (unsigned long label)
516 {
517 assert (label < INTERNAL_LABEL_SPECIAL);
518 internal_label_count[label]++;
519 colon (loongarch_internal_label_name (label, 0));
520 }
521
522 void
get_internal_label(expressionS * label_expr,unsigned long label,int augend)523 get_internal_label (expressionS *label_expr, unsigned long label,
524 int augend /* 0 for previous, 1 for next. */)
525 {
526 assert (label < INTERNAL_LABEL_SPECIAL);
527 as_fatal (_("internal error: we have no internal label yet"));
528 label_expr->X_op = O_symbol;
529 label_expr->X_add_symbol =
530 symbol_find_or_make (loongarch_internal_label_name (label, augend));
531 label_expr->X_add_number = 0;
532 }
533
534 static int
is_internal_label(const char * c_str)535 is_internal_label (const char *c_str)
536 {
537 do
538 {
539 if (*c_str != ':')
540 break;
541 c_str++;
542 if (!('0' <= *c_str && *c_str <= '9'))
543 break;
544 while ('0' <= *c_str && *c_str <= '9')
545 c_str++;
546 if (*c_str != 'b' && *c_str != 'f')
547 break;
548 c_str++;
549 return *c_str == '\0';
550 }
551 while (0);
552 return 0;
553 }
554
555 static int
is_label(const char * c_str)556 is_label (const char *c_str)
557 {
558 if (is_internal_label (c_str))
559 return 1;
560 else if ('0' <= *c_str && *c_str <= '9')
561 {
562 /* [0-9]+[bf] */
563 while ('0' <= *c_str && *c_str <= '9')
564 c_str++;
565 return *c_str == 'b' || *c_str == 'f';
566 }
567 else if (is_name_beginner (*c_str))
568 {
569 /* [a-zA-Z\._\$][0-9a-zA-Z\._\$]* */
570 c_str++;
571 while (is_part_of_name (*c_str))
572 c_str++;
573 return *c_str == '\0';
574 }
575 else
576 return 0;
577 }
578
579 static int
is_label_with_addend(const char * c_str)580 is_label_with_addend (const char *c_str)
581 {
582 if (is_internal_label (c_str))
583 return 1;
584 else if ('0' <= *c_str && *c_str <= '9')
585 {
586 /* [0-9]+[bf] */
587 while ('0' <= *c_str && *c_str <= '9')
588 c_str++;
589 if (*c_str == 'b' || *c_str == 'f')
590 c_str++;
591 else
592 return 0;
593 return *c_str == '\0'
594 || ((*c_str == '-' || *c_str == '+')
595 && is_unsigned (c_str + 1));
596 }
597 else if (is_name_beginner (*c_str))
598 {
599 /* [a-zA-Z\._\$][0-9a-zA-Z\._\$]* */
600 c_str++;
601 while (is_part_of_name (*c_str))
602 c_str++;
603 return *c_str == '\0'
604 || ((*c_str == '-' || *c_str == '+')
605 && is_unsigned (c_str + 1));
606 }
607 else
608 return 0;
609 }
610
611 static int32_t
loongarch_args_parser_can_match_arg_helper(char esc_ch1,char esc_ch2,const char * bit_field,const char * arg,void * context)612 loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
613 const char *bit_field,
614 const char *arg, void *context)
615 {
616 struct loongarch_cl_insn *ip = context;
617 offsetT imm, ret = 0;
618 size_t reloc_num_we_have = MAX_RELOC_NUMBER_A_INSN - ip->reloc_num;
619 size_t reloc_num = 0;
620
621 if (!ip->match_now)
622 return 0;
623
624 switch (esc_ch1)
625 {
626 case 'l':
627 switch (esc_ch2)
628 {
629 default:
630 ip->match_now = is_label (arg);
631 if (!ip->match_now && is_label_with_addend (arg))
632 as_fatal (_("This label shouldn't be with addend."));
633 break;
634 case 'a':
635 ip->match_now = is_label_with_addend (arg);
636 break;
637 }
638 break;
639 /* This is used for TLS, where the fourth operand is %le_add_r,
640 to get a relocation applied to an add instruction, for relaxation to use.
641 Two conditions, ip->match_now and reloc_num, are used to check tls insn
642 to prevent cases like add.d $a0,$a0,$a0,8. */
643 case 't':
644 ip->match_now = loongarch_parse_expr (arg, ip->reloc_info + ip->reloc_num,
645 reloc_num_we_have, &reloc_num, &imm) == 0;
646
647 if (!ip->match_now)
648 break;
649
650 bfd_reloc_code_real_type tls_reloc_type = BFD_RELOC_LARCH_TLS_LE_ADD_R;
651
652 if (reloc_num
653 && (ip->reloc_info[ip->reloc_num].type == tls_reloc_type))
654 {
655 ip->reloc_num += reloc_num;
656 ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_RELAX;
657 ip->reloc_info[ip->reloc_num].value = const_0;
658 ip->reloc_num++;
659 }
660 else
661 ip->match_now = 0;
662 break;
663 case 's':
664 case 'u':
665 ip->match_now =
666 loongarch_parse_expr (arg, ip->reloc_info + ip->reloc_num,
667 reloc_num_we_have, &reloc_num, &imm) == 0;
668
669 if (!ip->match_now)
670 break;
671
672 ret = imm;
673 if (reloc_num)
674 {
675 bfd_reloc_code_real_type reloc_type = BFD_RELOC_NONE;
676 reloc_num_we_have -= reloc_num;
677 if (reloc_num_we_have == 0)
678 as_fatal (_("expr too huge") /* Want one more reloc. */);
679 if (esc_ch1 == 'u')
680 {
681 if (strncmp (bit_field, "10:12", strlen ("10:12")) == 0)
682 reloc_type = BFD_RELOC_LARCH_SOP_POP_32_U_10_12;
683 }
684 else if (esc_ch1 == 's')
685 {
686 if (strncmp (bit_field, "10:16<<2", strlen ("10:16<<2")) == 0)
687 reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2;
688 else if (strncmp (bit_field, "0:5|10:16<<2",
689 strlen ("0:5|10:16<<2")) == 0)
690 reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2;
691 else if (strncmp (bit_field, "0:10|10:16<<2",
692 strlen ("0:10|10:16<<2")) == 0)
693 reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2;
694 else if (strncmp (bit_field, "10:12", strlen ("10:12")) == 0)
695 reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_12;
696 else if (strncmp (bit_field, "5:20", strlen ("5:20")) == 0)
697 reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_5_20;
698 else if (strncmp (bit_field, "10:16", strlen ("10:16")) == 0)
699 reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_16;
700 else if (strncmp (bit_field, "10:5", strlen ("10:5")) == 0)
701 reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_5;
702 }
703 if (reloc_type == BFD_RELOC_NONE)
704 as_fatal (
705 _("not support reloc bit-field\nfmt: %c%c %s\nargs: %s"),
706 esc_ch1, esc_ch2, bit_field, arg);
707
708 if (ip->reloc_info[0].type >= BFD_RELOC_LARCH_B16
709 && ip->reloc_info[0].type <= BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2)
710 {
711 /* As we compact stack-relocs, it is no need for pop operation.
712 But break out until here in order to check the imm field.
713 May be reloc_num > 1 if implement relax? */
714 ip->reloc_num += reloc_num;
715 reloc_type = ip->reloc_info[0].type;
716
717 if (LARCH_opts.relax
718 && (BFD_RELOC_LARCH_TLS_LE_HI20_R == reloc_type
719 || BFD_RELOC_LARCH_TLS_LE_LO12_R == reloc_type))
720 {
721 ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_RELAX;
722 ip->reloc_info[ip->reloc_num].value = const_0;
723 ip->reloc_num++;
724 }
725
726 /* Only one register macros (used in normal code model)
727 emit R_LARCH_RELAX.
728 LARCH_opts.ase_labs and LARCH_opts.ase_gabs are used
729 to generate the code model of absolute addresses, and
730 we do not relax this code model. */
731 if (LARCH_opts.relax && (ip->expand_from_macro & 1)
732 && ! (LARCH_opts.ase_labs | LARCH_opts.ase_gabs)
733 && (BFD_RELOC_LARCH_PCALA_HI20 == reloc_type
734 || BFD_RELOC_LARCH_PCALA_LO12 == reloc_type
735 || BFD_RELOC_LARCH_GOT_PC_HI20 == reloc_type
736 || BFD_RELOC_LARCH_GOT_PC_LO12 == reloc_type
737 || BFD_RELOC_LARCH_TLS_LD_PC_HI20 == reloc_type
738 || BFD_RELOC_LARCH_TLS_GD_PC_HI20 == reloc_type
739 || BFD_RELOC_LARCH_TLS_DESC_PC_HI20 == reloc_type
740 || BFD_RELOC_LARCH_TLS_DESC_PC_LO12 == reloc_type
741 || BFD_RELOC_LARCH_TLS_DESC_LD == reloc_type
742 || BFD_RELOC_LARCH_TLS_DESC_CALL == reloc_type
743 || BFD_RELOC_LARCH_TLS_IE_PC_HI20 == reloc_type
744 || BFD_RELOC_LARCH_TLS_IE_PC_LO12 == reloc_type))
745 {
746 ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_RELAX;
747 ip->reloc_info[ip->reloc_num].value = const_0;
748 ip->reloc_num++;
749 }
750 break;
751 }
752 reloc_num++;
753 ip->reloc_num += reloc_num;
754 ip->reloc_info[ip->reloc_num - 1].type = reloc_type;
755 ip->reloc_info[ip->reloc_num - 1].value = const_0;
756 }
757 break;
758 case 'r':
759 imm = (intptr_t) str_hash_find (r_htab, arg);
760 ip->match_now = 0 < imm;
761 ret = imm - 1;
762 if (ip->match_now)
763 break;
764 /* Handle potential usage of deprecated register aliases. */
765 imm = (intptr_t) str_hash_find (r_deprecated_htab, arg);
766 ip->match_now = 0 < imm;
767 ret = imm - 1;
768 /* !ip->expand_from_macro: avoiding duplicate output warnings,
769 only the first macro output warning. */
770 if (ip->match_now && !ip->expand_from_macro)
771 as_warn (_("register alias %s is deprecated, use %s instead"),
772 arg, r_abi_names[ret]);
773 break;
774 case 'f':
775 switch (esc_ch2)
776 {
777 case 'c':
778 imm = (intptr_t) str_hash_find (fc_htab, arg);
779 if (0 >= imm)
780 {
781 imm = (intptr_t) str_hash_find (fcn_htab, arg);
782 }
783 break;
784 default:
785 imm = (intptr_t) str_hash_find (f_htab, arg);
786 }
787 ip->match_now = 0 < imm;
788 ret = imm - 1;
789 if (ip->match_now && !ip->expand_from_macro)
790 break;
791 /* Handle potential usage of deprecated register aliases. */
792 imm = (intptr_t) str_hash_find (f_deprecated_htab, arg);
793 ip->match_now = 0 < imm;
794 ret = imm - 1;
795 if (ip->match_now)
796 as_warn (_("register alias %s is deprecated, use %s instead"),
797 arg, f_abi_names[ret]);
798 break;
799 case 'c':
800 switch (esc_ch2)
801 {
802 case 'r':
803 imm = (intptr_t) str_hash_find (cr_htab, arg);
804 break;
805 default:
806 imm = (intptr_t) str_hash_find (c_htab, arg);
807 }
808 ip->match_now = 0 < imm;
809 ret = imm - 1;
810 break;
811 case 'v':
812 imm = (intptr_t) str_hash_find (v_htab, arg);
813 ip->match_now = 0 < imm;
814 ret = imm - 1;
815 break;
816 case 'x':
817 imm = (intptr_t) str_hash_find (x_htab, arg);
818 ip->match_now = 0 < imm;
819 ret = imm - 1;
820 break;
821 case '\0':
822 ip->all_match = ip->match_now;
823 ip->insn_length =
824 ip->insn->mask ? loongarch_insn_length (ip->insn->match) : 0;
825 /* FIXME: now we have no relax insn. */
826 ip->relax_max_length = ip->insn_length;
827 break;
828 default:
829 as_fatal (_("unknown escape"));
830 }
831
832 do
833 {
834 /* Check imm overflow. */
835 int bit_width, bits_needed_s, bits_needed_u;
836 char *t;
837
838 if (!ip->match_now)
839 break;
840
841 if (0 < reloc_num)
842 break;
843
844 bit_width = loongarch_get_bit_field_width (bit_field, &t);
845
846 if (bit_width == -1)
847 /* No specify bit width. */
848 break;
849
850 imm = ret;
851 if (t[0] == '<' && t[1] == '<')
852 {
853 int i = strtol (t += 2, &t, 10), j;
854 for (j = i; 0 < j; j--, imm >>= 1)
855 if (imm & 1)
856 as_fatal (_("require imm low %d bit is 0."), i);
857 }
858
859 if (*t == '+')
860 imm -= strtol (t, &t, 10);
861
862 bits_needed_s = loongarch_bits_imm_needed (imm, 1);
863 bits_needed_u = loongarch_bits_imm_needed (imm, 0);
864
865 if ((esc_ch1 == 's' && bit_width < bits_needed_s)
866 || (esc_ch1 != 's' && bit_width < bits_needed_u))
867 /* How to do after we detect overflow. */
868 as_fatal (_("Immediate overflow.\n"
869 "format: %c%c%s\n"
870 "arg: %s"),
871 esc_ch1, esc_ch2, bit_field, arg);
872 }
873 while (0);
874
875 if (esc_ch1 != '\0')
876 {
877 ip->args[ip->arg_num] = ret;
878 ip->arg_num++;
879 }
880 return ret;
881 }
882
883 static void
get_loongarch_opcode(struct loongarch_cl_insn * insn)884 get_loongarch_opcode (struct loongarch_cl_insn *insn)
885 {
886 const struct loongarch_opcode *it;
887 struct loongarch_ase *ase;
888 for (ase = loongarch_ASEs; ase->enabled; ase++)
889 {
890 if (!*ase->enabled || (ase->include && !*ase->include)
891 || (ase->exclude && *ase->exclude))
892 continue;
893
894 if (!ase->name_hash_entry)
895 {
896 ase->name_hash_entry = str_htab_create ();
897 for (it = ase->opcodes; it->name; it++)
898 {
899 if ((!it->include || (it->include && *it->include))
900 && (!it->exclude || (it->exclude && !(*it->exclude)))
901 && !(it->pinfo & INSN_DIS_ALIAS))
902 str_hash_insert (ase->name_hash_entry, it->name,
903 (void *) it, 0);
904 }
905 }
906
907 if ((it = str_hash_find (ase->name_hash_entry, insn->name)) == NULL)
908 continue;
909
910 do
911 {
912 insn->insn = it;
913 insn->match_now = 1;
914 insn->all_match = 0;
915 insn->arg_num = 0;
916 insn->reloc_num = 0;
917 insn->insn_bin = (loongarch_foreach_args
918 (it->format, insn->arg_strs,
919 loongarch_args_parser_can_match_arg_helper,
920 insn));
921 if (insn->all_match && !(it->include && !*it->include)
922 && !(it->exclude && *it->exclude))
923 {
924 insn->insn_bin |= it->match;
925 return;
926 }
927 it++;
928 }
929 while (it->name && strcasecmp (it->name, insn->name) == 0);
930 }
931 }
932
933 static int
check_this_insn_before_appending(struct loongarch_cl_insn * ip)934 check_this_insn_before_appending (struct loongarch_cl_insn *ip)
935 {
936 int ret = 0;
937
938 if (strncmp (ip->name, "la.abs", 6) == 0)
939 {
940 ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_MARK_LA;
941 ip->reloc_info[ip->reloc_num].value = const_0;
942 ip->reloc_num++;
943 }
944 else if (ip->insn->mask == 0xffff8000
945 /* amcas.b rd, rk, rj */
946 && ((ip->insn_bin & 0xfff80000) == 0x38580000
947 /* amswap.w rd, rk, rj */
948 || (ip->insn_bin & 0xfff00000) == 0x38600000
949 /* ammax_db.wu rd, rk, rj */
950 || (ip->insn_bin & 0xffff0000) == 0x38700000
951 /* ammin_db.wu rd, rk, rj */
952 || (ip->insn_bin & 0xffff0000) == 0x38710000))
953 {
954 /* For AMO insn amswap.[wd], amadd.[wd], etc. */
955 if (ip->args[0] != 0
956 && (ip->args[0] == ip->args[1] || ip->args[0] == ip->args[2]))
957 as_fatal (_("AMO insns require rd != base && rd != rt"
958 " when rd isn't $r0"));
959 }
960 else if ((ip->insn->mask == 0xffe08000
961 /* bstrins.w rd, rj, msbw, lsbw */
962 && (ip->insn_bin & 0xffe00000) == 0x00600000)
963 || (ip->insn->mask == 0xffc00000
964 /* bstrins.d rd, rj, msbd, lsbd */
965 && (ip->insn_bin & 0xff800000) == 0x00800000))
966 {
967 /* For bstr(ins|pick).[wd]. */
968 if (ip->args[2] < ip->args[3])
969 as_fatal (_("bstr(ins|pick).[wd] require msbd >= lsbd"));
970 }
971 else if (ip->insn->mask != 0 && (ip->insn_bin & 0xfe0003c0) == 0x04000000
972 /* csrxchg rd, rj, csr_num */
973 && (strcmp ("csrxchg", ip->name) == 0))
974 as_fatal (_("csrxchg require rj != $r0 && rj != $r1"));
975
976 return ret;
977 }
978
979 static void
install_insn(const struct loongarch_cl_insn * insn)980 install_insn (const struct loongarch_cl_insn *insn)
981 {
982 char *f = insn->frag->fr_literal + insn->where;
983 if (0 < insn->insn_length)
984 md_number_to_chars (f, insn->insn_bin, insn->insn_length);
985 }
986
987 static void
move_insn(struct loongarch_cl_insn * insn,fragS * frag,long where)988 move_insn (struct loongarch_cl_insn *insn, fragS *frag, long where)
989 {
990 size_t i;
991 insn->frag = frag;
992 insn->where = where;
993 for (i = 0; i < insn->reloc_num; i++)
994 {
995 if (insn->fixp[i])
996 {
997 insn->fixp[i]->fx_frag = frag;
998 insn->fixp[i]->fx_where = where;
999 }
1000 }
1001 install_insn (insn);
1002 }
1003
1004 /* Add INSN to the end of the output. */
1005 static void
append_fixed_insn(struct loongarch_cl_insn * insn)1006 append_fixed_insn (struct loongarch_cl_insn *insn)
1007 {
1008 /* Ensure the jirl is emitted to the same frag as the pcaddu18i. */
1009 if (BFD_RELOC_LARCH_CALL36 == insn->reloc_info[0].type)
1010 frag_grow (8);
1011
1012 char *f = frag_more (insn->insn_length);
1013 move_insn (insn, frag_now, f - frag_now->fr_literal);
1014 }
1015
1016 /* Add instructions based on the worst-case scenario firstly. */
1017 static void
append_relaxed_branch_insn(struct loongarch_cl_insn * insn,int max_chars,int var,relax_substateT subtype,symbolS * symbol,offsetT offset)1018 append_relaxed_branch_insn (struct loongarch_cl_insn *insn, int max_chars,
1019 int var, relax_substateT subtype, symbolS *symbol, offsetT offset)
1020 {
1021 frag_grow (max_chars);
1022 move_insn (insn, frag_now, frag_more (0) - frag_now->fr_literal);
1023 frag_var (rs_machine_dependent, max_chars, var,
1024 subtype, symbol, offset, NULL);
1025 }
1026
1027 static void
append_fixp_and_insn(struct loongarch_cl_insn * ip)1028 append_fixp_and_insn (struct loongarch_cl_insn *ip)
1029 {
1030 reloc_howto_type *howto;
1031 bfd_reloc_code_real_type r_type;
1032 struct reloc_info *reloc_info = ip->reloc_info;
1033 size_t i;
1034
1035 dwarf2_emit_insn (0);
1036
1037 for (i = 0; i < ip->reloc_num; i++)
1038 {
1039 r_type = reloc_info[i].type;
1040
1041 if (r_type != BFD_RELOC_UNUSED)
1042 {
1043
1044 gas_assert (&(reloc_info[i].value));
1045 if (BFD_RELOC_LARCH_B16 == r_type || BFD_RELOC_LARCH_B21 == r_type)
1046 {
1047 int min_bytes = 4; /* One branch instruction. */
1048 unsigned max_bytes = 8; /* Branch and jump instructions. */
1049
1050 if (now_seg == absolute_section)
1051 {
1052 as_bad (_("relaxable branches not supported in absolute section"));
1053 return;
1054 }
1055
1056 append_relaxed_branch_insn (ip, max_bytes, min_bytes,
1057 RELAX_BRANCH_ENCODE (r_type),
1058 reloc_info[i].value.X_add_symbol,
1059 reloc_info[i].value.X_add_number);
1060 return;
1061 }
1062 else
1063 {
1064 howto = bfd_reloc_type_lookup (stdoutput, r_type);
1065 if (howto == NULL)
1066 as_fatal (_("no HOWTO loong relocation number %d"), r_type);
1067
1068 ip->fixp[i] = fix_new_exp (ip->frag, ip->where,
1069 bfd_get_reloc_size (howto),
1070 &reloc_info[i].value, FALSE, r_type);
1071 }
1072 }
1073 }
1074
1075 if (ip->insn_length < ip->relax_max_length)
1076 as_fatal (_("Internal error: not support relax now"));
1077 else
1078 append_fixed_insn (ip);
1079
1080 /* We need to start a new frag after any instruction that can be
1081 optimized away or compressed by the linker during relaxation, to prevent
1082 the assembler from computing static offsets across such an instruction.
1083
1084 This is necessary to get correct .eh_frame FDE DW_CFA_advance_loc info.
1085 If one cfi_insn_data's two symbols are not in the same frag, it will
1086 generate ADD and SUB relocations pairs to calculate DW_CFA_advance_loc.
1087 (gas/dw2gencfi.c: output_cfi_insn:
1088 if (symbol_get_frag (to) == symbol_get_frag (from)))
1089
1090 For macro instructions, only the first instruction expanded from macro
1091 need to start a new frag. */
1092 if (LARCH_opts.relax
1093 && (BFD_RELOC_LARCH_PCALA_HI20 == reloc_info[0].type
1094 || BFD_RELOC_LARCH_GOT_PC_HI20 == reloc_info[0].type
1095 || BFD_RELOC_LARCH_TLS_LE_HI20_R == reloc_info[0].type
1096 || BFD_RELOC_LARCH_TLS_LE_ADD_R == reloc_info[0].type
1097 || BFD_RELOC_LARCH_TLS_LD_PC_HI20 == reloc_info[0].type
1098 || BFD_RELOC_LARCH_TLS_GD_PC_HI20 == reloc_info[0].type
1099 || BFD_RELOC_LARCH_TLS_DESC_PC_HI20 == reloc_info[0].type
1100 || BFD_RELOC_LARCH_TLS_DESC_PC_LO12 == reloc_info[0].type
1101 || BFD_RELOC_LARCH_TLS_DESC_LD == reloc_info[0].type
1102 || BFD_RELOC_LARCH_TLS_DESC_CALL == reloc_info[0].type
1103 || BFD_RELOC_LARCH_TLS_IE_PC_HI20 == reloc_info[0].type
1104 || BFD_RELOC_LARCH_TLS_IE_PC_LO12 == reloc_info[0].type))
1105 {
1106 frag_wane (frag_now);
1107 frag_new (0);
1108 }
1109 }
1110
1111 /* Ask helper for returning a malloced c_str or NULL. */
1112 static char *
assember_macro_helper(const char * const args[],void * context_ptr)1113 assember_macro_helper (const char *const args[], void *context_ptr)
1114 {
1115 struct loongarch_cl_insn *insn = context_ptr;
1116 char *ret = NULL;
1117 if ( strcmp (insn->name, "li.w") == 0 || strcmp (insn->name, "li.d") == 0)
1118 {
1119 char args_buf[50], insns_buf[200];
1120 const char *arg_strs[6];
1121 uint32_t hi32, lo32;
1122
1123 /* We pay attention to sign extend beacause it is chance of reduce insn.
1124 The exception is 12-bit and hi-12-bit unsigned,
1125 we need a 'ori' or a 'lu52i.d' accordingly. */
1126 char all0_bit_vec, sign_bit_vec, allf_bit_vec, paritial_is_sext_of_prev;
1127
1128 lo32 = insn->args[1] & 0xffffffff;
1129 hi32 = insn->args[1] >> 32;
1130
1131 if (strcmp (insn->name, "li.w") == 0)
1132 {
1133 if (hi32 != 0 && hi32 != 0xffffffff)
1134 as_fatal (_("li overflow: hi32:0x%x lo32:0x%x"), hi32, lo32);
1135 hi32 = lo32 & 0x80000000 ? 0xffffffff : 0;
1136 }
1137
1138 if (strcmp (insn->name, "li.d") == 0 && !LARCH_opts.ase_lp64)
1139 as_fatal (_("we can't li.d on 32bit-arch"));
1140
1141 snprintf (args_buf, sizeof (args_buf), "0x%x,0x%x,0x%x,0x%x,%s",
1142 (hi32 >> 20) & 0xfff, hi32 & 0xfffff, (lo32 >> 12) & 0xfffff,
1143 lo32 & 0xfff, args[0]);
1144 loongarch_split_args_by_comma (args_buf, arg_strs);
1145
1146 all0_bit_vec =
1147 ((((hi32 & 0xfff00000) == 0) << 3) | (((hi32 & 0x000fffff) == 0) << 2)
1148 | (((lo32 & 0xfffff000) == 0) << 1) | ((lo32 & 0x00000fff) == 0));
1149 sign_bit_vec =
1150 ((((hi32 & 0x80000000) != 0) << 3) | (((hi32 & 0x00080000) != 0) << 2)
1151 | (((lo32 & 0x80000000) != 0) << 1) | ((lo32 & 0x00000800) != 0));
1152 allf_bit_vec =
1153 ((((hi32 & 0xfff00000) == 0xfff00000) << 3)
1154 | (((hi32 & 0x000fffff) == 0x000fffff) << 2)
1155 | (((lo32 & 0xfffff000) == 0xfffff000) << 1)
1156 | ((lo32 & 0x00000fff) == 0x00000fff));
1157 paritial_is_sext_of_prev =
1158 (all0_bit_vec ^ allf_bit_vec) & (all0_bit_vec ^ (sign_bit_vec << 1));
1159
1160 static const char *const li_32bit[] =
1161 {
1162 "lu12i.w %5,%3&0x80000?%3-0x100000:%3;ori %5,%5,%4;",
1163 "lu12i.w %5,%3&0x80000?%3-0x100000:%3;",
1164 "addi.w %5,$r0,%4&0x800?%4-0x1000:%4;",
1165 "or %5,$r0,$r0;",
1166 };
1167 static const char *const li_hi_32bit[] =
1168 {
1169 "lu32i.d %5,%2&0x80000?%2-0x100000:%2;"
1170 "lu52i.d %5,%5,%1&0x800?%1-0x1000:%1;",
1171 "lu52i.d %5,%5,%1&0x800?%1-0x1000:%1;",
1172 "lu32i.d %5,%2&0x80000?%2-0x100000:%2;",
1173 "",
1174 };
1175 do
1176 {
1177 insns_buf[0] = '\0';
1178 if (paritial_is_sext_of_prev == 0x7)
1179 {
1180 strcat (insns_buf, "lu52i.d %5,$r0,%1&0x800?%1-0x1000:%1;");
1181 break;
1182 }
1183 if ((all0_bit_vec & 0x3) == 0x2)
1184 strcat (insns_buf, "ori %5,$r0,%4;");
1185 else
1186 strcat (insns_buf, li_32bit[paritial_is_sext_of_prev & 0x3]);
1187 strcat (insns_buf, li_hi_32bit[paritial_is_sext_of_prev >> 2]);
1188 }
1189 while (0);
1190
1191 ret = loongarch_expand_macro (insns_buf, arg_strs, NULL, NULL,
1192 sizeof (args_buf));
1193 }
1194
1195 return ret;
1196 }
1197
1198 /* Accept instructions separated by ';'
1199 * assuming 'not starting with space and not ending with space' or pass in
1200 * empty c_str. */
1201 static void
loongarch_assemble_INSNs(char * str,unsigned int expand_from_macro)1202 loongarch_assemble_INSNs (char *str, unsigned int expand_from_macro)
1203 {
1204 char *rest;
1205 size_t len_str = strlen(str);
1206
1207 for (rest = str; *rest != ';' && *rest != '\0'; rest++);
1208 if (*rest == ';')
1209 *rest++ = '\0';
1210
1211 if (*str == ':')
1212 {
1213 str++;
1214 setup_internal_label_here (strtol (str, &str, 10));
1215 str++;
1216 }
1217
1218 do
1219 {
1220 if (*str == '\0')
1221 break;
1222
1223 struct loongarch_cl_insn the_one = { 0 };
1224 the_one.name = str;
1225 the_one.expand_from_macro = expand_from_macro;
1226
1227 for (; *str && *str != ' '; str++)
1228 ;
1229 if (*str == ' ')
1230 *str++ = '\0';
1231
1232 loongarch_split_args_by_comma (str, the_one.arg_strs);
1233 get_loongarch_opcode (&the_one);
1234
1235 if (!the_one.all_match)
1236 {
1237 char *ss = loongarch_cat_splited_strs (the_one.arg_strs);
1238 as_bad (_("no match insn: %s\t%s"), the_one.name, ss ? ss : "");
1239 free(ss);
1240 return;
1241 }
1242
1243 if (check_this_insn_before_appending (&the_one) != 0)
1244 break;
1245
1246 append_fixp_and_insn (&the_one);
1247
1248 /* Expanding macro instructions. */
1249 if (the_one.insn_length == 0 && the_one.insn->macro)
1250 {
1251 unsigned int new_expand_from_macro = 0;
1252 if (2 == the_one.arg_num)
1253 new_expand_from_macro |= 1;
1254 else if (3 == the_one.arg_num)
1255 new_expand_from_macro |= 2;
1256
1257 char *c_str = loongarch_expand_macro (the_one.insn->macro,
1258 the_one.arg_strs,
1259 assember_macro_helper,
1260 &the_one, len_str);
1261 /* The first instruction expanded from macro. */
1262 loongarch_assemble_INSNs (c_str, new_expand_from_macro);
1263 free (c_str);
1264 }
1265 }
1266 while (0);
1267
1268 /* The rest instructions expanded from macro, split by semicolon(;),
1269 assembly one by one. */
1270 if (*rest != '\0')
1271 loongarch_assemble_INSNs (rest, expand_from_macro);
1272 }
1273
1274 void
md_assemble(char * str)1275 md_assemble (char *str)
1276 {
1277 loongarch_assemble_INSNs (str, 0);
1278 }
1279
1280 const char *
md_atof(int type,char * litP,int * sizeP)1281 md_atof (int type, char *litP, int *sizeP)
1282 {
1283 return ieee_md_atof (type, litP, sizeP, FALSE);
1284 }
1285
1286 void
md_number_to_chars(char * buf,valueT val,int n)1287 md_number_to_chars (char *buf, valueT val, int n)
1288 {
1289 number_to_chars_littleendian (buf, val, n);
1290 }
1291
1292 /* The location from which a PC relative jump should be calculated,
1293 given a PC relative reloc. */
1294 long
md_pcrel_from(fixS * fixP ATTRIBUTE_UNUSED)1295 md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
1296 {
1297 return 0;
1298 }
1299
fix_reloc_insn(fixS * fixP,bfd_vma reloc_val,char * buf)1300 static void fix_reloc_insn (fixS *fixP, bfd_vma reloc_val, char *buf)
1301 {
1302 reloc_howto_type *howto;
1303 insn_t insn;
1304 howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
1305
1306 insn = bfd_getl32 (buf);
1307
1308 if (!loongarch_adjust_reloc_bitsfield (NULL, howto, &reloc_val))
1309 as_bad_where (fixP->fx_file, fixP->fx_line, "Reloc overflow");
1310
1311 insn = (insn & (insn_t)howto->src_mask)
1312 | ((insn & (~(insn_t)howto->dst_mask)) | reloc_val);
1313
1314 bfd_putl32 (insn, buf);
1315 }
1316
1317 void
md_apply_fix(fixS * fixP,valueT * valP,segT seg ATTRIBUTE_UNUSED)1318 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
1319 {
1320 static int64_t stack_top;
1321 static int last_reloc_is_sop_push_pcrel_1 = 0;
1322 int last_reloc_is_sop_push_pcrel = last_reloc_is_sop_push_pcrel_1;
1323 segT sub_segment;
1324 last_reloc_is_sop_push_pcrel_1 = 0;
1325
1326 char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
1327 switch (fixP->fx_r_type)
1328 {
1329 case BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL:
1330 case BFD_RELOC_LARCH_SOP_PUSH_TLS_GD:
1331 case BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT:
1332 case BFD_RELOC_LARCH_TLS_LE_HI20:
1333 case BFD_RELOC_LARCH_TLS_LE_LO12:
1334 case BFD_RELOC_LARCH_TLS_LE64_LO20:
1335 case BFD_RELOC_LARCH_TLS_LE64_HI12:
1336 case BFD_RELOC_LARCH_TLS_IE_PC_HI20:
1337 case BFD_RELOC_LARCH_TLS_IE_PC_LO12:
1338 case BFD_RELOC_LARCH_TLS_IE64_PC_LO20:
1339 case BFD_RELOC_LARCH_TLS_IE64_PC_HI12:
1340 case BFD_RELOC_LARCH_TLS_IE_HI20:
1341 case BFD_RELOC_LARCH_TLS_IE_LO12:
1342 case BFD_RELOC_LARCH_TLS_IE64_LO20:
1343 case BFD_RELOC_LARCH_TLS_IE64_HI12:
1344 case BFD_RELOC_LARCH_TLS_LD_PC_HI20:
1345 case BFD_RELOC_LARCH_TLS_LD_HI20:
1346 case BFD_RELOC_LARCH_TLS_GD_PC_HI20:
1347 case BFD_RELOC_LARCH_TLS_GD_HI20:
1348 case BFD_RELOC_LARCH_TLS_DESC_PC_HI20:
1349 case BFD_RELOC_LARCH_TLS_DESC_PC_LO12:
1350 case BFD_RELOC_LARCH_TLS_DESC64_PC_LO20:
1351 case BFD_RELOC_LARCH_TLS_DESC64_PC_HI12:
1352 case BFD_RELOC_LARCH_TLS_DESC_HI20:
1353 case BFD_RELOC_LARCH_TLS_DESC_LO12:
1354 case BFD_RELOC_LARCH_TLS_DESC64_LO20:
1355 case BFD_RELOC_LARCH_TLS_DESC64_HI12:
1356 /* Add tls lo (got_lo reloc type). */
1357 if (fixP->fx_addsy == NULL)
1358 as_bad_where (fixP->fx_file, fixP->fx_line,
1359 _("Relocation against a constant"));
1360 S_SET_THREAD_LOCAL (fixP->fx_addsy);
1361 break;
1362
1363 case BFD_RELOC_LARCH_SOP_PUSH_PCREL:
1364 if (fixP->fx_addsy == NULL)
1365 as_bad_where (fixP->fx_file, fixP->fx_line,
1366 _("Relocation against a constant"));
1367
1368 last_reloc_is_sop_push_pcrel_1 = 1;
1369 if (S_GET_SEGMENT (fixP->fx_addsy) == seg)
1370 stack_top = (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset
1371 - (fixP->fx_where + fixP->fx_frag->fr_address));
1372 else
1373 stack_top = 0;
1374 break;
1375
1376 case BFD_RELOC_LARCH_TLS_DESC_LD:
1377 case BFD_RELOC_LARCH_TLS_DESC_CALL:
1378 break;
1379
1380 case BFD_RELOC_LARCH_SOP_POP_32_S_10_5:
1381 case BFD_RELOC_LARCH_SOP_POP_32_S_10_12:
1382 case BFD_RELOC_LARCH_SOP_POP_32_U_10_12:
1383 case BFD_RELOC_LARCH_SOP_POP_32_S_10_16:
1384 case BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2:
1385 case BFD_RELOC_LARCH_SOP_POP_32_S_5_20:
1386 case BFD_RELOC_LARCH_SOP_POP_32_U:
1387 case BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2:
1388 case BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2:
1389 if (!last_reloc_is_sop_push_pcrel)
1390 break;
1391
1392 fix_reloc_insn (fixP, (bfd_vma)stack_top, buf);
1393 break;
1394
1395 /* LARCH only has R_LARCH_64/32, not has R_LARCH_24/16/8.
1396 For BFD_RELOC_64/32, if fx_addsy and fx_subsy not null, wer need
1397 generate BFD_RELOC_LARCH_ADD64/32 and BFD_RELOC_LARCH_SUB64/32 here.
1398 Then will parse howto table bfd_reloc_code_real_type to generate
1399 R_LARCH_ADD64/32 and R_LARCH_SUB64/32 reloc at tc_gen_reloc function.
1400 If only fx_addsy not null, skip here directly, then generate
1401 R_LARCH_64/32.
1402
1403 For BFD_RELOC_24/16/8, if fx_addsy and fx_subsy not null, wer need
1404 generate BFD_RELOC_LARCH_ADD24/16/8 and BFD_RELOC_LARCH_SUB24/16/8 here.
1405 Then will parse howto table bfd_reloc_code_real_type to generate
1406 R_LARCH_ADD24/16/8 and R_LARCH_SUB24/16/8 reloc at tc_gen_reloc
1407 function. If only fx_addsy not null, we generate
1408 BFD_RELOC_LARCH_ADD24/16/8 only, then generate R_LARCH_24/16/8.
1409 To avoid R_LARCH_ADDxx add extra value, we write 0 first
1410 (use md_number_to_chars (buf, 0, fixP->fx_size)). */
1411 case BFD_RELOC_64:
1412 case BFD_RELOC_32:
1413 if (fixP->fx_pcrel)
1414 {
1415 switch (fixP->fx_r_type)
1416 {
1417 case BFD_RELOC_64:
1418 fixP->fx_r_type = BFD_RELOC_LARCH_64_PCREL;
1419 break;
1420 case BFD_RELOC_32:
1421 fixP->fx_r_type = BFD_RELOC_LARCH_32_PCREL;
1422 break;
1423 default:
1424 break;
1425 }
1426 }
1427
1428 /* If symbol in .eh_frame the address may be adjusted, and contents of
1429 .eh_frame will be adjusted, so use pc-relative relocation for FDE
1430 initial location.
1431 The Option of mthin-add-sub does not affect the generation of
1432 R_LARCH_32_PCREL relocation in .eh_frame. */
1433 if (fixP->fx_r_type == BFD_RELOC_32
1434 && fixP->fx_addsy && fixP->fx_subsy
1435 && (sub_segment = S_GET_SEGMENT (fixP->fx_subsy))
1436 && strcmp (sub_segment->name, ".eh_frame") == 0
1437 && S_GET_VALUE (fixP->fx_subsy)
1438 == fixP->fx_frag->fr_address + fixP->fx_where)
1439 {
1440 fixP->fx_r_type = BFD_RELOC_LARCH_32_PCREL;
1441 fixP->fx_subsy = NULL;
1442 break;
1443 }
1444
1445 if (fixP->fx_addsy && fixP->fx_subsy)
1446 {
1447 fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
1448 fixP->fx_next->fx_addsy = fixP->fx_subsy;
1449 fixP->fx_next->fx_subsy = NULL;
1450 fixP->fx_next->fx_offset = 0;
1451 fixP->fx_subsy = NULL;
1452
1453 switch (fixP->fx_r_type)
1454 {
1455 case BFD_RELOC_64:
1456 fixP->fx_r_type = BFD_RELOC_LARCH_ADD64;
1457 fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB64;
1458 break;
1459 case BFD_RELOC_32:
1460 fixP->fx_r_type = BFD_RELOC_LARCH_ADD32;
1461 fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB32;
1462 break;
1463 default:
1464 break;
1465 }
1466
1467 md_number_to_chars (buf, 0, fixP->fx_size);
1468 }
1469
1470 if (fixP->fx_addsy == NULL)
1471 {
1472 fixP->fx_done = 1;
1473 md_number_to_chars (buf, *valP, fixP->fx_size);
1474 }
1475 break;
1476
1477 case BFD_RELOC_24:
1478 case BFD_RELOC_16:
1479 case BFD_RELOC_8:
1480 if (fixP->fx_addsy)
1481 {
1482 fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
1483 fixP->fx_next->fx_addsy = fixP->fx_subsy;
1484 fixP->fx_next->fx_subsy = NULL;
1485 fixP->fx_next->fx_offset = 0;
1486 fixP->fx_subsy = NULL;
1487
1488 switch (fixP->fx_r_type)
1489 {
1490 case BFD_RELOC_24:
1491 fixP->fx_r_type = BFD_RELOC_LARCH_ADD24;
1492 fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB24;
1493 break;
1494 case BFD_RELOC_16:
1495 fixP->fx_r_type = BFD_RELOC_LARCH_ADD16;
1496 fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB16;
1497 break;
1498 case BFD_RELOC_8:
1499 fixP->fx_r_type = BFD_RELOC_LARCH_ADD8;
1500 fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB8;
1501 break;
1502 default:
1503 break;
1504 }
1505
1506 md_number_to_chars (buf, 0, fixP->fx_size);
1507
1508 if (fixP->fx_next->fx_addsy == NULL)
1509 fixP->fx_next->fx_done = 1;
1510 }
1511
1512 if (fixP->fx_addsy == NULL)
1513 {
1514 fixP->fx_done = 1;
1515 md_number_to_chars (buf, *valP, fixP->fx_size);
1516 }
1517 break;
1518
1519 case BFD_RELOC_LARCH_CFA:
1520 if (fixP->fx_addsy && fixP->fx_subsy)
1521 {
1522 fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
1523 fixP->fx_next->fx_addsy = fixP->fx_subsy;
1524 fixP->fx_next->fx_subsy = NULL;
1525 fixP->fx_next->fx_offset = 0;
1526 fixP->fx_subsy = NULL;
1527
1528 unsigned int subtype;
1529 offsetT loc;
1530 subtype = bfd_get_8 (NULL, &((fragS *)
1531 (fixP->fx_frag->fr_opcode))->fr_literal[fixP->fx_where]);
1532 loc = fixP->fx_frag->fr_fix - (subtype & 7);
1533 switch (subtype)
1534 {
1535 case DW_CFA_advance_loc1:
1536 fixP->fx_where = loc + 1;
1537 fixP->fx_next->fx_where = loc + 1;
1538 fixP->fx_r_type = BFD_RELOC_LARCH_ADD8;
1539 fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB8;
1540 md_number_to_chars (buf+1, 0, fixP->fx_size);
1541 break;
1542
1543 case DW_CFA_advance_loc2:
1544 fixP->fx_size = 2;
1545 fixP->fx_next->fx_size = 2;
1546 fixP->fx_where = loc + 1;
1547 fixP->fx_next->fx_where = loc + 1;
1548 fixP->fx_r_type = BFD_RELOC_LARCH_ADD16;
1549 fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB16;
1550 md_number_to_chars (buf+1, 0, fixP->fx_size);
1551 break;
1552
1553 case DW_CFA_advance_loc4:
1554 fixP->fx_size = 4;
1555 fixP->fx_next->fx_size = 4;
1556 fixP->fx_where = loc;
1557 fixP->fx_next->fx_where = loc;
1558 fixP->fx_r_type = BFD_RELOC_LARCH_ADD32;
1559 fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB32;
1560 md_number_to_chars (buf+1, 0, fixP->fx_size);
1561 break;
1562
1563 default:
1564 if (subtype < 0x80 && (subtype & 0x40))
1565 {
1566 /* DW_CFA_advance_loc. */
1567 fixP->fx_frag = (fragS *) fixP->fx_frag->fr_opcode;
1568 fixP->fx_next->fx_frag = fixP->fx_frag;
1569 fixP->fx_r_type = BFD_RELOC_LARCH_ADD6;
1570 fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB6;
1571 md_number_to_chars (buf, 0x40, fixP->fx_size);
1572 }
1573 else
1574 as_fatal (_("internal: bad CFA value #%d"), subtype);
1575 break;
1576 }
1577 }
1578 break;
1579
1580 case BFD_RELOC_LARCH_B16:
1581 case BFD_RELOC_LARCH_B21:
1582 case BFD_RELOC_LARCH_B26:
1583 if (fixP->fx_addsy == NULL)
1584 {
1585 as_bad_where (fixP->fx_file, fixP->fx_line,
1586 _ ("Relocation against a constant."));
1587 }
1588 if (S_GET_SEGMENT (fixP->fx_addsy) == seg
1589 && !S_FORCE_RELOC (fixP->fx_addsy, 1))
1590 {
1591 int64_t sym_addend = S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset;
1592 int64_t pc = fixP->fx_where + fixP->fx_frag->fr_address;
1593 fix_reloc_insn (fixP, sym_addend - pc, buf);
1594
1595 /* If relax, symbol value may change at link time, so reloc need to
1596 be saved. */
1597 if (!LARCH_opts.relax)
1598 fixP->fx_done = 1;
1599 }
1600 break;
1601
1602 /* Because ADD_ULEB128/SUB_ULEB128 always occur in pairs.
1603 So just deal with one is ok.
1604 case BFD_RELOC_LARCH_ADD_ULEB128: */
1605 case BFD_RELOC_LARCH_SUB_ULEB128:
1606 {
1607 unsigned int len = 0;
1608 len = loongarch_get_uleb128_length ((bfd_byte *)buf);
1609 bfd_byte *endp = (bfd_byte*) buf + len -1;
1610 /* Clean the uleb128 value to 0. Do not reduce the length. */
1611 memset (buf, 0x80, len - 1);
1612 *endp = 0;
1613 break;
1614 }
1615
1616 default:
1617 break;
1618 }
1619 }
1620
1621 int
md_estimate_size_before_relax(fragS * fragp ATTRIBUTE_UNUSED,asection * segtype ATTRIBUTE_UNUSED)1622 md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED,
1623 asection *segtype ATTRIBUTE_UNUSED)
1624 {
1625 return (fragp->fr_var = 4);
1626 }
1627
1628 /* Translate internal representation of relocation info to BFD target
1629 format. */
1630 arelent *
tc_gen_reloc(asection * section ATTRIBUTE_UNUSED,fixS * fixp)1631 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
1632 {
1633 arelent *reloc = (arelent *) xmalloc (sizeof (arelent));
1634
1635 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
1636 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
1637 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
1638 reloc->addend = fixp->fx_offset;
1639
1640 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
1641 if (reloc->howto == NULL)
1642 {
1643 as_bad_where (fixp->fx_file, fixp->fx_line,
1644 _("cannot represent %s relocation in object file"),
1645 bfd_get_reloc_code_name (fixp->fx_r_type));
1646 return NULL;
1647 }
1648
1649 return reloc;
1650 }
1651
1652 /* Standard calling conventions leave the CFA at SP on entry. */
1653 void
loongarch_cfi_frame_initial_instructions(void)1654 loongarch_cfi_frame_initial_instructions (void)
1655 {
1656 cfi_add_CFA_def_cfa_register (3 /* $sp */);
1657 }
1658
1659 void
loongarch_pre_output_hook(void)1660 loongarch_pre_output_hook (void)
1661 {
1662 const frchainS *frch;
1663 segT s;
1664
1665 if (!LARCH_opts.relax)
1666 return;
1667
1668 /* Save the current segment info. */
1669 segT seg = now_seg;
1670 subsegT subseg = now_subseg;
1671
1672 for (s = stdoutput->sections; s; s = s->next)
1673 for (frch = seg_info (s)->frchainP; frch; frch = frch->frch_next)
1674 {
1675 fragS *frag;
1676
1677 for (frag = frch->frch_root; frag; frag = frag->fr_next)
1678 {
1679 if (frag->fr_type == rs_cfa)
1680 {
1681 expressionS exp;
1682 expressionS *symval;
1683
1684 symval = symbol_get_value_expression (frag->fr_symbol);
1685 exp.X_op = O_subtract;
1686 exp.X_add_symbol = symval->X_add_symbol;
1687 exp.X_add_number = 0;
1688 exp.X_op_symbol = symval->X_op_symbol;
1689
1690 /* We must set the segment before creating a frag after all
1691 frag chains have been chained together. */
1692 subseg_set (s, frch->frch_subseg);
1693
1694 fix_new_exp (frag, (int) frag->fr_offset, 1, &exp, 0,
1695 BFD_RELOC_LARCH_CFA);
1696 }
1697 }
1698 }
1699
1700 /* Restore the original segment info. */
1701 subseg_set (seg, subseg);
1702 }
1703
1704 void
tc_loongarch_parse_to_dw2regnum(expressionS * exp)1705 tc_loongarch_parse_to_dw2regnum (expressionS *exp)
1706 {
1707 expression_and_evaluate (exp);
1708 }
1709
1710 void
md_show_usage(FILE * stream)1711 md_show_usage (FILE *stream)
1712 {
1713 fprintf (stream, _("LARCH options:\n"));
1714 /* FIXME */
1715 fprintf (stream, _("\
1716 -mthin-add-sub Convert a pair of R_LARCH_ADD32/64 and R_LARCH_SUB32/64 to\n\
1717 R_LARCH_32/64_PCREL as much as possible\n\
1718 The option does not affect the generation of R_LARCH_32_PCREL\n\
1719 relocations in .eh_frame\n"));
1720 }
1721
1722 static void
loongarch_make_nops(char * buf,bfd_vma bytes)1723 loongarch_make_nops (char *buf, bfd_vma bytes)
1724 {
1725 bfd_vma i = 0;
1726
1727 /* Fill with 4-byte NOPs. */
1728 for ( ; i < bytes; i += 4)
1729 number_to_chars_littleendian (buf + i, LARCH_NOP, 4);
1730 }
1731
1732 /* Called from md_do_align. Used to create an alignment frag in a
1733 code section by emitting a worst-case NOP sequence that the linker
1734 will later relax to the correct number of NOPs. We can't compute
1735 the correct alignment now because of other linker relaxations. */
1736
1737 bool
loongarch_frag_align_code(int n,int max)1738 loongarch_frag_align_code (int n, int max)
1739 {
1740 char *nops;
1741 symbolS *s;
1742 expressionS ex;
1743
1744 bfd_vma insn_alignment = 4;
1745 bfd_vma bytes = (bfd_vma) 1 << n;
1746 bfd_vma worst_case_bytes = bytes - insn_alignment;
1747
1748 /* If we are moving to a smaller alignment than the instruction size, then no
1749 alignment is required. */
1750 if (bytes <= insn_alignment)
1751 return true;
1752
1753 /* When not relaxing, loongarch_handle_align handles code alignment. */
1754 if (!LARCH_opts.relax)
1755 return false;
1756
1757 nops = frag_more (worst_case_bytes);
1758
1759 s = symbol_find (".Lla-relax-align");
1760 if (s == NULL)
1761 s = (symbolS *)local_symbol_make (".Lla-relax-align", now_seg,
1762 &zero_address_frag, 0);
1763
1764 ex.X_add_symbol = s;
1765 ex.X_op = O_symbol;
1766 ex.X_add_number = (max << 8) | n;
1767
1768 loongarch_make_nops (nops, worst_case_bytes);
1769
1770 fix_new_exp (frag_now, nops - frag_now->fr_literal, 0,
1771 &ex, false, BFD_RELOC_LARCH_ALIGN);
1772
1773 /* We need to start a new frag after the alignment which may be removed by
1774 the linker, to prevent the assembler from computing static offsets.
1775 This is necessary to get correct EH info. */
1776 frag_wane (frag_now);
1777 frag_new (0);
1778
1779 return true;
1780 }
1781
1782 /* Fill in an rs_align_code fragment. We want to fill 'andi $r0,$r0,0'. */
1783 void
loongarch_handle_align(fragS * fragp)1784 loongarch_handle_align (fragS *fragp)
1785 {
1786 /* char nop_opcode; */
1787 char *p;
1788 int bytes, size, excess;
1789 valueT opcode;
1790
1791 if (fragp->fr_type != rs_align_code)
1792 return;
1793
1794 struct loongarch_cl_insn nop =
1795 { .name = "andi", .arg_strs = { "$r0", "$r0", "0", NULL } };
1796
1797 get_loongarch_opcode (&nop);
1798 gas_assert (nop.all_match);
1799
1800 p = fragp->fr_literal + fragp->fr_fix;
1801 opcode = nop.insn_bin;
1802 size = 4;
1803
1804 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
1805 excess = bytes % size;
1806
1807 gas_assert (excess < 4);
1808 fragp->fr_fix += excess;
1809
1810 while (excess-- != 0)
1811 *p++ = 0;
1812
1813 md_number_to_chars (p, opcode, size);
1814 fragp->fr_var = size;
1815 }
1816
1817 /* Scan uleb128 subtraction expressions and insert fixups for them.
1818 e.g., .uleb128 .L1 - .L0
1819 Because relaxation may change the value of the subtraction, we
1820 must resolve them at link-time. */
1821
1822 static void
loongarch_insert_uleb128_fixes(bfd * abfd ATTRIBUTE_UNUSED,asection * sec,void * xxx ATTRIBUTE_UNUSED)1823 loongarch_insert_uleb128_fixes (bfd *abfd ATTRIBUTE_UNUSED,
1824 asection *sec, void *xxx ATTRIBUTE_UNUSED)
1825 {
1826 segment_info_type *seginfo = seg_info (sec);
1827 struct frag *fragP;
1828
1829 subseg_set (sec, 0);
1830
1831 for (fragP = seginfo->frchainP->frch_root;
1832 fragP; fragP = fragP->fr_next)
1833 {
1834 expressionS *exp, *exp_dup;
1835
1836 if (fragP->fr_type != rs_leb128 || fragP->fr_symbol == NULL)
1837 continue;
1838
1839 exp = symbol_get_value_expression (fragP->fr_symbol);
1840
1841 if (exp->X_op != O_subtract)
1842 continue;
1843
1844 /* FIXME: Skip for .sleb128. */
1845 if (fragP->fr_subtype != 0)
1846 continue;
1847
1848 exp_dup = xmemdup (exp, sizeof (*exp), sizeof (*exp));
1849 exp_dup->X_op = O_symbol;
1850 exp_dup->X_op_symbol = NULL;
1851
1852 exp_dup->X_add_symbol = exp->X_add_symbol;
1853 fix_new_exp (fragP, fragP->fr_fix, 0,
1854 exp_dup, 0, BFD_RELOC_LARCH_ADD_ULEB128);
1855
1856 /* From binutils/testsuite/binutils-all/dw5.S
1857 section .debug_rnglists
1858 .uleb128 .Letext0-.Ltext0 Range length (*.LLRL2)
1859 Offset Info Type Symbol's Value Symbol's Name + Addend
1860 0000000000000015 0000000200000079 R_LARCH_ADD_ULEB128 0000000000000000 .text + 2
1861 0000000000000015 000000020000007a R_LARCH_SUB_ULEB128 0000000000000000 .text + 0. */
1862
1863 /* Only the ADD_ULEB128 has X_add_number (Addend)? */
1864 exp_dup->X_add_number = 0;
1865 exp_dup->X_add_symbol = exp->X_op_symbol;
1866 fix_new_exp (fragP, fragP->fr_fix, 0,
1867 exp_dup, 0, BFD_RELOC_LARCH_SUB_ULEB128);
1868 }
1869 }
1870
1871 void
loongarch_md_finish(void)1872 loongarch_md_finish (void)
1873 {
1874 /* Insert relocations for uleb128 directives, so the values can be recomputed
1875 at link time. */
1876 if (LARCH_opts.relax)
1877 bfd_map_over_sections (stdoutput, loongarch_insert_uleb128_fixes, NULL);
1878 }
1879
1880 void
loongarch_elf_final_processing(void)1881 loongarch_elf_final_processing (void)
1882 {
1883 elf_elfheader (stdoutput)->e_flags = LARCH_opts.ase_abi;
1884 }
1885
1886 /* Compute the length of a branch sequence, and adjust the stored length
1887 accordingly. If FRAGP is NULL, the worst-case length is returned. */
1888 static unsigned
loongarch_relaxed_branch_length(fragS * fragp,asection * sec,int update)1889 loongarch_relaxed_branch_length (fragS *fragp, asection *sec, int update)
1890 {
1891 int length = 4;
1892
1893 if (!fragp)
1894 return 8;
1895
1896 if (fragp->fr_symbol != NULL
1897 && S_IS_DEFINED (fragp->fr_symbol)
1898 && !S_IS_WEAK (fragp->fr_symbol)
1899 && sec == S_GET_SEGMENT (fragp->fr_symbol))
1900 {
1901 offsetT val = S_GET_VALUE (fragp->fr_symbol) + fragp->fr_offset;
1902
1903 val -= fragp->fr_address + fragp->fr_fix;
1904
1905 if (RELAX_BRANCH_16 == fragp->fr_subtype
1906 && OUT_OF_RANGE (val, 16, 2))
1907 {
1908 length = 8;
1909 if (update)
1910 fragp->fr_subtype = RELAX_BRANCH_26;
1911 }
1912
1913 if (RELAX_BRANCH_21 == fragp->fr_subtype
1914 && OUT_OF_RANGE (val, 21, 2))
1915 {
1916 length = 8;
1917 if (update)
1918 fragp->fr_subtype = RELAX_BRANCH_26;
1919 }
1920
1921 if (RELAX_BRANCH_26 == fragp->fr_subtype)
1922 length = 8;
1923 }
1924
1925 return length;
1926 }
1927
1928 int
loongarch_relax_frag(asection * sec ATTRIBUTE_UNUSED,fragS * fragp ATTRIBUTE_UNUSED,long stretch ATTRIBUTE_UNUSED)1929 loongarch_relax_frag (asection *sec ATTRIBUTE_UNUSED,
1930 fragS *fragp ATTRIBUTE_UNUSED,
1931 long stretch ATTRIBUTE_UNUSED)
1932 {
1933 if (RELAX_BRANCH (fragp->fr_subtype))
1934 {
1935 offsetT old_var = fragp->fr_var;
1936 fragp->fr_var = loongarch_relaxed_branch_length (fragp, sec, true);
1937 return fragp->fr_var - old_var;
1938 }
1939 return 0;
1940 }
1941
1942 /* Expand far branches to multi-instruction sequences.
1943 Branch instructions:
1944 beq, bne, blt, bgt, bltz, bgtz, ble, bge, blez, bgez
1945 bltu, bgtu, bleu, bgeu
1946 beqz, bnez, bceqz, bcnez. */
1947
1948 static void
loongarch_convert_frag_branch(fragS * fragp)1949 loongarch_convert_frag_branch (fragS *fragp)
1950 {
1951 bfd_byte *buf;
1952 expressionS exp;
1953 fixS *fixp;
1954 insn_t insn;
1955
1956 buf = (bfd_byte *)fragp->fr_literal + fragp->fr_fix;
1957
1958 exp.X_op = O_symbol;
1959 exp.X_add_symbol = fragp->fr_symbol;
1960 exp.X_add_number = fragp->fr_offset;
1961
1962 gas_assert ((fragp->fr_subtype & 0xf) == fragp->fr_var);
1963
1964 /* blt $t0, $t1, .L1
1965 nop
1966 change to:
1967 bge $t0, $t1, .L2
1968 b .L1
1969 .L2:
1970 nop */
1971 switch (fragp->fr_subtype)
1972 {
1973 case RELAX_BRANCH_26:
1974 insn = bfd_getl32 (buf);
1975 /* Invert the branch condition. */
1976 if (LARCH_FLOAT_BRANCH == (insn & LARCH_BRANCH_OPCODE_MASK))
1977 insn ^= LARCH_FLOAT_BRANCH_INVERT_BIT;
1978 else
1979 insn ^= LARCH_BRANCH_INVERT_BIT;
1980 insn |= ENCODE_BRANCH16_IMM (8); /* Set target to PC + 8. */
1981 bfd_putl32 (insn, buf);
1982 buf += 4;
1983
1984 /* Add the B instruction and jump to the original target. */
1985 bfd_putl32 (LARCH_B, buf);
1986 fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
1987 4, &exp, false, BFD_RELOC_LARCH_B26);
1988 buf += 4;
1989 break;
1990 case RELAX_BRANCH_21:
1991 fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
1992 4, &exp, false, BFD_RELOC_LARCH_B21);
1993 buf += 4;
1994 break;
1995 case RELAX_BRANCH_16:
1996 fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
1997 4, &exp, false, BFD_RELOC_LARCH_B16);
1998 buf += 4;
1999 break;
2000
2001 default:
2002 abort();
2003 }
2004
2005 fixp->fx_file = fragp->fr_file;
2006 fixp->fx_line = fragp->fr_line;
2007
2008 gas_assert (buf == (bfd_byte *)fragp->fr_literal
2009 + fragp->fr_fix + fragp->fr_var);
2010
2011 fragp->fr_fix += fragp->fr_var;
2012 }
2013
2014 /* Relax a machine dependent frag. This returns the amount by which
2015 the current size of the frag should change. */
2016
2017 void
md_convert_frag(bfd * abfd ATTRIBUTE_UNUSED,segT asec ATTRIBUTE_UNUSED,fragS * fragp)2018 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec ATTRIBUTE_UNUSED,
2019 fragS *fragp)
2020 {
2021 gas_assert (RELAX_BRANCH (fragp->fr_subtype));
2022 loongarch_convert_frag_branch (fragp);
2023 }
2024