(root)/
binutils-2.41/
gas/
config/
tc-loongarch.c
       1  /* tc-loongarch.c -- Assemble for the LoongArch ISA
       2  
       3     Copyright (C) 2021-2023 Free Software Foundation, Inc.
       4     Contributed by Loongson Ltd.
       5  
       6     This file is part of GAS.
       7  
       8     GAS is free software; you can redistribute it and/or modify
       9     it under the terms of the GNU General Public License as published by
      10     the Free Software Foundation; either version 3 of the license, or
      11     (at your option) any later version.
      12  
      13     GAS is distributed in the hope that it will be useful,
      14     but WITHOUT ANY WARRANTY; without even the implied warranty of
      15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16     GNU General Public License for more details.
      17  
      18     You should have received a copy of the GNU General Public License
      19     along with this program; see the file COPYING3.  If not,
      20     see <http://www.gnu.org/licenses/>.  */
      21  
      22  #include "as.h"
      23  #include "subsegs.h"
      24  #include "dw2gencfi.h"
      25  #include "loongarch-lex.h"
      26  #include "elf/loongarch.h"
      27  #include "opcode/loongarch.h"
      28  #include "obj-elf.h"
      29  #include "bfd/elfxx-loongarch.h"
      30  #include <stdlib.h>
      31  #include <string.h>
      32  #include <stdio.h>
      33  #include <assert.h>
      34  
      35  /* All information about an instruction during assemble.  */
      36  struct loongarch_cl_insn
      37  {
      38    /* First split string.  */
      39    const char *name;
      40    const char *arg_strs[MAX_ARG_NUM_PLUS_2];
      41    size_t arg_num;
      42  
      43    /* Second analyze name_str and each actual args string to match the insn
      44       in 'loongarch-opc.c'. And actual args may need be relocated.
      45       We get length of insn.  If 'insn_length == 0 && insn_mo->macro != NULL',
      46       it's a macro insntruction and we call 'md_assemble' recursively
      47       after expanding it.  */
      48    int match_now;
      49    int all_match;
      50  
      51    const struct loongarch_opcode *insn;
      52    size_t insn_length;
      53  
      54    offsetT args[MAX_ARG_NUM_PLUS_2];
      55    struct reloc_info reloc_info[MAX_RELOC_NUMBER_A_INSN];
      56    size_t reloc_num;
      57  
      58    /* For relax reserved.  We not support relax now.
      59       'insn_length < relax_max_length' means need to relax.
      60       And 'insn_length == relax_max_length' means no need to relax.  */
      61    size_t relax_max_length;
      62    relax_substateT subtype;
      63  
      64    /* Then we get the binary representation of insn
      65       and write it in to section.  */
      66    insn_t insn_bin;
      67  
      68    /* The frag that contains the instruction.  */
      69    struct frag *frag;
      70    /* The offset into FRAG of the first instruction byte.  */
      71    long where;
      72    /* The relocs associated with the instruction, if any.  */
      73    fixS *fixp[MAX_RELOC_NUMBER_A_INSN];
      74    long macro_id;
      75  };
      76  
      77  #ifndef DEFAULT_ARCH
      78  #define DEFAULT_ARCH "loongarch64"
      79  #endif
      80  
      81  /* This array holds the chars that always start a comment.  If the
      82     pre-processor is disabled, these aren't very useful.  */
      83  const char comment_chars[] = "#";
      84  
      85  /* This array holds the chars that only start a comment at the beginning of
      86     a line.  If the line seems to have the form '# 123 filename'
      87     .line and .file directives will appear in the pre-processed output.  */
      88  /* Note that input_file.c hand checks for '#' at the beginning of the
      89     first line of the input file.  This is because the compiler outputs
      90     #NO_APP at the beginning of its output.  */
      91  /* Also note that C style comments are always supported.  */
      92  const char line_comment_chars[] = "#";
      93  
      94  /* This array holds machine specific line separator characters.  */
      95  const char line_separator_chars[] = ";";
      96  
      97  /* Chars that can be used to separate mant from exp in floating point nums.  */
      98  const char EXP_CHARS[] = "eE";
      99  
     100  /* Chars that mean this number is a floating point constant.  */
     101  /* As in 0f12.456.  */
     102  /* or    0d1.2345e12.  */
     103  const char FLT_CHARS[] = "rRsSfFdDxXpP";
     104  
     105  const char *md_shortopts = "O::g::G:";
     106  
     107  static const char default_arch[] = DEFAULT_ARCH;
     108  
     109  enum options
     110  {
     111    OPTION_IGNORE = OPTION_MD_BASE,
     112  
     113    OPTION_ABI,
     114    OPTION_FLOAT_ABI,
     115  
     116    OPTION_FLOAT_ISA,
     117  
     118    OPTION_LA_LOCAL_WITH_ABS,
     119    OPTION_LA_GLOBAL_WITH_PCREL,
     120    OPTION_LA_GLOBAL_WITH_ABS,
     121    OPTION_RELAX,
     122    OPTION_NO_RELAX,
     123  
     124    OPTION_END_OF_ENUM,
     125  };
     126  
     127  struct option md_longopts[] =
     128  {
     129    { "mabi", required_argument, NULL, OPTION_ABI },
     130  
     131    { "mfpu", required_argument, NULL, OPTION_FLOAT_ISA },
     132  
     133    { "mla-local-with-abs", no_argument, NULL, OPTION_LA_LOCAL_WITH_ABS },
     134    { "mla-global-with-pcrel", no_argument, NULL, OPTION_LA_GLOBAL_WITH_PCREL },
     135    { "mla-global-with-abs", no_argument, NULL, OPTION_LA_GLOBAL_WITH_ABS },
     136  
     137    { "mrelax", no_argument, NULL, OPTION_RELAX },
     138    { "mno-relax", no_argument, NULL, OPTION_NO_RELAX },
     139  
     140    { NULL, no_argument, NULL, 0 }
     141  };
     142  
     143  size_t md_longopts_size = sizeof (md_longopts);
     144  
     145  int
     146  md_parse_option (int c, const char *arg)
     147  {
     148    int ret = 1;
     149    char lp64[256] = "";
     150    char ilp32[256] = "";
     151    unsigned char *suf = (unsigned char *)arg;
     152  
     153    lp64['s'] = lp64['S'] = EF_LOONGARCH_ABI_SOFT_FLOAT;
     154    lp64['f'] = lp64['F'] = EF_LOONGARCH_ABI_SINGLE_FLOAT;
     155    lp64['d'] = lp64['D'] = EF_LOONGARCH_ABI_DOUBLE_FLOAT;
     156  
     157    ilp32['s'] = ilp32['S'] = EF_LOONGARCH_ABI_SOFT_FLOAT;
     158    ilp32['f'] = ilp32['F'] = EF_LOONGARCH_ABI_SINGLE_FLOAT;
     159    ilp32['d'] = ilp32['D'] = EF_LOONGARCH_ABI_DOUBLE_FLOAT;
     160  
     161    switch (c)
     162      {
     163      case OPTION_ABI:
     164        if (strncasecmp (arg, "lp64", 4) == 0 && lp64[suf[4]] != 0)
     165  	{
     166  	  LARCH_opts.ase_ilp32 = 1;
     167  	  LARCH_opts.ase_lp64 = 1;
     168  	  LARCH_opts.ase_lsx = 1;
     169  	  LARCH_opts.ase_lasx = 1;
     170  	  LARCH_opts.ase_lvz = 1;
     171  	  LARCH_opts.ase_lbt = 1;
     172  	  LARCH_opts.ase_abi = lp64[suf[4]];
     173  	}
     174        else if (strncasecmp (arg, "ilp32", 5) == 0 && ilp32[suf[5]] != 0)
     175  	{
     176  	  LARCH_opts.ase_abi = ilp32[suf[5]];
     177  	  LARCH_opts.ase_ilp32 = 1;
     178  	}
     179        else
     180  	ret = 0;
     181        break;
     182  
     183      case OPTION_FLOAT_ISA:
     184        if (strcasecmp (arg, "soft") == 0)
     185  	LARCH_opts.ase_nf = 1;
     186        else if (strcasecmp (arg, "single") == 0)
     187  	LARCH_opts.ase_sf = 1;
     188        else if (strcasecmp (arg, "double") == 0)
     189  	{
     190  	  LARCH_opts.ase_sf = 1;
     191  	  LARCH_opts.ase_df = 1;
     192  	}
     193        else
     194  	ret = 0;
     195        break;
     196  
     197      case OPTION_LA_LOCAL_WITH_ABS:
     198        LARCH_opts.ase_labs = 1;
     199        break;
     200  
     201      case OPTION_LA_GLOBAL_WITH_PCREL:
     202        LARCH_opts.ase_gpcr = 1;
     203        break;
     204  
     205      case OPTION_LA_GLOBAL_WITH_ABS:
     206        LARCH_opts.ase_gabs = 1;
     207        break;
     208  
     209      case OPTION_RELAX:
     210        LARCH_opts.relax = 1;
     211        break;
     212  
     213      case OPTION_NO_RELAX:
     214        LARCH_opts.relax = 0;
     215        break;
     216  
     217      case OPTION_IGNORE:
     218        break;
     219  
     220      default:
     221        ret = 0;
     222        break;
     223      }
     224    return ret;
     225  }
     226  
     227  static const char *const *r_abi_names = NULL;
     228  static const char *const *f_abi_names = NULL;
     229  static struct htab *r_htab = NULL;
     230  static struct htab *r_deprecated_htab = NULL;
     231  static struct htab *f_htab = NULL;
     232  static struct htab *f_deprecated_htab = NULL;
     233  static struct htab *fc_htab = NULL;
     234  static struct htab *fcn_htab = NULL;
     235  static struct htab *c_htab = NULL;
     236  static struct htab *cr_htab = NULL;
     237  static struct htab *v_htab = NULL;
     238  static struct htab *x_htab = NULL;
     239  
     240  void
     241  loongarch_after_parse_args ()
     242  {
     243    /* Set default ABI/ISA LP64D.  */
     244    if (!LARCH_opts.ase_ilp32)
     245      {
     246        if (strcmp (default_arch, "loongarch64") == 0)
     247  	{
     248  	  LARCH_opts.ase_abi = EF_LOONGARCH_ABI_DOUBLE_FLOAT;
     249  	  LARCH_opts.ase_ilp32 = 1;
     250  	  LARCH_opts.ase_lp64 = 1;
     251  	  LARCH_opts.ase_lsx = 1;
     252  	  LARCH_opts.ase_lasx = 1;
     253  	  LARCH_opts.ase_lvz = 1;
     254  	  LARCH_opts.ase_lbt = 1;
     255  	}
     256        else if (strcmp (default_arch, "loongarch32") == 0)
     257  	{
     258  	  LARCH_opts.ase_abi = EF_LOONGARCH_ABI_DOUBLE_FLOAT;
     259  	  LARCH_opts.ase_ilp32 = 1;
     260  	}
     261        else
     262  	as_bad ("unknown default architecture `%s'", default_arch);
     263      }
     264  
     265    LARCH_opts.ase_abi |= EF_LOONGARCH_OBJABI_V1;
     266    /* Set default ISA double-float.  */
     267    if (!LARCH_opts.ase_nf
     268        && !LARCH_opts.ase_sf
     269        && !LARCH_opts.ase_df)
     270      {
     271        LARCH_opts.ase_sf = 1;
     272        LARCH_opts.ase_df = 1;
     273      }
     274  
     275    size_t i;
     276  
     277    assert(LARCH_opts.ase_ilp32);
     278  
     279    /* Init ilp32/lp64 registers names.  */
     280    if (!r_htab)
     281      r_htab = str_htab_create (), str_hash_insert (r_htab, "", 0, 0);
     282    if (!r_deprecated_htab)
     283      r_deprecated_htab = str_htab_create (),
     284  			str_hash_insert (r_deprecated_htab, "", 0, 0);
     285  
     286    r_abi_names = loongarch_r_normal_name;
     287    for (i = 0; i < ARRAY_SIZE (loongarch_r_normal_name); i++)
     288      str_hash_insert (r_htab, loongarch_r_normal_name[i], (void *) (i + 1), 0);
     289  
     290    if (!cr_htab)
     291      cr_htab = str_htab_create (), str_hash_insert (cr_htab, "", 0, 0);
     292  
     293    for (i = 0; i < ARRAY_SIZE (loongarch_cr_normal_name); i++)
     294      str_hash_insert (cr_htab, loongarch_cr_normal_name[i], (void *) (i + 1), 0);
     295  
     296    /* Init single/double float registers names.  */
     297    if (LARCH_opts.ase_sf || LARCH_opts.ase_df)
     298      {
     299        if (!f_htab)
     300  	f_htab = str_htab_create (), str_hash_insert (f_htab, "", 0, 0);
     301        if (!f_deprecated_htab)
     302  	f_deprecated_htab = str_htab_create (),
     303  			    str_hash_insert (f_deprecated_htab, "", 0, 0);
     304  
     305        f_abi_names = loongarch_f_normal_name;
     306        for (i = 0; i < ARRAY_SIZE (loongarch_f_normal_name); i++)
     307  	str_hash_insert (f_htab, loongarch_f_normal_name[i], (void *) (i + 1),
     308  			 0);
     309  
     310        if (!fc_htab)
     311  	fc_htab = str_htab_create (), str_hash_insert (fc_htab, "", 0, 0);
     312  
     313        for (i = 0; i < ARRAY_SIZE (loongarch_fc_normal_name); i++)
     314  	str_hash_insert (fc_htab, loongarch_fc_normal_name[i], (void *) (i + 1),
     315  			 0);
     316  
     317        if (!fcn_htab)
     318  	fcn_htab = str_htab_create (), str_hash_insert (fcn_htab, "", 0, 0);
     319  
     320        for (i = 0; i < ARRAY_SIZE (loongarch_fc_numeric_name); i++)
     321  	str_hash_insert (fcn_htab, loongarch_fc_numeric_name[i], (void *) (i + 1),
     322  			 0);
     323  
     324        if (!c_htab)
     325  	c_htab = str_htab_create (), str_hash_insert (c_htab, "", 0, 0);
     326  
     327        for (i = 0; i < ARRAY_SIZE (loongarch_c_normal_name); i++)
     328  	str_hash_insert (c_htab, loongarch_c_normal_name[i], (void *) (i + 1),
     329  			 0);
     330  
     331      }
     332  
     333    /* Init lsx registers names.  */
     334    if (LARCH_opts.ase_lsx)
     335      {
     336        if (!v_htab)
     337  	v_htab = str_htab_create (), str_hash_insert (v_htab, "", 0, 0);
     338        for (i = 0; i < ARRAY_SIZE (loongarch_v_normal_name); i++)
     339  	str_hash_insert (v_htab, loongarch_v_normal_name[i], (void *) (i + 1),
     340  			 0);
     341      }
     342  
     343    /* Init lasx registers names.  */
     344    if (LARCH_opts.ase_lasx)
     345      {
     346        if (!x_htab)
     347  	x_htab = str_htab_create (), str_hash_insert (x_htab, "", 0, 0);
     348        for (i = 0; i < ARRAY_SIZE (loongarch_x_normal_name); i++)
     349  	str_hash_insert (x_htab, loongarch_x_normal_name[i], (void *) (i + 1),
     350  			 0);
     351      }
     352  
     353    /* Init lp64 registers alias.  */
     354    if (LARCH_opts.ase_lp64)
     355      {
     356        r_abi_names = loongarch_r_lp64_name;
     357        for (i = 0; i < ARRAY_SIZE (loongarch_r_lp64_name); i++)
     358  	str_hash_insert (r_htab, loongarch_r_lp64_name[i], (void *) (i + 1),
     359  			 0);
     360        for (i = 0; i < ARRAY_SIZE (loongarch_r_lp64_name_deprecated); i++)
     361  	str_hash_insert (r_deprecated_htab, loongarch_r_lp64_name_deprecated[i],
     362  			 (void *) (i + 1), 0);
     363      }
     364  
     365    /* Init float-lp64 registers alias */
     366    if ((LARCH_opts.ase_sf || LARCH_opts.ase_df) && LARCH_opts.ase_lp64)
     367      {
     368        f_abi_names = loongarch_f_lp64_name;
     369        for (i = 0; i < ARRAY_SIZE (loongarch_f_lp64_name); i++)
     370  	str_hash_insert (f_htab, loongarch_f_lp64_name[i],
     371  			 (void *) (i + 1), 0);
     372        for (i = 0; i < ARRAY_SIZE (loongarch_f_lp64_name_deprecated); i++)
     373  	str_hash_insert (f_deprecated_htab, loongarch_f_lp64_name_deprecated[i],
     374  			 (void *) (i + 1), 0);
     375      }
     376  }
     377  
     378  const char *
     379  loongarch_target_format ()
     380  {
     381    return LARCH_opts.ase_lp64 ? "elf64-loongarch" : "elf32-loongarch";
     382  }
     383  
     384  void
     385  md_begin ()
     386  {
     387    const struct loongarch_opcode *it;
     388    struct loongarch_ase *ase;
     389    for (ase = loongarch_ASEs; ase->enabled; ase++)
     390      for (it = ase->opcodes; it->name; it++)
     391        {
     392  	if (loongarch_check_format (it->format) != 0)
     393  	  as_fatal (_("insn name: %s\tformat: %s\tsyntax error"),
     394  		    it->name, it->format);
     395  	if (it->mask == 0 && it->macro == 0)
     396  	  as_fatal (_("insn name: %s\nformat: %s\nwe want macro but "
     397  		      "macro is NULL"),
     398  		    it->name, it->format);
     399  	if (it->macro
     400  	    && loongarch_check_macro (it->format, it->macro) != 0)
     401  	  as_fatal (_("insn name: %s\nformat: %s\nmacro: %s\tsyntax error"),
     402  		    it->name, it->format, it->macro);
     403        }
     404  
     405    /* FIXME: expressionS use 'offsetT' as constant,
     406     * we want this is 64-bit type.  */
     407    assert (8 <= sizeof (offsetT));
     408  }
     409  
     410  unsigned long
     411  loongarch_mach (void)
     412  {
     413    return LARCH_opts.ase_lp64 ? bfd_mach_loongarch64 : bfd_mach_loongarch32;
     414  }
     415  
     416  static const expressionS const_0 = { .X_op = O_constant, .X_add_number = 0 };
     417  
     418  static void
     419  s_loongarch_align (int arg)
     420  {
     421    const char *t = input_line_pointer;
     422    while (!is_end_of_line[(unsigned char) *t] && *t != ',')
     423      ++t;
     424    if (*t == ',')
     425      s_align_ptwo (arg);
     426    else
     427      s_align_ptwo (0);
     428  }
     429  
     430  /* Handle the .dtprelword and .dtpreldword pseudo-ops.  They generate
     431     a 32-bit or 64-bit DTP-relative relocation (BYTES says which) for
     432     use in DWARF debug information.  */
     433  
     434  static void
     435  s_dtprel (int bytes)
     436  {
     437    expressionS ex;
     438    char *p;
     439  
     440    expression (&ex);
     441  
     442    if (ex.X_op != O_symbol)
     443      {
     444        as_bad (_("Unsupported use of %s"),
     445  	      (bytes == 8 ? ".dtpreldword" : ".dtprelword"));
     446        ignore_rest_of_line ();
     447      }
     448  
     449    p = frag_more (bytes);
     450    md_number_to_chars (p, 0, bytes);
     451    fix_new_exp (frag_now, p - frag_now->fr_literal, bytes, &ex, FALSE,
     452  	       (bytes == 8
     453  		? BFD_RELOC_LARCH_TLS_DTPREL64
     454  		: BFD_RELOC_LARCH_TLS_DTPREL32));
     455  
     456    demand_empty_rest_of_line ();
     457  }
     458  
     459  static const pseudo_typeS loongarch_pseudo_table[] =
     460  {
     461    { "align", s_loongarch_align, -4 },
     462    { "dword", cons, 8 },
     463    { "word", cons, 4 },
     464    { "half", cons, 2 },
     465    { "dtprelword", s_dtprel, 4 },
     466    { "dtpreldword", s_dtprel, 8 },
     467    { NULL, NULL, 0 },
     468  };
     469  
     470  void
     471  loongarch_pop_insert (void)
     472  {
     473    pop_insert (loongarch_pseudo_table);
     474  }
     475  
     476  #define INTERNAL_LABEL_SPECIAL 10
     477  static unsigned long internal_label_count[INTERNAL_LABEL_SPECIAL] = { 0 };
     478  
     479  static const char *
     480  loongarch_internal_label_name (unsigned long label, int augend)
     481  {
     482    static char symbol_name_build[24];
     483    unsigned long want_label;
     484    char *p;
     485  
     486    want_label = internal_label_count[label] + augend;
     487  
     488    p = symbol_name_build;
     489  #ifdef LOCAL_LABEL_PREFIX
     490    *p++ = LOCAL_LABEL_PREFIX;
     491  #endif
     492    *p++ = 'L';
     493    for (; label; label /= 10)
     494      *p++ = label % 10 + '0';
     495    /* Make sure internal label never belong to normal label namespace.  */
     496    *p++ = ':';
     497    for (; want_label; want_label /= 10)
     498      *p++ = want_label % 10 + '0';
     499    *p++ = '\0';
     500    return symbol_name_build;
     501  }
     502  
     503  static void
     504  setup_internal_label_here (unsigned long label)
     505  {
     506    assert (label < INTERNAL_LABEL_SPECIAL);
     507    internal_label_count[label]++;
     508    colon (loongarch_internal_label_name (label, 0));
     509  }
     510  
     511  void
     512  get_internal_label (expressionS *label_expr, unsigned long label,
     513  		    int augend /* 0 for previous, 1 for next.  */)
     514  {
     515    assert (label < INTERNAL_LABEL_SPECIAL);
     516      as_fatal (_("internal error: we have no internal label yet"));
     517    label_expr->X_op = O_symbol;
     518    label_expr->X_add_symbol =
     519      symbol_find_or_make (loongarch_internal_label_name (label, augend));
     520    label_expr->X_add_number = 0;
     521  }
     522  
     523  static int
     524  is_internal_label (const char *c_str)
     525  {
     526    do
     527      {
     528        if (*c_str != ':')
     529  	break;
     530        c_str++;
     531        if (!('0' <= *c_str && *c_str <= '9'))
     532  	break;
     533        while ('0' <= *c_str && *c_str <= '9')
     534  	c_str++;
     535        if (*c_str != 'b' && *c_str != 'f')
     536  	break;
     537        c_str++;
     538        return *c_str == '\0';
     539      }
     540    while (0);
     541    return 0;
     542  }
     543  
     544  static int
     545  is_label (const char *c_str)
     546  {
     547    if (is_internal_label (c_str))
     548      return 1;
     549    else if ('0' <= *c_str && *c_str <= '9')
     550      {
     551        /* [0-9]+[bf]  */
     552        while ('0' <= *c_str && *c_str <= '9')
     553  	c_str++;
     554        return *c_str == 'b' || *c_str == 'f';
     555      }
     556    else if (is_name_beginner (*c_str))
     557      {
     558        /* [a-zA-Z\._\$][0-9a-zA-Z\._\$]*  */
     559        c_str++;
     560        while (is_part_of_name (*c_str))
     561  	c_str++;
     562        return *c_str == '\0';
     563      }
     564    else
     565      return 0;
     566  }
     567  
     568  static int
     569  is_label_with_addend (const char *c_str)
     570  {
     571    if (is_internal_label (c_str))
     572      return 1;
     573    else if ('0' <= *c_str && *c_str <= '9')
     574      {
     575        /* [0-9]+[bf]  */
     576        while ('0' <= *c_str && *c_str <= '9')
     577  	c_str++;
     578        if (*c_str == 'b' || *c_str == 'f')
     579  	c_str++;
     580        else
     581  	return 0;
     582        return *c_str == '\0'
     583  		       || ((*c_str == '-' || *c_str == '+')
     584  			   && is_unsigned (c_str + 1));
     585      }
     586    else if (is_name_beginner (*c_str))
     587      {
     588        /* [a-zA-Z\._\$][0-9a-zA-Z\._\$]*  */
     589        c_str++;
     590        while (is_part_of_name (*c_str))
     591  	c_str++;
     592        return *c_str == '\0'
     593  		       || ((*c_str == '-' || *c_str == '+')
     594  			   && is_unsigned (c_str + 1));
     595      }
     596    else
     597      return 0;
     598  }
     599  
     600  static int32_t
     601  loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
     602  					    const char *bit_field,
     603  					    const char *arg, void *context)
     604  {
     605    struct loongarch_cl_insn *ip = context;
     606    offsetT imm, ret = 0;
     607    size_t reloc_num_we_have = MAX_RELOC_NUMBER_A_INSN - ip->reloc_num;
     608    size_t reloc_num = 0;
     609  
     610    if (!ip->match_now)
     611      return 0;
     612  
     613    switch (esc_ch1)
     614      {
     615      case 'l':
     616        switch (esc_ch2)
     617  	{
     618  	default:
     619  	  ip->match_now = is_label (arg);
     620  	  if (!ip->match_now && is_label_with_addend (arg))
     621  	    as_fatal (_("This label shouldn't be with addend."));
     622  	  break;
     623  	case 'a':
     624  	  ip->match_now = is_label_with_addend (arg);
     625  	  break;
     626  	}
     627        break;
     628      case 's':
     629      case 'u':
     630        ip->match_now =
     631  	loongarch_parse_expr (arg, ip->reloc_info + ip->reloc_num,
     632  			      reloc_num_we_have, &reloc_num, &imm) == 0;
     633  
     634        if (!ip->match_now)
     635  	break;
     636  
     637        ret = imm;
     638        if (reloc_num)
     639  	{
     640  	  bfd_reloc_code_real_type reloc_type = BFD_RELOC_NONE;
     641  	  reloc_num_we_have -= reloc_num;
     642  	  if (reloc_num_we_have == 0)
     643  	    as_fatal (_("expr too huge") /* Want one more reloc.  */);
     644  	  if (esc_ch1 == 'u')
     645  	    {
     646  	      if (strncmp (bit_field, "10:12", strlen ("10:12")) == 0)
     647  		reloc_type = BFD_RELOC_LARCH_SOP_POP_32_U_10_12;
     648  	    }
     649  	  else if (esc_ch1 == 's')
     650  	    {
     651  	      if (strncmp (bit_field, "10:16<<2", strlen ("10:16<<2")) == 0)
     652  		reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2;
     653  	      else if (strncmp (bit_field, "0:5|10:16<<2",
     654  				strlen ("0:5|10:16<<2")) == 0)
     655  		reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2;
     656  	      else if (strncmp (bit_field, "0:10|10:16<<2",
     657  				strlen ("0:10|10:16<<2")) == 0)
     658  		reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2;
     659  	      else if (strncmp (bit_field, "10:12", strlen ("10:12")) == 0)
     660  		reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_12;
     661  	      else if (strncmp (bit_field, "5:20", strlen ("5:20")) == 0)
     662  		reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_5_20;
     663  	      else if (strncmp (bit_field, "10:16", strlen ("10:16")) == 0)
     664  		reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_16;
     665  	      else if (strncmp (bit_field, "10:5", strlen ("10:5")) == 0)
     666  		reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_5;
     667  	    }
     668  	  if (reloc_type == BFD_RELOC_NONE)
     669  	    as_fatal (
     670  		      _("not support reloc bit-field\nfmt: %c%c %s\nargs: %s"),
     671  		      esc_ch1, esc_ch2, bit_field, arg);
     672  
     673  	  if (ip->reloc_info[0].type >= BFD_RELOC_LARCH_B16
     674  	      && ip->reloc_info[0].type < BFD_RELOC_LARCH_64_PCREL)
     675  	    {
     676  	      /* As we compact stack-relocs, it is no need for pop operation.
     677  		 But break out until here in order to check the imm field.
     678  		 May be reloc_num > 1 if implement relax?  */
     679  	      ip->reloc_num += reloc_num;
     680  	      reloc_type = ip->reloc_info[0].type;
     681  
     682  	      if (LARCH_opts.relax && ip->macro_id
     683  		    && (BFD_RELOC_LARCH_PCALA_HI20 == reloc_type
     684  			|| BFD_RELOC_LARCH_PCALA_LO12 == reloc_type
     685  			|| BFD_RELOC_LARCH_GOT_PC_HI20 == reloc_type
     686  			|| BFD_RELOC_LARCH_GOT_PC_LO12 == reloc_type))
     687  		{
     688  		  ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_RELAX;
     689  		  ip->reloc_info[ip->reloc_num].value = const_0;
     690  		  ip->reloc_num++;
     691  		}
     692  	      break;
     693  	    }
     694  	  reloc_num++;
     695  	  ip->reloc_num += reloc_num;
     696  	  ip->reloc_info[ip->reloc_num - 1].type = reloc_type;
     697  	  ip->reloc_info[ip->reloc_num - 1].value = const_0;
     698  	}
     699        break;
     700      case 'r':
     701        imm = (intptr_t) str_hash_find (r_htab, arg);
     702        ip->match_now = 0 < imm;
     703        ret = imm - 1;
     704        if (ip->match_now)
     705  	break;
     706        /* Handle potential usage of deprecated register aliases.  */
     707        imm = (intptr_t) str_hash_find (r_deprecated_htab, arg);
     708        ip->match_now = 0 < imm;
     709        ret = imm - 1;
     710        if (ip->match_now && !ip->macro_id)
     711  	as_warn (_("register alias %s is deprecated, use %s instead"),
     712  		 arg, r_abi_names[ret]);
     713        break;
     714      case 'f':
     715        switch (esc_ch2)
     716  	{
     717  	case 'c':
     718  	  imm = (intptr_t) str_hash_find (fc_htab, arg);
     719  	  if (0 >= imm)
     720  	    {
     721  	      imm = (intptr_t) str_hash_find (fcn_htab, arg);
     722  	    }
     723  	  break;
     724  	default:
     725  	  imm = (intptr_t) str_hash_find (f_htab, arg);
     726  	}
     727        ip->match_now = 0 < imm;
     728        ret = imm - 1;
     729        if (ip->match_now && !ip->macro_id)
     730  	break;
     731        /* Handle potential usage of deprecated register aliases.  */
     732        imm = (intptr_t) str_hash_find (f_deprecated_htab, arg);
     733        ip->match_now = 0 < imm;
     734        ret = imm - 1;
     735        if (ip->match_now)
     736  	as_warn (_("register alias %s is deprecated, use %s instead"),
     737  		 arg, f_abi_names[ret]);
     738        break;
     739      case 'c':
     740        switch (esc_ch2)
     741  	{
     742  	case 'r':
     743  	  imm = (intptr_t) str_hash_find (cr_htab, arg);
     744  	  break;
     745  	default:
     746  	  imm = (intptr_t) str_hash_find (c_htab, arg);
     747  	}
     748        ip->match_now = 0 < imm;
     749        ret = imm - 1;
     750        break;
     751      case 'v':
     752        imm = (intptr_t) str_hash_find (v_htab, arg);
     753        ip->match_now = 0 < imm;
     754        ret = imm - 1;
     755        break;
     756      case 'x':
     757        imm = (intptr_t) str_hash_find (x_htab, arg);
     758        ip->match_now = 0 < imm;
     759        ret = imm - 1;
     760        break;
     761      case '\0':
     762        ip->all_match = ip->match_now;
     763        ip->insn_length =
     764  	ip->insn->mask ? loongarch_insn_length (ip->insn->match) : 0;
     765        /* FIXME: now we have no relax insn.  */
     766        ip->relax_max_length = ip->insn_length;
     767        break;
     768      default:
     769        as_fatal (_("unknown escape"));
     770      }
     771  
     772    do
     773      {
     774        /* Check imm overflow.  */
     775        int bit_width, bits_needed_s, bits_needed_u;
     776        char *t;
     777  
     778        if (!ip->match_now)
     779  	break;
     780  
     781        if (0 < reloc_num)
     782  	break;
     783  
     784        bit_width = loongarch_get_bit_field_width (bit_field, &t);
     785  
     786        if (bit_width == -1)
     787  	/* No specify bit width.  */
     788  	break;
     789  
     790        imm = ret;
     791        if (t[0] == '<' && t[1] == '<')
     792  	{
     793  	  int i = strtol (t += 2, &t, 10), j;
     794  	  for (j = i; 0 < j; j--, imm >>= 1)
     795  	    if (imm & 1)
     796  	      as_fatal (_("require imm low %d bit is 0."), i);
     797  	}
     798  
     799        if (*t == '+')
     800  	imm -= strtol (t, &t, 10);
     801  
     802        bits_needed_s = loongarch_bits_imm_needed (imm, 1);
     803        bits_needed_u = loongarch_bits_imm_needed (imm, 0);
     804  
     805        if ((esc_ch1 == 's' && bit_width < bits_needed_s)
     806  	  || (esc_ch1 != 's' && bit_width < bits_needed_u))
     807  	/* How to do after we detect overflow.  */
     808  	as_fatal (_("Immediate overflow.\n"
     809  		    "format: %c%c%s\n"
     810  		    "arg: %s"),
     811  		  esc_ch1, esc_ch2, bit_field, arg);
     812      }
     813    while (0);
     814  
     815    if (esc_ch1 != '\0')
     816      {
     817        ip->args[ip->arg_num] = ret;
     818        ip->arg_num++;
     819      }
     820    return ret;
     821  }
     822  
     823  static void
     824  get_loongarch_opcode (struct loongarch_cl_insn *insn)
     825  {
     826    const struct loongarch_opcode *it;
     827    struct loongarch_ase *ase;
     828    for (ase = loongarch_ASEs; ase->enabled; ase++)
     829      {
     830        if (!*ase->enabled || (ase->include && !*ase->include)
     831  	  || (ase->exclude && *ase->exclude))
     832  	continue;
     833  
     834        if (!ase->name_hash_entry)
     835  	{
     836  	  ase->name_hash_entry = str_htab_create ();
     837  	  for (it = ase->opcodes; it->name; it++)
     838  	    {
     839  	      if ((!it->include || (it->include && *it->include))
     840  		  && (!it->exclude || (it->exclude && !(*it->exclude)))
     841  		  && !(it->pinfo & INSN_DIS_ALIAS))
     842  		str_hash_insert (ase->name_hash_entry, it->name,
     843  				 (void *) it, 0);
     844  	    }
     845  	}
     846  
     847        if ((it = str_hash_find (ase->name_hash_entry, insn->name)) == NULL)
     848  	continue;
     849  
     850        do
     851  	{
     852  	  insn->insn = it;
     853  	  insn->match_now = 1;
     854  	  insn->all_match = 0;
     855  	  insn->arg_num = 0;
     856  	  insn->reloc_num = 0;
     857  	  insn->insn_bin = (loongarch_foreach_args
     858  			    (it->format, insn->arg_strs,
     859  			     loongarch_args_parser_can_match_arg_helper,
     860  			     insn));
     861  	  if (insn->all_match && !(it->include && !*it->include)
     862  	      && !(it->exclude && *it->exclude))
     863  	    {
     864  	      insn->insn_bin |= it->match;
     865  	      return;
     866  	    }
     867  	  it++;
     868  	}
     869        while (it->name && strcasecmp (it->name, insn->name) == 0);
     870      }
     871  }
     872  
     873  static int
     874  check_this_insn_before_appending (struct loongarch_cl_insn *ip)
     875  {
     876    int ret = 0;
     877  
     878    if (strncmp (ip->name, "la.abs", 6) == 0)
     879      {
     880        ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_MARK_LA;
     881        ip->reloc_info[ip->reloc_num].value = const_0;
     882        ip->reloc_num++;
     883      }
     884    else if (ip->insn->mask == 0xffff8000
     885  	   /* amswap.w  rd, rk, rj  */
     886  	   && ((ip->insn_bin & 0xfff00000) == 0x38600000
     887  	       /* ammax_db.wu  rd, rk, rj  */
     888  	       || (ip->insn_bin & 0xffff0000) == 0x38700000
     889  	       /* ammin_db.wu  rd, rk, rj  */
     890  	       || (ip->insn_bin & 0xffff0000) == 0x38710000))
     891      {
     892        /* For AMO insn amswap.[wd], amadd.[wd], etc.  */
     893        if (ip->args[0] != 0
     894  	  && (ip->args[0] == ip->args[1] || ip->args[0] == ip->args[2]))
     895  	as_fatal (_("AMO insns require rd != base && rd != rt"
     896  		    " when rd isn't $r0"));
     897      }
     898    else if ((ip->insn->mask == 0xffe08000
     899  	    /* bstrins.w  rd, rj, msbw, lsbw  */
     900  	    && (ip->insn_bin & 0xffe00000) == 0x00600000)
     901  	   || (ip->insn->mask == 0xffc00000
     902  	       /* bstrins.d  rd, rj, msbd, lsbd  */
     903  	       && (ip->insn_bin & 0xff800000) == 0x00800000))
     904      {
     905        /* For bstr(ins|pick).[wd].  */
     906        if (ip->args[2] < ip->args[3])
     907  	as_fatal (_("bstr(ins|pick).[wd] require msbd >= lsbd"));
     908      }
     909    else if (ip->insn->mask != 0 && (ip->insn_bin & 0xfe0003c0) == 0x04000000
     910  	   /* csrxchg  rd, rj, csr_num  */
     911  	   && (strcmp ("csrxchg", ip->name) == 0))
     912      as_fatal (_("csrxchg require rj != $r0 && rj != $r1"));
     913  
     914    return ret;
     915  }
     916  
     917  static void
     918  install_insn (const struct loongarch_cl_insn *insn)
     919  {
     920    char *f = insn->frag->fr_literal + insn->where;
     921    if (0 < insn->insn_length)
     922      md_number_to_chars (f, insn->insn_bin, insn->insn_length);
     923  }
     924  
     925  static void
     926  move_insn (struct loongarch_cl_insn *insn, fragS *frag, long where)
     927  {
     928    size_t i;
     929    insn->frag = frag;
     930    insn->where = where;
     931    for (i = 0; i < insn->reloc_num; i++)
     932      {
     933        if (insn->fixp[i])
     934  	{
     935  	  insn->fixp[i]->fx_frag = frag;
     936  	  insn->fixp[i]->fx_where = where;
     937  	}
     938      }
     939    install_insn (insn);
     940  }
     941  
     942  /* Add INSN to the end of the output.  */
     943  static void
     944  append_fixed_insn (struct loongarch_cl_insn *insn)
     945  {
     946    char *f = frag_more (insn->insn_length);
     947    move_insn (insn, frag_now, f - frag_now->fr_literal);
     948  }
     949  
     950  static void
     951  append_fixp_and_insn (struct loongarch_cl_insn *ip)
     952  {
     953    reloc_howto_type *howto;
     954    bfd_reloc_code_real_type reloc_type;
     955    struct reloc_info *reloc_info = ip->reloc_info;
     956    size_t i;
     957  
     958    dwarf2_emit_insn (0);
     959  
     960    for (i = 0; i < ip->reloc_num; i++)
     961      {
     962        reloc_type = reloc_info[i].type;
     963        howto = bfd_reloc_type_lookup (stdoutput, reloc_type);
     964        if (howto == NULL)
     965  	as_fatal (_("no HOWTO loong relocation number %d"), reloc_type);
     966  
     967        ip->fixp[i] =
     968  	fix_new_exp (ip->frag, ip->where, bfd_get_reloc_size (howto),
     969  		     &reloc_info[i].value, FALSE, reloc_type);
     970      }
     971  
     972    if (ip->insn_length < ip->relax_max_length)
     973      as_fatal (_("Internal error: not support relax now"));
     974    else
     975      append_fixed_insn (ip);
     976  
     977    /* We need to start a new frag after any instruction that can be
     978       optimized away or compressed by the linker during relaxation, to prevent
     979       the assembler from computing static offsets across such an instruction.
     980  
     981       This is necessary to get correct .eh_frame cfa info. If one cfa's two
     982       symbol is not in the same frag, it will generate relocs to calculate
     983       symbol subtraction. (gas/dw2gencfi.c:output_cfi_insn:
     984       if (symbol_get_frag (to) == symbol_get_frag (from)))  */
     985    if (LARCH_opts.relax
     986        && (BFD_RELOC_LARCH_PCALA_HI20 == reloc_info[0].type
     987  	  || BFD_RELOC_LARCH_GOT_PC_HI20 == reloc_info[0].type))
     988      {
     989        frag_wane (frag_now);
     990        frag_new (0);
     991      }
     992  }
     993  
     994  /* Ask helper for returning a malloced c_str or NULL.  */
     995  static char *
     996  assember_macro_helper (const char *const args[], void *context_ptr)
     997  {
     998    struct loongarch_cl_insn *insn = context_ptr;
     999    char *ret = NULL;
    1000    if ( strcmp (insn->name, "li.w") == 0 || strcmp (insn->name, "li.d") == 0)
    1001      {
    1002        char args_buf[50], insns_buf[200];
    1003        const char *arg_strs[6];
    1004        uint32_t hi32, lo32;
    1005  
    1006        /* We pay attention to sign extend beacause it is chance of reduce insn.
    1007  	 The exception is 12-bit and hi-12-bit unsigned,
    1008  	 we need a 'ori' or a 'lu52i.d' accordingly.  */
    1009        char all0_bit_vec, sign_bit_vec, allf_bit_vec, paritial_is_sext_of_prev;
    1010  
    1011        lo32 = insn->args[1] & 0xffffffff;
    1012        hi32 = insn->args[1] >> 32;
    1013  
    1014        if (strcmp (insn->name, "li.w") == 0)
    1015  	{
    1016  	  if (hi32 != 0 && hi32 != 0xffffffff)
    1017  	    as_fatal (_("li overflow: hi32:0x%x lo32:0x%x"), hi32, lo32);
    1018  	  hi32 = lo32 & 0x80000000 ? 0xffffffff : 0;
    1019  	}
    1020  
    1021        if (strcmp (insn->name, "li.d") == 0 && !LARCH_opts.ase_lp64)
    1022  	as_fatal (_("we can't li.d on 32bit-arch"));
    1023  
    1024        snprintf (args_buf, sizeof (args_buf), "0x%x,0x%x,0x%x,0x%x,%s",
    1025  		(hi32 >> 20) & 0xfff, hi32 & 0xfffff, (lo32 >> 12) & 0xfffff,
    1026  		lo32 & 0xfff, args[0]);
    1027        loongarch_split_args_by_comma (args_buf, arg_strs);
    1028  
    1029        all0_bit_vec =
    1030  	((((hi32 & 0xfff00000) == 0) << 3) | (((hi32 & 0x000fffff) == 0) << 2)
    1031  	 | (((lo32 & 0xfffff000) == 0) << 1) | ((lo32 & 0x00000fff) == 0));
    1032        sign_bit_vec =
    1033  	((((hi32 & 0x80000000) != 0) << 3) | (((hi32 & 0x00080000) != 0) << 2)
    1034  	 | (((lo32 & 0x80000000) != 0) << 1) | ((lo32 & 0x00000800) != 0));
    1035        allf_bit_vec =
    1036  	((((hi32 & 0xfff00000) == 0xfff00000) << 3)
    1037  	 | (((hi32 & 0x000fffff) == 0x000fffff) << 2)
    1038  	 | (((lo32 & 0xfffff000) == 0xfffff000) << 1)
    1039  	 | ((lo32 & 0x00000fff) == 0x00000fff));
    1040        paritial_is_sext_of_prev =
    1041  	(all0_bit_vec ^ allf_bit_vec) & (all0_bit_vec ^ (sign_bit_vec << 1));
    1042  
    1043        static const char *const li_32bit[] =
    1044  	{
    1045  	  "lu12i.w %5,%3&0x80000?%3-0x100000:%3;ori %5,%5,%4;",
    1046  	  "lu12i.w %5,%3&0x80000?%3-0x100000:%3;",
    1047  	  "addi.w %5,$r0,%4&0x800?%4-0x1000:%4;",
    1048  	  "or %5,$r0,$r0;",
    1049  	};
    1050        static const char *const li_hi_32bit[] =
    1051  	{
    1052  	  "lu32i.d %5,%2&0x80000?%2-0x100000:%2;"
    1053  	  "lu52i.d %5,%5,%1&0x800?%1-0x1000:%1;",
    1054  	  "lu52i.d %5,%5,%1&0x800?%1-0x1000:%1;",
    1055  	  "lu32i.d %5,%2&0x80000?%2-0x100000:%2;",
    1056  	  "",
    1057  	};
    1058        do
    1059  	{
    1060  	  insns_buf[0] = '\0';
    1061  	  if (paritial_is_sext_of_prev == 0x7)
    1062  	    {
    1063  	      strcat (insns_buf, "lu52i.d %5,$r0,%1&0x800?%1-0x1000:%1;");
    1064  	      break;
    1065  	    }
    1066  	  if ((all0_bit_vec & 0x3) == 0x2)
    1067  	    strcat (insns_buf, "ori %5,$r0,%4;");
    1068  	  else
    1069  	    strcat (insns_buf, li_32bit[paritial_is_sext_of_prev & 0x3]);
    1070  	  strcat (insns_buf, li_hi_32bit[paritial_is_sext_of_prev >> 2]);
    1071  	}
    1072        while (0);
    1073  
    1074        ret = loongarch_expand_macro (insns_buf, arg_strs, NULL, NULL,
    1075  				    sizeof (args_buf));
    1076      }
    1077  
    1078    return ret;
    1079  }
    1080  
    1081  /* Accept instructions separated by ';'
    1082   * assuming 'not starting with space and not ending with space' or pass in
    1083   * empty c_str.  */
    1084  static void
    1085  loongarch_assemble_INSNs (char *str, struct loongarch_cl_insn *ctx)
    1086  {
    1087    char *rest;
    1088    size_t len_str = strlen(str);
    1089  
    1090    for (rest = str; *rest != ';' && *rest != '\0'; rest++);
    1091    if (*rest == ';')
    1092      *rest++ = '\0';
    1093  
    1094    if (*str == ':')
    1095      {
    1096        str++;
    1097        setup_internal_label_here (strtol (str, &str, 10));
    1098        str++;
    1099      }
    1100  
    1101    do
    1102      {
    1103        if (*str == '\0')
    1104  	break;
    1105  
    1106        struct loongarch_cl_insn the_one = { 0 };
    1107        the_one.name = str;
    1108        the_one.macro_id = ctx->macro_id;
    1109  
    1110        for (; *str && *str != ' '; str++)
    1111  	;
    1112        if (*str == ' ')
    1113  	*str++ = '\0';
    1114  
    1115        loongarch_split_args_by_comma (str, the_one.arg_strs);
    1116        get_loongarch_opcode (&the_one);
    1117  
    1118        if (!the_one.all_match)
    1119  	{
    1120  	  char *ss = loongarch_cat_splited_strs (the_one.arg_strs);
    1121  	  as_bad (_("no match insn: %s\t%s"), the_one.name, ss ? ss : "");
    1122  	  free(ss);
    1123  	  return;
    1124  	}
    1125  
    1126        if (check_this_insn_before_appending (&the_one) != 0)
    1127  	break;
    1128  
    1129        append_fixp_and_insn (&the_one);
    1130        if (the_one.insn_length == 0 && the_one.insn->macro)
    1131  	{
    1132  	  the_one.macro_id = 1;
    1133  
    1134  	  char *c_str = loongarch_expand_macro (the_one.insn->macro,
    1135  						the_one.arg_strs,
    1136  						assember_macro_helper,
    1137  						&the_one, len_str);
    1138  	  loongarch_assemble_INSNs (c_str, &the_one);
    1139  	  free (c_str);
    1140  	}
    1141      }
    1142    while (0);
    1143  
    1144    if (*rest != '\0')
    1145      loongarch_assemble_INSNs (rest, ctx);
    1146  }
    1147  
    1148  void
    1149  md_assemble (char *str)
    1150  {
    1151    struct loongarch_cl_insn the_one = { 0 };
    1152    loongarch_assemble_INSNs (str, &the_one);
    1153  }
    1154  
    1155  const char *
    1156  md_atof (int type, char *litP, int *sizeP)
    1157  {
    1158    return ieee_md_atof (type, litP, sizeP, FALSE);
    1159  }
    1160  
    1161  void
    1162  md_number_to_chars (char *buf, valueT val, int n)
    1163  {
    1164    number_to_chars_littleendian (buf, val, n);
    1165  }
    1166  
    1167  /* The location from which a PC relative jump should be calculated,
    1168     given a PC relative reloc.  */
    1169  long
    1170  md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
    1171  {
    1172    return 0;
    1173  }
    1174  
    1175  static void fix_reloc_insn (fixS *fixP, bfd_vma reloc_val, char *buf)
    1176  {
    1177    reloc_howto_type *howto;
    1178    insn_t insn;
    1179    howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
    1180  
    1181    insn = bfd_getl32 (buf);
    1182  
    1183    if (!loongarch_adjust_reloc_bitsfield (NULL, howto, &reloc_val))
    1184      as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow");
    1185  
    1186    insn = (insn & (insn_t)howto->src_mask)
    1187      | ((insn & (~(insn_t)howto->dst_mask)) | reloc_val);
    1188  
    1189    bfd_putl32 (insn, buf);
    1190  }
    1191  
    1192  void
    1193  md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
    1194  {
    1195    static int64_t stack_top;
    1196    static int last_reloc_is_sop_push_pcrel_1 = 0;
    1197    int last_reloc_is_sop_push_pcrel = last_reloc_is_sop_push_pcrel_1;
    1198    segT sub_segment;
    1199    last_reloc_is_sop_push_pcrel_1 = 0;
    1200  
    1201    char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
    1202    switch (fixP->fx_r_type)
    1203      {
    1204      case BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL:
    1205      case BFD_RELOC_LARCH_SOP_PUSH_TLS_GD:
    1206      case BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT:
    1207      case BFD_RELOC_LARCH_TLS_LE_HI20:
    1208      case BFD_RELOC_LARCH_TLS_LE_LO12:
    1209      case BFD_RELOC_LARCH_TLS_LE64_LO20:
    1210      case BFD_RELOC_LARCH_TLS_LE64_HI12:
    1211      case BFD_RELOC_LARCH_TLS_IE_PC_HI20:
    1212      case BFD_RELOC_LARCH_TLS_IE_PC_LO12:
    1213      case BFD_RELOC_LARCH_TLS_IE64_PC_LO20:
    1214      case BFD_RELOC_LARCH_TLS_IE64_PC_HI12:
    1215      case BFD_RELOC_LARCH_TLS_IE_HI20:
    1216      case BFD_RELOC_LARCH_TLS_IE_LO12:
    1217      case BFD_RELOC_LARCH_TLS_IE64_LO20:
    1218      case BFD_RELOC_LARCH_TLS_IE64_HI12:
    1219      case BFD_RELOC_LARCH_TLS_LD_PC_HI20:
    1220      case BFD_RELOC_LARCH_TLS_LD_HI20:
    1221      case BFD_RELOC_LARCH_TLS_GD_PC_HI20:
    1222      case BFD_RELOC_LARCH_TLS_GD_HI20:
    1223        /* Add tls lo (got_lo reloc type).  */
    1224        if (fixP->fx_addsy == NULL)
    1225  	as_bad_where (fixP->fx_file, fixP->fx_line,
    1226  		      _("Relocation against a constant"));
    1227        S_SET_THREAD_LOCAL (fixP->fx_addsy);
    1228        break;
    1229  
    1230      case BFD_RELOC_LARCH_SOP_PUSH_PCREL:
    1231        if (fixP->fx_addsy == NULL)
    1232  	as_bad_where (fixP->fx_file, fixP->fx_line,
    1233  		      _("Relocation against a constant"));
    1234  
    1235        last_reloc_is_sop_push_pcrel_1 = 1;
    1236        if (S_GET_SEGMENT (fixP->fx_addsy) == seg)
    1237  	stack_top = (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset
    1238  		     - (fixP->fx_where + fixP->fx_frag->fr_address));
    1239        else
    1240  	stack_top = 0;
    1241        break;
    1242  
    1243      case BFD_RELOC_LARCH_SOP_POP_32_S_10_5:
    1244      case BFD_RELOC_LARCH_SOP_POP_32_S_10_12:
    1245      case BFD_RELOC_LARCH_SOP_POP_32_U_10_12:
    1246      case BFD_RELOC_LARCH_SOP_POP_32_S_10_16:
    1247      case BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2:
    1248      case BFD_RELOC_LARCH_SOP_POP_32_S_5_20:
    1249      case BFD_RELOC_LARCH_SOP_POP_32_U:
    1250      case BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2:
    1251      case BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2:
    1252        if (!last_reloc_is_sop_push_pcrel)
    1253  	break;
    1254  
    1255        fix_reloc_insn (fixP, (bfd_vma)stack_top, buf);
    1256        break;
    1257  
    1258      /* LARCH only has R_LARCH_64/32, not has R_LARCH_24/16/8.
    1259         For BFD_RELOC_64/32, if fx_addsy and fx_subsy not null, wer need
    1260         generate BFD_RELOC_LARCH_ADD64/32 and BFD_RELOC_LARCH_SUB64/32 here.
    1261         Then will parse howto table bfd_reloc_code_real_type to generate
    1262         R_LARCH_ADD64/32 and R_LARCH_SUB64/32 reloc at tc_gen_reloc function.
    1263         If only fx_addsy not null, skip here directly, then generate
    1264         R_LARCH_64/32.
    1265  
    1266         For BFD_RELOC_24/16/8, if fx_addsy and fx_subsy not null, wer need
    1267         generate BFD_RELOC_LARCH_ADD24/16/8 and BFD_RELOC_LARCH_SUB24/16/8 here.
    1268         Then will parse howto table bfd_reloc_code_real_type to generate
    1269         R_LARCH_ADD24/16/8 and R_LARCH_SUB24/16/8 reloc at tc_gen_reloc
    1270         function. If only fx_addsy not null, we generate
    1271         BFD_RELOC_LARCH_ADD24/16/8 only, then generate R_LARCH_24/16/8.
    1272         To avoid R_LARCH_ADDxx add extra value, we write 0 first
    1273         (use md_number_to_chars (buf, 0, fixP->fx_size)).  */
    1274      case BFD_RELOC_64:
    1275      case BFD_RELOC_32:
    1276        if (fixP->fx_r_type == BFD_RELOC_32
    1277  	  && fixP->fx_addsy && fixP->fx_subsy
    1278  	  && (sub_segment = S_GET_SEGMENT (fixP->fx_subsy))
    1279  	  && strcmp (sub_segment->name, ".eh_frame") == 0
    1280  	  && S_GET_VALUE (fixP->fx_subsy)
    1281  	  == fixP->fx_frag->fr_address + fixP->fx_where)
    1282  	{
    1283  	  fixP->fx_r_type = BFD_RELOC_LARCH_32_PCREL;
    1284  	  fixP->fx_subsy = NULL;
    1285  	  break;
    1286  	}
    1287  
    1288        if (fixP->fx_addsy && fixP->fx_subsy)
    1289  	{
    1290  	  fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
    1291  	  fixP->fx_next->fx_addsy = fixP->fx_subsy;
    1292  	  fixP->fx_next->fx_subsy = NULL;
    1293  	  fixP->fx_next->fx_offset = 0;
    1294  	  fixP->fx_subsy = NULL;
    1295  
    1296  	  switch (fixP->fx_r_type)
    1297  	    {
    1298  	    case BFD_RELOC_64:
    1299  	      fixP->fx_r_type = BFD_RELOC_LARCH_ADD64;
    1300  	      fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB64;
    1301  	      break;
    1302  	    case BFD_RELOC_32:
    1303  	      fixP->fx_r_type = BFD_RELOC_LARCH_ADD32;
    1304  	      fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB32;
    1305  	      break;
    1306  	    default:
    1307  	      break;
    1308  	    }
    1309  
    1310  	  md_number_to_chars (buf, 0, fixP->fx_size);
    1311  	}
    1312  
    1313        if (fixP->fx_addsy == NULL)
    1314  	{
    1315  	  fixP->fx_done = 1;
    1316  	  md_number_to_chars (buf, *valP, fixP->fx_size);
    1317  	}
    1318        break;
    1319  
    1320      case BFD_RELOC_24:
    1321      case BFD_RELOC_16:
    1322      case BFD_RELOC_8:
    1323        if (fixP->fx_addsy)
    1324  	{
    1325  	  fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
    1326  	  fixP->fx_next->fx_addsy = fixP->fx_subsy;
    1327  	  fixP->fx_next->fx_subsy = NULL;
    1328  	  fixP->fx_next->fx_offset = 0;
    1329  	  fixP->fx_subsy = NULL;
    1330  
    1331  	  switch (fixP->fx_r_type)
    1332  	    {
    1333  	    case BFD_RELOC_24:
    1334  	      fixP->fx_r_type = BFD_RELOC_LARCH_ADD24;
    1335  	      fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB24;
    1336  	      break;
    1337  	    case BFD_RELOC_16:
    1338  	      fixP->fx_r_type = BFD_RELOC_LARCH_ADD16;
    1339  	      fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB16;
    1340  	      break;
    1341  	    case BFD_RELOC_8:
    1342  	      fixP->fx_r_type = BFD_RELOC_LARCH_ADD8;
    1343  	      fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB8;
    1344  	      break;
    1345  	    default:
    1346  	      break;
    1347  	    }
    1348  
    1349  	  md_number_to_chars (buf, 0, fixP->fx_size);
    1350  
    1351  	  if (fixP->fx_next->fx_addsy == NULL)
    1352  	    fixP->fx_next->fx_done = 1;
    1353  	}
    1354  
    1355        if (fixP->fx_addsy == NULL)
    1356  	{
    1357  	  fixP->fx_done = 1;
    1358  	  md_number_to_chars (buf, *valP, fixP->fx_size);
    1359  	}
    1360        break;
    1361  
    1362      case BFD_RELOC_LARCH_CFA:
    1363        if (fixP->fx_addsy && fixP->fx_subsy)
    1364  	{
    1365  	  fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
    1366  	  fixP->fx_next->fx_addsy = fixP->fx_subsy;
    1367  	  fixP->fx_next->fx_subsy = NULL;
    1368  	  fixP->fx_next->fx_offset = 0;
    1369  	  fixP->fx_subsy = NULL;
    1370  
    1371  	  unsigned int subtype;
    1372  	  offsetT loc;
    1373  	  subtype = bfd_get_8 (NULL, &((fragS *)
    1374  		      (fixP->fx_frag->fr_opcode))->fr_literal[fixP->fx_where]);
    1375  	  loc = fixP->fx_frag->fr_fix - (subtype & 7);
    1376  	  switch (subtype)
    1377  	    {
    1378  	    case DW_CFA_advance_loc1:
    1379  	      fixP->fx_where = loc + 1;
    1380  	      fixP->fx_next->fx_where = loc + 1;
    1381  	      fixP->fx_r_type = BFD_RELOC_LARCH_ADD8;
    1382  	      fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB8;
    1383  	      md_number_to_chars (buf+1, 0, fixP->fx_size);
    1384  	      break;
    1385  
    1386  	    case DW_CFA_advance_loc2:
    1387  	      fixP->fx_size = 2;
    1388  	      fixP->fx_next->fx_size = 2;
    1389  	      fixP->fx_where = loc + 1;
    1390  	      fixP->fx_next->fx_where = loc + 1;
    1391  	      fixP->fx_r_type = BFD_RELOC_LARCH_ADD16;
    1392  	      fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB16;
    1393  	      md_number_to_chars (buf+1, 0, fixP->fx_size);
    1394  	      break;
    1395  
    1396  	    case DW_CFA_advance_loc4:
    1397  	      fixP->fx_size = 4;
    1398  	      fixP->fx_next->fx_size = 4;
    1399  	      fixP->fx_where = loc;
    1400  	      fixP->fx_next->fx_where = loc;
    1401  	      fixP->fx_r_type = BFD_RELOC_LARCH_ADD32;
    1402  	      fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB32;
    1403  	      md_number_to_chars (buf+1, 0, fixP->fx_size);
    1404  	      break;
    1405  
    1406  	    default:
    1407  	      if (subtype < 0x80 && (subtype & 0x40))
    1408  		{
    1409  		  /* DW_CFA_advance_loc.  */
    1410  		  fixP->fx_frag = (fragS *) fixP->fx_frag->fr_opcode;
    1411  		  fixP->fx_next->fx_frag = fixP->fx_frag;
    1412  		  fixP->fx_r_type = BFD_RELOC_LARCH_ADD6;
    1413  		  fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB6;
    1414  		  md_number_to_chars (buf, 0x40, fixP->fx_size);
    1415  		  }
    1416  	      else
    1417  		as_fatal (_("internal: bad CFA value #%d"), subtype);
    1418  	      break;
    1419  	    }
    1420  	}
    1421        break;
    1422  
    1423      case BFD_RELOC_LARCH_B16:
    1424      case BFD_RELOC_LARCH_B21:
    1425      case BFD_RELOC_LARCH_B26:
    1426        if (fixP->fx_addsy == NULL)
    1427  	{
    1428  	  as_bad_where (fixP->fx_file, fixP->fx_line,
    1429  			_ ("Relocation against a constant."));
    1430  	}
    1431        if (S_GET_SEGMENT (fixP->fx_addsy) == seg
    1432  	  && !S_FORCE_RELOC (fixP->fx_addsy, 1))
    1433  	{
    1434  	  int64_t sym_addend = S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset;
    1435  	  int64_t pc = fixP->fx_where + fixP->fx_frag->fr_address;
    1436  	  fix_reloc_insn (fixP, sym_addend - pc, buf);
    1437  
    1438  	  /* If relax, symbol value may change at link time, so reloc need to
    1439  	     be saved.  */
    1440  	  if (!LARCH_opts.relax)
    1441  	    fixP->fx_done = 1;
    1442  	}
    1443        break;
    1444  
    1445      /* Because ADD_ULEB128/SUB_ULEB128 always occur in pairs.
    1446         So just deal with one is ok.
    1447      case BFD_RELOC_LARCH_ADD_ULEB128:  */
    1448      case BFD_RELOC_LARCH_SUB_ULEB128:
    1449        {
    1450  	unsigned int len = 0;
    1451  	len = loongarch_get_uleb128_length ((bfd_byte *)buf);
    1452  	bfd_byte *endp = (bfd_byte*) buf + len -1;
    1453  	/* Clean the uleb128 value to 0. Do not reduce the length.  */
    1454  	memset (buf, 0x80, len - 1);
    1455  	*endp = 0;
    1456  	break;
    1457        }
    1458  
    1459      default:
    1460        break;
    1461      }
    1462  }
    1463  
    1464  int
    1465  loongarch_relax_frag (asection *sec ATTRIBUTE_UNUSED,
    1466  		      fragS *fragp ATTRIBUTE_UNUSED,
    1467  		      long stretch ATTRIBUTE_UNUSED)
    1468  {
    1469    return 0;
    1470  }
    1471  
    1472  int
    1473  md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED,
    1474  			       asection *segtype ATTRIBUTE_UNUSED)
    1475  {
    1476    return (fragp->fr_var = 4);
    1477  }
    1478  
    1479  /* Translate internal representation of relocation info to BFD target
    1480     format.  */
    1481  arelent *
    1482  tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
    1483  {
    1484    arelent *reloc = (arelent *) xmalloc (sizeof (arelent));
    1485  
    1486    reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
    1487    *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
    1488    reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
    1489    reloc->addend = fixp->fx_offset;
    1490  
    1491    reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
    1492    if (reloc->howto == NULL)
    1493      {
    1494        as_bad_where (fixp->fx_file, fixp->fx_line,
    1495  		    _("cannot represent %s relocation in object file"),
    1496  		    bfd_get_reloc_code_name (fixp->fx_r_type));
    1497        return NULL;
    1498      }
    1499  
    1500    return reloc;
    1501  }
    1502  
    1503  /* Convert a machine dependent frag.  */
    1504  void
    1505  md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec ATTRIBUTE_UNUSED,
    1506  		 fragS *fragp)
    1507  {
    1508    expressionS exp;
    1509    exp.X_op = O_symbol;
    1510    exp.X_add_symbol = fragp->fr_symbol;
    1511    exp.X_add_number = fragp->fr_offset;
    1512    bfd_byte *buf = (bfd_byte *)fragp->fr_literal + fragp->fr_fix;
    1513  
    1514    fixS *fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
    1515  				4, &exp, false, fragp->fr_subtype);
    1516    buf += 4;
    1517  
    1518    fixp->fx_file = fragp->fr_file;
    1519    fixp->fx_line = fragp->fr_line;
    1520    fragp->fr_fix += fragp->fr_var;
    1521  
    1522    gas_assert (fragp->fr_next == NULL
    1523  	      || (fragp->fr_next->fr_address - fragp->fr_address
    1524  		  == fragp->fr_fix));
    1525  }
    1526  
    1527  /* Standard calling conventions leave the CFA at SP on entry.  */
    1528  void
    1529  loongarch_cfi_frame_initial_instructions (void)
    1530  {
    1531    cfi_add_CFA_def_cfa_register (3 /* $sp */);
    1532  }
    1533  
    1534  void
    1535  loongarch_pre_output_hook (void)
    1536  {
    1537    const frchainS *frch;
    1538    segT s;
    1539  
    1540    if (!LARCH_opts.relax)
    1541      return;
    1542  
    1543    /* Save the current segment info.  */
    1544    segT seg = now_seg;
    1545    subsegT subseg = now_subseg;
    1546  
    1547    for (s = stdoutput->sections; s; s = s->next)
    1548      for (frch = seg_info (s)->frchainP; frch; frch = frch->frch_next)
    1549        {
    1550  	fragS *frag;
    1551  
    1552  	for (frag = frch->frch_root; frag; frag = frag->fr_next)
    1553  	  {
    1554  	    if (frag->fr_type == rs_cfa)
    1555  	      {
    1556  		expressionS exp;
    1557  		expressionS *symval;
    1558  
    1559  		symval = symbol_get_value_expression (frag->fr_symbol);
    1560  		exp.X_op = O_subtract;
    1561  		exp.X_add_symbol = symval->X_add_symbol;
    1562  		exp.X_add_number = 0;
    1563  		exp.X_op_symbol = symval->X_op_symbol;
    1564  
    1565  		/* We must set the segment before creating a frag after all
    1566  		   frag chains have been chained together.  */
    1567  		subseg_set (s, frch->frch_subseg);
    1568  
    1569  		fix_new_exp (frag, (int) frag->fr_offset, 1, &exp, 0,
    1570  			     BFD_RELOC_LARCH_CFA);
    1571  	      }
    1572  	  }
    1573        }
    1574  
    1575    /* Restore the original segment info.  */
    1576    subseg_set (seg, subseg);
    1577  }
    1578  
    1579  void
    1580  tc_loongarch_parse_to_dw2regnum (expressionS *exp)
    1581  {
    1582    expression_and_evaluate (exp);
    1583  }
    1584  
    1585  void
    1586  md_show_usage (FILE *stream)
    1587  {
    1588    fprintf (stream, _("LARCH options:\n"));
    1589    /* FIXME */
    1590  }
    1591  
    1592  static void
    1593  loongarch_make_nops (char *buf, bfd_vma bytes)
    1594  {
    1595    bfd_vma i = 0;
    1596  
    1597    /* Fill with 4-byte NOPs.  */
    1598    for ( ; i < bytes; i += 4)
    1599      number_to_chars_littleendian (buf + i, LARCH_NOP, 4);
    1600  }
    1601  
    1602  /* Called from md_do_align.  Used to create an alignment frag in a
    1603     code section by emitting a worst-case NOP sequence that the linker
    1604     will later relax to the correct number of NOPs.  We can't compute
    1605     the correct alignment now because of other linker relaxations.  */
    1606  
    1607  bool
    1608  loongarch_frag_align_code (int n)
    1609  {
    1610    bfd_vma bytes = (bfd_vma) 1 << n;
    1611    bfd_vma insn_alignment = 4;
    1612    bfd_vma worst_case_bytes = bytes - insn_alignment;
    1613    char *nops;
    1614    expressionS ex;
    1615  
    1616    /* If we are moving to a smaller alignment than the instruction size, then no
    1617       alignment is required.  */
    1618    if (bytes <= insn_alignment)
    1619      return true;
    1620  
    1621    /* When not relaxing, loongarch_handle_align handles code alignment.  */
    1622    if (!LARCH_opts.relax)
    1623      return false;
    1624  
    1625    nops = frag_more (worst_case_bytes);
    1626  
    1627    ex.X_op = O_constant;
    1628    ex.X_add_number = worst_case_bytes;
    1629  
    1630    loongarch_make_nops (nops, worst_case_bytes);
    1631  
    1632    fix_new_exp (frag_now, nops - frag_now->fr_literal, 0,
    1633  	       &ex, false, BFD_RELOC_LARCH_ALIGN);
    1634  
    1635    /* We need to start a new frag after the alignment which may be removed by
    1636       the linker, to prevent the assembler from computing static offsets.
    1637       This is necessary to get correct EH info.  */
    1638    frag_wane (frag_now);
    1639    frag_new (0);
    1640  
    1641    return true;
    1642  }
    1643  
    1644  /* Fill in an rs_align_code fragment.  We want to fill 'andi $r0,$r0,0'.  */
    1645  void
    1646  loongarch_handle_align (fragS *fragp)
    1647  {
    1648    /* char nop_opcode; */
    1649    char *p;
    1650    int bytes, size, excess;
    1651    valueT opcode;
    1652  
    1653    if (fragp->fr_type != rs_align_code)
    1654      return;
    1655  
    1656    struct loongarch_cl_insn nop =
    1657      { .name = "andi", .arg_strs = { "$r0", "$r0", "0", NULL } };
    1658  
    1659    get_loongarch_opcode (&nop);
    1660    gas_assert (nop.all_match);
    1661  
    1662    p = fragp->fr_literal + fragp->fr_fix;
    1663    opcode = nop.insn_bin;
    1664    size = 4;
    1665  
    1666    bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
    1667    excess = bytes % size;
    1668  
    1669    gas_assert (excess < 4);
    1670    fragp->fr_fix += excess;
    1671  
    1672    while (excess-- != 0)
    1673      *p++ = 0;
    1674  
    1675    md_number_to_chars (p, opcode, size);
    1676    fragp->fr_var = size;
    1677  }
    1678  
    1679  /* Scan uleb128 subtraction expressions and insert fixups for them.
    1680     e.g., .uleb128 .L1 - .L0
    1681     Because relaxation may change the value of the subtraction, we
    1682     must resolve them at link-time.  */
    1683  
    1684  static void
    1685  loongarch_insert_uleb128_fixes (bfd *abfd ATTRIBUTE_UNUSED,
    1686  		      asection *sec, void *xxx ATTRIBUTE_UNUSED)
    1687  {
    1688    segment_info_type *seginfo = seg_info (sec);
    1689    struct frag *fragP;
    1690  
    1691    subseg_set (sec, 0);
    1692  
    1693    for (fragP = seginfo->frchainP->frch_root;
    1694         fragP; fragP = fragP->fr_next)
    1695      {
    1696        expressionS *exp, *exp_dup;
    1697  
    1698        if (fragP->fr_type != rs_leb128  || fragP->fr_symbol == NULL)
    1699  	continue;
    1700  
    1701        exp = symbol_get_value_expression (fragP->fr_symbol);
    1702  
    1703        if (exp->X_op != O_subtract)
    1704  	continue;
    1705  
    1706        /* FIXME: Skip for .sleb128.  */
    1707        if (fragP->fr_subtype != 0)
    1708  	continue;
    1709  
    1710        exp_dup = xmemdup (exp, sizeof (*exp), sizeof (*exp));
    1711        exp_dup->X_op = O_symbol;
    1712        exp_dup->X_op_symbol = NULL;
    1713  
    1714        exp_dup->X_add_symbol = exp->X_add_symbol;
    1715        fix_new_exp (fragP, fragP->fr_fix, 0,
    1716  		   exp_dup, 0, BFD_RELOC_LARCH_ADD_ULEB128);
    1717  
    1718        /* From binutils/testsuite/binutils-all/dw5.S
    1719  	 section .debug_rnglists
    1720  	 .uleb128 .Letext0-.Ltext0    Range length (*.LLRL2)
    1721      Offset             Info             Type               Symbol's Value  Symbol's Name + Addend
    1722  0000000000000015  0000000200000079 R_LARCH_ADD_ULEB128    0000000000000000 .text + 2
    1723  0000000000000015  000000020000007a R_LARCH_SUB_ULEB128    0000000000000000 .text + 0.  */
    1724  
    1725        /* Only the ADD_ULEB128 has X_add_number (Addend)?  */
    1726        exp_dup->X_add_number = 0;
    1727        exp_dup->X_add_symbol = exp->X_op_symbol;
    1728        fix_new_exp (fragP, fragP->fr_fix, 0,
    1729  		   exp_dup, 0, BFD_RELOC_LARCH_SUB_ULEB128);
    1730      }
    1731  }
    1732  
    1733  void
    1734  loongarch_md_finish (void)
    1735  {
    1736    /* Insert relocations for uleb128 directives, so the values can be recomputed
    1737       at link time.  */
    1738    if (LARCH_opts.relax)
    1739      bfd_map_over_sections (stdoutput, loongarch_insert_uleb128_fixes, NULL);
    1740  }
    1741  
    1742  void
    1743  loongarch_elf_final_processing (void)
    1744  {
    1745    elf_elfheader (stdoutput)->e_flags = LARCH_opts.ase_abi;
    1746  }