Home | History | Annotate | Line # | Download | only in bfd
elfxx-riscv.c revision 1.1.1.3
      1      1.1  christos /* RISC-V-specific support for ELF.
      2  1.1.1.3  christos    Copyright (C) 2011-2020 Free Software Foundation, Inc.
      3      1.1  christos 
      4      1.1  christos    Contributed by Andrew Waterman (andrew (at) sifive.com).
      5      1.1  christos    Based on TILE-Gx and MIPS targets.
      6      1.1  christos 
      7      1.1  christos    This file is part of BFD, the Binary File Descriptor library.
      8      1.1  christos 
      9      1.1  christos    This program is free software; you can redistribute it and/or modify
     10      1.1  christos    it under the terms of the GNU General Public License as published by
     11      1.1  christos    the Free Software Foundation; either version 3 of the License, or
     12      1.1  christos    (at your option) any later version.
     13      1.1  christos 
     14      1.1  christos    This program is distributed in the hope that it will be useful,
     15      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17      1.1  christos    GNU General Public License for more details.
     18      1.1  christos 
     19      1.1  christos    You should have received a copy of the GNU General Public License
     20      1.1  christos    along with this program; see the file COPYING3. If not,
     21      1.1  christos    see <http://www.gnu.org/licenses/>.  */
     22      1.1  christos 
     23      1.1  christos #include "sysdep.h"
     24      1.1  christos #include "bfd.h"
     25      1.1  christos #include "libbfd.h"
     26      1.1  christos #include "elf-bfd.h"
     27      1.1  christos #include "elf/riscv.h"
     28      1.1  christos #include "libiberty.h"
     29      1.1  christos #include "elfxx-riscv.h"
     30  1.1.1.2  christos #include "safe-ctype.h"
     31      1.1  christos 
     32      1.1  christos #define MINUS_ONE ((bfd_vma)0 - 1)
     33      1.1  christos 
     34  1.1.1.2  christos /* Special handler for ADD/SUB relocations that allows them to be filled out
     35  1.1.1.2  christos    both in the pre-linked and post-linked file.  This is necessary to make
     36  1.1.1.2  christos    pre-linked debug info work, as due to linker relaxations we need to emit
     37  1.1.1.2  christos    relocations for the debug info.  */
     38  1.1.1.2  christos static bfd_reloc_status_type riscv_elf_add_sub_reloc
     39  1.1.1.2  christos   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
     40  1.1.1.2  christos 
     41      1.1  christos /* The relocation table used for SHT_RELA sections.  */
     42      1.1  christos 
     43      1.1  christos static reloc_howto_type howto_table[] =
     44      1.1  christos {
     45      1.1  christos   /* No relocation.  */
     46      1.1  christos   HOWTO (R_RISCV_NONE,			/* type */
     47      1.1  christos 	 0,				/* rightshift */
     48      1.1  christos 	 3,				/* size */
     49      1.1  christos 	 0,				/* bitsize */
     50      1.1  christos 	 FALSE,				/* pc_relative */
     51      1.1  christos 	 0,				/* bitpos */
     52      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
     53      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
     54      1.1  christos 	 "R_RISCV_NONE",		/* name */
     55      1.1  christos 	 FALSE,				/* partial_inplace */
     56      1.1  christos 	 0,				/* src_mask */
     57      1.1  christos 	 0,				/* dst_mask */
     58      1.1  christos 	 FALSE),			/* pcrel_offset */
     59      1.1  christos 
     60      1.1  christos   /* 32 bit relocation.  */
     61      1.1  christos   HOWTO (R_RISCV_32,			/* type */
     62      1.1  christos 	 0,				/* rightshift */
     63      1.1  christos 	 2,				/* size */
     64      1.1  christos 	 32,				/* bitsize */
     65      1.1  christos 	 FALSE,				/* pc_relative */
     66      1.1  christos 	 0,				/* bitpos */
     67      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
     68      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
     69      1.1  christos 	 "R_RISCV_32",			/* name */
     70      1.1  christos 	 FALSE,				/* partial_inplace */
     71      1.1  christos 	 0,				/* src_mask */
     72      1.1  christos 	 MINUS_ONE,			/* dst_mask */
     73      1.1  christos 	 FALSE),			/* pcrel_offset */
     74      1.1  christos 
     75      1.1  christos   /* 64 bit relocation.  */
     76      1.1  christos   HOWTO (R_RISCV_64,			/* type */
     77      1.1  christos 	 0,				/* rightshift */
     78      1.1  christos 	 4,				/* size */
     79      1.1  christos 	 64,				/* bitsize */
     80      1.1  christos 	 FALSE,				/* pc_relative */
     81      1.1  christos 	 0,				/* bitpos */
     82      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
     83      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
     84      1.1  christos 	 "R_RISCV_64",			/* name */
     85      1.1  christos 	 FALSE,				/* partial_inplace */
     86      1.1  christos 	 0,				/* src_mask */
     87      1.1  christos 	 MINUS_ONE,			/* dst_mask */
     88      1.1  christos 	 FALSE),			/* pcrel_offset */
     89      1.1  christos 
     90      1.1  christos   /* Relocation against a local symbol in a shared object.  */
     91      1.1  christos   HOWTO (R_RISCV_RELATIVE,		/* type */
     92      1.1  christos 	 0,				/* rightshift */
     93      1.1  christos 	 2,				/* size */
     94      1.1  christos 	 32,				/* bitsize */
     95      1.1  christos 	 FALSE,				/* pc_relative */
     96      1.1  christos 	 0,				/* bitpos */
     97      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
     98      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
     99      1.1  christos 	 "R_RISCV_RELATIVE",		/* name */
    100      1.1  christos 	 FALSE,				/* partial_inplace */
    101      1.1  christos 	 0,				/* src_mask */
    102      1.1  christos 	 MINUS_ONE,			/* dst_mask */
    103      1.1  christos 	 FALSE),			/* pcrel_offset */
    104      1.1  christos 
    105      1.1  christos   HOWTO (R_RISCV_COPY,			/* type */
    106      1.1  christos 	 0,				/* rightshift */
    107      1.1  christos 	 0,				/* this one is variable size */
    108      1.1  christos 	 0,				/* bitsize */
    109      1.1  christos 	 FALSE,				/* pc_relative */
    110      1.1  christos 	 0,				/* bitpos */
    111      1.1  christos 	 complain_overflow_bitfield,	/* complain_on_overflow */
    112      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    113      1.1  christos 	 "R_RISCV_COPY",		/* name */
    114      1.1  christos 	 FALSE,				/* partial_inplace */
    115  1.1.1.2  christos 	 0,				/* src_mask */
    116  1.1.1.2  christos 	 0,				/* dst_mask */
    117      1.1  christos 	 FALSE),			/* pcrel_offset */
    118      1.1  christos 
    119      1.1  christos   HOWTO (R_RISCV_JUMP_SLOT,		/* type */
    120      1.1  christos 	 0,				/* rightshift */
    121      1.1  christos 	 4,				/* size */
    122      1.1  christos 	 64,				/* bitsize */
    123      1.1  christos 	 FALSE,				/* pc_relative */
    124      1.1  christos 	 0,				/* bitpos */
    125      1.1  christos 	 complain_overflow_bitfield,	/* complain_on_overflow */
    126      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    127      1.1  christos 	 "R_RISCV_JUMP_SLOT",		/* name */
    128      1.1  christos 	 FALSE,				/* partial_inplace */
    129  1.1.1.2  christos 	 0,				/* src_mask */
    130  1.1.1.2  christos 	 0,				/* dst_mask */
    131      1.1  christos 	 FALSE),			/* pcrel_offset */
    132      1.1  christos 
    133      1.1  christos   /* Dynamic TLS relocations.  */
    134      1.1  christos   HOWTO (R_RISCV_TLS_DTPMOD32,		/* type */
    135      1.1  christos 	 0,				/* rightshift */
    136      1.1  christos 	 4,				/* size */
    137      1.1  christos 	 32,				/* bitsize */
    138      1.1  christos 	 FALSE,				/* pc_relative */
    139      1.1  christos 	 0,				/* bitpos */
    140      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    141  1.1.1.2  christos 	 bfd_elf_generic_reloc,		/* special_function */
    142      1.1  christos 	 "R_RISCV_TLS_DTPMOD32",	/* name */
    143      1.1  christos 	 FALSE,				/* partial_inplace */
    144      1.1  christos 	 0,				/* src_mask */
    145      1.1  christos 	 MINUS_ONE,			/* dst_mask */
    146      1.1  christos 	 FALSE),			/* pcrel_offset */
    147      1.1  christos 
    148      1.1  christos   HOWTO (R_RISCV_TLS_DTPMOD64,		/* type */
    149      1.1  christos 	 0,				/* rightshift */
    150      1.1  christos 	 4,				/* size */
    151      1.1  christos 	 64,				/* bitsize */
    152      1.1  christos 	 FALSE,				/* pc_relative */
    153      1.1  christos 	 0,				/* bitpos */
    154      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    155  1.1.1.2  christos 	 bfd_elf_generic_reloc,		/* special_function */
    156      1.1  christos 	 "R_RISCV_TLS_DTPMOD64",	/* name */
    157      1.1  christos 	 FALSE,				/* partial_inplace */
    158      1.1  christos 	 0,				/* src_mask */
    159      1.1  christos 	 MINUS_ONE,			/* dst_mask */
    160      1.1  christos 	 FALSE),			/* pcrel_offset */
    161      1.1  christos 
    162      1.1  christos   HOWTO (R_RISCV_TLS_DTPREL32,		/* type */
    163      1.1  christos 	 0,				/* rightshift */
    164      1.1  christos 	 4,				/* size */
    165      1.1  christos 	 32,				/* bitsize */
    166      1.1  christos 	 FALSE,				/* pc_relative */
    167      1.1  christos 	 0,				/* bitpos */
    168      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    169  1.1.1.2  christos 	 bfd_elf_generic_reloc,		/* special_function */
    170      1.1  christos 	 "R_RISCV_TLS_DTPREL32",	/* name */
    171      1.1  christos 	 TRUE,				/* partial_inplace */
    172      1.1  christos 	 0,				/* src_mask */
    173      1.1  christos 	 MINUS_ONE,			/* dst_mask */
    174      1.1  christos 	 FALSE),			/* pcrel_offset */
    175      1.1  christos 
    176      1.1  christos   HOWTO (R_RISCV_TLS_DTPREL64,		/* type */
    177      1.1  christos 	 0,				/* rightshift */
    178      1.1  christos 	 4,				/* size */
    179      1.1  christos 	 64,				/* bitsize */
    180      1.1  christos 	 FALSE,				/* pc_relative */
    181      1.1  christos 	 0,				/* bitpos */
    182      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    183  1.1.1.2  christos 	 bfd_elf_generic_reloc,		/* special_function */
    184      1.1  christos 	 "R_RISCV_TLS_DTPREL64",	/* name */
    185      1.1  christos 	 TRUE,				/* partial_inplace */
    186      1.1  christos 	 0,				/* src_mask */
    187      1.1  christos 	 MINUS_ONE,			/* dst_mask */
    188      1.1  christos 	 FALSE),			/* pcrel_offset */
    189      1.1  christos 
    190      1.1  christos   HOWTO (R_RISCV_TLS_TPREL32,		/* type */
    191      1.1  christos 	 0,				/* rightshift */
    192      1.1  christos 	 2,				/* size */
    193      1.1  christos 	 32,				/* bitsize */
    194      1.1  christos 	 FALSE,				/* pc_relative */
    195      1.1  christos 	 0,				/* bitpos */
    196      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    197  1.1.1.2  christos 	 bfd_elf_generic_reloc,		/* special_function */
    198      1.1  christos 	 "R_RISCV_TLS_TPREL32",		/* name */
    199      1.1  christos 	 FALSE,				/* partial_inplace */
    200      1.1  christos 	 0,				/* src_mask */
    201      1.1  christos 	 MINUS_ONE,			/* dst_mask */
    202      1.1  christos 	 FALSE),			/* pcrel_offset */
    203      1.1  christos 
    204      1.1  christos   HOWTO (R_RISCV_TLS_TPREL64,		/* type */
    205      1.1  christos 	 0,				/* rightshift */
    206      1.1  christos 	 4,				/* size */
    207      1.1  christos 	 64,				/* bitsize */
    208      1.1  christos 	 FALSE,				/* pc_relative */
    209      1.1  christos 	 0,				/* bitpos */
    210      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    211  1.1.1.2  christos 	 bfd_elf_generic_reloc,		/* special_function */
    212      1.1  christos 	 "R_RISCV_TLS_TPREL64",		/* name */
    213      1.1  christos 	 FALSE,				/* partial_inplace */
    214      1.1  christos 	 0,				/* src_mask */
    215      1.1  christos 	 MINUS_ONE,			/* dst_mask */
    216      1.1  christos 	 FALSE),			/* pcrel_offset */
    217      1.1  christos 
    218      1.1  christos   /* Reserved for future relocs that the dynamic linker must understand.  */
    219      1.1  christos   EMPTY_HOWTO (12),
    220      1.1  christos   EMPTY_HOWTO (13),
    221      1.1  christos   EMPTY_HOWTO (14),
    222      1.1  christos   EMPTY_HOWTO (15),
    223      1.1  christos 
    224      1.1  christos   /* 12-bit PC-relative branch offset.  */
    225      1.1  christos   HOWTO (R_RISCV_BRANCH,		/* type */
    226      1.1  christos 	 0,				/* rightshift */
    227      1.1  christos 	 2,				/* size */
    228      1.1  christos 	 32,				/* bitsize */
    229      1.1  christos 	 TRUE,				/* pc_relative */
    230      1.1  christos 	 0,				/* bitpos */
    231      1.1  christos 	 complain_overflow_signed,	/* complain_on_overflow */
    232      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    233      1.1  christos 	 "R_RISCV_BRANCH",		/* name */
    234      1.1  christos 	 FALSE,				/* partial_inplace */
    235      1.1  christos 	 0,				/* src_mask */
    236      1.1  christos 	 ENCODE_SBTYPE_IMM (-1U),	/* dst_mask */
    237      1.1  christos 	 TRUE),				/* pcrel_offset */
    238      1.1  christos 
    239      1.1  christos   /* 20-bit PC-relative jump offset.  */
    240      1.1  christos   HOWTO (R_RISCV_JAL,			/* type */
    241      1.1  christos 	 0,				/* rightshift */
    242      1.1  christos 	 2,				/* size */
    243      1.1  christos 	 32,				/* bitsize */
    244      1.1  christos 	 TRUE,				/* pc_relative */
    245      1.1  christos 	 0,				/* bitpos */
    246      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    247      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    248      1.1  christos 	 "R_RISCV_JAL",			/* name */
    249      1.1  christos 	 FALSE,				/* partial_inplace */
    250      1.1  christos 	 0,				/* src_mask */
    251      1.1  christos 	 ENCODE_UJTYPE_IMM (-1U),	/* dst_mask */
    252      1.1  christos 	 TRUE),				/* pcrel_offset */
    253      1.1  christos 
    254      1.1  christos   /* 32-bit PC-relative function call (AUIPC/JALR).  */
    255      1.1  christos   HOWTO (R_RISCV_CALL,			/* type */
    256      1.1  christos 	 0,				/* rightshift */
    257      1.1  christos 	 2,				/* size */
    258      1.1  christos 	 64,				/* bitsize */
    259      1.1  christos 	 TRUE,				/* pc_relative */
    260      1.1  christos 	 0,				/* bitpos */
    261      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    262      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    263      1.1  christos 	 "R_RISCV_CALL",		/* name */
    264      1.1  christos 	 FALSE,				/* partial_inplace */
    265      1.1  christos 	 0,				/* src_mask */
    266      1.1  christos 	 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
    267      1.1  christos 					/* dst_mask */
    268      1.1  christos 	 TRUE),				/* pcrel_offset */
    269      1.1  christos 
    270      1.1  christos   /* Like R_RISCV_CALL, but not locally binding.  */
    271      1.1  christos   HOWTO (R_RISCV_CALL_PLT,		/* type */
    272      1.1  christos 	 0,				/* rightshift */
    273      1.1  christos 	 2,				/* size */
    274      1.1  christos 	 64,				/* bitsize */
    275      1.1  christos 	 TRUE,				/* pc_relative */
    276      1.1  christos 	 0,				/* bitpos */
    277      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    278      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    279      1.1  christos 	 "R_RISCV_CALL_PLT",		/* name */
    280      1.1  christos 	 FALSE,				/* partial_inplace */
    281      1.1  christos 	 0,				/* src_mask */
    282      1.1  christos 	 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32),
    283      1.1  christos 					/* dst_mask */
    284      1.1  christos 	 TRUE),				/* pcrel_offset */
    285      1.1  christos 
    286      1.1  christos   /* High 20 bits of 32-bit PC-relative GOT access.  */
    287      1.1  christos   HOWTO (R_RISCV_GOT_HI20,		/* type */
    288      1.1  christos 	 0,				/* rightshift */
    289      1.1  christos 	 2,				/* size */
    290      1.1  christos 	 32,				/* bitsize */
    291      1.1  christos 	 TRUE,				/* pc_relative */
    292      1.1  christos 	 0,				/* bitpos */
    293      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    294      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    295      1.1  christos 	 "R_RISCV_GOT_HI20",		/* name */
    296      1.1  christos 	 FALSE,				/* partial_inplace */
    297      1.1  christos 	 0,				/* src_mask */
    298      1.1  christos 	 ENCODE_UTYPE_IMM (-1U),	/* dst_mask */
    299      1.1  christos 	 FALSE),			/* pcrel_offset */
    300      1.1  christos 
    301      1.1  christos   /* High 20 bits of 32-bit PC-relative TLS IE GOT access.  */
    302      1.1  christos   HOWTO (R_RISCV_TLS_GOT_HI20,		/* type */
    303      1.1  christos 	 0,				/* rightshift */
    304      1.1  christos 	 2,				/* size */
    305      1.1  christos 	 32,				/* bitsize */
    306      1.1  christos 	 TRUE,				/* pc_relative */
    307      1.1  christos 	 0,				/* bitpos */
    308      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    309      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    310      1.1  christos 	 "R_RISCV_TLS_GOT_HI20",	/* name */
    311      1.1  christos 	 FALSE,				/* partial_inplace */
    312      1.1  christos 	 0,				/* src_mask */
    313      1.1  christos 	 ENCODE_UTYPE_IMM (-1U),	/* dst_mask */
    314      1.1  christos 	 FALSE),			/* pcrel_offset */
    315      1.1  christos 
    316      1.1  christos   /* High 20 bits of 32-bit PC-relative TLS GD GOT reference.  */
    317      1.1  christos   HOWTO (R_RISCV_TLS_GD_HI20,		/* type */
    318      1.1  christos 	 0,				/* rightshift */
    319      1.1  christos 	 2,				/* size */
    320      1.1  christos 	 32,				/* bitsize */
    321      1.1  christos 	 TRUE,				/* pc_relative */
    322      1.1  christos 	 0,				/* bitpos */
    323      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    324      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    325      1.1  christos 	 "R_RISCV_TLS_GD_HI20",		/* name */
    326      1.1  christos 	 FALSE,				/* partial_inplace */
    327      1.1  christos 	 0,				/* src_mask */
    328      1.1  christos 	 ENCODE_UTYPE_IMM (-1U),	/* dst_mask */
    329      1.1  christos 	 FALSE),			/* pcrel_offset */
    330      1.1  christos 
    331      1.1  christos   /* High 20 bits of 32-bit PC-relative reference.  */
    332      1.1  christos   HOWTO (R_RISCV_PCREL_HI20,		/* type */
    333      1.1  christos 	 0,				/* rightshift */
    334      1.1  christos 	 2,				/* size */
    335      1.1  christos 	 32,				/* bitsize */
    336      1.1  christos 	 TRUE,				/* pc_relative */
    337      1.1  christos 	 0,				/* bitpos */
    338      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    339      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    340      1.1  christos 	 "R_RISCV_PCREL_HI20",		/* name */
    341      1.1  christos 	 FALSE,				/* partial_inplace */
    342      1.1  christos 	 0,				/* src_mask */
    343      1.1  christos 	 ENCODE_UTYPE_IMM (-1U),	/* dst_mask */
    344      1.1  christos 	 TRUE),				/* pcrel_offset */
    345      1.1  christos 
    346      1.1  christos   /* Low 12 bits of a 32-bit PC-relative load or add.  */
    347      1.1  christos   HOWTO (R_RISCV_PCREL_LO12_I,		/* type */
    348      1.1  christos 	 0,				/* rightshift */
    349      1.1  christos 	 2,				/* size */
    350      1.1  christos 	 32,				/* bitsize */
    351      1.1  christos 	 FALSE,				/* pc_relative */
    352      1.1  christos 	 0,				/* bitpos */
    353      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    354      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    355      1.1  christos 	 "R_RISCV_PCREL_LO12_I",	/* name */
    356      1.1  christos 	 FALSE,				/* partial_inplace */
    357      1.1  christos 	 0,				/* src_mask */
    358      1.1  christos 	 ENCODE_ITYPE_IMM (-1U),	/* dst_mask */
    359      1.1  christos 	 FALSE),			/* pcrel_offset */
    360      1.1  christos 
    361      1.1  christos   /* Low 12 bits of a 32-bit PC-relative store.  */
    362      1.1  christos   HOWTO (R_RISCV_PCREL_LO12_S,		/* type */
    363      1.1  christos 	 0,				/* rightshift */
    364      1.1  christos 	 2,				/* size */
    365      1.1  christos 	 32,				/* bitsize */
    366      1.1  christos 	 FALSE,				/* pc_relative */
    367      1.1  christos 	 0,				/* bitpos */
    368      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    369      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    370      1.1  christos 	 "R_RISCV_PCREL_LO12_S",	/* name */
    371      1.1  christos 	 FALSE,				/* partial_inplace */
    372      1.1  christos 	 0,				/* src_mask */
    373      1.1  christos 	 ENCODE_STYPE_IMM (-1U),	/* dst_mask */
    374      1.1  christos 	 FALSE),			/* pcrel_offset */
    375      1.1  christos 
    376      1.1  christos   /* High 20 bits of 32-bit absolute address.  */
    377      1.1  christos   HOWTO (R_RISCV_HI20,			/* type */
    378      1.1  christos 	 0,				/* rightshift */
    379      1.1  christos 	 2,				/* size */
    380      1.1  christos 	 32,				/* bitsize */
    381      1.1  christos 	 FALSE,				/* pc_relative */
    382      1.1  christos 	 0,				/* bitpos */
    383      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    384      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    385      1.1  christos 	 "R_RISCV_HI20",		/* name */
    386      1.1  christos 	 FALSE,				/* partial_inplace */
    387      1.1  christos 	 0,				/* src_mask */
    388      1.1  christos 	 ENCODE_UTYPE_IMM (-1U),	/* dst_mask */
    389      1.1  christos 	 FALSE),			/* pcrel_offset */
    390      1.1  christos 
    391      1.1  christos   /* High 12 bits of 32-bit load or add.  */
    392      1.1  christos   HOWTO (R_RISCV_LO12_I,		/* type */
    393      1.1  christos 	 0,				/* rightshift */
    394      1.1  christos 	 2,				/* size */
    395      1.1  christos 	 32,				/* bitsize */
    396      1.1  christos 	 FALSE,				/* pc_relative */
    397      1.1  christos 	 0,				/* bitpos */
    398      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    399      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    400      1.1  christos 	 "R_RISCV_LO12_I",		/* name */
    401      1.1  christos 	 FALSE,				/* partial_inplace */
    402      1.1  christos 	 0,				/* src_mask */
    403      1.1  christos 	 ENCODE_ITYPE_IMM (-1U),	/* dst_mask */
    404      1.1  christos 	 FALSE),			/* pcrel_offset */
    405      1.1  christos 
    406      1.1  christos   /* High 12 bits of 32-bit store.  */
    407      1.1  christos   HOWTO (R_RISCV_LO12_S,		/* type */
    408      1.1  christos 	 0,				/* rightshift */
    409      1.1  christos 	 2,				/* size */
    410      1.1  christos 	 32,				/* bitsize */
    411      1.1  christos 	 FALSE,				/* pc_relative */
    412      1.1  christos 	 0,				/* bitpos */
    413      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    414      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    415      1.1  christos 	 "R_RISCV_LO12_S",		/* name */
    416      1.1  christos 	 FALSE,				/* partial_inplace */
    417      1.1  christos 	 0,				/* src_mask */
    418      1.1  christos 	 ENCODE_STYPE_IMM (-1U),	/* dst_mask */
    419      1.1  christos 	 FALSE),			/* pcrel_offset */
    420      1.1  christos 
    421      1.1  christos   /* High 20 bits of TLS LE thread pointer offset.  */
    422      1.1  christos   HOWTO (R_RISCV_TPREL_HI20,		/* type */
    423      1.1  christos 	 0,				/* rightshift */
    424      1.1  christos 	 2,				/* size */
    425      1.1  christos 	 32,				/* bitsize */
    426      1.1  christos 	 FALSE,				/* pc_relative */
    427      1.1  christos 	 0,				/* bitpos */
    428      1.1  christos 	 complain_overflow_signed,	/* complain_on_overflow */
    429      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    430      1.1  christos 	 "R_RISCV_TPREL_HI20",		/* name */
    431      1.1  christos 	 TRUE,				/* partial_inplace */
    432      1.1  christos 	 0,				/* src_mask */
    433      1.1  christos 	 ENCODE_UTYPE_IMM (-1U),	/* dst_mask */
    434      1.1  christos 	 FALSE),			/* pcrel_offset */
    435      1.1  christos 
    436      1.1  christos   /* Low 12 bits of TLS LE thread pointer offset for loads and adds.  */
    437      1.1  christos   HOWTO (R_RISCV_TPREL_LO12_I,		/* type */
    438      1.1  christos 	 0,				/* rightshift */
    439      1.1  christos 	 2,				/* size */
    440      1.1  christos 	 32,				/* bitsize */
    441      1.1  christos 	 FALSE,				/* pc_relative */
    442      1.1  christos 	 0,				/* bitpos */
    443      1.1  christos 	 complain_overflow_signed,	/* complain_on_overflow */
    444      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    445      1.1  christos 	 "R_RISCV_TPREL_LO12_I",	/* name */
    446      1.1  christos 	 FALSE,				/* partial_inplace */
    447      1.1  christos 	 0,				/* src_mask */
    448      1.1  christos 	 ENCODE_ITYPE_IMM (-1U),	/* dst_mask */
    449      1.1  christos 	 FALSE),			/* pcrel_offset */
    450      1.1  christos 
    451      1.1  christos   /* Low 12 bits of TLS LE thread pointer offset for stores.  */
    452      1.1  christos   HOWTO (R_RISCV_TPREL_LO12_S,		/* type */
    453      1.1  christos 	 0,				/* rightshift */
    454      1.1  christos 	 2,				/* size */
    455      1.1  christos 	 32,				/* bitsize */
    456      1.1  christos 	 FALSE,				/* pc_relative */
    457      1.1  christos 	 0,				/* bitpos */
    458      1.1  christos 	 complain_overflow_signed,	/* complain_on_overflow */
    459      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    460      1.1  christos 	 "R_RISCV_TPREL_LO12_S",	/* name */
    461      1.1  christos 	 FALSE,				/* partial_inplace */
    462      1.1  christos 	 0,				/* src_mask */
    463      1.1  christos 	 ENCODE_STYPE_IMM (-1U),	/* dst_mask */
    464      1.1  christos 	 FALSE),			/* pcrel_offset */
    465      1.1  christos 
    466      1.1  christos   /* TLS LE thread pointer usage.  May be relaxed.  */
    467      1.1  christos   HOWTO (R_RISCV_TPREL_ADD,		/* type */
    468      1.1  christos 	 0,				/* rightshift */
    469      1.1  christos 	 2,				/* size */
    470      1.1  christos 	 32,				/* bitsize */
    471      1.1  christos 	 FALSE,				/* pc_relative */
    472      1.1  christos 	 0,				/* bitpos */
    473      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    474      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    475      1.1  christos 	 "R_RISCV_TPREL_ADD",		/* name */
    476      1.1  christos 	 TRUE,				/* partial_inplace */
    477      1.1  christos 	 0,				/* src_mask */
    478      1.1  christos 	 0,				/* dst_mask */
    479      1.1  christos 	 FALSE),			/* pcrel_offset */
    480      1.1  christos 
    481      1.1  christos   /* 8-bit in-place addition, for local label subtraction.  */
    482      1.1  christos   HOWTO (R_RISCV_ADD8,			/* type */
    483      1.1  christos 	 0,				/* rightshift */
    484      1.1  christos 	 0,				/* size */
    485      1.1  christos 	 8,				/* bitsize */
    486      1.1  christos 	 FALSE,				/* pc_relative */
    487      1.1  christos 	 0,				/* bitpos */
    488      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    489  1.1.1.2  christos 	 riscv_elf_add_sub_reloc,	/* special_function */
    490      1.1  christos 	 "R_RISCV_ADD8",		/* name */
    491      1.1  christos 	 FALSE,				/* partial_inplace */
    492      1.1  christos 	 0,				/* src_mask */
    493      1.1  christos 	 MINUS_ONE,			/* dst_mask */
    494      1.1  christos 	 FALSE),			/* pcrel_offset */
    495      1.1  christos 
    496      1.1  christos   /* 16-bit in-place addition, for local label subtraction.  */
    497      1.1  christos   HOWTO (R_RISCV_ADD16,			/* type */
    498      1.1  christos 	 0,				/* rightshift */
    499      1.1  christos 	 1,				/* size */
    500      1.1  christos 	 16,				/* bitsize */
    501      1.1  christos 	 FALSE,				/* pc_relative */
    502      1.1  christos 	 0,				/* bitpos */
    503      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    504  1.1.1.2  christos 	 riscv_elf_add_sub_reloc,	/* special_function */
    505      1.1  christos 	 "R_RISCV_ADD16",		/* name */
    506      1.1  christos 	 FALSE,				/* partial_inplace */
    507      1.1  christos 	 0,				/* src_mask */
    508      1.1  christos 	 MINUS_ONE,			/* dst_mask */
    509      1.1  christos 	 FALSE),			/* pcrel_offset */
    510      1.1  christos 
    511      1.1  christos   /* 32-bit in-place addition, for local label subtraction.  */
    512      1.1  christos   HOWTO (R_RISCV_ADD32,			/* type */
    513      1.1  christos 	 0,				/* rightshift */
    514      1.1  christos 	 2,				/* size */
    515      1.1  christos 	 32,				/* bitsize */
    516      1.1  christos 	 FALSE,				/* pc_relative */
    517      1.1  christos 	 0,				/* bitpos */
    518      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    519  1.1.1.2  christos 	 riscv_elf_add_sub_reloc,	/* special_function */
    520      1.1  christos 	 "R_RISCV_ADD32",		/* name */
    521      1.1  christos 	 FALSE,				/* partial_inplace */
    522      1.1  christos 	 0,				/* src_mask */
    523      1.1  christos 	 MINUS_ONE,			/* dst_mask */
    524      1.1  christos 	 FALSE),			/* pcrel_offset */
    525      1.1  christos 
    526      1.1  christos   /* 64-bit in-place addition, for local label subtraction.  */
    527      1.1  christos   HOWTO (R_RISCV_ADD64,			/* type */
    528      1.1  christos 	 0,				/* rightshift */
    529      1.1  christos 	 4,				/* size */
    530      1.1  christos 	 64,				/* bitsize */
    531      1.1  christos 	 FALSE,				/* pc_relative */
    532      1.1  christos 	 0,				/* bitpos */
    533      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    534  1.1.1.2  christos 	 riscv_elf_add_sub_reloc,	/* special_function */
    535      1.1  christos 	 "R_RISCV_ADD64",		/* name */
    536      1.1  christos 	 FALSE,				/* partial_inplace */
    537      1.1  christos 	 0,				/* src_mask */
    538      1.1  christos 	 MINUS_ONE,			/* dst_mask */
    539      1.1  christos 	 FALSE),			/* pcrel_offset */
    540      1.1  christos 
    541      1.1  christos   /* 8-bit in-place addition, for local label subtraction.  */
    542      1.1  christos   HOWTO (R_RISCV_SUB8,			/* type */
    543      1.1  christos 	 0,				/* rightshift */
    544      1.1  christos 	 0,				/* size */
    545      1.1  christos 	 8,				/* bitsize */
    546      1.1  christos 	 FALSE,				/* pc_relative */
    547      1.1  christos 	 0,				/* bitpos */
    548      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    549  1.1.1.2  christos 	 riscv_elf_add_sub_reloc,	/* special_function */
    550      1.1  christos 	 "R_RISCV_SUB8",		/* name */
    551      1.1  christos 	 FALSE,				/* partial_inplace */
    552      1.1  christos 	 0,				/* src_mask */
    553      1.1  christos 	 MINUS_ONE,			/* dst_mask */
    554      1.1  christos 	 FALSE),			/* pcrel_offset */
    555      1.1  christos 
    556      1.1  christos   /* 16-bit in-place addition, for local label subtraction.  */
    557      1.1  christos   HOWTO (R_RISCV_SUB16,			/* type */
    558      1.1  christos 	 0,				/* rightshift */
    559      1.1  christos 	 1,				/* size */
    560      1.1  christos 	 16,				/* bitsize */
    561      1.1  christos 	 FALSE,				/* pc_relative */
    562      1.1  christos 	 0,				/* bitpos */
    563      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    564  1.1.1.2  christos 	 riscv_elf_add_sub_reloc,	/* special_function */
    565      1.1  christos 	 "R_RISCV_SUB16",		/* name */
    566      1.1  christos 	 FALSE,				/* partial_inplace */
    567      1.1  christos 	 0,				/* src_mask */
    568      1.1  christos 	 MINUS_ONE,			/* dst_mask */
    569      1.1  christos 	 FALSE),			/* pcrel_offset */
    570      1.1  christos 
    571      1.1  christos   /* 32-bit in-place addition, for local label subtraction.  */
    572      1.1  christos   HOWTO (R_RISCV_SUB32,			/* type */
    573      1.1  christos 	 0,				/* rightshift */
    574      1.1  christos 	 2,				/* size */
    575      1.1  christos 	 32,				/* bitsize */
    576      1.1  christos 	 FALSE,				/* pc_relative */
    577      1.1  christos 	 0,				/* bitpos */
    578      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    579  1.1.1.2  christos 	 riscv_elf_add_sub_reloc,	/* special_function */
    580      1.1  christos 	 "R_RISCV_SUB32",		/* name */
    581      1.1  christos 	 FALSE,				/* partial_inplace */
    582      1.1  christos 	 0,				/* src_mask */
    583      1.1  christos 	 MINUS_ONE,			/* dst_mask */
    584      1.1  christos 	 FALSE),			/* pcrel_offset */
    585      1.1  christos 
    586      1.1  christos   /* 64-bit in-place addition, for local label subtraction.  */
    587      1.1  christos   HOWTO (R_RISCV_SUB64,			/* type */
    588      1.1  christos 	 0,				/* rightshift */
    589      1.1  christos 	 4,				/* size */
    590      1.1  christos 	 64,				/* bitsize */
    591      1.1  christos 	 FALSE,				/* pc_relative */
    592      1.1  christos 	 0,				/* bitpos */
    593      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    594  1.1.1.2  christos 	 riscv_elf_add_sub_reloc,	/* special_function */
    595      1.1  christos 	 "R_RISCV_SUB64",		/* name */
    596      1.1  christos 	 FALSE,				/* partial_inplace */
    597      1.1  christos 	 0,				/* src_mask */
    598      1.1  christos 	 MINUS_ONE,			/* dst_mask */
    599      1.1  christos 	 FALSE),			/* pcrel_offset */
    600      1.1  christos 
    601      1.1  christos   /* GNU extension to record C++ vtable hierarchy */
    602      1.1  christos   HOWTO (R_RISCV_GNU_VTINHERIT,		/* type */
    603      1.1  christos 	 0,				/* rightshift */
    604      1.1  christos 	 4,				/* size */
    605      1.1  christos 	 0,				/* bitsize */
    606      1.1  christos 	 FALSE,				/* pc_relative */
    607      1.1  christos 	 0,				/* bitpos */
    608      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    609      1.1  christos 	 NULL,				/* special_function */
    610      1.1  christos 	 "R_RISCV_GNU_VTINHERIT",	/* name */
    611      1.1  christos 	 FALSE,				/* partial_inplace */
    612      1.1  christos 	 0,				/* src_mask */
    613      1.1  christos 	 0,				/* dst_mask */
    614      1.1  christos 	 FALSE),			/* pcrel_offset */
    615      1.1  christos 
    616      1.1  christos   /* GNU extension to record C++ vtable member usage */
    617      1.1  christos   HOWTO (R_RISCV_GNU_VTENTRY,		/* type */
    618      1.1  christos 	 0,				/* rightshift */
    619      1.1  christos 	 4,				/* size */
    620      1.1  christos 	 0,				/* bitsize */
    621      1.1  christos 	 FALSE,				/* pc_relative */
    622      1.1  christos 	 0,				/* bitpos */
    623      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    624      1.1  christos 	 _bfd_elf_rel_vtable_reloc_fn,	/* special_function */
    625      1.1  christos 	 "R_RISCV_GNU_VTENTRY",		/* name */
    626      1.1  christos 	 FALSE,				/* partial_inplace */
    627      1.1  christos 	 0,				/* src_mask */
    628      1.1  christos 	 0,				/* dst_mask */
    629      1.1  christos 	 FALSE),			/* pcrel_offset */
    630      1.1  christos 
    631      1.1  christos   /* Indicates an alignment statement.  The addend field encodes how many
    632      1.1  christos      bytes of NOPs follow the statement.  The desired alignment is the
    633      1.1  christos      addend rounded up to the next power of two.  */
    634      1.1  christos   HOWTO (R_RISCV_ALIGN,			/* type */
    635      1.1  christos 	 0,				/* rightshift */
    636      1.1  christos 	 2,				/* size */
    637      1.1  christos 	 0,				/* bitsize */
    638      1.1  christos 	 FALSE,				/* pc_relative */
    639      1.1  christos 	 0,				/* bitpos */
    640      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    641      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    642      1.1  christos 	 "R_RISCV_ALIGN",		/* name */
    643      1.1  christos 	 FALSE,				/* partial_inplace */
    644      1.1  christos 	 0,				/* src_mask */
    645      1.1  christos 	 0,				/* dst_mask */
    646      1.1  christos 	 TRUE),				/* pcrel_offset */
    647      1.1  christos 
    648      1.1  christos   /* 8-bit PC-relative branch offset.  */
    649      1.1  christos   HOWTO (R_RISCV_RVC_BRANCH,		/* type */
    650      1.1  christos 	 0,				/* rightshift */
    651      1.1  christos 	 2,				/* size */
    652      1.1  christos 	 32,				/* bitsize */
    653      1.1  christos 	 TRUE,				/* pc_relative */
    654      1.1  christos 	 0,				/* bitpos */
    655      1.1  christos 	 complain_overflow_signed,	/* complain_on_overflow */
    656      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    657      1.1  christos 	 "R_RISCV_RVC_BRANCH",		/* name */
    658      1.1  christos 	 FALSE,				/* partial_inplace */
    659      1.1  christos 	 0,				/* src_mask */
    660      1.1  christos 	 ENCODE_RVC_B_IMM (-1U),	/* dst_mask */
    661      1.1  christos 	 TRUE),				/* pcrel_offset */
    662      1.1  christos 
    663      1.1  christos   /* 11-bit PC-relative jump offset.  */
    664      1.1  christos   HOWTO (R_RISCV_RVC_JUMP,		/* type */
    665      1.1  christos 	 0,				/* rightshift */
    666      1.1  christos 	 2,				/* size */
    667      1.1  christos 	 32,				/* bitsize */
    668      1.1  christos 	 TRUE,				/* pc_relative */
    669      1.1  christos 	 0,				/* bitpos */
    670      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    671      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    672      1.1  christos 	 "R_RISCV_RVC_JUMP",		/* name */
    673      1.1  christos 	 FALSE,				/* partial_inplace */
    674      1.1  christos 	 0,				/* src_mask */
    675      1.1  christos 	 ENCODE_RVC_J_IMM (-1U),	/* dst_mask */
    676      1.1  christos 	 TRUE),				/* pcrel_offset */
    677      1.1  christos 
    678      1.1  christos   /* High 6 bits of 18-bit absolute address.  */
    679      1.1  christos   HOWTO (R_RISCV_RVC_LUI,		/* type */
    680      1.1  christos 	 0,				/* rightshift */
    681      1.1  christos 	 2,				/* size */
    682      1.1  christos 	 32,				/* bitsize */
    683      1.1  christos 	 FALSE,				/* pc_relative */
    684      1.1  christos 	 0,				/* bitpos */
    685      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    686      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    687      1.1  christos 	 "R_RISCV_RVC_LUI",		/* name */
    688      1.1  christos 	 FALSE,				/* partial_inplace */
    689      1.1  christos 	 0,				/* src_mask */
    690      1.1  christos 	 ENCODE_RVC_IMM (-1U),		/* dst_mask */
    691      1.1  christos 	 FALSE),			/* pcrel_offset */
    692      1.1  christos 
    693      1.1  christos   /* GP-relative load.  */
    694      1.1  christos   HOWTO (R_RISCV_GPREL_I,		/* type */
    695      1.1  christos 	 0,				/* rightshift */
    696      1.1  christos 	 2,				/* size */
    697      1.1  christos 	 32,				/* bitsize */
    698      1.1  christos 	 FALSE,				/* pc_relative */
    699      1.1  christos 	 0,				/* bitpos */
    700      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    701      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    702      1.1  christos 	 "R_RISCV_GPREL_I",		/* name */
    703      1.1  christos 	 FALSE,				/* partial_inplace */
    704      1.1  christos 	 0,				/* src_mask */
    705      1.1  christos 	 ENCODE_ITYPE_IMM (-1U),	/* dst_mask */
    706      1.1  christos 	 FALSE),			/* pcrel_offset */
    707      1.1  christos 
    708      1.1  christos   /* GP-relative store.  */
    709      1.1  christos   HOWTO (R_RISCV_GPREL_S,		/* type */
    710      1.1  christos 	 0,				/* rightshift */
    711      1.1  christos 	 2,				/* size */
    712      1.1  christos 	 32,				/* bitsize */
    713      1.1  christos 	 FALSE,				/* pc_relative */
    714      1.1  christos 	 0,				/* bitpos */
    715      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    716      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    717      1.1  christos 	 "R_RISCV_GPREL_S",		/* name */
    718      1.1  christos 	 FALSE,				/* partial_inplace */
    719      1.1  christos 	 0,				/* src_mask */
    720      1.1  christos 	 ENCODE_STYPE_IMM (-1U),	/* dst_mask */
    721      1.1  christos 	 FALSE),			/* pcrel_offset */
    722      1.1  christos 
    723      1.1  christos   /* TP-relative TLS LE load.  */
    724      1.1  christos   HOWTO (R_RISCV_TPREL_I,		/* type */
    725      1.1  christos 	 0,				/* rightshift */
    726      1.1  christos 	 2,				/* size */
    727      1.1  christos 	 32,				/* bitsize */
    728      1.1  christos 	 FALSE,				/* pc_relative */
    729      1.1  christos 	 0,				/* bitpos */
    730      1.1  christos 	 complain_overflow_signed,	/* complain_on_overflow */
    731      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    732      1.1  christos 	 "R_RISCV_TPREL_I",		/* name */
    733      1.1  christos 	 FALSE,				/* partial_inplace */
    734      1.1  christos 	 0,				/* src_mask */
    735      1.1  christos 	 ENCODE_ITYPE_IMM (-1U),	/* dst_mask */
    736      1.1  christos 	 FALSE),			/* pcrel_offset */
    737      1.1  christos 
    738      1.1  christos   /* TP-relative TLS LE store.  */
    739      1.1  christos   HOWTO (R_RISCV_TPREL_S,		/* type */
    740      1.1  christos 	 0,				/* rightshift */
    741      1.1  christos 	 2,				/* size */
    742      1.1  christos 	 32,				/* bitsize */
    743      1.1  christos 	 FALSE,				/* pc_relative */
    744      1.1  christos 	 0,				/* bitpos */
    745      1.1  christos 	 complain_overflow_signed,	/* complain_on_overflow */
    746      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    747      1.1  christos 	 "R_RISCV_TPREL_S",		/* name */
    748      1.1  christos 	 FALSE,				/* partial_inplace */
    749      1.1  christos 	 0,				/* src_mask */
    750      1.1  christos 	 ENCODE_STYPE_IMM (-1U),	/* dst_mask */
    751      1.1  christos 	 FALSE),			/* pcrel_offset */
    752      1.1  christos 
    753      1.1  christos   /* The paired relocation may be relaxed.  */
    754      1.1  christos   HOWTO (R_RISCV_RELAX,			/* type */
    755      1.1  christos 	 0,				/* rightshift */
    756      1.1  christos 	 3,				/* size */
    757      1.1  christos 	 0,				/* bitsize */
    758      1.1  christos 	 FALSE,				/* pc_relative */
    759      1.1  christos 	 0,				/* bitpos */
    760      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    761      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    762      1.1  christos 	 "R_RISCV_RELAX",		/* name */
    763      1.1  christos 	 FALSE,				/* partial_inplace */
    764      1.1  christos 	 0,				/* src_mask */
    765      1.1  christos 	 0,				/* dst_mask */
    766      1.1  christos 	 FALSE),			/* pcrel_offset */
    767      1.1  christos 
    768      1.1  christos   /* 6-bit in-place addition, for local label subtraction.  */
    769      1.1  christos   HOWTO (R_RISCV_SUB6,			/* type */
    770      1.1  christos 	 0,				/* rightshift */
    771      1.1  christos 	 0,				/* size */
    772      1.1  christos 	 8,				/* bitsize */
    773      1.1  christos 	 FALSE,				/* pc_relative */
    774      1.1  christos 	 0,				/* bitpos */
    775      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    776  1.1.1.2  christos 	 riscv_elf_add_sub_reloc,	/* special_function */
    777      1.1  christos 	 "R_RISCV_SUB6",		/* name */
    778      1.1  christos 	 FALSE,				/* partial_inplace */
    779      1.1  christos 	 0,				/* src_mask */
    780      1.1  christos 	 0x3f,				/* dst_mask */
    781      1.1  christos 	 FALSE),			/* pcrel_offset */
    782      1.1  christos 
    783      1.1  christos   /* 6-bit in-place setting, for local label subtraction.  */
    784      1.1  christos   HOWTO (R_RISCV_SET6,			/* type */
    785      1.1  christos 	 0,				/* rightshift */
    786      1.1  christos 	 0,				/* size */
    787      1.1  christos 	 8,				/* bitsize */
    788      1.1  christos 	 FALSE,				/* pc_relative */
    789      1.1  christos 	 0,				/* bitpos */
    790      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    791      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    792      1.1  christos 	 "R_RISCV_SET6",		/* name */
    793      1.1  christos 	 FALSE,				/* partial_inplace */
    794      1.1  christos 	 0,				/* src_mask */
    795      1.1  christos 	 0x3f,				/* dst_mask */
    796      1.1  christos 	 FALSE),			/* pcrel_offset */
    797      1.1  christos 
    798      1.1  christos   /* 8-bit in-place setting, for local label subtraction.  */
    799      1.1  christos   HOWTO (R_RISCV_SET8,			/* type */
    800      1.1  christos 	 0,				/* rightshift */
    801      1.1  christos 	 0,				/* size */
    802      1.1  christos 	 8,				/* bitsize */
    803      1.1  christos 	 FALSE,				/* pc_relative */
    804      1.1  christos 	 0,				/* bitpos */
    805      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    806      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    807      1.1  christos 	 "R_RISCV_SET8",		/* name */
    808      1.1  christos 	 FALSE,				/* partial_inplace */
    809      1.1  christos 	 0,				/* src_mask */
    810      1.1  christos 	 MINUS_ONE,			/* dst_mask */
    811      1.1  christos 	 FALSE),			/* pcrel_offset */
    812      1.1  christos 
    813      1.1  christos   /* 16-bit in-place setting, for local label subtraction.  */
    814      1.1  christos   HOWTO (R_RISCV_SET16,			/* type */
    815      1.1  christos 	 0,				/* rightshift */
    816      1.1  christos 	 1,				/* size */
    817      1.1  christos 	 16,				/* bitsize */
    818      1.1  christos 	 FALSE,				/* pc_relative */
    819      1.1  christos 	 0,				/* bitpos */
    820      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    821      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    822      1.1  christos 	 "R_RISCV_SET16",		/* name */
    823      1.1  christos 	 FALSE,				/* partial_inplace */
    824      1.1  christos 	 0,				/* src_mask */
    825      1.1  christos 	 MINUS_ONE,			/* dst_mask */
    826      1.1  christos 	 FALSE),			/* pcrel_offset */
    827      1.1  christos 
    828      1.1  christos   /* 32-bit in-place setting, for local label subtraction.  */
    829      1.1  christos   HOWTO (R_RISCV_SET32,			/* type */
    830      1.1  christos 	 0,				/* rightshift */
    831      1.1  christos 	 2,				/* size */
    832      1.1  christos 	 32,				/* bitsize */
    833      1.1  christos 	 FALSE,				/* pc_relative */
    834      1.1  christos 	 0,				/* bitpos */
    835      1.1  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    836      1.1  christos 	 bfd_elf_generic_reloc,		/* special_function */
    837      1.1  christos 	 "R_RISCV_SET32",		/* name */
    838      1.1  christos 	 FALSE,				/* partial_inplace */
    839      1.1  christos 	 0,				/* src_mask */
    840      1.1  christos 	 MINUS_ONE,			/* dst_mask */
    841      1.1  christos 	 FALSE),			/* pcrel_offset */
    842  1.1.1.2  christos 
    843  1.1.1.2  christos   /* 32-bit PC relative.  */
    844  1.1.1.2  christos   HOWTO (R_RISCV_32_PCREL,		/* type */
    845  1.1.1.2  christos 	 0,				/* rightshift */
    846  1.1.1.2  christos 	 2,				/* size */
    847  1.1.1.2  christos 	 32,				/* bitsize */
    848  1.1.1.2  christos 	 TRUE,				/* pc_relative */
    849  1.1.1.2  christos 	 0,				/* bitpos */
    850  1.1.1.2  christos 	 complain_overflow_dont,	/* complain_on_overflow */
    851  1.1.1.2  christos 	 bfd_elf_generic_reloc,		/* special_function */
    852  1.1.1.2  christos 	 "R_RISCV_32_PCREL",		/* name */
    853  1.1.1.2  christos 	 FALSE,				/* partial_inplace */
    854  1.1.1.2  christos 	 0,				/* src_mask */
    855  1.1.1.2  christos 	 MINUS_ONE,			/* dst_mask */
    856  1.1.1.2  christos 	 FALSE),			/* pcrel_offset */
    857      1.1  christos };
    858      1.1  christos 
    859      1.1  christos /* A mapping from BFD reloc types to RISC-V ELF reloc types.  */
    860      1.1  christos 
    861      1.1  christos struct elf_reloc_map
    862      1.1  christos {
    863      1.1  christos   bfd_reloc_code_real_type bfd_val;
    864      1.1  christos   enum elf_riscv_reloc_type elf_val;
    865      1.1  christos };
    866      1.1  christos 
    867      1.1  christos static const struct elf_reloc_map riscv_reloc_map[] =
    868      1.1  christos {
    869      1.1  christos   { BFD_RELOC_NONE, R_RISCV_NONE },
    870      1.1  christos   { BFD_RELOC_32, R_RISCV_32 },
    871      1.1  christos   { BFD_RELOC_64, R_RISCV_64 },
    872      1.1  christos   { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 },
    873      1.1  christos   { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 },
    874      1.1  christos   { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 },
    875      1.1  christos   { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 },
    876      1.1  christos   { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 },
    877      1.1  christos   { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 },
    878      1.1  christos   { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 },
    879      1.1  christos   { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 },
    880      1.1  christos   { BFD_RELOC_CTOR, R_RISCV_64 },
    881      1.1  christos   { BFD_RELOC_12_PCREL, R_RISCV_BRANCH },
    882      1.1  christos   { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 },
    883      1.1  christos   { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I },
    884      1.1  christos   { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S },
    885      1.1  christos   { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I },
    886      1.1  christos   { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S },
    887      1.1  christos   { BFD_RELOC_RISCV_CALL, R_RISCV_CALL },
    888      1.1  christos   { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT },
    889      1.1  christos   { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 },
    890      1.1  christos   { BFD_RELOC_RISCV_JMP, R_RISCV_JAL },
    891      1.1  christos   { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 },
    892      1.1  christos   { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 },
    893      1.1  christos   { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 },
    894      1.1  christos   { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 },
    895      1.1  christos   { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 },
    896      1.1  christos   { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 },
    897      1.1  christos   { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 },
    898      1.1  christos   { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 },
    899      1.1  christos   { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD },
    900      1.1  christos   { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S },
    901      1.1  christos   { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I },
    902      1.1  christos   { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 },
    903      1.1  christos   { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 },
    904      1.1  christos   { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN },
    905      1.1  christos   { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH },
    906      1.1  christos   { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP },
    907      1.1  christos   { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
    908      1.1  christos   { BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
    909      1.1  christos   { BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
    910      1.1  christos   { BFD_RELOC_RISCV_TPREL_I, R_RISCV_TPREL_I },
    911      1.1  christos   { BFD_RELOC_RISCV_TPREL_S, R_RISCV_TPREL_S },
    912      1.1  christos   { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
    913      1.1  christos   { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
    914      1.1  christos   { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
    915      1.1  christos   { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
    916      1.1  christos   { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
    917      1.1  christos   { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
    918  1.1.1.2  christos   { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL },
    919      1.1  christos };
    920      1.1  christos 
    921      1.1  christos /* Given a BFD reloc type, return a howto structure.  */
    922      1.1  christos 
    923      1.1  christos reloc_howto_type *
    924      1.1  christos riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    925      1.1  christos 			 bfd_reloc_code_real_type code)
    926      1.1  christos {
    927      1.1  christos   unsigned int i;
    928      1.1  christos 
    929      1.1  christos   for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++)
    930      1.1  christos     if (riscv_reloc_map[i].bfd_val == code)
    931      1.1  christos       return &howto_table[(int) riscv_reloc_map[i].elf_val];
    932      1.1  christos 
    933      1.1  christos   bfd_set_error (bfd_error_bad_value);
    934      1.1  christos   return NULL;
    935      1.1  christos }
    936      1.1  christos 
    937      1.1  christos reloc_howto_type *
    938      1.1  christos riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
    939      1.1  christos {
    940      1.1  christos   unsigned int i;
    941      1.1  christos 
    942      1.1  christos   for (i = 0; i < ARRAY_SIZE (howto_table); i++)
    943      1.1  christos     if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
    944      1.1  christos       return &howto_table[i];
    945      1.1  christos 
    946      1.1  christos   return NULL;
    947      1.1  christos }
    948      1.1  christos 
    949      1.1  christos reloc_howto_type *
    950  1.1.1.2  christos riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
    951      1.1  christos {
    952      1.1  christos   if (r_type >= ARRAY_SIZE (howto_table))
    953      1.1  christos     {
    954  1.1.1.2  christos       (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
    955  1.1.1.2  christos 			     abfd, r_type);
    956      1.1  christos       bfd_set_error (bfd_error_bad_value);
    957      1.1  christos       return NULL;
    958      1.1  christos     }
    959      1.1  christos   return &howto_table[r_type];
    960      1.1  christos }
    961  1.1.1.2  christos 
    962  1.1.1.2  christos /* Special_function of RISCV_ADD and RISCV_SUB relocations.  */
    963  1.1.1.2  christos 
    964  1.1.1.2  christos static bfd_reloc_status_type
    965  1.1.1.2  christos riscv_elf_add_sub_reloc (bfd *abfd,
    966  1.1.1.2  christos 			 arelent *reloc_entry,
    967  1.1.1.2  christos 			 asymbol *symbol,
    968  1.1.1.2  christos 			 void *data,
    969  1.1.1.2  christos 			 asection *input_section,
    970  1.1.1.2  christos 			 bfd *output_bfd,
    971  1.1.1.2  christos 			 char **error_message ATTRIBUTE_UNUSED)
    972  1.1.1.2  christos {
    973  1.1.1.2  christos   reloc_howto_type *howto = reloc_entry->howto;
    974  1.1.1.2  christos   bfd_vma relocation;
    975  1.1.1.2  christos 
    976  1.1.1.2  christos   if (output_bfd != NULL
    977  1.1.1.2  christos       && (symbol->flags & BSF_SECTION_SYM) == 0
    978  1.1.1.2  christos       && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
    979  1.1.1.2  christos     {
    980  1.1.1.2  christos       reloc_entry->address += input_section->output_offset;
    981  1.1.1.2  christos       return bfd_reloc_ok;
    982  1.1.1.2  christos     }
    983  1.1.1.2  christos 
    984  1.1.1.2  christos   if (output_bfd != NULL)
    985  1.1.1.2  christos     return bfd_reloc_continue;
    986  1.1.1.2  christos 
    987  1.1.1.2  christos   relocation = symbol->value + symbol->section->output_section->vma
    988  1.1.1.2  christos     + symbol->section->output_offset + reloc_entry->addend;
    989  1.1.1.2  christos   bfd_vma old_value = bfd_get (howto->bitsize, abfd,
    990  1.1.1.2  christos 			       data + reloc_entry->address);
    991  1.1.1.2  christos 
    992  1.1.1.2  christos   switch (howto->type)
    993  1.1.1.2  christos     {
    994  1.1.1.2  christos     case R_RISCV_ADD8:
    995  1.1.1.2  christos     case R_RISCV_ADD16:
    996  1.1.1.2  christos     case R_RISCV_ADD32:
    997  1.1.1.2  christos     case R_RISCV_ADD64:
    998  1.1.1.2  christos       relocation = old_value + relocation;
    999  1.1.1.2  christos       break;
   1000  1.1.1.2  christos     case R_RISCV_SUB6:
   1001  1.1.1.2  christos     case R_RISCV_SUB8:
   1002  1.1.1.2  christos     case R_RISCV_SUB16:
   1003  1.1.1.2  christos     case R_RISCV_SUB32:
   1004  1.1.1.2  christos     case R_RISCV_SUB64:
   1005  1.1.1.2  christos       relocation = old_value - relocation;
   1006  1.1.1.2  christos       break;
   1007  1.1.1.2  christos     }
   1008  1.1.1.2  christos   bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
   1009  1.1.1.2  christos 
   1010  1.1.1.2  christos   return bfd_reloc_ok;
   1011  1.1.1.2  christos }
   1012  1.1.1.2  christos 
   1013  1.1.1.2  christos /* Parsing subset version.
   1014  1.1.1.2  christos 
   1015  1.1.1.2  christos    Return Value:
   1016  1.1.1.2  christos      Points to the end of version
   1017  1.1.1.2  christos 
   1018  1.1.1.2  christos    Arguments:
   1019  1.1.1.2  christos      `rps`: Hooks and status for parsing subset.
   1020  1.1.1.2  christos      `march`: Full arch string.
   1021  1.1.1.2  christos      `p`: Curent parsing position.
   1022  1.1.1.2  christos      `major_version`: Parsing result of major version, using
   1023  1.1.1.2  christos       default_major_version if version is not present in arch string.
   1024  1.1.1.2  christos      `minor_version`: Parsing result of minor version, set to 0 if version is
   1025  1.1.1.2  christos      not present in arch string, but set to `default_minor_version` if
   1026  1.1.1.2  christos      `major_version` using default_major_version.
   1027  1.1.1.3  christos      `std_ext_p`: True if parsing std extension.
   1028  1.1.1.3  christos      `use_default_version`: Set it to True if we need the default version.  */
   1029  1.1.1.2  christos 
   1030  1.1.1.2  christos static const char *
   1031  1.1.1.2  christos riscv_parsing_subset_version (riscv_parse_subset_t *rps,
   1032  1.1.1.2  christos 			      const char *march,
   1033  1.1.1.2  christos 			      const char *p,
   1034  1.1.1.2  christos 			      unsigned *major_version,
   1035  1.1.1.2  christos 			      unsigned *minor_version,
   1036  1.1.1.3  christos 			      bfd_boolean std_ext_p,
   1037  1.1.1.3  christos 			      bfd_boolean *use_default_version)
   1038  1.1.1.2  christos {
   1039  1.1.1.2  christos   bfd_boolean major_p = TRUE;
   1040  1.1.1.2  christos   unsigned version = 0;
   1041  1.1.1.2  christos   char np;
   1042  1.1.1.2  christos 
   1043  1.1.1.3  christos   *major_version = 0;
   1044  1.1.1.3  christos   *minor_version = 0;
   1045  1.1.1.3  christos   for (; *p; ++p)
   1046  1.1.1.2  christos     {
   1047  1.1.1.2  christos       if (*p == 'p')
   1048  1.1.1.2  christos 	{
   1049  1.1.1.2  christos 	  np = *(p + 1);
   1050  1.1.1.2  christos 
   1051  1.1.1.2  christos 	  if (!ISDIGIT (np))
   1052  1.1.1.2  christos 	    {
   1053  1.1.1.2  christos 	      /* Might be beginning of `p` extension.  */
   1054  1.1.1.2  christos 	      if (std_ext_p)
   1055  1.1.1.2  christos 		{
   1056  1.1.1.2  christos 		  *major_version = version;
   1057  1.1.1.2  christos 		  *minor_version = 0;
   1058  1.1.1.2  christos 		  return p;
   1059  1.1.1.2  christos 		}
   1060  1.1.1.2  christos 	      else
   1061  1.1.1.2  christos 		{
   1062  1.1.1.3  christos 		  rps->error_handler
   1063  1.1.1.3  christos 		    (_("-march=%s: Expect number after `%dp'."),
   1064  1.1.1.3  christos 		     march, version);
   1065  1.1.1.2  christos 		  return NULL;
   1066  1.1.1.2  christos 		}
   1067  1.1.1.2  christos 	    }
   1068  1.1.1.2  christos 
   1069  1.1.1.3  christos 	  *major_version = version;
   1070  1.1.1.2  christos 	  major_p = FALSE;
   1071  1.1.1.2  christos 	  version = 0;
   1072  1.1.1.2  christos 	}
   1073  1.1.1.2  christos       else if (ISDIGIT (*p))
   1074  1.1.1.2  christos 	version = (version * 10) + (*p - '0');
   1075  1.1.1.2  christos       else
   1076  1.1.1.2  christos 	break;
   1077  1.1.1.2  christos     }
   1078  1.1.1.2  christos 
   1079  1.1.1.2  christos   if (major_p)
   1080  1.1.1.3  christos     *major_version = version;
   1081  1.1.1.2  christos   else
   1082  1.1.1.3  christos     *minor_version = version;
   1083  1.1.1.2  christos 
   1084  1.1.1.3  christos   /* We can not find any version in string, need to parse default version.  */
   1085  1.1.1.3  christos   if (use_default_version != NULL
   1086  1.1.1.3  christos       && *major_version == 0
   1087  1.1.1.3  christos       && *minor_version == 0)
   1088  1.1.1.3  christos     *use_default_version = TRUE;
   1089  1.1.1.2  christos   return p;
   1090  1.1.1.2  christos }
   1091  1.1.1.2  christos 
   1092  1.1.1.2  christos /* Return string which contain all supported standard extensions in
   1093  1.1.1.2  christos    canonical order.  */
   1094  1.1.1.2  christos 
   1095  1.1.1.2  christos const char *
   1096  1.1.1.2  christos riscv_supported_std_ext (void)
   1097  1.1.1.2  christos {
   1098  1.1.1.2  christos   return "mafdqlcbjtpvn";
   1099  1.1.1.2  christos }
   1100  1.1.1.2  christos 
   1101  1.1.1.2  christos /* Parsing function for standard extensions.
   1102  1.1.1.2  christos 
   1103  1.1.1.2  christos    Return Value:
   1104  1.1.1.2  christos      Points to the end of extensions.
   1105  1.1.1.2  christos 
   1106  1.1.1.2  christos    Arguments:
   1107  1.1.1.2  christos      `rps`: Hooks and status for parsing subset.
   1108  1.1.1.2  christos      `march`: Full arch string.
   1109  1.1.1.2  christos      `p`: Curent parsing position.  */
   1110  1.1.1.2  christos 
   1111  1.1.1.2  christos static const char *
   1112  1.1.1.2  christos riscv_parse_std_ext (riscv_parse_subset_t *rps,
   1113  1.1.1.3  christos 		     const char *march,
   1114  1.1.1.3  christos 		     const char *p)
   1115  1.1.1.2  christos {
   1116  1.1.1.2  christos   const char *all_std_exts = riscv_supported_std_ext ();
   1117  1.1.1.2  christos   const char *std_exts = all_std_exts;
   1118  1.1.1.2  christos   unsigned major_version = 0;
   1119  1.1.1.2  christos   unsigned minor_version = 0;
   1120  1.1.1.2  christos   char std_ext = '\0';
   1121  1.1.1.3  christos   bfd_boolean use_default_version = FALSE;
   1122  1.1.1.2  christos 
   1123  1.1.1.2  christos   /* First letter must start with i, e or g.  */
   1124  1.1.1.2  christos   switch (*p)
   1125  1.1.1.2  christos     {
   1126  1.1.1.2  christos       case 'i':
   1127  1.1.1.3  christos 	p = riscv_parsing_subset_version (rps,
   1128  1.1.1.3  christos 					  march,
   1129  1.1.1.3  christos 					  ++p,
   1130  1.1.1.3  christos 					  &major_version,
   1131  1.1.1.3  christos 					  &minor_version,
   1132  1.1.1.3  christos 					  /* std_ext_p= */TRUE,
   1133  1.1.1.3  christos 					  &use_default_version);
   1134  1.1.1.3  christos 
   1135  1.1.1.3  christos 	/* Find the default version if needed.  */
   1136  1.1.1.3  christos 	if (use_default_version
   1137  1.1.1.3  christos 	    && rps->get_default_version != NULL)
   1138  1.1.1.3  christos 	  rps->get_default_version ("i",
   1139  1.1.1.3  christos 				    &major_version,
   1140  1.1.1.3  christos 				    &minor_version);
   1141  1.1.1.3  christos 	riscv_add_subset (rps->subset_list, "i",
   1142  1.1.1.3  christos 			  major_version, minor_version);
   1143  1.1.1.2  christos 	break;
   1144  1.1.1.2  christos 
   1145  1.1.1.2  christos       case 'e':
   1146  1.1.1.3  christos 	p = riscv_parsing_subset_version (rps,
   1147  1.1.1.3  christos 					  march,
   1148  1.1.1.3  christos 					  ++p,
   1149  1.1.1.3  christos 					  &major_version,
   1150  1.1.1.3  christos 					  &minor_version,
   1151  1.1.1.3  christos 					  /* std_ext_p= */TRUE,
   1152  1.1.1.3  christos 					  &use_default_version);
   1153  1.1.1.3  christos 
   1154  1.1.1.3  christos 	/* Find the default version if needed.  */
   1155  1.1.1.3  christos 	if (use_default_version
   1156  1.1.1.3  christos 	    && rps->get_default_version != NULL)
   1157  1.1.1.3  christos 	  rps->get_default_version ("e",
   1158  1.1.1.3  christos 				    &major_version,
   1159  1.1.1.3  christos 				    &minor_version);
   1160  1.1.1.3  christos 	riscv_add_subset (rps->subset_list, "e",
   1161  1.1.1.3  christos 			  major_version, minor_version);
   1162  1.1.1.3  christos 
   1163  1.1.1.3  christos 	/* i-ext must be enabled.  */
   1164  1.1.1.3  christos 	if (rps->get_default_version != NULL)
   1165  1.1.1.3  christos 	  rps->get_default_version ("i",
   1166  1.1.1.3  christos 				    &major_version,
   1167  1.1.1.3  christos 				    &minor_version);
   1168  1.1.1.3  christos 	riscv_add_subset (rps->subset_list, "i",
   1169  1.1.1.3  christos 			  major_version, minor_version);
   1170  1.1.1.2  christos 
   1171  1.1.1.2  christos 	if (*rps->xlen > 32)
   1172  1.1.1.2  christos 	  {
   1173  1.1.1.3  christos 	    rps->error_handler
   1174  1.1.1.3  christos 	      (_("-march=%s: rv%de is not a valid base ISA"),
   1175  1.1.1.3  christos 	       march, *rps->xlen);
   1176  1.1.1.2  christos 	    return NULL;
   1177  1.1.1.2  christos 	  }
   1178  1.1.1.2  christos 	break;
   1179  1.1.1.2  christos 
   1180  1.1.1.2  christos       case 'g':
   1181  1.1.1.3  christos 	/* The g-ext shouldn't has the version, so we just
   1182  1.1.1.3  christos 	   skip the setting if user set a version to it.  */
   1183  1.1.1.3  christos 	p = riscv_parsing_subset_version (rps,
   1184  1.1.1.3  christos 					  march,
   1185  1.1.1.3  christos 					  ++p,
   1186  1.1.1.3  christos 					  &major_version,
   1187  1.1.1.3  christos 					  &minor_version,
   1188  1.1.1.3  christos 					  TRUE,
   1189  1.1.1.3  christos 					  &use_default_version);
   1190  1.1.1.3  christos 
   1191  1.1.1.3  christos 	/* i-ext must be enabled.  */
   1192  1.1.1.3  christos 	if (rps->get_default_version != NULL)
   1193  1.1.1.3  christos 	  rps->get_default_version ("i",
   1194  1.1.1.3  christos 				    &major_version,
   1195  1.1.1.3  christos 				    &minor_version);
   1196  1.1.1.3  christos 	riscv_add_subset (rps->subset_list, "i",
   1197  1.1.1.3  christos 			  major_version, minor_version);
   1198  1.1.1.2  christos 
   1199  1.1.1.2  christos 	for ( ; *std_exts != 'q'; std_exts++)
   1200  1.1.1.2  christos 	  {
   1201  1.1.1.2  christos 	    const char subset[] = {*std_exts, '\0'};
   1202  1.1.1.3  christos 
   1203  1.1.1.3  christos 	    if (rps->get_default_version != NULL)
   1204  1.1.1.3  christos 	      rps->get_default_version (subset,
   1205  1.1.1.3  christos 					&major_version,
   1206  1.1.1.3  christos 					&minor_version);
   1207  1.1.1.3  christos 	    riscv_add_subset (rps->subset_list, subset,
   1208  1.1.1.3  christos 			      major_version, minor_version);
   1209  1.1.1.2  christos 	  }
   1210  1.1.1.2  christos 	break;
   1211  1.1.1.2  christos 
   1212  1.1.1.2  christos       default:
   1213  1.1.1.3  christos 	rps->error_handler
   1214  1.1.1.3  christos 	  (_("-march=%s: first ISA subset must be `e', `i' or `g'"), march);
   1215  1.1.1.2  christos 	return NULL;
   1216  1.1.1.2  christos     }
   1217  1.1.1.2  christos 
   1218  1.1.1.3  christos   /* The riscv_parsing_subset_version may set `p` to NULL, so I think we should
   1219  1.1.1.3  christos      skip parsing the string if `p` is NULL or value of `p` is `\0`.  */
   1220  1.1.1.3  christos   while (p != NULL && *p != '\0')
   1221  1.1.1.2  christos     {
   1222  1.1.1.2  christos       char subset[2] = {0, 0};
   1223  1.1.1.2  christos 
   1224  1.1.1.3  christos       if (*p == 'x' || *p == 's' || *p == 'z')
   1225  1.1.1.2  christos 	break;
   1226  1.1.1.2  christos 
   1227  1.1.1.2  christos       if (*p == '_')
   1228  1.1.1.2  christos 	{
   1229  1.1.1.2  christos 	  p++;
   1230  1.1.1.2  christos 	  continue;
   1231  1.1.1.2  christos 	}
   1232  1.1.1.2  christos 
   1233  1.1.1.2  christos       std_ext = *p;
   1234  1.1.1.2  christos 
   1235  1.1.1.2  christos       /* Checking canonical order.  */
   1236  1.1.1.2  christos       while (*std_exts && std_ext != *std_exts) std_exts++;
   1237  1.1.1.2  christos 
   1238  1.1.1.2  christos       if (std_ext != *std_exts)
   1239  1.1.1.2  christos 	{
   1240  1.1.1.2  christos 	  if (strchr (all_std_exts, std_ext) == NULL)
   1241  1.1.1.3  christos 	    rps->error_handler
   1242  1.1.1.3  christos 	      (_("-march=%s: unsupported ISA subset `%c'"), march, *p);
   1243  1.1.1.2  christos 	  else
   1244  1.1.1.3  christos 	    rps->error_handler
   1245  1.1.1.3  christos 	      (_("-march=%s: ISA string is not in canonical order. `%c'"),
   1246  1.1.1.3  christos 	       march, *p);
   1247  1.1.1.2  christos 	  return NULL;
   1248  1.1.1.2  christos 	}
   1249  1.1.1.2  christos 
   1250  1.1.1.2  christos       std_exts++;
   1251  1.1.1.2  christos 
   1252  1.1.1.3  christos       use_default_version = FALSE;
   1253  1.1.1.2  christos       subset[0] = std_ext;
   1254  1.1.1.3  christos       p = riscv_parsing_subset_version (rps,
   1255  1.1.1.3  christos 					march,
   1256  1.1.1.3  christos 					++p,
   1257  1.1.1.3  christos 					&major_version,
   1258  1.1.1.3  christos 					&minor_version,
   1259  1.1.1.3  christos 					TRUE,
   1260  1.1.1.3  christos 					&use_default_version);
   1261  1.1.1.3  christos 
   1262  1.1.1.3  christos       /* Find the default version if needed.  */
   1263  1.1.1.3  christos       if (use_default_version
   1264  1.1.1.3  christos 	  && rps->get_default_version != NULL)
   1265  1.1.1.3  christos 	rps->get_default_version (subset,
   1266  1.1.1.3  christos 				  &major_version,
   1267  1.1.1.3  christos 				  &minor_version);
   1268  1.1.1.3  christos       riscv_add_subset (rps->subset_list, subset,
   1269  1.1.1.3  christos 			major_version, minor_version);
   1270  1.1.1.2  christos     }
   1271  1.1.1.2  christos   return p;
   1272  1.1.1.2  christos }
   1273  1.1.1.2  christos 
   1274  1.1.1.3  christos /* Classify the argument 'arch' into one of riscv_isa_ext_class_t.  */
   1275  1.1.1.2  christos 
   1276  1.1.1.3  christos riscv_isa_ext_class_t
   1277  1.1.1.3  christos riscv_get_prefix_class (const char *arch)
   1278  1.1.1.3  christos {
   1279  1.1.1.3  christos   switch (*arch)
   1280  1.1.1.3  christos     {
   1281  1.1.1.3  christos     case 's': return RV_ISA_CLASS_S;
   1282  1.1.1.3  christos     case 'x': return RV_ISA_CLASS_X;
   1283  1.1.1.3  christos     case 'z': return RV_ISA_CLASS_Z;
   1284  1.1.1.3  christos     default: return RV_ISA_CLASS_UNKNOWN;
   1285  1.1.1.3  christos     }
   1286  1.1.1.3  christos }
   1287  1.1.1.2  christos 
   1288  1.1.1.3  christos /* Structure describing parameters to use when parsing a particular
   1289  1.1.1.3  christos    riscv_isa_ext_class_t. One of these should be provided for each
   1290  1.1.1.3  christos    possible class, except RV_ISA_CLASS_UNKNOWN.  */
   1291  1.1.1.3  christos 
   1292  1.1.1.3  christos typedef struct riscv_parse_config
   1293  1.1.1.3  christos {
   1294  1.1.1.3  christos   /* Class of the extension. */
   1295  1.1.1.3  christos   riscv_isa_ext_class_t class;
   1296  1.1.1.3  christos 
   1297  1.1.1.3  christos   /* Lower-case prefix string for error printing
   1298  1.1.1.3  christos      and internal parser usage, e.g. "z", "x".  */
   1299  1.1.1.3  christos   const char *prefix;
   1300  1.1.1.3  christos 
   1301  1.1.1.3  christos   /* Predicate which is used for checking whether
   1302  1.1.1.3  christos      this is a "known" extension. For 'x',
   1303  1.1.1.3  christos      it always returns true (since they are by
   1304  1.1.1.3  christos      definition non-standard and cannot be known.  */
   1305  1.1.1.3  christos   bfd_boolean (*ext_valid_p) (const char *);
   1306  1.1.1.3  christos } riscv_parse_config_t;
   1307  1.1.1.3  christos 
   1308  1.1.1.3  christos /* Parse a generic prefixed extension.
   1309  1.1.1.3  christos    `rps`: Hooks and status for parsing subset.
   1310  1.1.1.3  christos    `march`: The full architecture string as passed in by "-march=...".
   1311  1.1.1.3  christos    `p`: Point from which to start parsing the -march string.
   1312  1.1.1.3  christos    `config`: What class of extensions to parse, predicate funcs,
   1313  1.1.1.3  christos    and strings to use in error reporting.  */
   1314  1.1.1.2  christos 
   1315  1.1.1.2  christos static const char *
   1316  1.1.1.3  christos riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
   1317  1.1.1.3  christos 			  const char *march,
   1318  1.1.1.3  christos 			  const char *p,
   1319  1.1.1.3  christos 			  const riscv_parse_config_t *config)
   1320  1.1.1.2  christos {
   1321  1.1.1.2  christos   unsigned major_version = 0;
   1322  1.1.1.2  christos   unsigned minor_version = 0;
   1323  1.1.1.3  christos   const char *last_name;
   1324  1.1.1.3  christos   riscv_isa_ext_class_t class;
   1325  1.1.1.3  christos   bfd_boolean use_default_version;
   1326  1.1.1.2  christos 
   1327  1.1.1.2  christos   while (*p)
   1328  1.1.1.2  christos     {
   1329  1.1.1.2  christos       if (*p == '_')
   1330  1.1.1.2  christos 	{
   1331  1.1.1.2  christos 	  p++;
   1332  1.1.1.2  christos 	  continue;
   1333  1.1.1.2  christos 	}
   1334  1.1.1.2  christos 
   1335  1.1.1.3  christos       /* Assert that the current extension specifier matches our parsing
   1336  1.1.1.3  christos 	 class.  */
   1337  1.1.1.3  christos       class = riscv_get_prefix_class (p);
   1338  1.1.1.3  christos       if (class != config->class)
   1339  1.1.1.2  christos 	break;
   1340  1.1.1.2  christos 
   1341  1.1.1.2  christos       char *subset = xstrdup (p);
   1342  1.1.1.2  christos       char *q = subset;
   1343  1.1.1.2  christos       const char *end_of_version;
   1344  1.1.1.2  christos 
   1345  1.1.1.2  christos       while (*++q != '\0' && *q != '_' && !ISDIGIT (*q))
   1346  1.1.1.2  christos 	;
   1347  1.1.1.2  christos 
   1348  1.1.1.3  christos       use_default_version = FALSE;
   1349  1.1.1.2  christos       end_of_version =
   1350  1.1.1.3  christos 	riscv_parsing_subset_version (rps, march, q, &major_version,
   1351  1.1.1.3  christos 				      &minor_version, FALSE,
   1352  1.1.1.3  christos 				      &use_default_version);
   1353  1.1.1.2  christos       *q = '\0';
   1354  1.1.1.2  christos 
   1355  1.1.1.3  christos       /* Check that the name is valid.
   1356  1.1.1.3  christos 	 For 'x', anything goes but it cannot simply be 'x'.
   1357  1.1.1.3  christos 	 For 's', it must be known from a list and cannot simply be 's'.
   1358  1.1.1.3  christos 	 For 'z', it must be known from a list and cannot simply be 'z'.  */
   1359  1.1.1.3  christos 
   1360  1.1.1.3  christos       /* Check that the extension name is well-formed.  */
   1361  1.1.1.3  christos       if (!config->ext_valid_p (subset))
   1362  1.1.1.3  christos 	{
   1363  1.1.1.3  christos 	  rps->error_handler
   1364  1.1.1.3  christos 	    (_("-march=%s: Invalid or unknown %s ISA extension: '%s'"),
   1365  1.1.1.3  christos 	     march, config->prefix, subset);
   1366  1.1.1.3  christos 	  free (subset);
   1367  1.1.1.3  christos 	  return NULL;
   1368  1.1.1.3  christos 	}
   1369  1.1.1.3  christos 
   1370  1.1.1.3  christos       /* Check that the last item is not the same as this.  */
   1371  1.1.1.3  christos       last_name = rps->subset_list->tail->name;
   1372  1.1.1.3  christos       if (!strcasecmp (last_name, subset))
   1373  1.1.1.3  christos 	{
   1374  1.1.1.3  christos 	  rps->error_handler
   1375  1.1.1.3  christos 	    (_("-march=%s: Duplicate %s ISA extension: \'%s\'"),
   1376  1.1.1.3  christos 	     march, config->prefix, subset);
   1377  1.1.1.3  christos 	  free (subset);
   1378  1.1.1.3  christos 	  return NULL;
   1379  1.1.1.3  christos 	}
   1380  1.1.1.3  christos 
   1381  1.1.1.3  christos       /* Check that we are in alphabetical order within the subset.  */
   1382  1.1.1.3  christos       if (!strncasecmp (last_name, config->prefix, 1)
   1383  1.1.1.3  christos 	  && strcasecmp (last_name, subset) > 0)
   1384  1.1.1.3  christos 	{
   1385  1.1.1.3  christos 	  rps->error_handler
   1386  1.1.1.3  christos 	    (_("\
   1387  1.1.1.3  christos -march=%s: %s ISA extension not in alphabetical order: \'%s\' must come before \'%s\'."),
   1388  1.1.1.3  christos 	     march, config->prefix, subset, last_name);
   1389  1.1.1.3  christos 	  free (subset);
   1390  1.1.1.3  christos 	  return NULL;
   1391  1.1.1.3  christos 	}
   1392  1.1.1.3  christos 
   1393  1.1.1.3  christos       /* Find the default version if needed.  */
   1394  1.1.1.3  christos       if (use_default_version
   1395  1.1.1.3  christos          && rps->get_default_version != NULL)
   1396  1.1.1.3  christos        rps->get_default_version (subset,
   1397  1.1.1.3  christos                                  &major_version,
   1398  1.1.1.3  christos                                  &minor_version);
   1399  1.1.1.3  christos       riscv_add_subset (rps->subset_list, subset,
   1400  1.1.1.3  christos                        major_version, minor_version);
   1401  1.1.1.3  christos 
   1402  1.1.1.2  christos       free (subset);
   1403  1.1.1.2  christos       p += end_of_version - subset;
   1404  1.1.1.2  christos 
   1405  1.1.1.2  christos       if (*p != '\0' && *p != '_')
   1406  1.1.1.2  christos 	{
   1407  1.1.1.3  christos 	  rps->error_handler (_("-march=%s: %s must separate with _"),
   1408  1.1.1.3  christos 			      march, config->prefix);
   1409  1.1.1.2  christos 	  return NULL;
   1410  1.1.1.2  christos 	}
   1411  1.1.1.2  christos     }
   1412  1.1.1.2  christos 
   1413  1.1.1.2  christos   return p;
   1414  1.1.1.2  christos }
   1415  1.1.1.2  christos 
   1416  1.1.1.3  christos /* List of Z-class extensions that binutils should know about.
   1417  1.1.1.3  christos    Whether or not a particular entry is in this list will
   1418  1.1.1.3  christos    dictate if gas/ld will accept its presence in the -march
   1419  1.1.1.3  christos    string.
   1420  1.1.1.3  christos 
   1421  1.1.1.3  christos    Example: To add an extension called "Zbb" (bitmanip base extension),
   1422  1.1.1.3  christos    add "zbb" string to the list (all lowercase).
   1423  1.1.1.3  christos 
   1424  1.1.1.3  christos    Keep this list alphabetically ordered.  */
   1425  1.1.1.3  christos 
   1426  1.1.1.3  christos static const char * const riscv_std_z_ext_strtab[] =
   1427  1.1.1.3  christos   {
   1428  1.1.1.3  christos     "zicsr", NULL
   1429  1.1.1.3  christos   };
   1430  1.1.1.3  christos 
   1431  1.1.1.3  christos /* Same as `riscv_std_z_ext_strtab', but for S-class extensions.  */
   1432  1.1.1.3  christos 
   1433  1.1.1.3  christos static const char * const riscv_std_s_ext_strtab[] =
   1434  1.1.1.3  christos   {
   1435  1.1.1.3  christos     NULL
   1436  1.1.1.3  christos   };
   1437  1.1.1.3  christos 
   1438  1.1.1.3  christos /* For the extension EXT, search through the list of known extensions
   1439  1.1.1.3  christos    KNOWN_EXTS for a match, and return TRUE if found.  */
   1440  1.1.1.3  christos 
   1441  1.1.1.3  christos static bfd_boolean
   1442  1.1.1.3  christos riscv_multi_letter_ext_valid_p (const char *ext,
   1443  1.1.1.3  christos 				const char *const *known_exts)
   1444  1.1.1.3  christos {
   1445  1.1.1.3  christos   size_t i;
   1446  1.1.1.3  christos 
   1447  1.1.1.3  christos   for (i = 0; known_exts[i]; ++i)
   1448  1.1.1.3  christos     if (!strcmp (ext, known_exts[i]))
   1449  1.1.1.3  christos       return TRUE;
   1450  1.1.1.3  christos 
   1451  1.1.1.3  christos   return FALSE;
   1452  1.1.1.3  christos }
   1453  1.1.1.3  christos 
   1454  1.1.1.3  christos /* Predicator function for x-prefixed extensions.
   1455  1.1.1.3  christos    Anything goes, except the literal 'x'.  */
   1456  1.1.1.3  christos 
   1457  1.1.1.3  christos static bfd_boolean
   1458  1.1.1.3  christos riscv_ext_x_valid_p (const char *arg)
   1459  1.1.1.3  christos {
   1460  1.1.1.3  christos   if (!strcasecmp (arg, "x"))
   1461  1.1.1.3  christos     return FALSE;
   1462  1.1.1.3  christos 
   1463  1.1.1.3  christos   return TRUE;
   1464  1.1.1.3  christos }
   1465  1.1.1.3  christos 
   1466  1.1.1.3  christos /* Predicator functions for z-prefixed extensions.
   1467  1.1.1.3  christos    Only known z-extensions are permitted.  */
   1468  1.1.1.3  christos 
   1469  1.1.1.3  christos static bfd_boolean
   1470  1.1.1.3  christos riscv_ext_z_valid_p (const char *arg)
   1471  1.1.1.3  christos {
   1472  1.1.1.3  christos   return riscv_multi_letter_ext_valid_p (arg, riscv_std_z_ext_strtab);
   1473  1.1.1.3  christos }
   1474  1.1.1.3  christos 
   1475  1.1.1.3  christos /* Predicator function for 's' prefixed extensions.
   1476  1.1.1.3  christos    Must be either literal 's', or a known s-prefixed extension.  */
   1477  1.1.1.3  christos 
   1478  1.1.1.3  christos static bfd_boolean
   1479  1.1.1.3  christos riscv_ext_s_valid_p (const char *arg)
   1480  1.1.1.3  christos {
   1481  1.1.1.3  christos   return riscv_multi_letter_ext_valid_p (arg, riscv_std_s_ext_strtab);
   1482  1.1.1.3  christos }
   1483  1.1.1.3  christos 
   1484  1.1.1.3  christos /* Parsing order that is specified by the ISA manual.  */
   1485  1.1.1.3  christos 
   1486  1.1.1.3  christos static const riscv_parse_config_t parse_config[] =
   1487  1.1.1.3  christos {
   1488  1.1.1.3  christos    {RV_ISA_CLASS_S, "s", riscv_ext_s_valid_p},
   1489  1.1.1.3  christos    {RV_ISA_CLASS_Z, "z", riscv_ext_z_valid_p},
   1490  1.1.1.3  christos    {RV_ISA_CLASS_X, "x", riscv_ext_x_valid_p},
   1491  1.1.1.3  christos    {RV_ISA_CLASS_UNKNOWN, NULL, NULL}
   1492  1.1.1.3  christos };
   1493  1.1.1.3  christos 
   1494  1.1.1.2  christos /* Function for parsing arch string.
   1495  1.1.1.2  christos 
   1496  1.1.1.2  christos    Return Value:
   1497  1.1.1.2  christos      Return TRUE on success.
   1498  1.1.1.2  christos 
   1499  1.1.1.2  christos    Arguments:
   1500  1.1.1.2  christos      `rps`: Hooks and status for parsing subset.
   1501  1.1.1.2  christos      `arch`: Arch string.  */
   1502  1.1.1.2  christos 
   1503  1.1.1.2  christos bfd_boolean
   1504  1.1.1.2  christos riscv_parse_subset (riscv_parse_subset_t *rps,
   1505  1.1.1.2  christos 		    const char *arch)
   1506  1.1.1.2  christos {
   1507  1.1.1.2  christos   const char *p = arch;
   1508  1.1.1.3  christos   size_t i;
   1509  1.1.1.2  christos 
   1510  1.1.1.2  christos   if (strncmp (p, "rv32", 4) == 0)
   1511  1.1.1.2  christos     {
   1512  1.1.1.2  christos       *rps->xlen = 32;
   1513  1.1.1.2  christos       p += 4;
   1514  1.1.1.2  christos     }
   1515  1.1.1.2  christos   else if (strncmp (p, "rv64", 4) == 0)
   1516  1.1.1.2  christos     {
   1517  1.1.1.2  christos       *rps->xlen = 64;
   1518  1.1.1.2  christos       p += 4;
   1519  1.1.1.2  christos     }
   1520  1.1.1.2  christos   else
   1521  1.1.1.2  christos     {
   1522  1.1.1.3  christos       /* Arch string shouldn't be NULL or empty here.  However,
   1523  1.1.1.3  christos 	 it might be empty only when we failed to merge the arch
   1524  1.1.1.3  christos 	 string in the riscv_merge_attributes.  We have already
   1525  1.1.1.3  christos 	 issued the correct error message in another side, so do
   1526  1.1.1.3  christos 	 not issue this error when the arch string is empty.  */
   1527  1.1.1.3  christos       if (strlen (arch))
   1528  1.1.1.3  christos 	rps->error_handler (
   1529  1.1.1.3  christos 	  _("-march=%s: ISA string must begin with rv32 or rv64"),
   1530  1.1.1.3  christos 	  arch);
   1531  1.1.1.2  christos       return FALSE;
   1532  1.1.1.2  christos     }
   1533  1.1.1.2  christos 
   1534  1.1.1.2  christos   /* Parsing standard extension.  */
   1535  1.1.1.2  christos   p = riscv_parse_std_ext (rps, arch, p);
   1536  1.1.1.2  christos 
   1537  1.1.1.2  christos   if (p == NULL)
   1538  1.1.1.2  christos     return FALSE;
   1539  1.1.1.2  christos 
   1540  1.1.1.3  christos   /* Parse the different classes of extensions in the specified order.  */
   1541  1.1.1.3  christos   for (i = 0; i < ARRAY_SIZE (parse_config); ++i) {
   1542  1.1.1.3  christos     p = riscv_parse_prefixed_ext (rps, arch, p, &parse_config[i]);
   1543  1.1.1.2  christos 
   1544  1.1.1.3  christos     if (p == NULL)
   1545  1.1.1.3  christos       return FALSE;
   1546  1.1.1.3  christos   }
   1547  1.1.1.2  christos 
   1548  1.1.1.2  christos   if (*p != '\0')
   1549  1.1.1.2  christos     {
   1550  1.1.1.3  christos       rps->error_handler (_("-march=%s: unexpected ISA string at end: %s"),
   1551  1.1.1.2  christos 			  arch, p);
   1552  1.1.1.2  christos       return FALSE;
   1553  1.1.1.2  christos     }
   1554  1.1.1.2  christos 
   1555  1.1.1.2  christos   if (riscv_lookup_subset (rps->subset_list, "e")
   1556  1.1.1.2  christos       && riscv_lookup_subset (rps->subset_list, "f"))
   1557  1.1.1.2  christos     {
   1558  1.1.1.3  christos       rps->error_handler
   1559  1.1.1.3  christos 	(_("-march=%s: rv32e does not support the `f' extension"),
   1560  1.1.1.3  christos 	 arch);
   1561  1.1.1.2  christos       return FALSE;
   1562  1.1.1.2  christos     }
   1563  1.1.1.2  christos 
   1564  1.1.1.2  christos   if (riscv_lookup_subset (rps->subset_list, "d")
   1565  1.1.1.2  christos       && !riscv_lookup_subset (rps->subset_list, "f"))
   1566  1.1.1.2  christos     {
   1567  1.1.1.3  christos       rps->error_handler
   1568  1.1.1.3  christos 	(_("-march=%s: `d' extension requires `f' extension"),
   1569  1.1.1.3  christos 	 arch);
   1570  1.1.1.2  christos       return FALSE;
   1571  1.1.1.2  christos     }
   1572  1.1.1.2  christos 
   1573  1.1.1.2  christos   if (riscv_lookup_subset (rps->subset_list, "q")
   1574  1.1.1.2  christos       && !riscv_lookup_subset (rps->subset_list, "d"))
   1575  1.1.1.2  christos     {
   1576  1.1.1.3  christos       rps->error_handler
   1577  1.1.1.3  christos 	(_("-march=%s: `q' extension requires `d' extension"),
   1578  1.1.1.3  christos 	 arch);
   1579  1.1.1.2  christos       return FALSE;
   1580  1.1.1.2  christos     }
   1581  1.1.1.2  christos 
   1582  1.1.1.2  christos   if (riscv_lookup_subset (rps->subset_list, "q") && *rps->xlen < 64)
   1583  1.1.1.2  christos     {
   1584  1.1.1.3  christos       rps->error_handler
   1585  1.1.1.3  christos 	(_("-march=%s: rv32 does not support the `q' extension"),
   1586  1.1.1.3  christos 	 arch);
   1587  1.1.1.2  christos       return FALSE;
   1588  1.1.1.2  christos     }
   1589  1.1.1.2  christos   return TRUE;
   1590  1.1.1.2  christos }
   1591  1.1.1.2  christos 
   1592  1.1.1.2  christos /* Add new subset to list.  */
   1593  1.1.1.2  christos 
   1594  1.1.1.2  christos void
   1595  1.1.1.2  christos riscv_add_subset (riscv_subset_list_t *subset_list,
   1596  1.1.1.2  christos 		  const char *subset,
   1597  1.1.1.3  christos 		  int major,
   1598  1.1.1.3  christos 		  int minor)
   1599  1.1.1.2  christos {
   1600  1.1.1.2  christos   riscv_subset_t *s = xmalloc (sizeof *s);
   1601  1.1.1.2  christos 
   1602  1.1.1.2  christos   if (subset_list->head == NULL)
   1603  1.1.1.2  christos     subset_list->head = s;
   1604  1.1.1.2  christos 
   1605  1.1.1.2  christos   s->name = xstrdup (subset);
   1606  1.1.1.2  christos   s->major_version = major;
   1607  1.1.1.2  christos   s->minor_version = minor;
   1608  1.1.1.2  christos   s->next = NULL;
   1609  1.1.1.2  christos 
   1610  1.1.1.2  christos   if (subset_list->tail != NULL)
   1611  1.1.1.2  christos     subset_list->tail->next = s;
   1612  1.1.1.2  christos 
   1613  1.1.1.2  christos   subset_list->tail = s;
   1614  1.1.1.2  christos }
   1615  1.1.1.2  christos 
   1616  1.1.1.2  christos /* Find subset in list without version checking, return NULL if not found.  */
   1617  1.1.1.2  christos 
   1618  1.1.1.2  christos riscv_subset_t *
   1619  1.1.1.2  christos riscv_lookup_subset (const riscv_subset_list_t *subset_list,
   1620  1.1.1.2  christos 		     const char *subset)
   1621  1.1.1.2  christos {
   1622  1.1.1.3  christos   return riscv_lookup_subset_version
   1623  1.1.1.3  christos     (subset_list, subset,
   1624  1.1.1.3  christos      RISCV_DONT_CARE_VERSION,
   1625  1.1.1.3  christos      RISCV_DONT_CARE_VERSION);
   1626  1.1.1.2  christos }
   1627  1.1.1.2  christos 
   1628  1.1.1.2  christos /* Find subset in list with version checking, return NULL if not found.  */
   1629  1.1.1.2  christos 
   1630  1.1.1.2  christos riscv_subset_t *
   1631  1.1.1.2  christos riscv_lookup_subset_version (const riscv_subset_list_t *subset_list,
   1632  1.1.1.2  christos 			     const char *subset,
   1633  1.1.1.2  christos 			     int major, int minor)
   1634  1.1.1.2  christos {
   1635  1.1.1.2  christos   riscv_subset_t *s;
   1636  1.1.1.2  christos 
   1637  1.1.1.2  christos   for (s = subset_list->head; s != NULL; s = s->next)
   1638  1.1.1.2  christos     if (strcasecmp (s->name, subset) == 0)
   1639  1.1.1.2  christos       {
   1640  1.1.1.2  christos 	if ((major != RISCV_DONT_CARE_VERSION)
   1641  1.1.1.2  christos 	    && (s->major_version != major))
   1642  1.1.1.2  christos 	  return NULL;
   1643  1.1.1.2  christos 
   1644  1.1.1.2  christos 	if ((minor != RISCV_DONT_CARE_VERSION)
   1645  1.1.1.2  christos 	    && (s->minor_version != minor))
   1646  1.1.1.2  christos 	  return NULL;
   1647  1.1.1.2  christos 
   1648  1.1.1.2  christos 	return s;
   1649  1.1.1.2  christos       }
   1650  1.1.1.2  christos 
   1651  1.1.1.2  christos   return NULL;
   1652  1.1.1.2  christos }
   1653  1.1.1.2  christos 
   1654  1.1.1.2  christos /* Release subset list.  */
   1655  1.1.1.2  christos 
   1656  1.1.1.2  christos void
   1657  1.1.1.2  christos riscv_release_subset_list (riscv_subset_list_t *subset_list)
   1658  1.1.1.2  christos {
   1659  1.1.1.2  christos    while (subset_list->head != NULL)
   1660  1.1.1.2  christos     {
   1661  1.1.1.2  christos       riscv_subset_t *next = subset_list->head->next;
   1662  1.1.1.2  christos       free ((void *)subset_list->head->name);
   1663  1.1.1.2  christos       free (subset_list->head);
   1664  1.1.1.2  christos       subset_list->head = next;
   1665  1.1.1.2  christos     }
   1666  1.1.1.2  christos 
   1667  1.1.1.2  christos   subset_list->tail = NULL;
   1668  1.1.1.2  christos }
   1669  1.1.1.2  christos 
   1670  1.1.1.2  christos /* Return the number of digits for the input.  */
   1671  1.1.1.2  christos 
   1672  1.1.1.3  christos size_t
   1673  1.1.1.2  christos riscv_estimate_digit (unsigned num)
   1674  1.1.1.2  christos {
   1675  1.1.1.2  christos   size_t digit = 0;
   1676  1.1.1.2  christos   if (num == 0)
   1677  1.1.1.2  christos     return 1;
   1678  1.1.1.2  christos 
   1679  1.1.1.2  christos   for (digit = 0; num ; num /= 10)
   1680  1.1.1.2  christos     digit++;
   1681  1.1.1.2  christos 
   1682  1.1.1.2  christos   return digit;
   1683  1.1.1.2  christos }
   1684  1.1.1.2  christos 
   1685  1.1.1.2  christos /* Auxiliary function to estimate string length of subset list.  */
   1686  1.1.1.2  christos 
   1687  1.1.1.2  christos static size_t
   1688  1.1.1.2  christos riscv_estimate_arch_strlen1 (const riscv_subset_t *subset)
   1689  1.1.1.2  christos {
   1690  1.1.1.2  christos   if (subset == NULL)
   1691  1.1.1.2  christos     return 6; /* For rv32/rv64/rv128 and string terminator.  */
   1692  1.1.1.2  christos 
   1693  1.1.1.2  christos   return riscv_estimate_arch_strlen1 (subset->next)
   1694  1.1.1.2  christos 	 + strlen (subset->name)
   1695  1.1.1.2  christos 	 + riscv_estimate_digit (subset->major_version)
   1696  1.1.1.2  christos 	 + 1 /* For version seperator: 'p'.  */
   1697  1.1.1.2  christos 	 + riscv_estimate_digit (subset->minor_version)
   1698  1.1.1.2  christos 	 + 1 /* For underscore.  */;
   1699  1.1.1.2  christos }
   1700  1.1.1.2  christos 
   1701  1.1.1.2  christos /* Estimate the string length of this subset list.  */
   1702  1.1.1.2  christos 
   1703  1.1.1.2  christos static size_t
   1704  1.1.1.2  christos riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list)
   1705  1.1.1.2  christos {
   1706  1.1.1.2  christos   return riscv_estimate_arch_strlen1 (subset_list->head);
   1707  1.1.1.2  christos }
   1708  1.1.1.2  christos 
   1709  1.1.1.2  christos /* Auxiliary function to convert subset info to string.  */
   1710  1.1.1.2  christos 
   1711  1.1.1.2  christos static void
   1712  1.1.1.2  christos riscv_arch_str1 (riscv_subset_t *subset,
   1713  1.1.1.2  christos 		 char *attr_str, char *buf, size_t bufsz)
   1714  1.1.1.2  christos {
   1715  1.1.1.2  christos   const char *underline = "_";
   1716  1.1.1.2  christos 
   1717  1.1.1.2  christos   if (subset == NULL)
   1718  1.1.1.2  christos     return;
   1719  1.1.1.2  christos 
   1720  1.1.1.2  christos   /* No underline between rvXX and i/e.   */
   1721  1.1.1.2  christos   if ((strcasecmp (subset->name, "i") == 0)
   1722  1.1.1.2  christos       || (strcasecmp (subset->name, "e") == 0))
   1723  1.1.1.2  christos     underline = "";
   1724  1.1.1.2  christos 
   1725  1.1.1.2  christos   snprintf (buf, bufsz, "%s%s%dp%d",
   1726  1.1.1.2  christos 	    underline,
   1727  1.1.1.3  christos 	    subset->name,
   1728  1.1.1.3  christos 	    subset->major_version,
   1729  1.1.1.3  christos 	    subset->minor_version);
   1730  1.1.1.2  christos 
   1731  1.1.1.2  christos   strncat (attr_str, buf, bufsz);
   1732  1.1.1.2  christos 
   1733  1.1.1.2  christos   /* Skip 'i' extension after 'e'.  */
   1734  1.1.1.2  christos   if ((strcasecmp (subset->name, "e") == 0)
   1735  1.1.1.2  christos       && subset->next
   1736  1.1.1.2  christos       && (strcasecmp (subset->next->name, "i") == 0))
   1737  1.1.1.2  christos     riscv_arch_str1 (subset->next->next, attr_str, buf, bufsz);
   1738  1.1.1.2  christos   else
   1739  1.1.1.2  christos     riscv_arch_str1 (subset->next, attr_str, buf, bufsz);
   1740  1.1.1.2  christos }
   1741  1.1.1.2  christos 
   1742  1.1.1.2  christos /* Convert subset info to string with explicit version info.  */
   1743  1.1.1.2  christos 
   1744  1.1.1.2  christos char *
   1745  1.1.1.2  christos riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset)
   1746  1.1.1.2  christos {
   1747  1.1.1.2  christos   size_t arch_str_len = riscv_estimate_arch_strlen (subset);
   1748  1.1.1.2  christos   char *attr_str = xmalloc (arch_str_len);
   1749  1.1.1.2  christos   char *buf = xmalloc (arch_str_len);
   1750  1.1.1.2  christos 
   1751  1.1.1.2  christos   snprintf (attr_str, arch_str_len, "rv%u", xlen);
   1752  1.1.1.2  christos 
   1753  1.1.1.2  christos   riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len);
   1754  1.1.1.2  christos   free (buf);
   1755  1.1.1.2  christos 
   1756  1.1.1.2  christos   return attr_str;
   1757  1.1.1.2  christos }
   1758