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