]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gas/config/tc-loongarch.c
Symbols with GOT relocatios do not fix adjustbale
[thirdparty/binutils-gdb.git] / gas / config / tc-loongarch.c
1 /* tc-loongarch.c -- Assemble for the LoongArch ISA
2
3 Copyright (C) 2021-2023 Free Software Foundation, Inc.
4 Contributed by Loongson Ltd.
5
6 This file is part of GAS.
7
8 GAS is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the license, or
11 (at your option) any later version.
12
13 GAS is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; see the file COPYING3. If not,
20 see <http://www.gnu.org/licenses/>. */
21
22 #include "as.h"
23 #include "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
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_SOFT_FLOAT;
147 lp64['f'] = lp64['F'] = EF_LOONGARCH_ABI_SINGLE_FLOAT;
148 lp64['d'] = lp64['D'] = EF_LOONGARCH_ABI_DOUBLE_FLOAT;
149
150 ilp32['s'] = ilp32['S'] = EF_LOONGARCH_ABI_SOFT_FLOAT;
151 ilp32['f'] = ilp32['F'] = EF_LOONGARCH_ABI_SINGLE_FLOAT;
152 ilp32['d'] = ilp32['D'] = EF_LOONGARCH_ABI_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
216 loongarch_after_parse_args ()
217 {
218 /* Set default ABI/ISA LP64D. */
219 if (!LARCH_opts.ase_ilp32)
220 {
221 if (strcmp (default_arch, "loongarch64") == 0)
222 {
223 LARCH_opts.ase_abi = EF_LOONGARCH_ABI_DOUBLE_FLOAT;
224 LARCH_opts.ase_ilp32 = 1;
225 LARCH_opts.ase_lp64 = 1;
226 }
227 else if (strcmp (default_arch, "loongarch32") == 0)
228 {
229 LARCH_opts.ase_abi = EF_LOONGARCH_ABI_DOUBLE_FLOAT;
230 LARCH_opts.ase_ilp32 = 1;
231 }
232 else
233 as_bad ("unknown default architecture `%s'", default_arch);
234 }
235
236 LARCH_opts.ase_abi |= EF_LOONGARCH_OBJABI_V1;
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 *
326 loongarch_target_format ()
327 {
328 return LARCH_opts.ase_lp64 ? "elf64-loongarch" : "elf32-loongarch";
329 }
330
331 void
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
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 void
366 s_loongarch_align (int arg)
367 {
368 const char *t = input_line_pointer;
369 while (!is_end_of_line[(unsigned char) *t] && *t != ',')
370 ++t;
371 if (*t == ',')
372 s_align_ptwo (arg);
373 else
374 s_align_ptwo (0);
375 }
376
377 /* Handle the .dtprelword and .dtpreldword pseudo-ops. They generate
378 a 32-bit or 64-bit DTP-relative relocation (BYTES says which) for
379 use in DWARF debug information. */
380
381 static void
382 s_dtprel (int bytes)
383 {
384 expressionS ex;
385 char *p;
386
387 expression (&ex);
388
389 if (ex.X_op != O_symbol)
390 {
391 as_bad (_("Unsupported use of %s"),
392 (bytes == 8 ? ".dtpreldword" : ".dtprelword"));
393 ignore_rest_of_line ();
394 }
395
396 p = frag_more (bytes);
397 md_number_to_chars (p, 0, bytes);
398 fix_new_exp (frag_now, p - frag_now->fr_literal, bytes, &ex, FALSE,
399 (bytes == 8
400 ? BFD_RELOC_LARCH_TLS_DTPREL64
401 : BFD_RELOC_LARCH_TLS_DTPREL32));
402
403 demand_empty_rest_of_line ();
404 }
405
406 static const pseudo_typeS loongarch_pseudo_table[] =
407 {
408 { "align", s_loongarch_align, -4 },
409 { "dword", cons, 8 },
410 { "word", cons, 4 },
411 { "half", cons, 2 },
412 { "dtprelword", s_dtprel, 4 },
413 { "dtpreldword", s_dtprel, 8 },
414 { NULL, NULL, 0 },
415 };
416
417 void
418 loongarch_pop_insert (void)
419 {
420 pop_insert (loongarch_pseudo_table);
421 }
422
423 #define INTERNAL_LABEL_SPECIAL 10
424 static unsigned long internal_label_count[INTERNAL_LABEL_SPECIAL] = { 0 };
425
426 static const char *
427 loongarch_internal_label_name (unsigned long label, int augend)
428 {
429 static char symbol_name_build[24];
430 unsigned long want_label;
431 char *p;
432
433 want_label = internal_label_count[label] + augend;
434
435 p = symbol_name_build;
436 #ifdef LOCAL_LABEL_PREFIX
437 *p++ = LOCAL_LABEL_PREFIX;
438 #endif
439 *p++ = 'L';
440 for (; label; label /= 10)
441 *p++ = label % 10 + '0';
442 /* Make sure internal label never belong to normal label namespace. */
443 *p++ = ':';
444 for (; want_label; want_label /= 10)
445 *p++ = want_label % 10 + '0';
446 *p++ = '\0';
447 return symbol_name_build;
448 }
449
450 static void
451 setup_internal_label_here (unsigned long label)
452 {
453 assert (label < INTERNAL_LABEL_SPECIAL);
454 internal_label_count[label]++;
455 colon (loongarch_internal_label_name (label, 0));
456 }
457
458 void
459 get_internal_label (expressionS *label_expr, unsigned long label,
460 int augend /* 0 for previous, 1 for next. */)
461 {
462 assert (label < INTERNAL_LABEL_SPECIAL);
463 if (augend == 0 && internal_label_count[label] == 0)
464 as_fatal (_("internal error: we have no internal label yet"));
465 label_expr->X_op = O_symbol;
466 label_expr->X_add_symbol =
467 symbol_find_or_make (loongarch_internal_label_name (label, augend));
468 label_expr->X_add_number = 0;
469 }
470
471 static int
472 is_internal_label (const char *c_str)
473 {
474 do
475 {
476 if (*c_str != ':')
477 break;
478 c_str++;
479 if (!('0' <= *c_str && *c_str <= '9'))
480 break;
481 while ('0' <= *c_str && *c_str <= '9')
482 c_str++;
483 if (*c_str != 'b' && *c_str != 'f')
484 break;
485 c_str++;
486 return *c_str == '\0';
487 }
488 while (0);
489 return 0;
490 }
491
492 static int
493 is_label (const char *c_str)
494 {
495 if (is_internal_label (c_str))
496 return 1;
497 else if ('0' <= *c_str && *c_str <= '9')
498 {
499 /* [0-9]+[bf] */
500 while ('0' <= *c_str && *c_str <= '9')
501 c_str++;
502 return *c_str == 'b' || *c_str == 'f';
503 }
504 else if (is_name_beginner (*c_str))
505 {
506 /* [a-zA-Z\._\$][0-9a-zA-Z\._\$]* */
507 c_str++;
508 while (is_part_of_name (*c_str))
509 c_str++;
510 return *c_str == '\0';
511 }
512 else
513 return 0;
514 }
515
516 static int
517 is_label_with_addend (const char *c_str)
518 {
519 if (is_internal_label (c_str))
520 return 1;
521 else if ('0' <= *c_str && *c_str <= '9')
522 {
523 /* [0-9]+[bf] */
524 while ('0' <= *c_str && *c_str <= '9')
525 c_str++;
526 if (*c_str == 'b' || *c_str == 'f')
527 c_str++;
528 else
529 return 0;
530 return *c_str == '\0'
531 || ((*c_str == '-' || *c_str == '+')
532 && is_unsigned (c_str + 1));
533 }
534 else if (is_name_beginner (*c_str))
535 {
536 /* [a-zA-Z\._\$][0-9a-zA-Z\._\$]* */
537 c_str++;
538 while (is_part_of_name (*c_str))
539 c_str++;
540 return *c_str == '\0'
541 || ((*c_str == '-' || *c_str == '+')
542 && is_unsigned (c_str + 1));
543 }
544 else
545 return 0;
546 }
547
548 static int32_t
549 loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
550 const char *bit_field,
551 const char *arg, void *context)
552 {
553 struct loongarch_cl_insn *ip = context;
554 offsetT imm, ret = 0;
555 size_t reloc_num_we_have = MAX_RELOC_NUMBER_A_INSN - ip->reloc_num;
556 size_t reloc_num = 0;
557
558 if (!ip->match_now)
559 return 0;
560
561 switch (esc_ch1)
562 {
563 case 'l':
564 switch (esc_ch2)
565 {
566 default:
567 ip->match_now = is_label (arg);
568 if (!ip->match_now && is_label_with_addend (arg))
569 as_fatal (_("This label shouldn't be with addend."));
570 break;
571 case 'a':
572 ip->match_now = is_label_with_addend (arg);
573 break;
574 }
575 break;
576 case 's':
577 case 'u':
578 ip->match_now =
579 loongarch_parse_expr (arg, ip->reloc_info + ip->reloc_num,
580 reloc_num_we_have, &reloc_num, &imm) == 0;
581
582 if (!ip->match_now)
583 break;
584
585 ret = imm;
586 if (reloc_num)
587 {
588 bfd_reloc_code_real_type reloc_type = BFD_RELOC_NONE;
589 reloc_num_we_have -= reloc_num;
590 if (reloc_num_we_have == 0)
591 as_fatal (_("expr too huge") /* Want one more reloc. */);
592 if (esc_ch1 == 'u')
593 {
594 if (strncmp (bit_field, "10:12", strlen ("10:12")) == 0)
595 reloc_type = BFD_RELOC_LARCH_SOP_POP_32_U_10_12;
596 }
597 else if (esc_ch1 == 's')
598 {
599 if (strncmp (bit_field, "10:16<<2", strlen ("10:16<<2")) == 0)
600 reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2;
601 else if (strncmp (bit_field, "0:5|10:16<<2",
602 strlen ("0:5|10:16<<2")) == 0)
603 reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2;
604 else if (strncmp (bit_field, "0:10|10:16<<2",
605 strlen ("0:10|10:16<<2")) == 0)
606 reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2;
607 else if (strncmp (bit_field, "10:12", strlen ("10:12")) == 0)
608 reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_12;
609 else if (strncmp (bit_field, "5:20", strlen ("5:20")) == 0)
610 reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_5_20;
611 else if (strncmp (bit_field, "10:16", strlen ("10:16")) == 0)
612 reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_16;
613 else if (strncmp (bit_field, "10:5", strlen ("10:5")) == 0)
614 reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_5;
615 }
616 if (reloc_type == BFD_RELOC_NONE)
617 as_fatal (
618 _("not support reloc bit-field\nfmt: %c%c %s\nargs: %s"),
619 esc_ch1, esc_ch2, bit_field, arg);
620 if (ip->reloc_info[0].type >= BFD_RELOC_LARCH_B16
621 && ip->reloc_info[0].type < BFD_RELOC_LARCH_RELAX)
622 {
623 /* As we compact stack-relocs, it is no need for pop operation.
624 But break out until here in order to check the imm field.
625 May be reloc_num > 1 if implement relax? */
626 ip->reloc_num += reloc_num;
627 break;
628 }
629 reloc_num++;
630 ip->reloc_num += reloc_num;
631 ip->reloc_info[ip->reloc_num - 1].type = reloc_type;
632 ip->reloc_info[ip->reloc_num - 1].value = const_0;
633 }
634 break;
635 case 'r':
636 imm = (intptr_t) str_hash_find (r_htab, arg);
637 ip->match_now = 0 < imm;
638 ret = imm - 1;
639 break;
640 case 'f':
641 imm = (intptr_t) str_hash_find (f_htab, arg);
642 ip->match_now = 0 < imm;
643 ret = imm - 1;
644 break;
645 case 'c':
646 switch (esc_ch2)
647 {
648 case 'r':
649 imm = (intptr_t) str_hash_find (cr_htab, arg);
650 break;
651 default:
652 imm = (intptr_t) str_hash_find (c_htab, arg);
653 }
654 ip->match_now = 0 < imm;
655 ret = imm - 1;
656 break;
657 case 'v':
658 imm = (intptr_t) str_hash_find (v_htab, arg);
659 ip->match_now = 0 < imm;
660 ret = imm - 1;
661 break;
662 case 'x':
663 imm = (intptr_t) str_hash_find (x_htab, arg);
664 ip->match_now = 0 < imm;
665 ret = imm - 1;
666 break;
667 case '\0':
668 ip->all_match = ip->match_now;
669 ip->insn_length =
670 ip->insn->mask ? loongarch_insn_length (ip->insn->match) : 0;
671 /* FIXME: now we have no relax insn. */
672 ip->relax_max_length = ip->insn_length;
673 break;
674 default:
675 as_fatal (_("unknown escape"));
676 }
677
678 do
679 {
680 /* Check imm overflow. */
681 int bit_width, bits_needed_s, bits_needed_u;
682 char *t;
683
684 if (!ip->match_now)
685 break;
686
687 if (0 < reloc_num)
688 break;
689
690 bit_width = loongarch_get_bit_field_width (bit_field, &t);
691
692 if (bit_width == -1)
693 /* No specify bit width. */
694 break;
695
696 imm = ret;
697 if (t[0] == '<' && t[1] == '<')
698 {
699 int i = strtol (t += 2, &t, 10), j;
700 for (j = i; 0 < j; j--, imm >>= 1)
701 if (imm & 1)
702 as_fatal (_("require imm low %d bit is 0."), i);
703 }
704
705 if (*t == '+')
706 imm -= strtol (t, &t, 10);
707
708 bits_needed_s = loongarch_bits_imm_needed (imm, 1);
709 bits_needed_u = loongarch_bits_imm_needed (imm, 0);
710
711 if ((esc_ch1 == 's' && bit_width < bits_needed_s)
712 || (esc_ch1 != 's' && bit_width < bits_needed_u))
713 /* How to do after we detect overflow. */
714 as_fatal (_("Immediate overflow.\n"
715 "format: %c%c%s\n"
716 "arg: %s"),
717 esc_ch1, esc_ch2, bit_field, arg);
718 }
719 while (0);
720
721 if (esc_ch1 != '\0')
722 {
723 ip->args[ip->arg_num] = ret;
724 ip->arg_num++;
725 }
726 return ret;
727 }
728
729 static void
730 get_loongarch_opcode (struct loongarch_cl_insn *insn)
731 {
732 const struct loongarch_opcode *it;
733 struct loongarch_ase *ase;
734 for (ase = loongarch_ASEs; ase->enabled; ase++)
735 {
736 if (!*ase->enabled || (ase->include && !*ase->include)
737 || (ase->exclude && *ase->exclude))
738 continue;
739
740 if (!ase->name_hash_entry)
741 {
742 ase->name_hash_entry = str_htab_create ();
743 for (it = ase->opcodes; it->name; it++)
744 {
745 if ((!it->include || (it->include && *it->include))
746 && (!it->exclude || (it->exclude && !(*it->exclude))))
747 str_hash_insert (ase->name_hash_entry, it->name,
748 (void *) it, 0);
749 }
750 }
751
752 if ((it = str_hash_find (ase->name_hash_entry, insn->name)) == NULL)
753 continue;
754
755 do
756 {
757 insn->insn = it;
758 insn->match_now = 1;
759 insn->all_match = 0;
760 insn->arg_num = 0;
761 insn->reloc_num = 0;
762 insn->insn_bin = (loongarch_foreach_args
763 (it->format, insn->arg_strs,
764 loongarch_args_parser_can_match_arg_helper,
765 insn));
766 if (insn->all_match && !(it->include && !*it->include)
767 && !(it->exclude && *it->exclude))
768 {
769 insn->insn_bin |= it->match;
770 return;
771 }
772 it++;
773 }
774 while (it->name && strcasecmp (it->name, insn->name) == 0);
775 }
776 }
777
778 static int
779 check_this_insn_before_appending (struct loongarch_cl_insn *ip)
780 {
781 int ret = 0;
782
783 if (strncmp (ip->name, "la.abs", 6) == 0)
784 {
785 ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_MARK_LA;
786 ip->reloc_info[ip->reloc_num].value = const_0;
787 ip->reloc_num++;
788 }
789 else if (ip->insn->mask == 0xffff8000
790 /* amswap.w rd, rk, rj */
791 && ((ip->insn_bin & 0xfff00000) == 0x38600000
792 /* ammax_db.wu rd, rk, rj */
793 || (ip->insn_bin & 0xffff0000) == 0x38700000
794 /* ammin_db.wu rd, rk, rj */
795 || (ip->insn_bin & 0xffff0000) == 0x38710000))
796 {
797 /* For AMO insn amswap.[wd], amadd.[wd], etc. */
798 if (ip->args[0] != 0
799 && (ip->args[0] == ip->args[1] || ip->args[0] == ip->args[2]))
800 as_fatal (_("AMO insns require rd != base && rd != rt"
801 " when rd isn't $r0"));
802 }
803 else if ((ip->insn->mask == 0xffe08000
804 /* bstrins.w rd, rj, msbw, lsbw */
805 && (ip->insn_bin & 0xffe00000) == 0x00600000)
806 || (ip->insn->mask == 0xffc00000
807 /* bstrins.d rd, rj, msbd, lsbd */
808 && (ip->insn_bin & 0xff800000) == 0x00800000))
809 {
810 /* For bstr(ins|pick).[wd]. */
811 if (ip->args[2] < ip->args[3])
812 as_fatal (_("bstr(ins|pick).[wd] require msbd >= lsbd"));
813 }
814 else if (ip->insn->mask != 0 && (ip->insn_bin & 0xfe0003c0) == 0x04000000
815 /* csrxchg rd, rj, csr_num */
816 && (strcmp ("csrxchg", ip->name) == 0))
817 as_fatal (_("csrxchg require rj != $r0 && rj != $r1"));
818
819 return ret;
820 }
821
822 static void
823 install_insn (const struct loongarch_cl_insn *insn)
824 {
825 char *f = insn->frag->fr_literal + insn->where;
826 if (0 < insn->insn_length)
827 md_number_to_chars (f, insn->insn_bin, insn->insn_length);
828 }
829
830 static void
831 move_insn (struct loongarch_cl_insn *insn, fragS *frag, long where)
832 {
833 size_t i;
834 insn->frag = frag;
835 insn->where = where;
836 for (i = 0; i < insn->reloc_num; i++)
837 {
838 insn->fixp[i]->fx_frag = frag;
839 insn->fixp[i]->fx_where = where;
840 }
841 install_insn (insn);
842 }
843
844 /* Add INSN to the end of the output. */
845 static void
846 append_fixed_insn (struct loongarch_cl_insn *insn)
847 {
848 char *f = frag_more (insn->insn_length);
849 move_insn (insn, frag_now, f - frag_now->fr_literal);
850 }
851
852 static void
853 append_fixp_and_insn (struct loongarch_cl_insn *ip)
854 {
855 reloc_howto_type *howto;
856 bfd_reloc_code_real_type reloc_type;
857 struct reloc_info *reloc_info = ip->reloc_info;
858 size_t i;
859
860 dwarf2_emit_insn (0);
861
862 for (i = 0; i < ip->reloc_num; i++)
863 {
864 reloc_type = reloc_info[i].type;
865 howto = bfd_reloc_type_lookup (stdoutput, reloc_type);
866 if (howto == NULL)
867 as_fatal (_("no HOWTO loong relocation number %d"), reloc_type);
868
869 ip->fixp[i] =
870 fix_new_exp (ip->frag, ip->where, bfd_get_reloc_size (howto),
871 &reloc_info[i].value, FALSE, reloc_type);
872 }
873
874 if (ip->insn_length < ip->relax_max_length)
875 as_fatal (_("Internal error: not support relax now"));
876 else
877 append_fixed_insn (ip);
878 }
879
880 /* Ask helper for returning a malloced c_str or NULL. */
881 static char *
882 assember_macro_helper (const char *const args[], void *context_ptr)
883 {
884 struct loongarch_cl_insn *insn = context_ptr;
885 char *ret = NULL;
886 if ( strcmp (insn->name, "li.w") == 0 || strcmp (insn->name, "li.d") == 0)
887 {
888 char args_buf[50], insns_buf[200];
889 const char *arg_strs[6];
890 uint32_t hi32, lo32;
891
892 /* We pay attention to sign extend beacause it is chance of reduce insn.
893 The exception is 12-bit and hi-12-bit unsigned,
894 we need a 'ori' or a 'lu52i.d' accordingly. */
895 char all0_bit_vec, sign_bit_vec, allf_bit_vec, paritial_is_sext_of_prev;
896
897 lo32 = insn->args[1] & 0xffffffff;
898 hi32 = insn->args[1] >> 32;
899
900 if (strcmp (insn->name, "li.w") == 0)
901 {
902 if (hi32 != 0 && hi32 != 0xffffffff)
903 as_fatal (_("li overflow: hi32:0x%x lo32:0x%x"), hi32, lo32);
904 hi32 = lo32 & 0x80000000 ? 0xffffffff : 0;
905 }
906
907 if (strcmp (insn->name, "li.d") == 0 && !LARCH_opts.ase_lp64)
908 as_fatal (_("we can't li.d on 32bit-arch"));
909
910 snprintf (args_buf, sizeof (args_buf), "0x%x,0x%x,0x%x,0x%x,%s",
911 (hi32 >> 20) & 0xfff, hi32 & 0xfffff, (lo32 >> 12) & 0xfffff,
912 lo32 & 0xfff, args[0]);
913 loongarch_split_args_by_comma (args_buf, arg_strs);
914
915 all0_bit_vec =
916 ((((hi32 & 0xfff00000) == 0) << 3) | (((hi32 & 0x000fffff) == 0) << 2)
917 | (((lo32 & 0xfffff000) == 0) << 1) | ((lo32 & 0x00000fff) == 0));
918 sign_bit_vec =
919 ((((hi32 & 0x80000000) != 0) << 3) | (((hi32 & 0x00080000) != 0) << 2)
920 | (((lo32 & 0x80000000) != 0) << 1) | ((lo32 & 0x00000800) != 0));
921 allf_bit_vec =
922 ((((hi32 & 0xfff00000) == 0xfff00000) << 3)
923 | (((hi32 & 0x000fffff) == 0x000fffff) << 2)
924 | (((lo32 & 0xfffff000) == 0xfffff000) << 1)
925 | ((lo32 & 0x00000fff) == 0x00000fff));
926 paritial_is_sext_of_prev =
927 (all0_bit_vec ^ allf_bit_vec) & (all0_bit_vec ^ (sign_bit_vec << 1));
928
929 static const char *const li_32bit[] =
930 {
931 "lu12i.w %5,%3&0x80000?%3-0x100000:%3;ori %5,%5,%4;",
932 "lu12i.w %5,%3&0x80000?%3-0x100000:%3;",
933 "addi.w %5,$r0,%4&0x800?%4-0x1000:%4;",
934 "or %5,$r0,$r0;",
935 };
936 static const char *const li_hi_32bit[] =
937 {
938 "lu32i.d %5,%2&0x80000?%2-0x100000:%2;"
939 "lu52i.d %5,%5,%1&0x800?%1-0x1000:%1;",
940 "lu52i.d %5,%5,%1&0x800?%1-0x1000:%1;",
941 "lu32i.d %5,%2&0x80000?%2-0x100000:%2;",
942 "",
943 };
944 do
945 {
946 insns_buf[0] = '\0';
947 if (paritial_is_sext_of_prev == 0x7)
948 {
949 strcat (insns_buf, "lu52i.d %5,$r0,%1&0x800?%1-0x1000:%1;");
950 break;
951 }
952 if ((all0_bit_vec & 0x3) == 0x2)
953 strcat (insns_buf, "ori %5,$r0,%4;");
954 else
955 strcat (insns_buf, li_32bit[paritial_is_sext_of_prev & 0x3]);
956 strcat (insns_buf, li_hi_32bit[paritial_is_sext_of_prev >> 2]);
957 }
958 while (0);
959
960 ret = loongarch_expand_macro (insns_buf, arg_strs, NULL, NULL,
961 sizeof (args_buf));
962 }
963
964 return ret;
965 }
966
967 /* Accept instructions separated by ';'
968 * assuming 'not starting with space and not ending with space' or pass in
969 * empty c_str. */
970 static void
971 loongarch_assemble_INSNs (char *str)
972 {
973 char *rest;
974 size_t len_str = strlen(str);
975
976 for (rest = str; *rest != ';' && *rest != '\0'; rest++);
977 if (*rest == ';')
978 *rest++ = '\0';
979
980 if (*str == ':')
981 {
982 str++;
983 setup_internal_label_here (strtol (str, &str, 10));
984 str++;
985 }
986
987 do
988 {
989 if (*str == '\0')
990 break;
991
992 struct loongarch_cl_insn the_one = { 0 };
993 the_one.name = str;
994
995 for (; *str && *str != ' '; str++)
996 ;
997 if (*str == ' ')
998 *str++ = '\0';
999
1000 loongarch_split_args_by_comma (str, the_one.arg_strs);
1001 get_loongarch_opcode (&the_one);
1002
1003 if (!the_one.all_match)
1004 {
1005 char *ss = loongarch_cat_splited_strs (the_one.arg_strs);
1006 as_bad (_("no match insn: %s\t%s"), the_one.name, ss ? ss : "");
1007 free(ss);
1008 return;
1009 }
1010
1011 if (check_this_insn_before_appending (&the_one) != 0)
1012 break;
1013
1014 append_fixp_and_insn (&the_one);
1015 if (the_one.insn_length == 0 && the_one.insn->macro)
1016 {
1017 char *c_str = loongarch_expand_macro (the_one.insn->macro,
1018 the_one.arg_strs,
1019 assember_macro_helper,
1020 &the_one, len_str);
1021 loongarch_assemble_INSNs (c_str);
1022 free (c_str);
1023 }
1024 }
1025 while (0);
1026
1027 if (*rest != '\0')
1028 loongarch_assemble_INSNs (rest);
1029 }
1030
1031 void
1032 md_assemble (char *str)
1033 {
1034 loongarch_assemble_INSNs (str);
1035 }
1036
1037 const char *
1038 md_atof (int type, char *litP, int *sizeP)
1039 {
1040 return ieee_md_atof (type, litP, sizeP, FALSE);
1041 }
1042
1043 void
1044 md_number_to_chars (char *buf, valueT val, int n)
1045 {
1046 number_to_chars_littleendian (buf, val, n);
1047 }
1048
1049 /* The location from which a PC relative jump should be calculated,
1050 given a PC relative reloc. */
1051 long
1052 md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
1053 {
1054 return 0;
1055 }
1056
1057 static void fix_reloc_insn (fixS *fixP, bfd_vma reloc_val, char *buf)
1058 {
1059 reloc_howto_type *howto;
1060 insn_t insn;
1061 howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
1062
1063 insn = bfd_getl32 (buf);
1064
1065 if (!loongarch_adjust_reloc_bitsfield(howto, &reloc_val))
1066 as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow");
1067
1068 insn = (insn & (insn_t)howto->src_mask)
1069 | ((insn & (~(insn_t)howto->dst_mask)) | reloc_val);
1070
1071 bfd_putl32 (insn, buf);
1072 }
1073
1074 void
1075 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
1076 {
1077 static int64_t stack_top;
1078 static int last_reloc_is_sop_push_pcrel_1 = 0;
1079 int last_reloc_is_sop_push_pcrel = last_reloc_is_sop_push_pcrel_1;
1080 segT sub_segment;
1081 last_reloc_is_sop_push_pcrel_1 = 0;
1082
1083 char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
1084 switch (fixP->fx_r_type)
1085 {
1086 case BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL:
1087 case BFD_RELOC_LARCH_SOP_PUSH_TLS_GD:
1088 case BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT:
1089 case BFD_RELOC_LARCH_TLS_LE_HI20:
1090 case BFD_RELOC_LARCH_TLS_LE_LO12:
1091 case BFD_RELOC_LARCH_TLS_LE64_LO20:
1092 case BFD_RELOC_LARCH_TLS_LE64_HI12:
1093 case BFD_RELOC_LARCH_TLS_IE_PC_HI20:
1094 case BFD_RELOC_LARCH_TLS_IE_PC_LO12:
1095 case BFD_RELOC_LARCH_TLS_IE64_PC_LO20:
1096 case BFD_RELOC_LARCH_TLS_IE64_PC_HI12:
1097 case BFD_RELOC_LARCH_TLS_IE_HI20:
1098 case BFD_RELOC_LARCH_TLS_IE_LO12:
1099 case BFD_RELOC_LARCH_TLS_IE64_LO20:
1100 case BFD_RELOC_LARCH_TLS_IE64_HI12:
1101 case BFD_RELOC_LARCH_TLS_LD_PC_HI20:
1102 case BFD_RELOC_LARCH_TLS_LD_HI20:
1103 case BFD_RELOC_LARCH_TLS_GD_PC_HI20:
1104 case BFD_RELOC_LARCH_TLS_GD_HI20:
1105 /* Add tls lo (got_lo reloc type). */
1106 if (fixP->fx_addsy == NULL)
1107 as_bad_where (fixP->fx_file, fixP->fx_line,
1108 _("Relocation against a constant"));
1109 S_SET_THREAD_LOCAL (fixP->fx_addsy);
1110 break;
1111
1112 case BFD_RELOC_LARCH_SOP_PUSH_PCREL:
1113 if (fixP->fx_addsy == NULL)
1114 as_bad_where (fixP->fx_file, fixP->fx_line,
1115 _("Relocation against a constant"));
1116
1117 last_reloc_is_sop_push_pcrel_1 = 1;
1118 if (S_GET_SEGMENT (fixP->fx_addsy) == seg)
1119 stack_top = (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset
1120 - (fixP->fx_where + fixP->fx_frag->fr_address));
1121 else
1122 stack_top = 0;
1123 break;
1124
1125 case BFD_RELOC_LARCH_SOP_POP_32_S_10_5:
1126 case BFD_RELOC_LARCH_SOP_POP_32_S_10_12:
1127 case BFD_RELOC_LARCH_SOP_POP_32_U_10_12:
1128 case BFD_RELOC_LARCH_SOP_POP_32_S_10_16:
1129 case BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2:
1130 case BFD_RELOC_LARCH_SOP_POP_32_S_5_20:
1131 case BFD_RELOC_LARCH_SOP_POP_32_U:
1132 case BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2:
1133 case BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2:
1134 if (!last_reloc_is_sop_push_pcrel)
1135 break;
1136
1137 fix_reloc_insn (fixP, (bfd_vma)stack_top, buf);
1138 break;
1139
1140 case BFD_RELOC_64:
1141 case BFD_RELOC_32:
1142 if (fixP->fx_r_type == BFD_RELOC_32
1143 && fixP->fx_addsy && fixP->fx_subsy
1144 && (sub_segment = S_GET_SEGMENT (fixP->fx_subsy))
1145 && strcmp (sub_segment->name, ".eh_frame") == 0
1146 && S_GET_VALUE (fixP->fx_subsy)
1147 == fixP->fx_frag->fr_address + fixP->fx_where)
1148 {
1149 fixP->fx_r_type = BFD_RELOC_LARCH_32_PCREL;
1150 fixP->fx_subsy = NULL;
1151 break;
1152 }
1153
1154 if (fixP->fx_subsy)
1155 {
1156 fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
1157 fixP->fx_next->fx_addsy = fixP->fx_subsy;
1158 fixP->fx_next->fx_subsy = NULL;
1159 fixP->fx_next->fx_offset = 0;
1160 fixP->fx_subsy = NULL;
1161
1162 switch (fixP->fx_r_type)
1163 {
1164 case BFD_RELOC_64:
1165 fixP->fx_r_type = BFD_RELOC_LARCH_ADD64;
1166 fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB64;
1167 break;
1168 case BFD_RELOC_32:
1169 fixP->fx_r_type = BFD_RELOC_LARCH_ADD32;
1170 fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB32;
1171 break;
1172 default:
1173 break;
1174 }
1175
1176 md_number_to_chars (buf, 0, fixP->fx_size);
1177 }
1178
1179 if (fixP->fx_addsy == NULL)
1180 {
1181 fixP->fx_done = 1;
1182 md_number_to_chars (buf, *valP, fixP->fx_size);
1183 }
1184 break;
1185
1186 case BFD_RELOC_24:
1187 case BFD_RELOC_16:
1188 case BFD_RELOC_8:
1189 fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
1190 fixP->fx_next->fx_addsy = fixP->fx_subsy;
1191 fixP->fx_next->fx_subsy = NULL;
1192 fixP->fx_next->fx_offset = 0;
1193 fixP->fx_subsy = NULL;
1194
1195 switch (fixP->fx_r_type)
1196 {
1197 case BFD_RELOC_24:
1198 fixP->fx_r_type = BFD_RELOC_LARCH_ADD24;
1199 fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB24;
1200 break;
1201 case BFD_RELOC_16:
1202 fixP->fx_r_type = BFD_RELOC_LARCH_ADD16;
1203 fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB16;
1204 break;
1205 case BFD_RELOC_8:
1206 fixP->fx_r_type = BFD_RELOC_LARCH_ADD8;
1207 fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB8;
1208 break;
1209 default:
1210 break;
1211 }
1212
1213 md_number_to_chars (buf, 0, fixP->fx_size);
1214
1215 if (fixP->fx_next->fx_addsy == NULL)
1216 fixP->fx_next->fx_done = 1;
1217
1218 if (fixP->fx_addsy == NULL)
1219 {
1220 fixP->fx_done = 1;
1221 md_number_to_chars (buf, *valP, fixP->fx_size);
1222 }
1223 break;
1224
1225 case BFD_RELOC_LARCH_B16:
1226 case BFD_RELOC_LARCH_B21:
1227 case BFD_RELOC_LARCH_B26:
1228 if (fixP->fx_addsy == NULL)
1229 {
1230 as_bad_where (fixP->fx_file, fixP->fx_line,
1231 _ ("Relocation against a constant."));
1232 }
1233 if (S_GET_SEGMENT (fixP->fx_addsy) == seg
1234 && !S_FORCE_RELOC (fixP->fx_addsy, 1))
1235 {
1236 int64_t sym_addend = S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset;
1237 int64_t pc = fixP->fx_where + fixP->fx_frag->fr_address;
1238 fix_reloc_insn (fixP, sym_addend - pc, buf);
1239 fixP->fx_done = 1;
1240 }
1241
1242 break;
1243
1244 default:
1245 break;
1246 }
1247 }
1248
1249 int
1250 loongarch_relax_frag (asection *sec ATTRIBUTE_UNUSED,
1251 fragS *fragp ATTRIBUTE_UNUSED,
1252 long stretch ATTRIBUTE_UNUSED)
1253 {
1254 return 0;
1255 }
1256
1257 int
1258 md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED,
1259 asection *segtype ATTRIBUTE_UNUSED)
1260 {
1261 return 0;
1262 }
1263
1264 int
1265 loongarch_fix_adjustable (fixS *fix)
1266 {
1267 /* Prevent all adjustments to global symbols. */
1268 if (S_IS_EXTERNAL (fix->fx_addsy)
1269 || S_IS_WEAK (fix->fx_addsy)
1270 || S_FORCE_RELOC (fix->fx_addsy, true))
1271 return 0;
1272
1273 /* Loongarch loads extern symbols by GOT, and if there are embedded
1274 asm(".local S"), gcc just output ".local S" to assembly file.
1275 For a local symbol with GOT relocations, this adjustments will make
1276 GOT relocation's addend not equal to zero. So this adjustments is
1277 forbidden for got relocs. */
1278 if(fix->fx_r_type == BFD_RELOC_LARCH_GOT_PC_HI20
1279 || fix->fx_r_type == BFD_RELOC_LARCH_GOT_PC_LO12
1280 || fix->fx_r_type == BFD_RELOC_LARCH_GOT64_PC_LO20
1281 || fix->fx_r_type == BFD_RELOC_LARCH_GOT64_PC_HI12
1282 || fix->fx_r_type == BFD_RELOC_LARCH_GOT_HI20
1283 || fix->fx_r_type == BFD_RELOC_LARCH_GOT_LO12
1284 || fix->fx_r_type == BFD_RELOC_LARCH_GOT64_LO20
1285 || fix->fx_r_type == BFD_RELOC_LARCH_GOT64_HI12)
1286 return 0;
1287
1288 return 1;
1289 }
1290
1291 /* Translate internal representation of relocation info to BFD target
1292 format. */
1293 arelent *
1294 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
1295 {
1296 arelent *reloc = (arelent *) xmalloc (sizeof (arelent));
1297
1298 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
1299 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
1300 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
1301 reloc->addend = fixp->fx_offset;
1302
1303 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
1304 if (reloc->howto == NULL)
1305 {
1306 as_bad_where (fixp->fx_file, fixp->fx_line,
1307 _("cannot represent %s relocation in object file"),
1308 bfd_get_reloc_code_name (fixp->fx_r_type));
1309 return NULL;
1310 }
1311
1312 return reloc;
1313 }
1314
1315 /* Convert a machine dependent frag. */
1316 void
1317 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec ATTRIBUTE_UNUSED,
1318 fragS *fragp ATTRIBUTE_UNUSED)
1319 {
1320 /* fragp->fr_fix += 8; */
1321 }
1322
1323 /* Standard calling conventions leave the CFA at SP on entry. */
1324 void
1325 loongarch_cfi_frame_initial_instructions (void)
1326 {
1327 cfi_add_CFA_def_cfa_register (3 /* $sp */);
1328 }
1329
1330 void
1331 tc_loongarch_parse_to_dw2regnum (expressionS *exp)
1332 {
1333 expression_and_evaluate (exp);
1334 }
1335
1336 void
1337 md_show_usage (FILE *stream)
1338 {
1339 fprintf (stream, _("LARCH options:\n"));
1340 /* FIXME */
1341 }
1342
1343 /* Fill in an rs_align_code fragment. We want to fill 'andi $r0,$r0,0'. */
1344 void
1345 loongarch_handle_align (fragS *fragp)
1346 {
1347 /* char nop_opcode; */
1348 char *p;
1349 int bytes, size, excess;
1350 valueT opcode;
1351
1352 if (fragp->fr_type != rs_align_code)
1353 return;
1354
1355 struct loongarch_cl_insn nop =
1356 { .name = "andi", .arg_strs = { "$r0", "$r0", "0", NULL } };
1357
1358 get_loongarch_opcode (&nop);
1359 gas_assert (nop.all_match);
1360
1361 p = fragp->fr_literal + fragp->fr_fix;
1362 opcode = nop.insn_bin;
1363 size = 4;
1364
1365 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
1366 excess = bytes % size;
1367
1368 gas_assert (excess < 4);
1369 fragp->fr_fix += excess;
1370
1371 while (excess-- != 0)
1372 *p++ = 0;
1373
1374 md_number_to_chars (p, opcode, size);
1375 fragp->fr_var = size;
1376 }
1377
1378 void
1379 loongarch_elf_final_processing (void)
1380 {
1381 elf_elfheader (stdoutput)->e_flags = LARCH_opts.ase_abi;
1382 }