33f3e71ce2f225874ba4f9ffaa13707ece05236a
[binutils-gdb.git] / gas / config / tc-loongarch.c
1 /* tc-loongarch.c -- Assemble for the LoongArch ISA
2
3 Copyright (C) 2021-2023 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 long macro_id;
75 };
76
77 #ifndef DEFAULT_ARCH
78 #define DEFAULT_ARCH "loongarch64"
79 #endif
80
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[] = "#";
84
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[] = "#";
93
94 /* This array holds machine specific line separator characters. */
95 const char line_separator_chars[] = ";";
96
97 /* Chars that can be used to separate mant from exp in floating point nums. */
98 const char EXP_CHARS[] = "eE";
99
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";
104
105 const char *md_shortopts = "O::g::G:";
106
107 static const char default_arch[] = DEFAULT_ARCH;
108
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
113
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)
118
119 enum options
120 {
121 OPTION_IGNORE = OPTION_MD_BASE,
122
123 OPTION_ABI,
124 OPTION_FLOAT_ABI,
125
126 OPTION_FLOAT_ISA,
127
128 OPTION_LA_LOCAL_WITH_ABS,
129 OPTION_LA_GLOBAL_WITH_PCREL,
130 OPTION_LA_GLOBAL_WITH_ABS,
131 OPTION_RELAX,
132 OPTION_NO_RELAX,
133 OPTION_THIN_ADD_SUB,
134
135 OPTION_END_OF_ENUM,
136 };
137
138 struct option md_longopts[] =
139 {
140 { "mabi", required_argument, NULL, OPTION_ABI },
141
142 { "mfpu", required_argument, NULL, OPTION_FLOAT_ISA },
143
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 },
147
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},
151
152 { NULL, no_argument, NULL, 0 }
153 };
154
155 size_t md_longopts_size = sizeof (md_longopts);
156
157 int
158 md_parse_option (int c, const char *arg)
159 {
160 int ret = 1;
161 char lp64[256] = "";
162 char ilp32[256] = "";
163 unsigned char *suf = (unsigned char *)arg;
164
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;
168
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;
172
173 switch (c)
174 {
175 case OPTION_ABI:
176 if (strncasecmp (arg, "lp64", 4) == 0 && lp64[suf[4]] != 0)
177 {
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]];
185 }
186 else if (strncasecmp (arg, "ilp32", 5) == 0 && ilp32[suf[5]] != 0)
187 {
188 LARCH_opts.ase_abi = ilp32[suf[5]];
189 LARCH_opts.ase_ilp32 = 1;
190 }
191 else
192 ret = 0;
193 break;
194
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)
201 {
202 LARCH_opts.ase_sf = 1;
203 LARCH_opts.ase_df = 1;
204 }
205 else
206 ret = 0;
207 break;
208
209 case OPTION_LA_LOCAL_WITH_ABS:
210 LARCH_opts.ase_labs = 1;
211 break;
212
213 case OPTION_LA_GLOBAL_WITH_PCREL:
214 LARCH_opts.ase_gpcr = 1;
215 break;
216
217 case OPTION_LA_GLOBAL_WITH_ABS:
218 LARCH_opts.ase_gabs = 1;
219 break;
220
221 case OPTION_RELAX:
222 LARCH_opts.relax = 1;
223 break;
224
225 case OPTION_NO_RELAX:
226 LARCH_opts.relax = 0;
227 break;
228
229 case OPTION_THIN_ADD_SUB:
230 LARCH_opts.thin_add_sub = 1;
231 break;
232
233 case OPTION_IGNORE:
234 break;
235
236 default:
237 ret = 0;
238 break;
239 }
240 return ret;
241 }
242
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;
255
256 void
257 loongarch_after_parse_args ()
258 {
259 /* Set default ABI/ISA LP64D. */
260 if (!LARCH_opts.ase_ilp32)
261 {
262 if (strcmp (default_arch, "loongarch64") == 0)
263 {
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;
271 }
272 else if (strcmp (default_arch, "loongarch32") == 0)
273 {
274 LARCH_opts.ase_abi = EF_LOONGARCH_ABI_DOUBLE_FLOAT;
275 LARCH_opts.ase_ilp32 = 1;
276 }
277 else
278 as_bad ("unknown default architecture `%s'", default_arch);
279 }
280
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)
286 {
287 LARCH_opts.ase_sf = 1;
288 LARCH_opts.ase_df = 1;
289 }
290
291 size_t i;
292
293 assert(LARCH_opts.ase_ilp32);
294
295 /* Init ilp32/lp64 registers names. */
296 if (!r_htab)
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);
301
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);
305
306 if (!cr_htab)
307 cr_htab = str_htab_create (), str_hash_insert (cr_htab, "", 0, 0);
308
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);
311
312 /* Init single/double float registers names. */
313 if (LARCH_opts.ase_sf || LARCH_opts.ase_df)
314 {
315 if (!f_htab)
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);
320
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),
324 0);
325
326 if (!fc_htab)
327 fc_htab = str_htab_create (), str_hash_insert (fc_htab, "", 0, 0);
328
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),
331 0);
332
333 if (!fcn_htab)
334 fcn_htab = str_htab_create (), str_hash_insert (fcn_htab, "", 0, 0);
335
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),
338 0);
339
340 if (!c_htab)
341 c_htab = str_htab_create (), str_hash_insert (c_htab, "", 0, 0);
342
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),
345 0);
346
347 }
348
349 /* Init lsx registers names. */
350 if (LARCH_opts.ase_lsx)
351 {
352 if (!v_htab)
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),
356 0);
357 }
358
359 /* Init lasx registers names. */
360 if (LARCH_opts.ase_lasx)
361 {
362 if (!x_htab)
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),
366 0);
367 }
368
369 /* Init lp64 registers alias. */
370 if (LARCH_opts.ase_lp64)
371 {
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),
375 0);
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);
379 }
380
381 /* Init float-lp64 registers alias */
382 if ((LARCH_opts.ase_sf || LARCH_opts.ase_df) && LARCH_opts.ase_lp64)
383 {
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);
391 }
392 }
393
394 const char *
395 loongarch_target_format ()
396 {
397 return LARCH_opts.ase_lp64 ? "elf64-loongarch" : "elf32-loongarch";
398 }
399
400 void
401 md_begin ()
402 {
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++)
407 {
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 "
413 "macro is NULL"),
414 it->name, it->format);
415 if (it->macro
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);
419 }
420
421 /* FIXME: expressionS use 'offsetT' as constant,
422 * we want this is 64-bit type. */
423 assert (8 <= sizeof (offsetT));
424 }
425
426 unsigned long
427 loongarch_mach (void)
428 {
429 return LARCH_opts.ase_lp64 ? bfd_mach_loongarch64 : bfd_mach_loongarch32;
430 }
431
432 static const expressionS const_0 = { .X_op = O_constant, .X_add_number = 0 };
433
434 static void
435 s_loongarch_align (int arg)
436 {
437 const char *t = input_line_pointer;
438 while (!is_end_of_line[(unsigned char) *t] && *t != ',')
439 ++t;
440 if (*t == ',')
441 s_align_ptwo (arg);
442 else
443 s_align_ptwo (0);
444 }
445
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. */
449
450 static void
451 s_dtprel (int bytes)
452 {
453 expressionS ex;
454 char *p;
455
456 expression (&ex);
457
458 if (ex.X_op != O_symbol)
459 {
460 as_bad (_("Unsupported use of %s"),
461 (bytes == 8 ? ".dtpreldword" : ".dtprelword"));
462 ignore_rest_of_line ();
463 }
464
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,
468 (bytes == 8
469 ? BFD_RELOC_LARCH_TLS_DTPREL64
470 : BFD_RELOC_LARCH_TLS_DTPREL32));
471
472 demand_empty_rest_of_line ();
473 }
474
475 static const pseudo_typeS loongarch_pseudo_table[] =
476 {
477 { "align", s_loongarch_align, -4 },
478 { "dword", cons, 8 },
479 { "word", cons, 4 },
480 { "half", cons, 2 },
481 { "dtprelword", s_dtprel, 4 },
482 { "dtpreldword", s_dtprel, 8 },
483 { NULL, NULL, 0 },
484 };
485
486 void
487 loongarch_pop_insert (void)
488 {
489 pop_insert (loongarch_pseudo_table);
490 }
491
492 #define INTERNAL_LABEL_SPECIAL 10
493 static unsigned long internal_label_count[INTERNAL_LABEL_SPECIAL] = { 0 };
494
495 static const char *
496 loongarch_internal_label_name (unsigned long label, int augend)
497 {
498 static char symbol_name_build[24];
499 unsigned long want_label;
500 char *p;
501
502 want_label = internal_label_count[label] + augend;
503
504 p = symbol_name_build;
505 #ifdef LOCAL_LABEL_PREFIX
506 *p++ = LOCAL_LABEL_PREFIX;
507 #endif
508 *p++ = 'L';
509 for (; label; label /= 10)
510 *p++ = label % 10 + '0';
511 /* Make sure internal label never belong to normal label namespace. */
512 *p++ = ':';
513 for (; want_label; want_label /= 10)
514 *p++ = want_label % 10 + '0';
515 *p++ = '\0';
516 return symbol_name_build;
517 }
518
519 static void
520 setup_internal_label_here (unsigned long label)
521 {
522 assert (label < INTERNAL_LABEL_SPECIAL);
523 internal_label_count[label]++;
524 colon (loongarch_internal_label_name (label, 0));
525 }
526
527 void
528 get_internal_label (expressionS *label_expr, unsigned long label,
529 int augend /* 0 for previous, 1 for next. */)
530 {
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;
537 }
538
539 static int
540 is_internal_label (const char *c_str)
541 {
542 do
543 {
544 if (*c_str != ':')
545 break;
546 c_str++;
547 if (!('0' <= *c_str && *c_str <= '9'))
548 break;
549 while ('0' <= *c_str && *c_str <= '9')
550 c_str++;
551 if (*c_str != 'b' && *c_str != 'f')
552 break;
553 c_str++;
554 return *c_str == '\0';
555 }
556 while (0);
557 return 0;
558 }
559
560 static int
561 is_label (const char *c_str)
562 {
563 if (is_internal_label (c_str))
564 return 1;
565 else if ('0' <= *c_str && *c_str <= '9')
566 {
567 /* [0-9]+[bf] */
568 while ('0' <= *c_str && *c_str <= '9')
569 c_str++;
570 return *c_str == 'b' || *c_str == 'f';
571 }
572 else if (is_name_beginner (*c_str))
573 {
574 /* [a-zA-Z\._\$][0-9a-zA-Z\._\$]* */
575 c_str++;
576 while (is_part_of_name (*c_str))
577 c_str++;
578 return *c_str == '\0';
579 }
580 else
581 return 0;
582 }
583
584 static int
585 is_label_with_addend (const char *c_str)
586 {
587 if (is_internal_label (c_str))
588 return 1;
589 else if ('0' <= *c_str && *c_str <= '9')
590 {
591 /* [0-9]+[bf] */
592 while ('0' <= *c_str && *c_str <= '9')
593 c_str++;
594 if (*c_str == 'b' || *c_str == 'f')
595 c_str++;
596 else
597 return 0;
598 return *c_str == '\0'
599 || ((*c_str == '-' || *c_str == '+')
600 && is_unsigned (c_str + 1));
601 }
602 else if (is_name_beginner (*c_str))
603 {
604 /* [a-zA-Z\._\$][0-9a-zA-Z\._\$]* */
605 c_str++;
606 while (is_part_of_name (*c_str))
607 c_str++;
608 return *c_str == '\0'
609 || ((*c_str == '-' || *c_str == '+')
610 && is_unsigned (c_str + 1));
611 }
612 else
613 return 0;
614 }
615
616 static int32_t
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)
620 {
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;
625
626 if (!ip->match_now)
627 return 0;
628
629 switch (esc_ch1)
630 {
631 case 'l':
632 switch (esc_ch2)
633 {
634 default:
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."));
638 break;
639 case 'a':
640 ip->match_now = is_label_with_addend (arg);
641 break;
642 }
643 break;
644 case 's':
645 case 'u':
646 ip->match_now =
647 loongarch_parse_expr (arg, ip->reloc_info + ip->reloc_num,
648 reloc_num_we_have, &reloc_num, &imm) == 0;
649
650 if (!ip->match_now)
651 break;
652
653 ret = imm;
654 if (reloc_num)
655 {
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. */);
660 if (esc_ch1 == 'u')
661 {
662 if (strncmp (bit_field, "10:12", strlen ("10:12")) == 0)
663 reloc_type = BFD_RELOC_LARCH_SOP_POP_32_U_10_12;
664 }
665 else if (esc_ch1 == 's')
666 {
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;
683 }
684 if (reloc_type == BFD_RELOC_NONE)
685 as_fatal (
686 _("not support reloc bit-field\nfmt: %c%c %s\nargs: %s"),
687 esc_ch1, esc_ch2, bit_field, arg);
688
689 if (ip->reloc_info[0].type >= BFD_RELOC_LARCH_B16
690 && ip->reloc_info[0].type < BFD_RELOC_LARCH_64_PCREL)
691 {
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;
697
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))
703 {
704 ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_RELAX;
705 ip->reloc_info[ip->reloc_num].value = const_0;
706 ip->reloc_num++;
707 }
708 break;
709 }
710 reloc_num++;
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;
714 }
715 break;
716 case 'r':
717 imm = (intptr_t) str_hash_find (r_htab, arg);
718 ip->match_now = 0 < imm;
719 ret = imm - 1;
720 if (ip->match_now)
721 break;
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;
725 ret = imm - 1;
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]);
729 break;
730 case 'f':
731 switch (esc_ch2)
732 {
733 case 'c':
734 imm = (intptr_t) str_hash_find (fc_htab, arg);
735 if (0 >= imm)
736 {
737 imm = (intptr_t) str_hash_find (fcn_htab, arg);
738 }
739 break;
740 default:
741 imm = (intptr_t) str_hash_find (f_htab, arg);
742 }
743 ip->match_now = 0 < imm;
744 ret = imm - 1;
745 if (ip->match_now && !ip->macro_id)
746 break;
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;
750 ret = imm - 1;
751 if (ip->match_now)
752 as_warn (_("register alias %s is deprecated, use %s instead"),
753 arg, f_abi_names[ret]);
754 break;
755 case 'c':
756 switch (esc_ch2)
757 {
758 case 'r':
759 imm = (intptr_t) str_hash_find (cr_htab, arg);
760 break;
761 default:
762 imm = (intptr_t) str_hash_find (c_htab, arg);
763 }
764 ip->match_now = 0 < imm;
765 ret = imm - 1;
766 break;
767 case 'v':
768 imm = (intptr_t) str_hash_find (v_htab, arg);
769 ip->match_now = 0 < imm;
770 ret = imm - 1;
771 break;
772 case 'x':
773 imm = (intptr_t) str_hash_find (x_htab, arg);
774 ip->match_now = 0 < imm;
775 ret = imm - 1;
776 break;
777 case '\0':
778 ip->all_match = ip->match_now;
779 ip->insn_length =
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;
783 break;
784 default:
785 as_fatal (_("unknown escape"));
786 }
787
788 do
789 {
790 /* Check imm overflow. */
791 int bit_width, bits_needed_s, bits_needed_u;
792 char *t;
793
794 if (!ip->match_now)
795 break;
796
797 if (0 < reloc_num)
798 break;
799
800 bit_width = loongarch_get_bit_field_width (bit_field, &t);
801
802 if (bit_width == -1)
803 /* No specify bit width. */
804 break;
805
806 imm = ret;
807 if (t[0] == '<' && t[1] == '<')
808 {
809 int i = strtol (t += 2, &t, 10), j;
810 for (j = i; 0 < j; j--, imm >>= 1)
811 if (imm & 1)
812 as_fatal (_("require imm low %d bit is 0."), i);
813 }
814
815 if (*t == '+')
816 imm -= strtol (t, &t, 10);
817
818 bits_needed_s = loongarch_bits_imm_needed (imm, 1);
819 bits_needed_u = loongarch_bits_imm_needed (imm, 0);
820
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"
825 "format: %c%c%s\n"
826 "arg: %s"),
827 esc_ch1, esc_ch2, bit_field, arg);
828 }
829 while (0);
830
831 if (esc_ch1 != '\0')
832 {
833 ip->args[ip->arg_num] = ret;
834 ip->arg_num++;
835 }
836 return ret;
837 }
838
839 static void
840 get_loongarch_opcode (struct loongarch_cl_insn *insn)
841 {
842 const struct loongarch_opcode *it;
843 struct loongarch_ase *ase;
844 for (ase = loongarch_ASEs; ase->enabled; ase++)
845 {
846 if (!*ase->enabled || (ase->include && !*ase->include)
847 || (ase->exclude && *ase->exclude))
848 continue;
849
850 if (!ase->name_hash_entry)
851 {
852 ase->name_hash_entry = str_htab_create ();
853 for (it = ase->opcodes; it->name; it++)
854 {
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,
859 (void *) it, 0);
860 }
861 }
862
863 if ((it = str_hash_find (ase->name_hash_entry, insn->name)) == NULL)
864 continue;
865
866 do
867 {
868 insn->insn = it;
869 insn->match_now = 1;
870 insn->all_match = 0;
871 insn->arg_num = 0;
872 insn->reloc_num = 0;
873 insn->insn_bin = (loongarch_foreach_args
874 (it->format, insn->arg_strs,
875 loongarch_args_parser_can_match_arg_helper,
876 insn));
877 if (insn->all_match && !(it->include && !*it->include)
878 && !(it->exclude && *it->exclude))
879 {
880 insn->insn_bin |= it->match;
881 return;
882 }
883 it++;
884 }
885 while (it->name && strcasecmp (it->name, insn->name) == 0);
886 }
887 }
888
889 static int
890 check_this_insn_before_appending (struct loongarch_cl_insn *ip)
891 {
892 int ret = 0;
893
894 if (strncmp (ip->name, "la.abs", 6) == 0)
895 {
896 ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_MARK_LA;
897 ip->reloc_info[ip->reloc_num].value = const_0;
898 ip->reloc_num++;
899 }
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))
907 {
908 /* For AMO insn amswap.[wd], amadd.[wd], etc. */
909 if (ip->args[0] != 0
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"));
913 }
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))
920 {
921 /* For bstr(ins|pick).[wd]. */
922 if (ip->args[2] < ip->args[3])
923 as_fatal (_("bstr(ins|pick).[wd] require msbd >= lsbd"));
924 }
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"));
929
930 return ret;
931 }
932
933 static void
934 install_insn (const struct loongarch_cl_insn *insn)
935 {
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);
939 }
940
941 static void
942 move_insn (struct loongarch_cl_insn *insn, fragS *frag, long where)
943 {
944 size_t i;
945 insn->frag = frag;
946 insn->where = where;
947 for (i = 0; i < insn->reloc_num; i++)
948 {
949 if (insn->fixp[i])
950 {
951 insn->fixp[i]->fx_frag = frag;
952 insn->fixp[i]->fx_where = where;
953 }
954 }
955 install_insn (insn);
956 }
957
958 /* Add INSN to the end of the output. */
959 static void
960 append_fixed_insn (struct loongarch_cl_insn *insn)
961 {
962 char *f = frag_more (insn->insn_length);
963 move_insn (insn, frag_now, f - frag_now->fr_literal);
964 }
965
966 /* Add instructions based on the worst-case scenario firstly. */
967 static void
968 append_relaxed_branch_insn (struct loongarch_cl_insn *insn, int max_chars,
969 int var, relax_substateT subtype, symbolS *symbol, offsetT offset)
970 {
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);
975 }
976
977 static void
978 append_fixp_and_insn (struct loongarch_cl_insn *ip)
979 {
980 reloc_howto_type *howto;
981 bfd_reloc_code_real_type r_type;
982 struct reloc_info *reloc_info = ip->reloc_info;
983 size_t i;
984
985 dwarf2_emit_insn (0);
986
987 for (i = 0; i < ip->reloc_num; i++)
988 {
989 r_type = reloc_info[i].type;
990
991 if (r_type != BFD_RELOC_UNUSED)
992 {
993
994 gas_assert (&(reloc_info[i].value));
995 if (BFD_RELOC_LARCH_B16 == r_type || BFD_RELOC_LARCH_B21 == r_type)
996 {
997 int min_bytes = 4; /* One branch instruction. */
998 unsigned max_bytes = 8; /* Branch and jump instructions. */
999
1000 if (now_seg == absolute_section)
1001 {
1002 as_bad (_("relaxable branches not supported in absolute section"));
1003 return;
1004 }
1005
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);
1010 return;
1011 }
1012 else
1013 {
1014 howto = bfd_reloc_type_lookup (stdoutput, r_type);
1015 if (howto == NULL)
1016 as_fatal (_("no HOWTO loong relocation number %d"), r_type);
1017
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);
1021 }
1022 }
1023 }
1024
1025 if (ip->insn_length < ip->relax_max_length)
1026 as_fatal (_("Internal error: not support relax now"));
1027 else
1028 append_fixed_insn (ip);
1029
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.
1033
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))
1041 {
1042 frag_wane (frag_now);
1043 frag_new (0);
1044 }
1045 }
1046
1047 /* Ask helper for returning a malloced c_str or NULL. */
1048 static char *
1049 assember_macro_helper (const char *const args[], void *context_ptr)
1050 {
1051 struct loongarch_cl_insn *insn = context_ptr;
1052 char *ret = NULL;
1053 if ( strcmp (insn->name, "li.w") == 0 || strcmp (insn->name, "li.d") == 0)
1054 {
1055 char args_buf[50], insns_buf[200];
1056 const char *arg_strs[6];
1057 uint32_t hi32, lo32;
1058
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;
1063
1064 lo32 = insn->args[1] & 0xffffffff;
1065 hi32 = insn->args[1] >> 32;
1066
1067 if (strcmp (insn->name, "li.w") == 0)
1068 {
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;
1072 }
1073
1074 if (strcmp (insn->name, "li.d") == 0 && !LARCH_opts.ase_lp64)
1075 as_fatal (_("we can't li.d on 32bit-arch"));
1076
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);
1081
1082 all0_bit_vec =
1083 ((((hi32 & 0xfff00000) == 0) << 3) | (((hi32 & 0x000fffff) == 0) << 2)
1084 | (((lo32 & 0xfffff000) == 0) << 1) | ((lo32 & 0x00000fff) == 0));
1085 sign_bit_vec =
1086 ((((hi32 & 0x80000000) != 0) << 3) | (((hi32 & 0x00080000) != 0) << 2)
1087 | (((lo32 & 0x80000000) != 0) << 1) | ((lo32 & 0x00000800) != 0));
1088 allf_bit_vec =
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));
1095
1096 static const char *const li_32bit[] =
1097 {
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;",
1101 "or %5,$r0,$r0;",
1102 };
1103 static const char *const li_hi_32bit[] =
1104 {
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;",
1109 "",
1110 };
1111 do
1112 {
1113 insns_buf[0] = '\0';
1114 if (paritial_is_sext_of_prev == 0x7)
1115 {
1116 strcat (insns_buf, "lu52i.d %5,$r0,%1&0x800?%1-0x1000:%1;");
1117 break;
1118 }
1119 if ((all0_bit_vec & 0x3) == 0x2)
1120 strcat (insns_buf, "ori %5,$r0,%4;");
1121 else
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]);
1124 }
1125 while (0);
1126
1127 ret = loongarch_expand_macro (insns_buf, arg_strs, NULL, NULL,
1128 sizeof (args_buf));
1129 }
1130
1131 return ret;
1132 }
1133
1134 /* Accept instructions separated by ';'
1135 * assuming 'not starting with space and not ending with space' or pass in
1136 * empty c_str. */
1137 static void
1138 loongarch_assemble_INSNs (char *str, struct loongarch_cl_insn *ctx)
1139 {
1140 char *rest;
1141 size_t len_str = strlen(str);
1142
1143 for (rest = str; *rest != ';' && *rest != '\0'; rest++);
1144 if (*rest == ';')
1145 *rest++ = '\0';
1146
1147 if (*str == ':')
1148 {
1149 str++;
1150 setup_internal_label_here (strtol (str, &str, 10));
1151 str++;
1152 }
1153
1154 do
1155 {
1156 if (*str == '\0')
1157 break;
1158
1159 struct loongarch_cl_insn the_one = { 0 };
1160 the_one.name = str;
1161 the_one.macro_id = ctx->macro_id;
1162
1163 for (; *str && *str != ' '; str++)
1164 ;
1165 if (*str == ' ')
1166 *str++ = '\0';
1167
1168 loongarch_split_args_by_comma (str, the_one.arg_strs);
1169 get_loongarch_opcode (&the_one);
1170
1171 if (!the_one.all_match)
1172 {
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 : "");
1175 free(ss);
1176 return;
1177 }
1178
1179 if (check_this_insn_before_appending (&the_one) != 0)
1180 break;
1181
1182 append_fixp_and_insn (&the_one);
1183 if (the_one.insn_length == 0 && the_one.insn->macro)
1184 {
1185 the_one.macro_id = 1;
1186
1187 char *c_str = loongarch_expand_macro (the_one.insn->macro,
1188 the_one.arg_strs,
1189 assember_macro_helper,
1190 &the_one, len_str);
1191 loongarch_assemble_INSNs (c_str, &the_one);
1192 free (c_str);
1193 }
1194 }
1195 while (0);
1196
1197 if (*rest != '\0')
1198 loongarch_assemble_INSNs (rest, ctx);
1199 }
1200
1201 void
1202 md_assemble (char *str)
1203 {
1204 struct loongarch_cl_insn the_one = { 0 };
1205 loongarch_assemble_INSNs (str, &the_one);
1206 }
1207
1208 const char *
1209 md_atof (int type, char *litP, int *sizeP)
1210 {
1211 return ieee_md_atof (type, litP, sizeP, FALSE);
1212 }
1213
1214 void
1215 md_number_to_chars (char *buf, valueT val, int n)
1216 {
1217 number_to_chars_littleendian (buf, val, n);
1218 }
1219
1220 /* The location from which a PC relative jump should be calculated,
1221 given a PC relative reloc. */
1222 long
1223 md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
1224 {
1225 return 0;
1226 }
1227
1228 static void fix_reloc_insn (fixS *fixP, bfd_vma reloc_val, char *buf)
1229 {
1230 reloc_howto_type *howto;
1231 insn_t insn;
1232 howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
1233
1234 insn = bfd_getl32 (buf);
1235
1236 if (!loongarch_adjust_reloc_bitsfield (NULL, howto, &reloc_val))
1237 as_bad_where (fixP->fx_file, fixP->fx_line, "Reloc overflow");
1238
1239 insn = (insn & (insn_t)howto->src_mask)
1240 | ((insn & (~(insn_t)howto->dst_mask)) | reloc_val);
1241
1242 bfd_putl32 (insn, buf);
1243 }
1244
1245 void
1246 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
1247 {
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;
1251 segT sub_segment;
1252 last_reloc_is_sop_push_pcrel_1 = 0;
1253
1254 char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
1255 switch (fixP->fx_r_type)
1256 {
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);
1281 break;
1282
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"));
1287
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));
1292 else
1293 stack_top = 0;
1294 break;
1295
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)
1306 break;
1307
1308 fix_reloc_insn (fixP, (bfd_vma)stack_top, buf);
1309 break;
1310
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
1317 R_LARCH_64/32.
1318
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)). */
1327 case BFD_RELOC_64:
1328 case BFD_RELOC_32:
1329 if (fixP->fx_pcrel)
1330 {
1331 switch (fixP->fx_r_type)
1332 {
1333 case BFD_RELOC_64:
1334 fixP->fx_r_type = BFD_RELOC_LARCH_64_PCREL;
1335 break;
1336 case BFD_RELOC_32:
1337 fixP->fx_r_type = BFD_RELOC_LARCH_32_PCREL;
1338 break;
1339 default:
1340 break;
1341 }
1342 }
1343
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
1346 initial location.
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)
1355 {
1356 fixP->fx_r_type = BFD_RELOC_LARCH_32_PCREL;
1357 fixP->fx_subsy = NULL;
1358 break;
1359 }
1360
1361 if (fixP->fx_addsy && fixP->fx_subsy)
1362 {
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;
1368
1369 switch (fixP->fx_r_type)
1370 {
1371 case BFD_RELOC_64:
1372 fixP->fx_r_type = BFD_RELOC_LARCH_ADD64;
1373 fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB64;
1374 break;
1375 case BFD_RELOC_32:
1376 fixP->fx_r_type = BFD_RELOC_LARCH_ADD32;
1377 fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB32;
1378 break;
1379 default:
1380 break;
1381 }
1382
1383 md_number_to_chars (buf, 0, fixP->fx_size);
1384 }
1385
1386 if (fixP->fx_addsy == NULL)
1387 {
1388 fixP->fx_done = 1;
1389 md_number_to_chars (buf, *valP, fixP->fx_size);
1390 }
1391 break;
1392
1393 case BFD_RELOC_24:
1394 case BFD_RELOC_16:
1395 case BFD_RELOC_8:
1396 if (fixP->fx_addsy)
1397 {
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;
1403
1404 switch (fixP->fx_r_type)
1405 {
1406 case BFD_RELOC_24:
1407 fixP->fx_r_type = BFD_RELOC_LARCH_ADD24;
1408 fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB24;
1409 break;
1410 case BFD_RELOC_16:
1411 fixP->fx_r_type = BFD_RELOC_LARCH_ADD16;
1412 fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB16;
1413 break;
1414 case BFD_RELOC_8:
1415 fixP->fx_r_type = BFD_RELOC_LARCH_ADD8;
1416 fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB8;
1417 break;
1418 default:
1419 break;
1420 }
1421
1422 md_number_to_chars (buf, 0, fixP->fx_size);
1423
1424 if (fixP->fx_next->fx_addsy == NULL)
1425 fixP->fx_next->fx_done = 1;
1426 }
1427
1428 if (fixP->fx_addsy == NULL)
1429 {
1430 fixP->fx_done = 1;
1431 md_number_to_chars (buf, *valP, fixP->fx_size);
1432 }
1433 break;
1434
1435 case BFD_RELOC_LARCH_CFA:
1436 if (fixP->fx_addsy && fixP->fx_subsy)
1437 {
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;
1443
1444 unsigned int subtype;
1445 offsetT loc;
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);
1449 switch (subtype)
1450 {
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);
1457 break;
1458
1459 case DW_CFA_advance_loc2:
1460 fixP->fx_size = 2;
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);
1467 break;
1468
1469 case DW_CFA_advance_loc4:
1470 fixP->fx_size = 4;
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);
1477 break;
1478
1479 default:
1480 if (subtype < 0x80 && (subtype & 0x40))
1481 {
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);
1488 }
1489 else
1490 as_fatal (_("internal: bad CFA value #%d"), subtype);
1491 break;
1492 }
1493 }
1494 break;
1495
1496 case BFD_RELOC_LARCH_B16:
1497 case BFD_RELOC_LARCH_B21:
1498 case BFD_RELOC_LARCH_B26:
1499 if (fixP->fx_addsy == NULL)
1500 {
1501 as_bad_where (fixP->fx_file, fixP->fx_line,
1502 _ ("Relocation against a constant."));
1503 }
1504 if (S_GET_SEGMENT (fixP->fx_addsy) == seg
1505 && !S_FORCE_RELOC (fixP->fx_addsy, 1))
1506 {
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);
1510
1511 /* If relax, symbol value may change at link time, so reloc need to
1512 be saved. */
1513 if (!LARCH_opts.relax)
1514 fixP->fx_done = 1;
1515 }
1516 break;
1517
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:
1522 {
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);
1528 *endp = 0;
1529 break;
1530 }
1531
1532 default:
1533 break;
1534 }
1535 }
1536
1537 int
1538 md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED,
1539 asection *segtype ATTRIBUTE_UNUSED)
1540 {
1541 return (fragp->fr_var = 4);
1542 }
1543
1544 /* Translate internal representation of relocation info to BFD target
1545 format. */
1546 arelent *
1547 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
1548 {
1549 arelent *reloc = (arelent *) xmalloc (sizeof (arelent));
1550
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;
1555
1556 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
1557 if (reloc->howto == NULL)
1558 {
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));
1562 return NULL;
1563 }
1564
1565 return reloc;
1566 }
1567
1568 /* Standard calling conventions leave the CFA at SP on entry. */
1569 void
1570 loongarch_cfi_frame_initial_instructions (void)
1571 {
1572 cfi_add_CFA_def_cfa_register (3 /* $sp */);
1573 }
1574
1575 void
1576 loongarch_pre_output_hook (void)
1577 {
1578 const frchainS *frch;
1579 segT s;
1580
1581 if (!LARCH_opts.relax)
1582 return;
1583
1584 /* Save the current segment info. */
1585 segT seg = now_seg;
1586 subsegT subseg = now_subseg;
1587
1588 for (s = stdoutput->sections; s; s = s->next)
1589 for (frch = seg_info (s)->frchainP; frch; frch = frch->frch_next)
1590 {
1591 fragS *frag;
1592
1593 for (frag = frch->frch_root; frag; frag = frag->fr_next)
1594 {
1595 if (frag->fr_type == rs_cfa)
1596 {
1597 expressionS exp;
1598 expressionS *symval;
1599
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;
1605
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);
1609
1610 fix_new_exp (frag, (int) frag->fr_offset, 1, &exp, 0,
1611 BFD_RELOC_LARCH_CFA);
1612 }
1613 }
1614 }
1615
1616 /* Restore the original segment info. */
1617 subseg_set (seg, subseg);
1618 }
1619
1620 void
1621 tc_loongarch_parse_to_dw2regnum (expressionS *exp)
1622 {
1623 expression_and_evaluate (exp);
1624 }
1625
1626 void
1627 md_show_usage (FILE *stream)
1628 {
1629 fprintf (stream, _("LARCH options:\n"));
1630 /* FIXME */
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"));
1636 }
1637
1638 static void
1639 loongarch_make_nops (char *buf, bfd_vma bytes)
1640 {
1641 bfd_vma i = 0;
1642
1643 /* Fill with 4-byte NOPs. */
1644 for ( ; i < bytes; i += 4)
1645 number_to_chars_littleendian (buf + i, LARCH_NOP, 4);
1646 }
1647
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. */
1652
1653 bool
1654 loongarch_frag_align_code (int n)
1655 {
1656 bfd_vma bytes = (bfd_vma) 1 << n;
1657 bfd_vma insn_alignment = 4;
1658 bfd_vma worst_case_bytes = bytes - insn_alignment;
1659 char *nops;
1660 expressionS ex;
1661
1662 /* If we are moving to a smaller alignment than the instruction size, then no
1663 alignment is required. */
1664 if (bytes <= insn_alignment)
1665 return true;
1666
1667 /* When not relaxing, loongarch_handle_align handles code alignment. */
1668 if (!LARCH_opts.relax)
1669 return false;
1670
1671 nops = frag_more (worst_case_bytes);
1672
1673 ex.X_op = O_constant;
1674 ex.X_add_number = worst_case_bytes;
1675
1676 loongarch_make_nops (nops, worst_case_bytes);
1677
1678 fix_new_exp (frag_now, nops - frag_now->fr_literal, 0,
1679 &ex, false, BFD_RELOC_LARCH_ALIGN);
1680
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);
1685 frag_new (0);
1686
1687 return true;
1688 }
1689
1690 /* Fill in an rs_align_code fragment. We want to fill 'andi $r0,$r0,0'. */
1691 void
1692 loongarch_handle_align (fragS *fragp)
1693 {
1694 /* char nop_opcode; */
1695 char *p;
1696 int bytes, size, excess;
1697 valueT opcode;
1698
1699 if (fragp->fr_type != rs_align_code)
1700 return;
1701
1702 struct loongarch_cl_insn nop =
1703 { .name = "andi", .arg_strs = { "$r0", "$r0", "0", NULL } };
1704
1705 get_loongarch_opcode (&nop);
1706 gas_assert (nop.all_match);
1707
1708 p = fragp->fr_literal + fragp->fr_fix;
1709 opcode = nop.insn_bin;
1710 size = 4;
1711
1712 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
1713 excess = bytes % size;
1714
1715 gas_assert (excess < 4);
1716 fragp->fr_fix += excess;
1717
1718 while (excess-- != 0)
1719 *p++ = 0;
1720
1721 md_number_to_chars (p, opcode, size);
1722 fragp->fr_var = size;
1723 }
1724
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. */
1729
1730 static void
1731 loongarch_insert_uleb128_fixes (bfd *abfd ATTRIBUTE_UNUSED,
1732 asection *sec, void *xxx ATTRIBUTE_UNUSED)
1733 {
1734 segment_info_type *seginfo = seg_info (sec);
1735 struct frag *fragP;
1736
1737 subseg_set (sec, 0);
1738
1739 for (fragP = seginfo->frchainP->frch_root;
1740 fragP; fragP = fragP->fr_next)
1741 {
1742 expressionS *exp, *exp_dup;
1743
1744 if (fragP->fr_type != rs_leb128 || fragP->fr_symbol == NULL)
1745 continue;
1746
1747 exp = symbol_get_value_expression (fragP->fr_symbol);
1748
1749 if (exp->X_op != O_subtract)
1750 continue;
1751
1752 /* FIXME: Skip for .sleb128. */
1753 if (fragP->fr_subtype != 0)
1754 continue;
1755
1756 exp_dup = xmemdup (exp, sizeof (*exp), sizeof (*exp));
1757 exp_dup->X_op = O_symbol;
1758 exp_dup->X_op_symbol = NULL;
1759
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);
1763
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. */
1770
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);
1776 }
1777 }
1778
1779 void
1780 loongarch_md_finish (void)
1781 {
1782 /* Insert relocations for uleb128 directives, so the values can be recomputed
1783 at link time. */
1784 if (LARCH_opts.relax)
1785 bfd_map_over_sections (stdoutput, loongarch_insert_uleb128_fixes, NULL);
1786 }
1787
1788 void
1789 loongarch_elf_final_processing (void)
1790 {
1791 elf_elfheader (stdoutput)->e_flags = LARCH_opts.ase_abi;
1792 }
1793
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. */
1796 static unsigned
1797 loongarch_relaxed_branch_length (fragS *fragp, asection *sec, int update)
1798 {
1799 int length = 4;
1800
1801 if (!fragp)
1802 return 8;
1803
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))
1808 {
1809 offsetT val = S_GET_VALUE (fragp->fr_symbol) + fragp->fr_offset;
1810
1811 val -= fragp->fr_address + fragp->fr_fix;
1812
1813 if (RELAX_BRANCH_16 == fragp->fr_subtype
1814 && OUT_OF_RANGE (val, 16, 2))
1815 {
1816 length = 8;
1817 if (update)
1818 fragp->fr_subtype = RELAX_BRANCH_26;
1819 }
1820
1821 if (RELAX_BRANCH_21 == fragp->fr_subtype
1822 && OUT_OF_RANGE (val, 21, 2))
1823 {
1824 length = 8;
1825 if (update)
1826 fragp->fr_subtype = RELAX_BRANCH_26;
1827 }
1828
1829 if (RELAX_BRANCH_26 == fragp->fr_subtype)
1830 length = 8;
1831 }
1832
1833 return length;
1834 }
1835
1836 int
1837 loongarch_relax_frag (asection *sec ATTRIBUTE_UNUSED,
1838 fragS *fragp ATTRIBUTE_UNUSED,
1839 long stretch ATTRIBUTE_UNUSED)
1840 {
1841 if (RELAX_BRANCH (fragp->fr_subtype))
1842 {
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;
1846 }
1847 return 0;
1848 }
1849
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. */
1855
1856 static void
1857 loongarch_convert_frag_branch (fragS *fragp)
1858 {
1859 bfd_byte *buf;
1860 expressionS exp;
1861 fixS *fixp;
1862 insn_t insn;
1863
1864 buf = (bfd_byte *)fragp->fr_literal + fragp->fr_fix;
1865
1866 exp.X_op = O_symbol;
1867 exp.X_add_symbol = fragp->fr_symbol;
1868 exp.X_add_number = fragp->fr_offset;
1869
1870 gas_assert ((fragp->fr_subtype & 0xf) == fragp->fr_var);
1871
1872 /* blt $t0, $t1, .L1
1873 nop
1874 change to:
1875 bge $t0, $t1, .L2
1876 b .L1
1877 .L2:
1878 nop */
1879 switch (fragp->fr_subtype)
1880 {
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;
1886 else
1887 insn ^= LARCH_BRANCH_INVERT_BIT;
1888 insn |= ENCODE_BRANCH16_IMM (8); /* Set target to PC + 8. */
1889 bfd_putl32 (insn, buf);
1890 buf += 4;
1891
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);
1896 buf += 4;
1897 break;
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);
1901 buf += 4;
1902 break;
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);
1906 buf += 4;
1907 break;
1908
1909 default:
1910 abort();
1911 }
1912
1913 fixp->fx_file = fragp->fr_file;
1914 fixp->fx_line = fragp->fr_line;
1915
1916 gas_assert (buf == (bfd_byte *)fragp->fr_literal
1917 + fragp->fr_fix + fragp->fr_var);
1918
1919 fragp->fr_fix += fragp->fr_var;
1920 }
1921
1922 /* Relax a machine dependent frag. This returns the amount by which
1923 the current size of the frag should change. */
1924
1925 void
1926 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec ATTRIBUTE_UNUSED,
1927 fragS *fragp)
1928 {
1929 gas_assert (RELAX_BRANCH (fragp->fr_subtype));
1930 loongarch_convert_frag_branch (fragp);
1931 }