X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Fcpu-riscv.c;h=eec61b401c0359aa385ee868383189e348c7ce0d;hb=250d07de5cf6efc81ed934c25292beb63c7e3129;hp=a938199889a5d8552dcb414bb74eeabaf32cc461;hpb=e23eba971dd409b999dd83d8df0f842680c1c642;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/cpu-riscv.c b/bfd/cpu-riscv.c index a938199889..eec61b401c 100644 --- a/bfd/cpu-riscv.c +++ b/bfd/cpu-riscv.c @@ -1,5 +1,5 @@ /* BFD backend for RISC-V - Copyright 2011-2016 Free Software Foundation, Inc. + Copyright (C) 2011-2021 Free Software Foundation, Inc. Contributed by Andrew Waterman (andrew@sifive.com). Based on MIPS target. @@ -23,6 +23,86 @@ #include "sysdep.h" #include "bfd.h" #include "libbfd.h" +#include "elfxx-riscv.h" + +/* Record the priv spec version string and the corresponding class. */ + +struct priv_spec_t +{ + const char *name; + enum riscv_priv_spec_class class; +}; + +/* List for all supported privilege versions. */ + +static const struct priv_spec_t priv_specs[] = +{ + {"1.9.1", PRIV_SPEC_CLASS_1P9P1}, + {"1.10", PRIV_SPEC_CLASS_1P10}, + {"1.11", PRIV_SPEC_CLASS_1P11}, + +/* Terminate the list. */ + {NULL, 0} +}; + +/* Get the corresponding CSR version class by giving a privilege + version string. */ + +int +riscv_get_priv_spec_class (const char *s, + enum riscv_priv_spec_class *class) +{ + const struct priv_spec_t *version; + + if (s == NULL) + return 0; + + for (version = &priv_specs[0]; version->name != NULL; ++version) + if (strcmp (version->name, s) == 0) + { + *class = version->class; + return 1; + } + + /* Can not find the supported privilege version. */ + return 0; +} + +/* Get the corresponding CSR version class by giving privilege + version numbers. It is usually used to convert the priv + attribute numbers into the corresponding class. */ + +int +riscv_get_priv_spec_class_from_numbers (unsigned int major, + unsigned int minor, + unsigned int revision, + enum riscv_priv_spec_class *class) +{ + char buf[36]; + + if (major == 0 && minor == 0 && revision == 0) + { + *class = PRIV_SPEC_CLASS_NONE; + return 1; + } + + if (revision != 0) + snprintf (buf, sizeof (buf), "%u.%u.%u", major, minor, revision); + else + snprintf (buf, sizeof (buf), "%u.%u", major, minor); + + return riscv_get_priv_spec_class (buf, class); +} + +/* Get the corresponding privilege version string by giving a CSR + version class. */ + +const char * +riscv_get_priv_spec_name (enum riscv_priv_spec_class class) +{ + /* The first enum is PRIV_SPEC_CLASS_NONE. */ + return priv_specs[class - 1].name; +} /* This routine is provided two arch_infos and returns an arch_info that is compatible with both, or NULL if none exists. */ @@ -39,11 +119,38 @@ riscv_compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b) return a; } -#define N(BITS_WORD, BITS_ADDR, NUMBER, PRINT, DEFAULT, NEXT) \ +/* Return TRUE if STRING matches the architecture described by INFO. */ + +static bfd_boolean +riscv_scan (const struct bfd_arch_info *info, const char *string) +{ + if (bfd_default_scan (info, string)) + return TRUE; + + /* The incoming STRING might take the form of riscv:rvXXzzz, where XX is + 32 or 64, and zzz are one or more extension characters. As we + currently only have 3 architectures defined, 'riscv', 'riscv:rv32', + and 'riscv:rv64', we would like to ignore the zzz for the purpose of + matching here. + + However, we don't want the default 'riscv' to match over a more + specific 'riscv:rv32' or 'riscv:rv64', so in the case of the default + architecture (with the shorter 'riscv' name) we don't allow any + special matching, but for the 'riscv:rvXX' cases, we allow a match + with any additional trailing characters being ignored. */ + if (!info->the_default + && strncasecmp (string, info->printable_name, + strlen (info->printable_name)) == 0) + return TRUE; + + return FALSE; +} + +#define N(BITS, NUMBER, PRINT, DEFAULT, NEXT) \ { \ - BITS_WORD, /* bits in a word */ \ - BITS_ADDR, /* bits in an address */ \ - 8, /* 8 bits in a byte */ \ + BITS, /* Bits in a word. */ \ + BITS, /* Bits in an address. */ \ + 8, /* Bits in a byte. */ \ bfd_arch_riscv, \ NUMBER, \ "riscv", \ @@ -51,9 +158,10 @@ riscv_compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b) 3, \ DEFAULT, \ riscv_compatible, \ - bfd_default_scan, \ + riscv_scan, \ bfd_arch_default_fill, \ NEXT, \ + 0 /* Maximum offset of a reloc from the start of an insn. */\ } /* This enum must be kept in the same order as arch_info_struct. */ @@ -69,11 +177,11 @@ enum and each entry except the last should end with NN (my enum value). */ static const bfd_arch_info_type arch_info_struct[] = { - N (64, 64, bfd_mach_riscv64, "riscv:rv64", FALSE, NN (I_riscv64)), - N (32, 32, bfd_mach_riscv32, "riscv:rv32", FALSE, 0) + N (64, bfd_mach_riscv64, "riscv:rv64", FALSE, NN (I_riscv64)), + N (32, bfd_mach_riscv32, "riscv:rv32", FALSE, NULL) }; /* The default architecture is riscv:rv64. */ const bfd_arch_info_type bfd_riscv_arch = - N (64, 64, 0, "riscv", TRUE, &arch_info_struct[0]); + N (64, 0, "riscv", TRUE, &arch_info_struct[0]);