Home | History | Annotate | Line # | Download | only in config
tc-loongarch.c revision 1.1
      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
    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
    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 *
    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 const char *
    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
    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
    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
    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 *
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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 *
    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
    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
   1051 md_assemble (char *str)
   1052 {
   1053   loongarch_assemble_INSNs (str);
   1054 }
   1055 
   1056 const char *
   1057 md_atof (int type, char *litP, int *sizeP)
   1058 {
   1059   return ieee_md_atof (type, litP, sizeP, FALSE);
   1060 }
   1061 
   1062 void
   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
   1071 md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
   1072 {
   1073   return 0;
   1074 }
   1075 
   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
   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
   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
   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 *
   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
   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
   1247 loongarch_cfi_frame_initial_instructions (void)
   1248 {
   1249   cfi_add_CFA_def_cfa_register (3 /* $sp */);
   1250 }
   1251 
   1252 int
   1253 loongarch_dwarf2_addr_size (void)
   1254 {
   1255   return LARCH_opts.ase_lp64 ? 8 : 4;
   1256 }
   1257 
   1258 void
   1259 tc_loongarch_parse_to_dw2regnum (expressionS *exp)
   1260 {
   1261   expression_and_evaluate (exp);
   1262 }
   1263 
   1264 void
   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
   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
   1307 loongarch_elf_final_processing (void)
   1308 {
   1309   elf_elfheader (stdoutput)->e_flags = LARCH_opts.ase_abi;
   1310 }
   1311