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