xref: /netbsd-src/external/gpl3/binutils.old/dist/gas/config/tc-loongarch.c (revision c42dbd0ed2e61fe6eda8590caa852ccf34719964)
1 /* tc-loongarch.c -- Assemble for the LoongArch ISA
2 
3    Copyright (C) 2021-2022 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 "dw2gencfi.h"
24 #include "loongarch-lex.h"
25 #include "elf/loongarch.h"
26 #include "opcode/loongarch.h"
27 #include "obj-elf.h"
28 #include "bfd/elfxx-loongarch.h"
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdio.h>
32 #include <assert.h>
33 
34 /* All information about an instruction during assemble.  */
35 struct loongarch_cl_insn
36 {
37   /* First split string.  */
38   const char *name;
39   const char *arg_strs[MAX_ARG_NUM_PLUS_2];
40   size_t arg_num;
41 
42   /* Second analyze name_str and each actual args string to match the insn
43      in 'loongarch-opc.c'. And actual args may need be relocated.
44      We get length of insn.  If 'insn_length == 0 && insn_mo->macro != NULL',
45      it's a macro insntruction and we call 'md_assemble' recursively
46      after expanding it.  */
47   int match_now;
48   int all_match;
49 
50   const struct loongarch_opcode *insn;
51   size_t insn_length;
52 
53   offsetT args[MAX_ARG_NUM_PLUS_2];
54   struct reloc_info reloc_info[MAX_RELOC_NUMBER_A_INSN];
55   size_t reloc_num;
56 
57   /* For relax reserved.  We not support relax now.
58      'insn_length < relax_max_length' means need to relax.
59      And 'insn_length == relax_max_length' means no need to relax.  */
60   size_t relax_max_length;
61   relax_substateT subtype;
62 
63   /* Then we get the binary representation of insn
64      and write it in to section.  */
65   insn_t insn_bin;
66 
67   /* The frag that contains the instruction.  */
68   struct frag *frag;
69   /* The offset into FRAG of the first instruction byte.  */
70   long where;
71   /* The relocs associated with the instruction, if any.  */
72   fixS *fixp[MAX_RELOC_NUMBER_A_INSN];
73 };
74 
75 #ifndef DEFAULT_ARCH
76 #define DEFAULT_ARCH "loongarch64"
77 #endif
78 
79 /* This array holds the chars that always start a comment.  If the
80    pre-processor is disabled, these aren't very useful.  */
81 const char comment_chars[] = "#";
82 
83 /* This array holds the chars that only start a comment at the beginning of
84    a line.  If the line seems to have the form '# 123 filename'
85    .line and .file directives will appear in the pre-processed output.  */
86 /* Note that input_file.c hand checks for '#' at the beginning of the
87    first line of the input file.  This is because the compiler outputs
88    #NO_APP at the beginning of its output.  */
89 /* Also note that C style comments are always supported.  */
90 const char line_comment_chars[] = "#";
91 
92 /* This array holds machine specific line separator characters.  */
93 const char line_separator_chars[] = ";";
94 
95 /* Chars that can be used to separate mant from exp in floating point nums.  */
96 const char EXP_CHARS[] = "eE";
97 
98 /* Chars that mean this number is a floating point constant.  */
99 /* As in 0f12.456.  */
100 /* or    0d1.2345e12.  */
101 const char FLT_CHARS[] = "rRsSfFdDxXpP";
102 
103 const char *md_shortopts = "O::g::G:";
104 
105 static const char default_arch[] = DEFAULT_ARCH;
106 
107 enum options
108 {
109   OPTION_IGNORE = OPTION_MD_BASE,
110 
111   OPTION_ABI,
112   OPTION_FLOAT_ABI,
113 
114   OPTION_FLOAT_ISA,
115 
116   OPTION_LA_LOCAL_WITH_ABS,
117   OPTION_LA_GLOBAL_WITH_PCREL,
118   OPTION_LA_GLOBAL_WITH_ABS,
119 
120   OPTION_END_OF_ENUM,
121 };
122 
123 struct option md_longopts[] =
124 {
125   { "mabi", required_argument, NULL, OPTION_ABI },
126 
127   { "mfpu", required_argument, NULL, OPTION_FLOAT_ISA },
128 
129   { "mla-local-with-abs", no_argument, NULL, OPTION_LA_LOCAL_WITH_ABS },
130   { "mla-global-with-pcrel", no_argument, NULL, OPTION_LA_GLOBAL_WITH_PCREL },
131   { "mla-global-with-abs", no_argument, NULL, OPTION_LA_GLOBAL_WITH_ABS },
132 
133   { NULL, no_argument, NULL, 0 }
134 };
135 
136 size_t md_longopts_size = sizeof (md_longopts);
137 
138 int
md_parse_option(int c,const char * arg)139 md_parse_option (int c, const char *arg)
140 {
141   int ret = 1;
142   char lp64[256] = "";
143   char ilp32[256] = "";
144   unsigned char *suf = (unsigned char *)arg;
145 
146   lp64['s'] = lp64['S'] = EF_LOONGARCH_ABI_LP64_SOFT_FLOAT;
147   lp64['f'] = lp64['F'] = EF_LOONGARCH_ABI_LP64_SINGLE_FLOAT;
148   lp64['d'] = lp64['D'] = EF_LOONGARCH_ABI_LP64_DOUBLE_FLOAT;
149 
150   ilp32['s'] = ilp32['S'] = EF_LOONGARCH_ABI_ILP32_SOFT_FLOAT;
151   ilp32['f'] = ilp32['F'] = EF_LOONGARCH_ABI_ILP32_SINGLE_FLOAT;
152   ilp32['d'] = ilp32['D'] = EF_LOONGARCH_ABI_ILP32_DOUBLE_FLOAT;
153 
154   switch (c)
155     {
156     case OPTION_ABI:
157       if (strncasecmp (arg, "lp64", 4) == 0 && lp64[suf[4]] != 0)
158 	{
159 	  LARCH_opts.ase_ilp32 = 1;
160 	  LARCH_opts.ase_lp64 = 1;
161 	  LARCH_opts.ase_abi = lp64[suf[4]];
162 	}
163       else if (strncasecmp (arg, "ilp32", 5) == 0 && ilp32[suf[5]] != 0)
164 	{
165 	  LARCH_opts.ase_abi = ilp32[suf[5]];
166 	  LARCH_opts.ase_ilp32 = 1;
167 	}
168       else
169 	ret = 0;
170       break;
171 
172     case OPTION_FLOAT_ISA:
173       if (strcasecmp (arg, "soft") == 0)
174 	LARCH_opts.ase_nf = 1;
175       else if (strcasecmp (arg, "single") == 0)
176 	LARCH_opts.ase_sf = 1;
177       else if (strcasecmp (arg, "double") == 0)
178 	{
179 	  LARCH_opts.ase_sf = 1;
180 	  LARCH_opts.ase_df = 1;
181 	}
182       else
183 	ret = 0;
184       break;
185 
186     case OPTION_LA_LOCAL_WITH_ABS:
187       LARCH_opts.ase_labs = 1;
188       break;
189 
190     case OPTION_LA_GLOBAL_WITH_PCREL:
191       LARCH_opts.ase_gpcr = 1;
192       break;
193 
194     case OPTION_LA_GLOBAL_WITH_ABS:
195       LARCH_opts.ase_gabs = 1;
196       break;
197 
198     case OPTION_IGNORE:
199       break;
200 
201     default:
202       ret = 0;
203       break;
204     }
205   return ret;
206 }
207 
208 static struct htab *r_htab = NULL;
209 static struct htab *f_htab = NULL;
210 static struct htab *c_htab = NULL;
211 static struct htab *cr_htab = NULL;
212 static struct htab *v_htab = NULL;
213 static struct htab *x_htab = NULL;
214 
215 void
loongarch_after_parse_args()216 loongarch_after_parse_args ()
217 {
218   /* Set default ABI/ISA LP64D.  */
219   if (!EF_LOONGARCH_IS_LP64(LARCH_opts.ase_abi)
220       && !EF_LOONGARCH_IS_ILP32(LARCH_opts.ase_abi))
221     {
222       if (strcmp (default_arch, "loongarch64") == 0)
223 	{
224 	  LARCH_opts.ase_abi = EF_LOONGARCH_ABI_LP64_DOUBLE_FLOAT;
225 	  LARCH_opts.ase_ilp32 = 1;
226 	  LARCH_opts.ase_lp64 = 1;
227 	}
228       else if (strcmp (default_arch, "loongarch32") == 0)
229 	{
230 	  LARCH_opts.ase_abi = EF_LOONGARCH_ABI_ILP32_DOUBLE_FLOAT;
231 	  LARCH_opts.ase_ilp32 = 1;
232 	}
233       else
234 	as_bad ("unknown default architecture `%s'", default_arch);
235     }
236 
237   /* Set default ISA double-float.  */
238   if (!LARCH_opts.ase_nf
239       && !LARCH_opts.ase_sf
240       && !LARCH_opts.ase_df)
241     {
242       LARCH_opts.ase_sf = 1;
243       LARCH_opts.ase_df = 1;
244     }
245 
246   size_t i;
247 
248   assert(LARCH_opts.ase_ilp32);
249 
250   /* Init ilp32/lp64 registers names.  */
251   if (!r_htab)
252     r_htab = str_htab_create (), str_hash_insert (r_htab, "", 0, 0);
253 
254   for (i = 0; i < ARRAY_SIZE (loongarch_r_normal_name); i++)
255     str_hash_insert (r_htab, loongarch_r_normal_name[i], (void *) (i + 1), 0);
256 
257   if (!cr_htab)
258     cr_htab = str_htab_create (), str_hash_insert (cr_htab, "", 0, 0);
259 
260   for (i = 0; i < ARRAY_SIZE (loongarch_cr_normal_name); i++)
261     str_hash_insert (cr_htab, loongarch_cr_normal_name[i], (void *) (i + 1), 0);
262 
263   /* Init single/double float registers names.  */
264   if (LARCH_opts.ase_sf || LARCH_opts.ase_df)
265     {
266       if (!f_htab)
267 	f_htab = str_htab_create (), str_hash_insert (f_htab, "", 0, 0);
268 
269       for (i = 0; i < ARRAY_SIZE (loongarch_f_normal_name); i++)
270 	str_hash_insert (f_htab, loongarch_f_normal_name[i], (void *) (i + 1),
271 			 0);
272 
273       if (!c_htab)
274 	c_htab = str_htab_create (), str_hash_insert (c_htab, "", 0, 0);
275 
276       for (i = 0; i < ARRAY_SIZE (loongarch_c_normal_name); i++)
277 	str_hash_insert (c_htab, loongarch_c_normal_name[i], (void *) (i + 1),
278 			 0);
279 
280     }
281 
282   /* Init lsx registers names.  */
283   if (LARCH_opts.ase_lsx)
284     {
285       if (!v_htab)
286 	v_htab = str_htab_create (), str_hash_insert (v_htab, "", 0, 0);
287       for (i = 0; i < ARRAY_SIZE (loongarch_v_normal_name); i++)
288 	str_hash_insert (v_htab, loongarch_v_normal_name[i], (void *) (i + 1),
289 			 0);
290     }
291 
292   /* Init lasx registers names.  */
293   if (LARCH_opts.ase_lasx)
294     {
295       if (!x_htab)
296 	x_htab = str_htab_create (), str_hash_insert (x_htab, "", 0, 0);
297       for (i = 0; i < ARRAY_SIZE (loongarch_x_normal_name); i++)
298 	str_hash_insert (x_htab, loongarch_x_normal_name[i], (void *) (i + 1),
299 			 0);
300     }
301 
302   /* Init lp64 registers alias.  */
303   if (LARCH_opts.ase_lp64)
304     {
305       for (i = 0; i < ARRAY_SIZE (loongarch_r_lp64_name); i++)
306 	str_hash_insert (r_htab, loongarch_r_lp64_name[i], (void *) (i + 1),
307 			 0);
308       for (i = 0; i < ARRAY_SIZE (loongarch_r_lp64_name1); i++)
309 	str_hash_insert (r_htab, loongarch_r_lp64_name1[i], (void *) (i + 1),
310 			 0);
311     }
312 
313   /* Init float-lp64 registers alias */
314   if ((LARCH_opts.ase_sf || LARCH_opts.ase_df) && LARCH_opts.ase_lp64)
315     {
316       for (i = 0; i < ARRAY_SIZE (loongarch_f_lp64_name); i++)
317 	str_hash_insert (f_htab, loongarch_f_lp64_name[i],
318 			 (void *) (i + 1), 0);
319       for (i = 0; i < ARRAY_SIZE (loongarch_f_lp64_name1); i++)
320 	str_hash_insert (f_htab, loongarch_f_lp64_name1[i],
321 			 (void *) (i + 1), 0);
322     }
323 }
324 
325 const char *
loongarch_target_format()326 loongarch_target_format ()
327 {
328   return LARCH_opts.ase_lp64 ? "elf64-loongarch" : "elf32-loongarch";
329 }
330 
331 void
md_begin()332 md_begin ()
333 {
334   const struct loongarch_opcode *it;
335   struct loongarch_ase *ase;
336   for (ase = loongarch_ASEs; ase->enabled; ase++)
337     for (it = ase->opcodes; it->name; it++)
338       {
339 	if (loongarch_check_format (it->format) != 0)
340 	  as_fatal (_("insn name: %s\tformat: %s\tsyntax error"),
341 		    it->name, it->format);
342 	if (it->mask == 0 && it->macro == 0)
343 	  as_fatal (_("insn name: %s\nformat: %s\nwe want macro but "
344 		      "macro is NULL"),
345 		    it->name, it->format);
346 	if (it->macro
347 	    && loongarch_check_macro (it->format, it->macro) != 0)
348 	  as_fatal (_("insn name: %s\nformat: %s\nmacro: %s\tsyntax error"),
349 		    it->name, it->format, it->macro);
350       }
351 
352   /* FIXME: expressionS use 'offsetT' as constant,
353    * we want this is 64-bit type.  */
354   assert (8 <= sizeof (offsetT));
355 }
356 
357 unsigned long
loongarch_mach(void)358 loongarch_mach (void)
359 {
360   return LARCH_opts.ase_lp64 ? bfd_mach_loongarch64 : bfd_mach_loongarch32;
361 }
362 
363 static const expressionS const_0 = { .X_op = O_constant, .X_add_number = 0 };
364 
365 static const char *
my_getExpression(expressionS * ep,const char * str)366 my_getExpression (expressionS *ep, const char *str)
367 {
368   char *save_in, *ret;
369   save_in = input_line_pointer;
370   input_line_pointer = (char *) str;
371   expression (ep);
372   ret = input_line_pointer;
373   input_line_pointer = save_in;
374   return ret;
375 }
376 
377 static void
s_loongarch_align(int arg)378 s_loongarch_align (int arg)
379 {
380   const char *t = input_line_pointer;
381   while (!is_end_of_line[(unsigned char) *t] && *t != ',')
382     ++t;
383   if (*t == ',')
384     s_align_ptwo (arg);
385   else
386     s_align_ptwo (0);
387 }
388 
389 /* Handle the .dtprelword and .dtpreldword pseudo-ops.  They generate
390    a 32-bit or 64-bit DTP-relative relocation (BYTES says which) for
391    use in DWARF debug information.  */
392 
393 static void
s_dtprel(int bytes)394 s_dtprel (int bytes)
395 {
396   expressionS ex;
397   char *p;
398 
399   expression (&ex);
400 
401   if (ex.X_op != O_symbol)
402     {
403       as_bad (_("Unsupported use of %s"),
404 	      (bytes == 8 ? ".dtpreldword" : ".dtprelword"));
405       ignore_rest_of_line ();
406     }
407 
408   p = frag_more (bytes);
409   md_number_to_chars (p, 0, bytes);
410   fix_new_exp (frag_now, p - frag_now->fr_literal, bytes, &ex, FALSE,
411 	       (bytes == 8
412 		? BFD_RELOC_LARCH_TLS_DTPREL64
413 		: BFD_RELOC_LARCH_TLS_DTPREL32));
414 
415   demand_empty_rest_of_line ();
416 }
417 
418 static const pseudo_typeS loongarch_pseudo_table[] =
419 {
420   { "align", s_loongarch_align, -4 },
421   { "dword", cons, 8 },
422   { "word", cons, 4 },
423   { "half", cons, 2 },
424   { "dtprelword", s_dtprel, 4 },
425   { "dtpreldword", s_dtprel, 8 },
426   { NULL, NULL, 0 },
427 };
428 
429 void
loongarch_pop_insert(void)430 loongarch_pop_insert (void)
431 {
432   pop_insert (loongarch_pseudo_table);
433 }
434 
435 #define INTERNAL_LABEL_SPECIAL 10
436 static unsigned long internal_label_count[INTERNAL_LABEL_SPECIAL] = { 0 };
437 
438 static const char *
loongarch_internal_label_name(unsigned long label,int augend)439 loongarch_internal_label_name (unsigned long label, int augend)
440 {
441   static char symbol_name_build[24];
442   unsigned long want_label;
443   char *p;
444 
445   want_label = internal_label_count[label] + augend;
446 
447   p = symbol_name_build;
448 #ifdef LOCAL_LABEL_PREFIX
449   *p++ = LOCAL_LABEL_PREFIX;
450 #endif
451   *p++ = 'L';
452   for (; label; label /= 10)
453     *p++ = label % 10 + '0';
454   /* Make sure internal label never belong to normal label namespace.  */
455   *p++ = ':';
456   for (; want_label; want_label /= 10)
457     *p++ = want_label % 10 + '0';
458   *p++ = '\0';
459   return symbol_name_build;
460 }
461 
462 static void
setup_internal_label_here(unsigned long label)463 setup_internal_label_here (unsigned long label)
464 {
465   assert (label < INTERNAL_LABEL_SPECIAL);
466   internal_label_count[label]++;
467   colon (loongarch_internal_label_name (label, 0));
468 }
469 
470 void
get_internal_label(expressionS * label_expr,unsigned long label,int augend)471 get_internal_label (expressionS *label_expr, unsigned long label,
472 		    int augend /* 0 for previous, 1 for next.  */)
473 {
474   assert (label < INTERNAL_LABEL_SPECIAL);
475   if (augend == 0 && internal_label_count[label] == 0)
476     as_fatal (_("internal error: we have no internal label yet"));
477   label_expr->X_op = O_symbol;
478   label_expr->X_add_symbol =
479     symbol_find_or_make (loongarch_internal_label_name (label, augend));
480   label_expr->X_add_number = 0;
481 }
482 
483 extern int loongarch_parse_expr (const char *expr,
484 				 struct reloc_info *reloc_stack_top,
485 				 size_t max_reloc_num, size_t *reloc_num,
486 				 offsetT *imm_if_no_reloc);
487 
488 static int
is_internal_label(const char * c_str)489 is_internal_label (const char *c_str)
490 {
491   do
492     {
493       if (*c_str != ':')
494 	break;
495       c_str++;
496       if (!('0' <= *c_str && *c_str <= '9'))
497 	break;
498       while ('0' <= *c_str && *c_str <= '9')
499 	c_str++;
500       if (*c_str != 'b' && *c_str != 'f')
501 	break;
502       c_str++;
503       return *c_str == '\0';
504     }
505   while (0);
506   return 0;
507 }
508 
509 static int
is_label(const char * c_str)510 is_label (const char *c_str)
511 {
512   if (is_internal_label (c_str))
513     return 1;
514   else if ('0' <= *c_str && *c_str <= '9')
515     {
516       /* [0-9]+[bf]  */
517       while ('0' <= *c_str && *c_str <= '9')
518 	c_str++;
519       return *c_str == 'b' || *c_str == 'f';
520     }
521   else if (is_name_beginner (*c_str))
522     {
523       /* [a-zA-Z\._\$][0-9a-zA-Z\._\$]*  */
524       c_str++;
525       while (is_part_of_name (*c_str))
526 	c_str++;
527       return *c_str == '\0';
528     }
529   else
530     return 0;
531 }
532 
533 static int
is_label_with_addend(const char * c_str)534 is_label_with_addend (const char *c_str)
535 {
536   if (is_internal_label (c_str))
537     return 1;
538   else if ('0' <= *c_str && *c_str <= '9')
539     {
540       /* [0-9]+[bf]  */
541       while ('0' <= *c_str && *c_str <= '9')
542 	c_str++;
543       if (*c_str == 'b' || *c_str == 'f')
544 	c_str++;
545       else
546 	return 0;
547       return *c_str == '\0'
548 		       || ((*c_str == '-' || *c_str == '+')
549 			   && is_unsigned (c_str + 1));
550     }
551   else if (is_name_beginner (*c_str))
552     {
553       /* [a-zA-Z\._\$][0-9a-zA-Z\._\$]*  */
554       c_str++;
555       while (is_part_of_name (*c_str))
556 	c_str++;
557       return *c_str == '\0'
558 		       || ((*c_str == '-' || *c_str == '+')
559 			   && is_unsigned (c_str + 1));
560     }
561   else
562     return 0;
563 }
564 
565 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)566 loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
567 					    const char *bit_field,
568 					    const char *arg, void *context)
569 {
570   struct loongarch_cl_insn *ip = context;
571   offsetT imm, ret = 0;
572   size_t reloc_num_we_have = MAX_RELOC_NUMBER_A_INSN - ip->reloc_num;
573   size_t reloc_num = 0;
574 
575   if (!ip->match_now)
576     return 0;
577 
578   switch (esc_ch1)
579     {
580     case 'l':
581       switch (esc_ch2)
582 	{
583 	default:
584 	  ip->match_now = is_label (arg);
585 	  if (!ip->match_now && is_label_with_addend (arg))
586 	    as_fatal (_("This label shouldn't be with addend."));
587 	  break;
588 	case 'a':
589 	  ip->match_now = is_label_with_addend (arg);
590 	  break;
591 	}
592       break;
593     case 's':
594     case 'u':
595       ip->match_now =
596 	loongarch_parse_expr (arg, ip->reloc_info + ip->reloc_num,
597 			      reloc_num_we_have, &reloc_num, &imm) == 0;
598 
599       if (!ip->match_now)
600 	break;
601 
602       if (esc_ch1 == 's')
603 	switch (esc_ch2)
604 	  {
605 	  case 'c':
606 	    ip->match_now = reloc_num == 0;
607 	    break;
608 	  }
609       else
610 	switch (esc_ch2)
611 	  {
612 	  case 'c':
613 	    ip->match_now = reloc_num == 0 && 0 <= imm;
614 	    break;
615 	  }
616 
617       if (!ip->match_now)
618 	break;
619 
620       ret = imm;
621       if (reloc_num)
622 	{
623 	  bfd_reloc_code_real_type reloc_type = BFD_RELOC_NONE;
624 	  reloc_num_we_have -= reloc_num;
625 	  if (reloc_num_we_have == 0)
626 	    as_fatal (_("expr too huge") /* Want one more reloc.  */);
627 	  if (esc_ch1 == 'u')
628 	    {
629 	      if (strncmp (bit_field, "10:12", strlen ("10:12")) == 0)
630 		reloc_type = BFD_RELOC_LARCH_SOP_POP_32_U_10_12;
631 	    }
632 	  else if (esc_ch1 == 's')
633 	    {
634 	      if (strncmp (bit_field, "10:16<<2", strlen ("10:16<<2")) == 0)
635 		reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2;
636 	      else if (strncmp (bit_field, "0:5|10:16<<2",
637 				strlen ("0:5|10:16<<2")) == 0)
638 		reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2;
639 	      else if (strncmp (bit_field, "0:10|10:16<<2",
640 				strlen ("0:10|10:16<<2")) == 0)
641 		reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2;
642 	      else if (strncmp (bit_field, "10:12", strlen ("10:12")) == 0)
643 		reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_12;
644 	      else if (strncmp (bit_field, "5:20", strlen ("5:20")) == 0)
645 		reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_5_20;
646 	      else if (strncmp (bit_field, "10:16", strlen ("10:16")) == 0)
647 		reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_16;
648 	      else if (strncmp (bit_field, "10:5", strlen ("10:5")) == 0)
649 		reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_5;
650 	    }
651 	  if (reloc_type == BFD_RELOC_NONE)
652 	    as_fatal (
653 		      _("not support reloc bit-field\nfmt: %c%c %s\nargs: %s"),
654 		      esc_ch1, esc_ch2, bit_field, arg);
655 	  reloc_num++;
656 	  ip->reloc_num += reloc_num;
657 	  ip->reloc_info[ip->reloc_num - 1].type = reloc_type;
658 	  ip->reloc_info[ip->reloc_num - 1].value = const_0;
659 	}
660       break;
661     case 'r':
662       imm = (intptr_t) str_hash_find (r_htab, arg);
663       ip->match_now = 0 < imm;
664       ret = imm - 1;
665       break;
666     case 'f':
667       imm = (intptr_t) str_hash_find (f_htab, arg);
668       ip->match_now = 0 < imm;
669       ret = imm - 1;
670       break;
671     case 'c':
672       switch (esc_ch2)
673 	{
674 	case 'r':
675 	  imm = (intptr_t) str_hash_find (cr_htab, arg);
676 	  break;
677 	default:
678 	  imm = (intptr_t) str_hash_find (c_htab, arg);
679 	}
680       ip->match_now = 0 < imm;
681       ret = imm - 1;
682       break;
683     case 'v':
684       imm = (intptr_t) str_hash_find (v_htab, arg);
685       ip->match_now = 0 < imm;
686       ret = imm - 1;
687       break;
688     case 'x':
689       imm = (intptr_t) str_hash_find (x_htab, arg);
690       ip->match_now = 0 < imm;
691       ret = imm - 1;
692       break;
693     case '\0':
694       ip->all_match = ip->match_now;
695       ip->insn_length =
696 	ip->insn->mask ? loongarch_insn_length (ip->insn->match) : 0;
697       /* FIXME: now we have no relax insn.  */
698       ip->relax_max_length = ip->insn_length;
699       break;
700     default:
701       as_fatal (_("unknown escape"));
702     }
703 
704   do
705     {
706       /* Check imm overflow.  */
707       int bit_width, bits_needed_s, bits_needed_u;
708       char *t;
709 
710       if (!ip->match_now)
711 	break;
712 
713       if (0 < reloc_num)
714 	break;
715 
716       bit_width = loongarch_get_bit_field_width (bit_field, &t);
717 
718       if (bit_width == -1)
719 	/* No specify bit width.  */
720 	break;
721 
722       imm = ret;
723       if (t[0] == '<' && t[1] == '<')
724 	{
725 	  int i = strtol (t += 2, &t, 10), j;
726 	  for (j = i; 0 < j; j--, imm >>= 1)
727 	    if (imm & 1)
728 	      as_fatal (_("require imm low %d bit is 0."), i);
729 	}
730 
731       if (*t == '+')
732 	imm -= strtol (t, &t, 10);
733 
734       bits_needed_s = loongarch_bits_imm_needed (imm, 1);
735       bits_needed_u = loongarch_bits_imm_needed (imm, 0);
736 
737       if ((esc_ch1 == 's' && bit_width < bits_needed_s)
738 	  || (esc_ch1 != 's' && bit_width < bits_needed_u))
739 	/* How to do after we detect overflow.  */
740 	as_fatal (_("Immediate overflow.\n"
741 		    "format: %c%c%s\n"
742 		    "arg: %s"),
743 		  esc_ch1, esc_ch2, bit_field, arg);
744     }
745   while (0);
746 
747   if (esc_ch1 != '\0')
748     {
749       ip->args[ip->arg_num] = ret;
750       ip->arg_num++;
751     }
752   return ret;
753 }
754 
755 static void
get_loongarch_opcode(struct loongarch_cl_insn * insn)756 get_loongarch_opcode (struct loongarch_cl_insn *insn)
757 {
758   const struct loongarch_opcode *it;
759   struct loongarch_ase *ase;
760   for (ase = loongarch_ASEs; ase->enabled; ase++)
761     {
762       if (!*ase->enabled || (ase->include && !*ase->include)
763 	  || (ase->exclude && *ase->exclude))
764 	continue;
765 
766       if (!ase->name_hash_entry)
767 	{
768 	  ase->name_hash_entry = str_htab_create ();
769 	  for (it = ase->opcodes; it->name; it++)
770 	    str_hash_insert (ase->name_hash_entry, it->name, (void *) it, 0);
771 	}
772 
773       if ((it = str_hash_find (ase->name_hash_entry, insn->name)) == NULL)
774 	continue;
775 
776       do
777 	{
778 	  insn->insn = it;
779 	  insn->match_now = 1;
780 	  insn->all_match = 0;
781 	  insn->arg_num = 0;
782 	  insn->reloc_num = 0;
783 	  insn->insn_bin = (loongarch_foreach_args
784 			    (it->format, insn->arg_strs,
785 			     loongarch_args_parser_can_match_arg_helper,
786 			     insn));
787 	  if (insn->all_match && !(it->include && !*it->include)
788 	      && !(it->exclude && *it->exclude))
789 	    {
790 	      insn->insn_bin |= it->match;
791 	      return;
792 	    }
793 	  it++;
794 	}
795       while (it->name && strcasecmp (it->name, insn->name) == 0);
796     }
797 }
798 
799 static int
check_this_insn_before_appending(struct loongarch_cl_insn * ip)800 check_this_insn_before_appending (struct loongarch_cl_insn *ip)
801 {
802   int ret = 0;
803   if (strcmp (ip->name, "la.abs") == 0)
804     {
805       ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_MARK_LA;
806       my_getExpression (&ip->reloc_info[ip->reloc_num].value, ip->arg_strs[1]);
807       ip->reloc_num++;
808     }
809   else if (ip->insn->mask == 0xffff8000
810 	   /* amswap.w  rd, rk, rj  */
811 	   && ((ip->insn_bin & 0xfff00000) == 0x38600000
812 	       /* ammax_db.wu  rd, rk, rj  */
813 	       || (ip->insn_bin & 0xffff0000) == 0x38700000
814 	       /* ammin_db.wu  rd, rk, rj  */
815 	       || (ip->insn_bin & 0xffff0000) == 0x38710000))
816     {
817       /* For AMO insn amswap.[wd], amadd.[wd], etc.  */
818       if (ip->args[0] != 0
819 	  && (ip->args[0] == ip->args[1] || ip->args[0] == ip->args[2]))
820 	as_fatal (_("AMO insns require rd != base && rd != rt"
821 		    " when rd isn't $r0"));
822     }
823   else if ((ip->insn->mask == 0xffe08000
824 	    /* bstrins.w  rd, rj, msbw, lsbw  */
825 	    && (ip->insn_bin & 0xffe00000) == 0x00600000)
826 	   || (ip->insn->mask == 0xffc00000
827 	       /* bstrins.d  rd, rj, msbd, lsbd  */
828 	       && (ip->insn_bin & 0xff800000) == 0x00800000))
829     {
830       /* For bstr(ins|pick).[wd].  */
831       if (ip->args[2] < ip->args[3])
832 	as_fatal (_("bstr(ins|pick).[wd] require msbd >= lsbd"));
833     }
834   else if (ip->insn->mask != 0 && (ip->insn_bin & 0xfe0003c0) == 0x04000000
835 	   /* csrxchg  rd, rj, csr_num  */
836 	   && (strcmp ("csrxchg", ip->name) == 0))
837     as_fatal (_("csrxchg require rj != $r0 && rj != $r1"));
838 
839   return ret;
840 }
841 
842 static void
install_insn(const struct loongarch_cl_insn * insn)843 install_insn (const struct loongarch_cl_insn *insn)
844 {
845   char *f = insn->frag->fr_literal + insn->where;
846   if (0 < insn->insn_length)
847     md_number_to_chars (f, insn->insn_bin, insn->insn_length);
848 }
849 
850 static void
move_insn(struct loongarch_cl_insn * insn,fragS * frag,long where)851 move_insn (struct loongarch_cl_insn *insn, fragS *frag, long where)
852 {
853   size_t i;
854   insn->frag = frag;
855   insn->where = where;
856   for (i = 0; i < insn->reloc_num; i++)
857     {
858       insn->fixp[i]->fx_frag = frag;
859       insn->fixp[i]->fx_where = where;
860     }
861   install_insn (insn);
862 }
863 
864 /* Add INSN to the end of the output.  */
865 static void
append_fixed_insn(struct loongarch_cl_insn * insn)866 append_fixed_insn (struct loongarch_cl_insn *insn)
867 {
868   char *f = frag_more (insn->insn_length);
869   move_insn (insn, frag_now, f - frag_now->fr_literal);
870 }
871 
872 static void
append_fixp_and_insn(struct loongarch_cl_insn * ip)873 append_fixp_and_insn (struct loongarch_cl_insn *ip)
874 {
875   reloc_howto_type *howto;
876   bfd_reloc_code_real_type reloc_type;
877   struct reloc_info *reloc_info = ip->reloc_info;
878   size_t i;
879 
880   dwarf2_emit_insn (0);
881 
882   for (i = 0; i < ip->reloc_num; i++)
883     {
884       reloc_type = reloc_info[i].type;
885       howto = bfd_reloc_type_lookup (stdoutput, reloc_type);
886       if (howto == NULL)
887 	as_fatal (_("no HOWTO loong relocation number %d"), reloc_type);
888 
889       ip->fixp[i] =
890 	fix_new_exp (ip->frag, ip->where, bfd_get_reloc_size (howto),
891 		     &reloc_info[i].value, FALSE, reloc_type);
892     }
893 
894   if (ip->insn_length < ip->relax_max_length)
895     as_fatal (_("Internal error: not support relax now"));
896   else
897     append_fixed_insn (ip);
898 }
899 
900 /* Ask helper for returning a malloced c_str or NULL.  */
901 static char *
assember_macro_helper(const char * const args[],void * context_ptr)902 assember_macro_helper (const char *const args[], void *context_ptr)
903 {
904   struct loongarch_cl_insn *insn = context_ptr;
905   char *ret = NULL;
906   if ( strcmp (insn->name, "li.w") == 0 || strcmp (insn->name, "li.d") == 0)
907     {
908       char args_buf[50], insns_buf[200];
909       const char *arg_strs[6];
910       uint32_t hi32, lo32;
911 
912       /* We pay attention to sign extend beacause it is chance of reduce insn.
913 	 The exception is 12-bit and hi-12-bit unsigned,
914 	 we need a 'ori' or a 'lu52i.d' accordingly.  */
915       char all0_bit_vec, sign_bit_vec, allf_bit_vec, paritial_is_sext_of_prev;
916 
917       lo32 = insn->args[1] & 0xffffffff;
918       hi32 = insn->args[1] >> 32;
919 
920       if (strcmp (insn->name, "li.w") == 0)
921 	{
922 	  if (hi32 != 0 && hi32 != 0xffffffff)
923 	    as_fatal (_("li overflow: hi32:0x%x lo32:0x%x"), hi32, lo32);
924 	  hi32 = lo32 & 0x80000000 ? 0xffffffff : 0;
925 	}
926 
927       if (strcmp (insn->name, "li.d") == 0 && !LARCH_opts.ase_lp64)
928 	as_fatal (_("we can't li.d on 32bit-arch"));
929 
930       snprintf (args_buf, sizeof (args_buf), "0x%x,0x%x,0x%x,0x%x,%s",
931 		(hi32 >> 20) & 0xfff, hi32 & 0xfffff, (lo32 >> 12) & 0xfffff,
932 		lo32 & 0xfff, args[0]);
933       loongarch_split_args_by_comma (args_buf, arg_strs);
934 
935       all0_bit_vec =
936 	((((hi32 & 0xfff00000) == 0) << 3) | (((hi32 & 0x000fffff) == 0) << 2)
937 	 | (((lo32 & 0xfffff000) == 0) << 1) | ((lo32 & 0x00000fff) == 0));
938       sign_bit_vec =
939 	((((hi32 & 0x80000000) != 0) << 3) | (((hi32 & 0x00080000) != 0) << 2)
940 	 | (((lo32 & 0x80000000) != 0) << 1) | ((lo32 & 0x00000800) != 0));
941       allf_bit_vec =
942 	((((hi32 & 0xfff00000) == 0xfff00000) << 3)
943 	 | (((hi32 & 0x000fffff) == 0x000fffff) << 2)
944 	 | (((lo32 & 0xfffff000) == 0xfffff000) << 1)
945 	 | ((lo32 & 0x00000fff) == 0x00000fff));
946       paritial_is_sext_of_prev =
947 	(all0_bit_vec ^ allf_bit_vec) & (all0_bit_vec ^ (sign_bit_vec << 1));
948 
949       static const char *const li_32bit[] =
950 	{
951 	  "lu12i.w %5,%3&0x80000?%3-0x100000:%3;ori %5,%5,%4;",
952 	  "lu12i.w %5,%3&0x80000?%3-0x100000:%3;",
953 	  "addi.w %5,$r0,%4&0x800?%4-0x1000:%4;",
954 	  "or %5,$r0,$r0;",
955 	};
956       static const char *const li_hi_32bit[] =
957 	{
958 	  "lu32i.d %5,%2&0x80000?%2-0x100000:%2;"
959 	  "lu52i.d %5,%5,%1&0x800?%1-0x1000:%1;",
960 	  "lu52i.d %5,%5,%1&0x800?%1-0x1000:%1;",
961 	  "lu32i.d %5,%2&0x80000?%2-0x100000:%2;",
962 	  "",
963 	};
964       do
965 	{
966 	  insns_buf[0] = '\0';
967 	  if (paritial_is_sext_of_prev == 0x7)
968 	    {
969 	      strcat (insns_buf, "lu52i.d %5,$r0,%1&0x800?%1-0x1000:%1;");
970 	      break;
971 	    }
972 	  if ((all0_bit_vec & 0x3) == 0x2)
973 	    strcat (insns_buf, "ori %5,$r0,%4;");
974 	  else
975 	    strcat (insns_buf, li_32bit[paritial_is_sext_of_prev & 0x3]);
976 	  strcat (insns_buf, li_hi_32bit[paritial_is_sext_of_prev >> 2]);
977 	}
978       while (0);
979 
980       ret = loongarch_expand_macro (insns_buf, arg_strs, NULL, NULL,
981 				    sizeof (args_buf));
982     }
983   return ret;
984 }
985 
986 /* Accept instructions separated by ';'
987  * assuming 'not starting with space and not ending with space' or pass in
988  * empty c_str.  */
989 static void
loongarch_assemble_INSNs(char * str)990 loongarch_assemble_INSNs (char *str)
991 {
992   char *rest;
993   size_t len_str = strlen(str);
994 
995   for (rest = str; *rest != ';' && *rest != '\0'; rest++);
996   if (*rest == ';')
997     *rest++ = '\0';
998 
999   if (*str == ':')
1000     {
1001       str++;
1002       setup_internal_label_here (strtol (str, &str, 10));
1003       str++;
1004     }
1005 
1006   do
1007     {
1008       if (*str == '\0')
1009 	break;
1010 
1011       struct loongarch_cl_insn the_one = { 0 };
1012       the_one.name = str;
1013 
1014       for (; *str && *str != ' '; str++)
1015 	;
1016       if (*str == ' ')
1017 	*str++ = '\0';
1018 
1019       loongarch_split_args_by_comma (str, the_one.arg_strs);
1020       get_loongarch_opcode (&the_one);
1021 
1022       if (!the_one.all_match)
1023 	{
1024 	  char *ss = loongarch_cat_splited_strs (the_one.arg_strs);
1025 	  as_bad (_("no match insn: %s\t%s"), the_one.name, ss ? ss : "");
1026 	  free(ss);
1027 	  return;
1028 	}
1029 
1030       if (check_this_insn_before_appending (&the_one) != 0)
1031 	break;
1032 
1033       append_fixp_and_insn (&the_one);
1034       if (the_one.insn_length == 0 && the_one.insn->macro)
1035 	{
1036 	  char *c_str = loongarch_expand_macro (the_one.insn->macro,
1037 						the_one.arg_strs,
1038 						assember_macro_helper,
1039 						&the_one, len_str);
1040 	  loongarch_assemble_INSNs (c_str);
1041 	  free (c_str);
1042 	}
1043     }
1044   while (0);
1045 
1046   if (*rest != '\0')
1047     loongarch_assemble_INSNs (rest);
1048 }
1049 
1050 void
md_assemble(char * str)1051 md_assemble (char *str)
1052 {
1053   loongarch_assemble_INSNs (str);
1054 }
1055 
1056 const char *
md_atof(int type,char * litP,int * sizeP)1057 md_atof (int type, char *litP, int *sizeP)
1058 {
1059   return ieee_md_atof (type, litP, sizeP, FALSE);
1060 }
1061 
1062 void
md_number_to_chars(char * buf,valueT val,int n)1063 md_number_to_chars (char *buf, valueT val, int n)
1064 {
1065   number_to_chars_littleendian (buf, val, n);
1066 }
1067 
1068 /* The location from which a PC relative jump should be calculated,
1069    given a PC relative reloc.  */
1070 long
md_pcrel_from(fixS * fixP ATTRIBUTE_UNUSED)1071 md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
1072 {
1073   return 0;
1074 }
1075 
fix_reloc_insn(fixS * fixP,bfd_vma reloc_val,char * buf)1076 static void fix_reloc_insn (fixS *fixP, bfd_vma reloc_val, char *buf)
1077 {
1078   reloc_howto_type *howto;
1079   insn_t insn;
1080   howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
1081 
1082   insn = bfd_getl32 (buf);
1083 
1084   if (!loongarch_adjust_reloc_bitsfield(howto, &reloc_val))
1085     as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow");
1086 
1087   insn = (insn & (insn_t)howto->src_mask)
1088     | ((insn & (~(insn_t)howto->dst_mask)) | reloc_val);
1089 
1090   bfd_putl32 (insn, buf);
1091 }
1092 
1093 void
md_apply_fix(fixS * fixP,valueT * valP,segT seg ATTRIBUTE_UNUSED)1094 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
1095 {
1096   static int64_t stack_top;
1097   static int last_reloc_is_sop_push_pcrel_1 = 0;
1098   int last_reloc_is_sop_push_pcrel = last_reloc_is_sop_push_pcrel_1;
1099   last_reloc_is_sop_push_pcrel_1 = 0;
1100 
1101   char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
1102   switch (fixP->fx_r_type)
1103     {
1104     case BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL:
1105     case BFD_RELOC_LARCH_SOP_PUSH_TLS_GD:
1106     case BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT:
1107     case BFD_RELOC_LARCH_SOP_PUSH_PCREL:
1108     case BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL:
1109       if (fixP->fx_addsy == NULL)
1110 	as_bad_where (fixP->fx_file, fixP->fx_line,
1111 		      _("Relocation against a constant"));
1112 
1113       if (fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL
1114 	  || fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_TLS_GD
1115 	  || fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT)
1116 	S_SET_THREAD_LOCAL (fixP->fx_addsy);
1117 
1118       if (fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_PCREL)
1119 	{
1120 	  last_reloc_is_sop_push_pcrel_1 = 1;
1121 	  if (S_GET_SEGMENT (fixP->fx_addsy) == seg)
1122 	    stack_top = (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset
1123 			 - (fixP->fx_where + fixP->fx_frag->fr_address));
1124 	  else
1125 	    stack_top = 0;
1126 	}
1127       break;
1128 
1129     case BFD_RELOC_LARCH_SOP_POP_32_S_10_5:
1130     case BFD_RELOC_LARCH_SOP_POP_32_S_10_12:
1131     case BFD_RELOC_LARCH_SOP_POP_32_U_10_12:
1132     case BFD_RELOC_LARCH_SOP_POP_32_S_10_16:
1133     case BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2:
1134     case BFD_RELOC_LARCH_SOP_POP_32_S_5_20:
1135     case BFD_RELOC_LARCH_SOP_POP_32_U:
1136     case BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2:
1137     case BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2:
1138       if (!last_reloc_is_sop_push_pcrel)
1139 	break;
1140 
1141       fix_reloc_insn (fixP, (bfd_vma)stack_top, buf);
1142       break;
1143 
1144     case BFD_RELOC_64:
1145     case BFD_RELOC_32:
1146       if (fixP->fx_subsy)
1147 	{
1148 	case BFD_RELOC_24:
1149 	case BFD_RELOC_16:
1150 	case BFD_RELOC_8:
1151 	  fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
1152 	  fixP->fx_next->fx_addsy = fixP->fx_subsy;
1153 	  fixP->fx_next->fx_subsy = NULL;
1154 	  fixP->fx_next->fx_offset = 0;
1155 	  fixP->fx_subsy = NULL;
1156 
1157 	  switch (fixP->fx_r_type)
1158 	    {
1159 	    case BFD_RELOC_64:
1160 	      fixP->fx_r_type = BFD_RELOC_LARCH_ADD64;
1161 	      fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB64;
1162 	      break;
1163 	    case BFD_RELOC_32:
1164 	      fixP->fx_r_type = BFD_RELOC_LARCH_ADD32;
1165 	      fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB32;
1166 	      break;
1167 	    case BFD_RELOC_24:
1168 	      fixP->fx_r_type = BFD_RELOC_LARCH_ADD24;
1169 	      fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB24;
1170 	      break;
1171 	    case BFD_RELOC_16:
1172 	      fixP->fx_r_type = BFD_RELOC_LARCH_ADD16;
1173 	      fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB16;
1174 	      break;
1175 	    case BFD_RELOC_8:
1176 	      fixP->fx_r_type = BFD_RELOC_LARCH_ADD8;
1177 	      fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB8;
1178 	      break;
1179 	    default:
1180 	      break;
1181 	    }
1182 	  md_number_to_chars (buf, 0, fixP->fx_size);
1183 	  if (fixP->fx_next->fx_addsy == NULL)
1184 	    fixP->fx_next->fx_done = 1;
1185 	}
1186       if (fixP->fx_addsy == NULL)
1187 	{
1188 	  fixP->fx_done = 1;
1189 	  md_number_to_chars (buf, *valP, fixP->fx_size);
1190 	}
1191       break;
1192 
1193     default:
1194       break;
1195     }
1196 }
1197 
1198 int
loongarch_relax_frag(asection * sec ATTRIBUTE_UNUSED,fragS * fragp ATTRIBUTE_UNUSED,long stretch ATTRIBUTE_UNUSED)1199 loongarch_relax_frag (asection *sec ATTRIBUTE_UNUSED,
1200 		      fragS *fragp ATTRIBUTE_UNUSED,
1201 		      long stretch ATTRIBUTE_UNUSED)
1202 {
1203   return 0;
1204 }
1205 
1206 int
md_estimate_size_before_relax(fragS * fragp ATTRIBUTE_UNUSED,asection * segtype ATTRIBUTE_UNUSED)1207 md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED,
1208 			       asection *segtype ATTRIBUTE_UNUSED)
1209 {
1210   return 0;
1211 }
1212 
1213 /* Translate internal representation of relocation info to BFD target
1214    format.  */
1215 arelent *
tc_gen_reloc(asection * section ATTRIBUTE_UNUSED,fixS * fixp)1216 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
1217 {
1218   arelent *reloc = (arelent *) xmalloc (sizeof (arelent));
1219 
1220   reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
1221   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
1222   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
1223   reloc->addend = fixp->fx_offset;
1224 
1225   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
1226   if (reloc->howto == NULL)
1227     {
1228       as_bad_where (fixp->fx_file, fixp->fx_line,
1229 		    _("cannot represent %s relocation in object file"),
1230 		    bfd_get_reloc_code_name (fixp->fx_r_type));
1231       return NULL;
1232     }
1233 
1234   return reloc;
1235 }
1236 
1237 /* Convert a machine dependent frag.  */
1238 void
md_convert_frag(bfd * abfd ATTRIBUTE_UNUSED,segT asec ATTRIBUTE_UNUSED,fragS * fragp ATTRIBUTE_UNUSED)1239 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec ATTRIBUTE_UNUSED,
1240 		 fragS *fragp ATTRIBUTE_UNUSED)
1241 {
1242   /* fragp->fr_fix += 8; */
1243 }
1244 
1245 /* Standard calling conventions leave the CFA at SP on entry.  */
1246 void
loongarch_cfi_frame_initial_instructions(void)1247 loongarch_cfi_frame_initial_instructions (void)
1248 {
1249   cfi_add_CFA_def_cfa_register (3 /* $sp */);
1250 }
1251 
1252 int
loongarch_dwarf2_addr_size(void)1253 loongarch_dwarf2_addr_size (void)
1254 {
1255   return LARCH_opts.ase_lp64 ? 8 : 4;
1256 }
1257 
1258 void
tc_loongarch_parse_to_dw2regnum(expressionS * exp)1259 tc_loongarch_parse_to_dw2regnum (expressionS *exp)
1260 {
1261   expression_and_evaluate (exp);
1262 }
1263 
1264 void
md_show_usage(FILE * stream)1265 md_show_usage (FILE *stream)
1266 {
1267   fprintf (stream, _("LARCH options:\n"));
1268   /* FIXME */
1269 }
1270 
1271 /* Fill in an rs_align_code fragment.  We want to fill 'andi $r0,$r0,0'.  */
1272 void
loongarch_handle_align(fragS * fragp)1273 loongarch_handle_align (fragS *fragp)
1274 {
1275   /* char nop_opcode; */
1276   char *p;
1277   int bytes, size, excess;
1278   valueT opcode;
1279 
1280   if (fragp->fr_type != rs_align_code)
1281     return;
1282 
1283   struct loongarch_cl_insn nop =
1284     { .name = "andi", .arg_strs = { "$r0", "$r0", "0", NULL } };
1285 
1286   get_loongarch_opcode (&nop);
1287   gas_assert (nop.all_match);
1288 
1289   p = fragp->fr_literal + fragp->fr_fix;
1290   opcode = nop.insn_bin;
1291   size = 4;
1292 
1293   bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
1294   excess = bytes % size;
1295 
1296   gas_assert (excess < 4);
1297   fragp->fr_fix += excess;
1298 
1299   while (excess-- != 0)
1300     *p++ = 0;
1301 
1302   md_number_to_chars (p, opcode, size);
1303   fragp->fr_var = size;
1304 }
1305 
1306 void
loongarch_elf_final_processing(void)1307 loongarch_elf_final_processing (void)
1308 {
1309   elf_elfheader (stdoutput)->e_flags = LARCH_opts.ase_abi;
1310 }
1311