From 47ab8926b04a592128b924da0bdbd622213568f8 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Tue, 11 Jul 2023 17:48:04 -0700 Subject: Move isa_parser_t to libdisasm out of libriscv --- disasm/disasm.mk.in | 1 + disasm/isa_parser.cc | 396 +++++++++++++++++++++++++++++++++++++++++++++++++++ riscv/isa_parser.cc | 396 --------------------------------------------------- riscv/riscv.mk.in | 1 - 4 files changed, 397 insertions(+), 397 deletions(-) create mode 100644 disasm/isa_parser.cc delete mode 100644 riscv/isa_parser.cc diff --git a/disasm/disasm.mk.in b/disasm/disasm.mk.in index 445c430..090911b 100644 --- a/disasm/disasm.mk.in +++ b/disasm/disasm.mk.in @@ -1,5 +1,6 @@ disasm_srcs = \ disasm.cc \ + isa_parser.cc \ regnames.cc \ disasm_install_lib = yes diff --git a/disasm/isa_parser.cc b/disasm/isa_parser.cc new file mode 100644 index 0000000..59472a4 --- /dev/null +++ b/disasm/isa_parser.cc @@ -0,0 +1,396 @@ +#include "isa_parser.h" +#include "extension.h" + +static std::string strtolower(const char* str) +{ + std::string res; + for (const char *r = str; *r; r++) + res += std::tolower(*r); + return res; +} + +static void bad_option_string(const char *option, const char *value, + const char *msg) +{ + fprintf(stderr, "error: bad %s option '%s'. %s\n", option, value, msg); + abort(); +} + +static void bad_isa_string(const char* isa, const char* msg) +{ + bad_option_string("--isa", isa, msg); +} + +static void bad_priv_string(const char* priv) +{ + fprintf(stderr, "error: bad --priv option %s\n", priv); + abort(); +} + +isa_parser_t::isa_parser_t(const char* str, const char *priv) +{ + isa_string = strtolower(str); + const char* all_subsets = "mafdqchpv"; + + if (isa_string.compare(0, 4, "rv32") == 0) + max_xlen = 32; + else if (isa_string.compare(0, 4, "rv64") == 0) + max_xlen = 64; + else + bad_isa_string(str, "ISA strings must begin with RV32 or RV64"); + + switch (isa_string[4]) { + case 'g': + // G = IMAFD_Zicsr_Zifencei, but Spike includes the latter two + // unconditionally, so they need not be explicitly added here. + isa_string = isa_string.substr(0, 4) + "imafd" + isa_string.substr(5); + // Fall through + case 'i': + extension_table['I'] = true; + break; + + case 'e': + extension_table['E'] = true; + break; + + default: + bad_isa_string(str, ("'" + isa_string.substr(0, 4) + "' must be followed by I, E, or G").c_str()); + } + + const char* isa_str = isa_string.c_str(); + auto p = isa_str, subset = all_subsets; + for (p += 5; islower(*p) && !strchr("zsx", *p); ++p) { + while (*subset && (*p != *subset)) + ++subset; + + if (!*subset) { + if (strchr(all_subsets, *p)) + bad_isa_string(str, ("Extension '" + std::string(1, *p) + "' appears too late in ISA string").c_str()); + else + bad_isa_string(str, ("Unsupported extension '" + std::string(1, *p) + "'").c_str()); + } + + switch (*p) { + case 'p': extension_table[EXT_ZBPBO] = true; + extension_table[EXT_ZPN] = true; + extension_table[EXT_ZPSFOPERAND] = true; + extension_table[EXT_ZMMUL] = true; break; + case 'v': // even rv32iv implies double float + case 'q': extension_table['D'] = true; + // Fall through + case 'd': extension_table['F'] = true; + } + extension_table[toupper(*p)] = true; + while (isdigit(*(p + 1))) { + ++p; // skip major version, point, and minor version if presented + if (*(p + 1) == 'p') ++p; + } + p += *(p + 1) == '_'; // underscores may be used to improve readability + } + + while (islower(*p) || (*p == '_')) { + p += *p == '_'; // first underscore is optional + auto end = p; + do ++end; while (*end && *end != '_'); + auto ext_str = std::string(p, end); + if (ext_str == "zfh" || ext_str == "zfhmin") { + if (!extension_table['F']) + bad_isa_string(str, ("'" + ext_str + "' extension requires 'F'").c_str()); + extension_table[EXT_ZFHMIN] = true; + if (ext_str == "zfh") + extension_table[EXT_ZFH] = true; + } else if (ext_str == "zvfh" || ext_str == "zvfhmin") { + if (!extension_table['V']) + bad_isa_string(str, ("'" + ext_str + "' extension requires 'V'").c_str()); + + extension_table[EXT_ZVFHMIN] = true; + + if (ext_str == "zvfh") { + extension_table[EXT_ZVFH] = true; + // Zvfh implies Zfhmin + extension_table[EXT_ZFHMIN] = true; + } + } else if (ext_str == "zicsr") { + // Spike necessarily has Zicsr, because + // Zicsr is implied by the privileged architecture + } else if (ext_str == "zifencei") { + // For compatibility with version 2.0 of the base ISAs, we + // unconditionally include FENCE.I, so Zifencei adds nothing more. + } else if (ext_str == "zihintpause") { + // HINTs encoded in base-ISA instructions are always present. + } else if (ext_str == "zihintntl") { + // HINTs encoded in base-ISA instructions are always present. + } else if (ext_str == "zacas") { + extension_table[EXT_ZACAS] = true; + } else if (ext_str == "zmmul") { + extension_table[EXT_ZMMUL] = true; + } else if (ext_str == "zba") { + extension_table[EXT_ZBA] = true; + } else if (ext_str == "zbb") { + extension_table[EXT_ZBB] = true; + } else if (ext_str == "zbc") { + extension_table[EXT_ZBC] = true; + } else if (ext_str == "zbs") { + extension_table[EXT_ZBS] = true; + } else if (ext_str == "zbkb") { + extension_table[EXT_ZBKB] = true; + } else if (ext_str == "zbkc") { + extension_table[EXT_ZBKC] = true; + } else if (ext_str == "zbkx") { + extension_table[EXT_ZBKX] = true; + } else if (ext_str == "zdinx") { + extension_table[EXT_ZFINX] = true; + extension_table[EXT_ZDINX] = true; + } else if (ext_str == "zfbfmin") { + extension_table[EXT_ZFBFMIN] = true; + } else if (ext_str == "zfinx") { + extension_table[EXT_ZFINX] = true; + } else if (ext_str == "zhinx") { + extension_table[EXT_ZFINX] = true; + extension_table[EXT_ZHINX] = true; + extension_table[EXT_ZHINXMIN] = true; + } else if (ext_str == "zhinxmin") { + extension_table[EXT_ZFINX] = true; + extension_table[EXT_ZHINXMIN] = true; + } else if (ext_str == "zce") { + extension_table[EXT_ZCA] = true; + extension_table[EXT_ZCB] = true; + extension_table[EXT_ZCMT] = true; + extension_table[EXT_ZCMP] = true; + if (extension_table['F'] && max_xlen == 32) + extension_table[EXT_ZCF] = true; + } else if (ext_str == "zca") { + extension_table[EXT_ZCA] = true; + } else if (ext_str == "zcf") { + if (max_xlen != 32) + bad_isa_string(str, "'Zcf' requires RV32"); + extension_table[EXT_ZCF] = true; + } else if (ext_str == "zcb") { + extension_table[EXT_ZCB] = true; + } else if (ext_str == "zcd") { + extension_table[EXT_ZCD] = true; + } else if (ext_str == "zcmp") { + extension_table[EXT_ZCMP] = true; + } else if (ext_str == "zcmt") { + extension_table[EXT_ZCMT] = true; + } else if (ext_str == "zk") { + extension_table[EXT_ZBKB] = true; + extension_table[EXT_ZBKC] = true; + extension_table[EXT_ZBKX] = true; + extension_table[EXT_ZKND] = true; + extension_table[EXT_ZKNE] = true; + extension_table[EXT_ZKNH] = true; + extension_table[EXT_ZKR] = true; + } else if (ext_str == "zkn") { + extension_table[EXT_ZBKB] = true; + extension_table[EXT_ZBKC] = true; + extension_table[EXT_ZBKX] = true; + extension_table[EXT_ZKND] = true; + extension_table[EXT_ZKNE] = true; + extension_table[EXT_ZKNH] = true; + } else if (ext_str == "zknd") { + extension_table[EXT_ZKND] = true; + } else if (ext_str == "zkne") { + extension_table[EXT_ZKNE] = true; + } else if (ext_str == "zknh") { + extension_table[EXT_ZKNH] = true; + } else if (ext_str == "zks") { + extension_table[EXT_ZBKB] = true; + extension_table[EXT_ZBKC] = true; + extension_table[EXT_ZBKX] = true; + extension_table[EXT_ZKSED] = true; + extension_table[EXT_ZKSH] = true; + } else if (ext_str == "zksed") { + extension_table[EXT_ZKSED] = true; + } else if (ext_str == "zksh") { + extension_table[EXT_ZKSH] = true; + } else if (ext_str == "zkr") { + extension_table[EXT_ZKR] = true; + } else if (ext_str == "zkt") { + } else if (ext_str == "smepmp") { + extension_table[EXT_SMEPMP] = true; + } else if (ext_str == "smstateen") { + extension_table[EXT_SMSTATEEN] = true; + } else if (ext_str == "smrnmi") { + extension_table[EXT_SMRNMI] = true; + } else if (ext_str == "sscofpmf") { + extension_table[EXT_SSCOFPMF] = true; + } else if (ext_str == "svadu") { + extension_table[EXT_SVADU] = true; + } else if (ext_str == "svnapot") { + extension_table[EXT_SVNAPOT] = true; + } else if (ext_str == "svpbmt") { + extension_table[EXT_SVPBMT] = true; + } else if (ext_str == "svinval") { + extension_table[EXT_SVINVAL] = true; + } else if (ext_str == "zfa") { + extension_table[EXT_ZFA] = true; + } else if (ext_str == "zicbom") { + extension_table[EXT_ZICBOM] = true; + } else if (ext_str == "zicboz") { + extension_table[EXT_ZICBOZ] = true; + } else if (ext_str == "zicbop") { + } else if (ext_str == "zicntr") { + extension_table[EXT_ZICNTR] = true; + } else if (ext_str == "zicond") { + extension_table[EXT_ZICOND] = true; + } else if (ext_str == "zihpm") { + extension_table[EXT_ZIHPM] = true; + } else if (ext_str == "zvbb") { + extension_table[EXT_ZVBB] = true; + } else if (ext_str == "zvbc") { + extension_table[EXT_ZVBC] = true; + } else if (ext_str == "zvfbfmin") { + extension_table[EXT_ZVFBFMIN] = true; + } else if (ext_str == "zvfbfwma") { + extension_table[EXT_ZVFBFWMA] = true; + } else if (ext_str == "zvkg") { + extension_table[EXT_ZVKG] = true; + } else if (ext_str == "zvkn") { + extension_table[EXT_ZVBB] = true; + extension_table[EXT_ZVKNED] = true; + extension_table[EXT_ZVKNHB] = true; + } else if (ext_str == "zvknc") { + extension_table[EXT_ZVBB] = true; + extension_table[EXT_ZVBC] = true; + extension_table[EXT_ZVKNED] = true; + extension_table[EXT_ZVKNHB] = true; + } else if (ext_str == "zvkng") { + extension_table[EXT_ZVBB] = true; + extension_table[EXT_ZVKG] = true; + extension_table[EXT_ZVKNED] = true; + extension_table[EXT_ZVKNHB] = true; + } else if (ext_str == "zvkned") { + extension_table[EXT_ZVKNED] = true; + } else if (ext_str == "zvknha") { + extension_table[EXT_ZVKNHA] = true; + } else if (ext_str == "zvknhb") { + extension_table[EXT_ZVKNHB] = true; + } else if (ext_str == "zvks") { + extension_table[EXT_ZVBB] = true; + extension_table[EXT_ZVKSED] = true; + extension_table[EXT_ZVKSH] = true; + } else if (ext_str == "zvksc") { + extension_table[EXT_ZVBB] = true; + extension_table[EXT_ZVBC] = true; + extension_table[EXT_ZVKSED] = true; + extension_table[EXT_ZVKSH] = true; + } else if (ext_str == "zvksg") { + extension_table[EXT_ZVBB] = true; + extension_table[EXT_ZVKG] = true; + extension_table[EXT_ZVKSED] = true; + extension_table[EXT_ZVKSH] = true; + } else if (ext_str == "zvksed") { + extension_table[EXT_ZVKSED] = true; + } else if (ext_str == "zvksh") { + extension_table[EXT_ZVKSH] = true; + } else if (ext_str == "zvkt") { + } else if (ext_str == "sstc") { + extension_table[EXT_SSTC] = true; + } else if (ext_str[0] == 'x') { + extension_table['X'] = true; + if (ext_str.size() == 1) { + bad_isa_string(str, "single 'X' is not a proper name"); + } else if (ext_str != "xdummy") { + extension_t* x = find_extension(ext_str.substr(1).c_str())(); + if (!extensions.insert(std::make_pair(x->name(), x)).second) { + fprintf(stderr, "extensions must have unique names (got two named \"%s\"!)\n", x->name()); + abort(); + } + } + } else { + bad_isa_string(str, ("unsupported extension: " + ext_str).c_str()); + } + p = end; + } + if (*p) { + bad_isa_string(str, ("can't parse: " + std::string(p)).c_str()); + } + + if (extension_table[EXT_ZFBFMIN] && !extension_table['F']) { + bad_isa_string(str, "'Zfbfmin' extension requires 'F' extension"); + } + + if ((extension_table[EXT_ZVFBFMIN] || extension_table[EXT_ZVFBFWMA]) && !extension_table['V']) { + bad_isa_string(str, "'Zvfbfmin/Zvfbfwma' extension requires 'V' extension"); + } + + if (extension_table[EXT_ZFBFMIN] || extension_table[EXT_ZVFBFMIN] || extension_table[EXT_ZFHMIN]) { + extension_table[EXT_INTERNAL_ZFH_MOVE] = true; + } + + if (extension_table['C']) { + extension_table[EXT_ZCA] = true; + if (extension_table['F'] && max_xlen == 32) + extension_table[EXT_ZCF] = true; + if (extension_table['D']) + extension_table[EXT_ZCD] = true; + } + + if (extension_table[EXT_ZFINX] && extension_table['F']) { + bad_isa_string(str, ("Zfinx/Zdinx/Zhinx{min} extensions conflict with 'F/D/Q/Zfh{min}' extensions")); + } + + if (extension_table[EXT_ZCF] && !extension_table['F']) { + bad_isa_string(str, "'Zcf' extension requires 'F' extension"); + } + + if (extension_table[EXT_ZCD] && !extension_table['D']) { + bad_isa_string(str, "'Zcd' extension requires 'D' extension"); + } + + if ((extension_table[EXT_ZCMP] || extension_table[EXT_ZCMT]) && extension_table[EXT_ZCD]) { + bad_isa_string(str, "Zcmp' and 'Zcmt' extensions are incompatible with 'Zcd' extension"); + } + + if ((extension_table[EXT_ZCF] || extension_table[EXT_ZCD] || extension_table[EXT_ZCB] || + extension_table[EXT_ZCMP] || extension_table[EXT_ZCMT]) && !extension_table[EXT_ZCA]) { + bad_isa_string(str, "'Zcf/Zcd/Zcb/Zcmp/Zcmt' extensions require 'Zca' extension"); + } + + if (extension_table[EXT_ZACAS] && !extension_table['A']) { + bad_isa_string(str, "'Zacas' extension requires 'A' extension"); + } + + // Zpn conflicts with Zvknha/Zvknhb in both rv32 and rv64 + if (extension_table[EXT_ZPN] && (extension_table[EXT_ZVKNHA] || extension_table[EXT_ZVKNHB])) { + bad_isa_string(str, "'Zvkna' and 'Zvknhb' extensions are incompatible with 'Zpn' extension"); + } + // In rv64 only, Zpn (rv64_zpn) conflicts with Zvkg/Zvkned/Zvksh + if (max_xlen == 64 && extension_table[EXT_ZPN] && + (extension_table[EXT_ZVKG] || extension_table[EXT_ZVKNED] || extension_table[EXT_ZVKSH])) { + bad_isa_string(str, "'Zvkg', 'Zvkned', and 'Zvksh' extensions are incompatible with 'Zpn' extension in rv64"); + } +#ifdef WORDS_BIGENDIAN + // Access to the vector registers as element groups is unimplemented on big-endian setups. + if (extension_table[EXT_ZVKG] || extension_table[EXT_ZVKNHA] || extension_table[EXT_ZVKNHB] || + extension_table[EXT_ZVKSED] || extension_table[EXT_ZVKSH]) { + bad_isa_string(str, + "'Zvkg', 'Zvkned', 'Zvknha', 'Zvknhb', 'Zvksed', and 'Zvksh' " + "extensions are incompatible with WORDS_BIGENDIAN setups."); + } +#endif + std::string lowercase = strtolower(priv); + bool user = false, supervisor = false; + + if (lowercase == "m") + ; + else if (lowercase == "mu") + user = true; + else if (lowercase == "msu") + user = supervisor = true; + else + bad_priv_string(priv); + + extension_table['U'] = user; + extension_table['S'] = supervisor; + + if (extension_table['H'] && !supervisor) + bad_isa_string(str, "'H' extension requires S mode"); + + max_isa = max_xlen == 32 ? reg_t(1) << 30 : reg_t(2) << 62; + for (unsigned char ch = 'A'; ch <= 'Z'; ch++) { + if (extension_table[ch]) + max_isa |= 1UL << (ch - 'A'); + } +} diff --git a/riscv/isa_parser.cc b/riscv/isa_parser.cc deleted file mode 100644 index 59472a4..0000000 --- a/riscv/isa_parser.cc +++ /dev/null @@ -1,396 +0,0 @@ -#include "isa_parser.h" -#include "extension.h" - -static std::string strtolower(const char* str) -{ - std::string res; - for (const char *r = str; *r; r++) - res += std::tolower(*r); - return res; -} - -static void bad_option_string(const char *option, const char *value, - const char *msg) -{ - fprintf(stderr, "error: bad %s option '%s'. %s\n", option, value, msg); - abort(); -} - -static void bad_isa_string(const char* isa, const char* msg) -{ - bad_option_string("--isa", isa, msg); -} - -static void bad_priv_string(const char* priv) -{ - fprintf(stderr, "error: bad --priv option %s\n", priv); - abort(); -} - -isa_parser_t::isa_parser_t(const char* str, const char *priv) -{ - isa_string = strtolower(str); - const char* all_subsets = "mafdqchpv"; - - if (isa_string.compare(0, 4, "rv32") == 0) - max_xlen = 32; - else if (isa_string.compare(0, 4, "rv64") == 0) - max_xlen = 64; - else - bad_isa_string(str, "ISA strings must begin with RV32 or RV64"); - - switch (isa_string[4]) { - case 'g': - // G = IMAFD_Zicsr_Zifencei, but Spike includes the latter two - // unconditionally, so they need not be explicitly added here. - isa_string = isa_string.substr(0, 4) + "imafd" + isa_string.substr(5); - // Fall through - case 'i': - extension_table['I'] = true; - break; - - case 'e': - extension_table['E'] = true; - break; - - default: - bad_isa_string(str, ("'" + isa_string.substr(0, 4) + "' must be followed by I, E, or G").c_str()); - } - - const char* isa_str = isa_string.c_str(); - auto p = isa_str, subset = all_subsets; - for (p += 5; islower(*p) && !strchr("zsx", *p); ++p) { - while (*subset && (*p != *subset)) - ++subset; - - if (!*subset) { - if (strchr(all_subsets, *p)) - bad_isa_string(str, ("Extension '" + std::string(1, *p) + "' appears too late in ISA string").c_str()); - else - bad_isa_string(str, ("Unsupported extension '" + std::string(1, *p) + "'").c_str()); - } - - switch (*p) { - case 'p': extension_table[EXT_ZBPBO] = true; - extension_table[EXT_ZPN] = true; - extension_table[EXT_ZPSFOPERAND] = true; - extension_table[EXT_ZMMUL] = true; break; - case 'v': // even rv32iv implies double float - case 'q': extension_table['D'] = true; - // Fall through - case 'd': extension_table['F'] = true; - } - extension_table[toupper(*p)] = true; - while (isdigit(*(p + 1))) { - ++p; // skip major version, point, and minor version if presented - if (*(p + 1) == 'p') ++p; - } - p += *(p + 1) == '_'; // underscores may be used to improve readability - } - - while (islower(*p) || (*p == '_')) { - p += *p == '_'; // first underscore is optional - auto end = p; - do ++end; while (*end && *end != '_'); - auto ext_str = std::string(p, end); - if (ext_str == "zfh" || ext_str == "zfhmin") { - if (!extension_table['F']) - bad_isa_string(str, ("'" + ext_str + "' extension requires 'F'").c_str()); - extension_table[EXT_ZFHMIN] = true; - if (ext_str == "zfh") - extension_table[EXT_ZFH] = true; - } else if (ext_str == "zvfh" || ext_str == "zvfhmin") { - if (!extension_table['V']) - bad_isa_string(str, ("'" + ext_str + "' extension requires 'V'").c_str()); - - extension_table[EXT_ZVFHMIN] = true; - - if (ext_str == "zvfh") { - extension_table[EXT_ZVFH] = true; - // Zvfh implies Zfhmin - extension_table[EXT_ZFHMIN] = true; - } - } else if (ext_str == "zicsr") { - // Spike necessarily has Zicsr, because - // Zicsr is implied by the privileged architecture - } else if (ext_str == "zifencei") { - // For compatibility with version 2.0 of the base ISAs, we - // unconditionally include FENCE.I, so Zifencei adds nothing more. - } else if (ext_str == "zihintpause") { - // HINTs encoded in base-ISA instructions are always present. - } else if (ext_str == "zihintntl") { - // HINTs encoded in base-ISA instructions are always present. - } else if (ext_str == "zacas") { - extension_table[EXT_ZACAS] = true; - } else if (ext_str == "zmmul") { - extension_table[EXT_ZMMUL] = true; - } else if (ext_str == "zba") { - extension_table[EXT_ZBA] = true; - } else if (ext_str == "zbb") { - extension_table[EXT_ZBB] = true; - } else if (ext_str == "zbc") { - extension_table[EXT_ZBC] = true; - } else if (ext_str == "zbs") { - extension_table[EXT_ZBS] = true; - } else if (ext_str == "zbkb") { - extension_table[EXT_ZBKB] = true; - } else if (ext_str == "zbkc") { - extension_table[EXT_ZBKC] = true; - } else if (ext_str == "zbkx") { - extension_table[EXT_ZBKX] = true; - } else if (ext_str == "zdinx") { - extension_table[EXT_ZFINX] = true; - extension_table[EXT_ZDINX] = true; - } else if (ext_str == "zfbfmin") { - extension_table[EXT_ZFBFMIN] = true; - } else if (ext_str == "zfinx") { - extension_table[EXT_ZFINX] = true; - } else if (ext_str == "zhinx") { - extension_table[EXT_ZFINX] = true; - extension_table[EXT_ZHINX] = true; - extension_table[EXT_ZHINXMIN] = true; - } else if (ext_str == "zhinxmin") { - extension_table[EXT_ZFINX] = true; - extension_table[EXT_ZHINXMIN] = true; - } else if (ext_str == "zce") { - extension_table[EXT_ZCA] = true; - extension_table[EXT_ZCB] = true; - extension_table[EXT_ZCMT] = true; - extension_table[EXT_ZCMP] = true; - if (extension_table['F'] && max_xlen == 32) - extension_table[EXT_ZCF] = true; - } else if (ext_str == "zca") { - extension_table[EXT_ZCA] = true; - } else if (ext_str == "zcf") { - if (max_xlen != 32) - bad_isa_string(str, "'Zcf' requires RV32"); - extension_table[EXT_ZCF] = true; - } else if (ext_str == "zcb") { - extension_table[EXT_ZCB] = true; - } else if (ext_str == "zcd") { - extension_table[EXT_ZCD] = true; - } else if (ext_str == "zcmp") { - extension_table[EXT_ZCMP] = true; - } else if (ext_str == "zcmt") { - extension_table[EXT_ZCMT] = true; - } else if (ext_str == "zk") { - extension_table[EXT_ZBKB] = true; - extension_table[EXT_ZBKC] = true; - extension_table[EXT_ZBKX] = true; - extension_table[EXT_ZKND] = true; - extension_table[EXT_ZKNE] = true; - extension_table[EXT_ZKNH] = true; - extension_table[EXT_ZKR] = true; - } else if (ext_str == "zkn") { - extension_table[EXT_ZBKB] = true; - extension_table[EXT_ZBKC] = true; - extension_table[EXT_ZBKX] = true; - extension_table[EXT_ZKND] = true; - extension_table[EXT_ZKNE] = true; - extension_table[EXT_ZKNH] = true; - } else if (ext_str == "zknd") { - extension_table[EXT_ZKND] = true; - } else if (ext_str == "zkne") { - extension_table[EXT_ZKNE] = true; - } else if (ext_str == "zknh") { - extension_table[EXT_ZKNH] = true; - } else if (ext_str == "zks") { - extension_table[EXT_ZBKB] = true; - extension_table[EXT_ZBKC] = true; - extension_table[EXT_ZBKX] = true; - extension_table[EXT_ZKSED] = true; - extension_table[EXT_ZKSH] = true; - } else if (ext_str == "zksed") { - extension_table[EXT_ZKSED] = true; - } else if (ext_str == "zksh") { - extension_table[EXT_ZKSH] = true; - } else if (ext_str == "zkr") { - extension_table[EXT_ZKR] = true; - } else if (ext_str == "zkt") { - } else if (ext_str == "smepmp") { - extension_table[EXT_SMEPMP] = true; - } else if (ext_str == "smstateen") { - extension_table[EXT_SMSTATEEN] = true; - } else if (ext_str == "smrnmi") { - extension_table[EXT_SMRNMI] = true; - } else if (ext_str == "sscofpmf") { - extension_table[EXT_SSCOFPMF] = true; - } else if (ext_str == "svadu") { - extension_table[EXT_SVADU] = true; - } else if (ext_str == "svnapot") { - extension_table[EXT_SVNAPOT] = true; - } else if (ext_str == "svpbmt") { - extension_table[EXT_SVPBMT] = true; - } else if (ext_str == "svinval") { - extension_table[EXT_SVINVAL] = true; - } else if (ext_str == "zfa") { - extension_table[EXT_ZFA] = true; - } else if (ext_str == "zicbom") { - extension_table[EXT_ZICBOM] = true; - } else if (ext_str == "zicboz") { - extension_table[EXT_ZICBOZ] = true; - } else if (ext_str == "zicbop") { - } else if (ext_str == "zicntr") { - extension_table[EXT_ZICNTR] = true; - } else if (ext_str == "zicond") { - extension_table[EXT_ZICOND] = true; - } else if (ext_str == "zihpm") { - extension_table[EXT_ZIHPM] = true; - } else if (ext_str == "zvbb") { - extension_table[EXT_ZVBB] = true; - } else if (ext_str == "zvbc") { - extension_table[EXT_ZVBC] = true; - } else if (ext_str == "zvfbfmin") { - extension_table[EXT_ZVFBFMIN] = true; - } else if (ext_str == "zvfbfwma") { - extension_table[EXT_ZVFBFWMA] = true; - } else if (ext_str == "zvkg") { - extension_table[EXT_ZVKG] = true; - } else if (ext_str == "zvkn") { - extension_table[EXT_ZVBB] = true; - extension_table[EXT_ZVKNED] = true; - extension_table[EXT_ZVKNHB] = true; - } else if (ext_str == "zvknc") { - extension_table[EXT_ZVBB] = true; - extension_table[EXT_ZVBC] = true; - extension_table[EXT_ZVKNED] = true; - extension_table[EXT_ZVKNHB] = true; - } else if (ext_str == "zvkng") { - extension_table[EXT_ZVBB] = true; - extension_table[EXT_ZVKG] = true; - extension_table[EXT_ZVKNED] = true; - extension_table[EXT_ZVKNHB] = true; - } else if (ext_str == "zvkned") { - extension_table[EXT_ZVKNED] = true; - } else if (ext_str == "zvknha") { - extension_table[EXT_ZVKNHA] = true; - } else if (ext_str == "zvknhb") { - extension_table[EXT_ZVKNHB] = true; - } else if (ext_str == "zvks") { - extension_table[EXT_ZVBB] = true; - extension_table[EXT_ZVKSED] = true; - extension_table[EXT_ZVKSH] = true; - } else if (ext_str == "zvksc") { - extension_table[EXT_ZVBB] = true; - extension_table[EXT_ZVBC] = true; - extension_table[EXT_ZVKSED] = true; - extension_table[EXT_ZVKSH] = true; - } else if (ext_str == "zvksg") { - extension_table[EXT_ZVBB] = true; - extension_table[EXT_ZVKG] = true; - extension_table[EXT_ZVKSED] = true; - extension_table[EXT_ZVKSH] = true; - } else if (ext_str == "zvksed") { - extension_table[EXT_ZVKSED] = true; - } else if (ext_str == "zvksh") { - extension_table[EXT_ZVKSH] = true; - } else if (ext_str == "zvkt") { - } else if (ext_str == "sstc") { - extension_table[EXT_SSTC] = true; - } else if (ext_str[0] == 'x') { - extension_table['X'] = true; - if (ext_str.size() == 1) { - bad_isa_string(str, "single 'X' is not a proper name"); - } else if (ext_str != "xdummy") { - extension_t* x = find_extension(ext_str.substr(1).c_str())(); - if (!extensions.insert(std::make_pair(x->name(), x)).second) { - fprintf(stderr, "extensions must have unique names (got two named \"%s\"!)\n", x->name()); - abort(); - } - } - } else { - bad_isa_string(str, ("unsupported extension: " + ext_str).c_str()); - } - p = end; - } - if (*p) { - bad_isa_string(str, ("can't parse: " + std::string(p)).c_str()); - } - - if (extension_table[EXT_ZFBFMIN] && !extension_table['F']) { - bad_isa_string(str, "'Zfbfmin' extension requires 'F' extension"); - } - - if ((extension_table[EXT_ZVFBFMIN] || extension_table[EXT_ZVFBFWMA]) && !extension_table['V']) { - bad_isa_string(str, "'Zvfbfmin/Zvfbfwma' extension requires 'V' extension"); - } - - if (extension_table[EXT_ZFBFMIN] || extension_table[EXT_ZVFBFMIN] || extension_table[EXT_ZFHMIN]) { - extension_table[EXT_INTERNAL_ZFH_MOVE] = true; - } - - if (extension_table['C']) { - extension_table[EXT_ZCA] = true; - if (extension_table['F'] && max_xlen == 32) - extension_table[EXT_ZCF] = true; - if (extension_table['D']) - extension_table[EXT_ZCD] = true; - } - - if (extension_table[EXT_ZFINX] && extension_table['F']) { - bad_isa_string(str, ("Zfinx/Zdinx/Zhinx{min} extensions conflict with 'F/D/Q/Zfh{min}' extensions")); - } - - if (extension_table[EXT_ZCF] && !extension_table['F']) { - bad_isa_string(str, "'Zcf' extension requires 'F' extension"); - } - - if (extension_table[EXT_ZCD] && !extension_table['D']) { - bad_isa_string(str, "'Zcd' extension requires 'D' extension"); - } - - if ((extension_table[EXT_ZCMP] || extension_table[EXT_ZCMT]) && extension_table[EXT_ZCD]) { - bad_isa_string(str, "Zcmp' and 'Zcmt' extensions are incompatible with 'Zcd' extension"); - } - - if ((extension_table[EXT_ZCF] || extension_table[EXT_ZCD] || extension_table[EXT_ZCB] || - extension_table[EXT_ZCMP] || extension_table[EXT_ZCMT]) && !extension_table[EXT_ZCA]) { - bad_isa_string(str, "'Zcf/Zcd/Zcb/Zcmp/Zcmt' extensions require 'Zca' extension"); - } - - if (extension_table[EXT_ZACAS] && !extension_table['A']) { - bad_isa_string(str, "'Zacas' extension requires 'A' extension"); - } - - // Zpn conflicts with Zvknha/Zvknhb in both rv32 and rv64 - if (extension_table[EXT_ZPN] && (extension_table[EXT_ZVKNHA] || extension_table[EXT_ZVKNHB])) { - bad_isa_string(str, "'Zvkna' and 'Zvknhb' extensions are incompatible with 'Zpn' extension"); - } - // In rv64 only, Zpn (rv64_zpn) conflicts with Zvkg/Zvkned/Zvksh - if (max_xlen == 64 && extension_table[EXT_ZPN] && - (extension_table[EXT_ZVKG] || extension_table[EXT_ZVKNED] || extension_table[EXT_ZVKSH])) { - bad_isa_string(str, "'Zvkg', 'Zvkned', and 'Zvksh' extensions are incompatible with 'Zpn' extension in rv64"); - } -#ifdef WORDS_BIGENDIAN - // Access to the vector registers as element groups is unimplemented on big-endian setups. - if (extension_table[EXT_ZVKG] || extension_table[EXT_ZVKNHA] || extension_table[EXT_ZVKNHB] || - extension_table[EXT_ZVKSED] || extension_table[EXT_ZVKSH]) { - bad_isa_string(str, - "'Zvkg', 'Zvkned', 'Zvknha', 'Zvknhb', 'Zvksed', and 'Zvksh' " - "extensions are incompatible with WORDS_BIGENDIAN setups."); - } -#endif - std::string lowercase = strtolower(priv); - bool user = false, supervisor = false; - - if (lowercase == "m") - ; - else if (lowercase == "mu") - user = true; - else if (lowercase == "msu") - user = supervisor = true; - else - bad_priv_string(priv); - - extension_table['U'] = user; - extension_table['S'] = supervisor; - - if (extension_table['H'] && !supervisor) - bad_isa_string(str, "'H' extension requires S mode"); - - max_isa = max_xlen == 32 ? reg_t(1) << 30 : reg_t(2) << 62; - for (unsigned char ch = 'A'; ch <= 'Z'; ch++) { - if (extension_table[ch]) - max_isa |= 1UL << (ch - 'A'); - } -} diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index 1ad8b23..3a0333c 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -49,7 +49,6 @@ riscv_precompiled_hdrs = \ insn_template.h \ riscv_srcs = \ - isa_parser.cc \ processor.cc \ execute.cc \ dts.cc \ -- cgit v1.1 From 2eb2b40102ba0302e1b28959072d9ccb91930a8f Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Tue, 11 Jul 2023 17:53:23 -0700 Subject: Remove dependency of isa_parser_t on extension_t --- disasm/isa_parser.cc | 7 +------ riscv/isa_parser.h | 9 +++------ riscv/processor.cc | 2 +- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/disasm/isa_parser.cc b/disasm/isa_parser.cc index 59472a4..c18a72d 100644 --- a/disasm/isa_parser.cc +++ b/disasm/isa_parser.cc @@ -1,5 +1,4 @@ #include "isa_parser.h" -#include "extension.h" static std::string strtolower(const char* str) { @@ -292,11 +291,7 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) if (ext_str.size() == 1) { bad_isa_string(str, "single 'X' is not a proper name"); } else if (ext_str != "xdummy") { - extension_t* x = find_extension(ext_str.substr(1).c_str())(); - if (!extensions.insert(std::make_pair(x->name(), x)).second) { - fprintf(stderr, "extensions must have unique names (got two named \"%s\"!)\n", x->name()); - abort(); - } + extensions.insert(ext_str.substr(1)); } } else { bad_isa_string(str, ("unsupported extension: " + ext_str).c_str()); diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h index 5b04347..335a42b 100644 --- a/riscv/isa_parser.h +++ b/riscv/isa_parser.h @@ -6,9 +6,7 @@ #include #include -#include - -class extension_t; +#include typedef enum { // 65('A') ~ 90('Z') is reserved for standard isa in misa @@ -109,15 +107,14 @@ public: std::bitset get_extension_table() const { return extension_table; } - const std::unordered_map & - get_extensions() const { return extensions; } + const std::set &get_extensions() const { return extensions; } protected: unsigned max_xlen; reg_t max_isa; std::bitset extension_table; std::string isa_string; - std::unordered_map extensions; + std::set extensions; }; #endif diff --git a/riscv/processor.cc b/riscv/processor.cc index 1d5675a..e81375a 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -61,7 +61,7 @@ processor_t::processor_t(const isa_parser_t *isa, const cfg_t *cfg, disassembler = new disassembler_t(isa); for (auto e : isa->get_extensions()) - register_extension(e.second); + register_extension(find_extension(e.c_str())()); set_pmp_granularity(1 << PMP_SHIFT); set_pmp_num(cfg->pmpregions); -- cgit v1.1 From fe0576044590751e0a10a22ec28077f72d8c5414 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Sun, 9 Jul 2023 22:21:54 -0700 Subject: build: Support project-defined LDFLAGS --- Makefile.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.in b/Makefile.in index b5013bd..f236576 100644 --- a/Makefile.in +++ b/Makefile.in @@ -264,7 +264,7 @@ $$($(2)_test_objs) : %.o : %.cc $(COMPILE) -c $$< $$($(2)_test_exes) : %-utst : %.t.o $$($(2)_test_libnames) - $(LINK) -o $$@ $$< $$($(2)_test_libnames) $(LIBS) + $(LINK) $$($(2)_LDFLAGS) -o $$@ $$< $$($(2)_test_libnames) $(LIBS) $(2)_deps += $$($(2)_test_deps) $(2)_junk += \ @@ -292,7 +292,7 @@ $$($(2)_prog_objs) : %.o : %.cc $(COMPILE) -c $$< $$($(2)_prog_exes) : % : %.o $$($(2)_prog_libnames) - $(LINK) -o $$@ $$< $$($(2)_prog_libnames) $(LIBS) + $(LINK) $$($(2)_LDFLAGS) -o $$@ $$< $$($(2)_prog_libnames) $(LIBS) $(2)_deps += $$($(2)_prog_deps) $(2)_junk += $$($(2)_prog_objs) $$($(2)_prog_deps) $$($(2)_prog_exes) @@ -307,7 +307,7 @@ $$($(2)_install_prog_objs) : %.o : %.cc $$($(2)_gen_hdrs) $(COMPILE) -c $$< $$($(2)_install_prog_exes) : % : %.o $$($(2)_prog_libnames) - $(LINK) -o $$@ $$< $$($(2)_prog_libnames) $(LIBS) + $(LINK) $$($(2)_LDFLAGS) -o $$@ $$< $$($(2)_prog_libnames) $(LIBS) $(2)_deps += $$($(2)_install_prog_deps) $(2)_junk += \ -- cgit v1.1 From 3b0d3c2004e97bbbcc1ae17a4053f1913b01991f Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Sun, 9 Jul 2023 22:22:11 -0700 Subject: build: Force inclusion of all symbols from extension.o in spike-main The --extension feature requires that all symbols in extension.o be available when the libraries are dynamically loaded by dlopen. Prepending extension.o to the linker command adds the otherwise omitted symbols to spike's dynamic symbol table. --- spike_main/spike_main.mk.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spike_main/spike_main.mk.in b/spike_main/spike_main.mk.in index 25a7a6c..c842c4e 100644 --- a/spike_main/spike_main.mk.in +++ b/spike_main/spike_main.mk.in @@ -14,3 +14,7 @@ spike_main_install_prog_srcs = \ spike_main_srcs = \ spike_main_CFLAGS = -fPIC + +# This hack adds all symbols from extension.o to spike's dynamic symbol +# table, which is required for dynamically loaded --extension libraries +spike_main_LDFLAGS = extension.o -- cgit v1.1