Browse Source

Merge pull request #2287 from jerryzj/master

Refactor ISA parser extension handling
pull/2279/merge
Andrew Waterman 2 weeks ago
committed by GitHub
parent
commit
20feb9c2bf
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 645
      disasm/isa_parser.cc
  2. 1
      riscv/isa_parser.h

645
disasm/isa_parser.cc

@ -1,6 +1,10 @@
#include "isa_parser.h" #include "isa_parser.h"
#include <cstring> #include <cstring>
#include <initializer_list>
#include <stdexcept> #include <stdexcept>
#include <vector>
namespace {
static std::string strtolower(const char* str) static std::string strtolower(const char* str)
{ {
@ -48,366 +52,259 @@ static void bad_priv_string(const char* priv)
abort(); abort();
} }
void isa_parser_t::add_extension(const std::string& ext_str, const char* str) struct extension_info_t {
const char* name;
std::vector<unsigned> enables;
std::vector<const char*> implies;
// `enables` sets extension_table bits directly
// `implies` recursively parses and applies other named extensions
extension_info_t(const char* name,
std::initializer_list<unsigned> enables = {},
std::initializer_list<const char*> implies = {})
: name(name), enables(enables), implies(implies) {}
};
// if every extension in components is set, also set the enable
struct extension_combination_t {
unsigned enable;
std::vector<unsigned> components;
extension_combination_t(unsigned enable,
std::initializer_list<unsigned> components = {})
: enable(enable), components(components) {}
};
// Entries without enables set no extension_table bits directly. This is either
// because no dedicated EXT_* bit exists for them (their full effect is expressed
// through their implies chain), or because their behavior is always present in
// Spike, is currently unmodeled, or is handled by later parser checks.
static const extension_info_t extension_infos[] = {
{"i", {'I'}},
{"e", {'E'}},
{"m", {'M'}},
{"a", {'A'}, {"zaamo", "zalrsc"}},
{"f", {'F'}},
{"d", {'D', 'F'}},
{"q", {'Q', 'D', 'F'}},
{"c", {'C'}, {"zca"}},
{"b", {'B'}, {"zba", "zbb", "zbs"}},
{"p", {'P'}},
{"v", {'V'}, {"zve64d", "zvl128b"}},
{"h", {'H'}},
{"zfh", {EXT_ZFH}, {"zfhmin"}},
{"zfhmin", {'F', EXT_ZFHMIN}},
{"zvfh", {EXT_ZVFH}, {"zvfhmin", "zfhmin"}},
{"zvfhmin", {EXT_ZVFHMIN}, {"zve32f"}},
{"zvfbfa", {EXT_ZVFBFA}, {"zve32f", "zfbfmin"}},
{"zvfofp4min", {EXT_ZVFOFP4MIN}, {"zve32f"}},
{"zvfofp8min", {EXT_ZVFOFP8MIN}, {"zve32f"}},
{"zicsr"},
{"zifencei"},
{"zihintpause"},
{"zihintntl"},
{"ziccid", {EXT_ZICCID}},
{"ziccif"},
{"zve32x", {}, {"zicsr", "zvl32b"}},
{"zve32f", {}, {"zve32x", "f"}},
{"zve64x", {}, {"zve32x", "zvl64b"}},
{"zve64f", {}, {"zve32f", "zve64x"}},
{"zve64d", {}, {"zve64f", "d"}},
{"zaamo", {EXT_ZAAMO}},
{"zalrsc", {EXT_ZALRSC}},
{"zacas", {EXT_ZACAS, EXT_ZAAMO}},
{"zabha", {EXT_ZABHA, EXT_ZAAMO}},
{"zawrs", {EXT_ZAWRS, EXT_ZALRSC}},
{"zama16b", {EXT_ZAMA16B}},
{"zmmul", {EXT_ZMMUL}},
{"zba", {EXT_ZBA}},
{"zbb", {EXT_ZBB}},
{"zbc", {EXT_ZBC}},
{"zbs", {EXT_ZBS}},
{"zbkb", {EXT_ZBKB}},
{"zbkc", {EXT_ZBKC}},
{"zbkx", {EXT_ZBKX}},
{"zdinx", {EXT_ZFINX, EXT_ZDINX}},
{"zfbfmin", {'F', EXT_ZFBFMIN}},
{"zfinx", {EXT_ZFINX}},
{"zhinx", {EXT_ZFINX, EXT_ZHINX, EXT_ZHINXMIN}},
{"zhinxmin", {EXT_ZFINX, EXT_ZHINXMIN}},
{"zce", {EXT_ZCE}, {"zcb", "zcmp", "zcmt"}},
{"zca", {EXT_ZCA}},
{"zcf", {'F', EXT_ZCF}, {"zca"}},
{"zcb", {EXT_ZCB}, {"zca"}},
{"zcd", {EXT_ZCD, 'F', 'D'}, {"zca"}},
{"zcmp", {EXT_ZCMP}, {"zca"}},
{"zcmt", {EXT_ZCMT}, {"zca", "zicsr"}},
{"zibi", {EXT_ZIBI}},
{"zk", {EXT_ZBKB, EXT_ZBKC, EXT_ZBKX, EXT_ZKND, EXT_ZKNE, EXT_ZKNH, EXT_ZKR}},
{"zkn", {EXT_ZBKB, EXT_ZBKC, EXT_ZBKX, EXT_ZKND, EXT_ZKNE, EXT_ZKNH}},
{"zknd", {EXT_ZKND}},
{"zkne", {EXT_ZKNE}},
{"zknh", {EXT_ZKNH}},
{"zks", {EXT_ZBKB, EXT_ZBKC, EXT_ZBKX, EXT_ZKSED, EXT_ZKSH}},
{"zksed", {EXT_ZKSED}},
{"zksh", {EXT_ZKSH}},
{"zkr", {EXT_ZKR}},
{"zkt"},
{"smepmp", {EXT_SMEPMP}},
{"smstateen", {EXT_SMSTATEEN}},
{"smpmpmt", {EXT_SMPMPMT}},
{"smrnmi", {EXT_SMRNMI}},
{"sscofpmf", {EXT_SSCOFPMF}},
{"svadu", {EXT_SVADU}},
{"svade", {EXT_SVADE}},
{"svnapot", {EXT_SVNAPOT}},
{"svpbmt", {EXT_SVPBMT}},
{"svinval", {EXT_SVINVAL}},
{"svukte", {EXT_SVUKTE}},
{"zfa", {EXT_ZFA}},
{"zicbom", {EXT_ZICBOM}},
{"zicboz", {EXT_ZICBOZ}},
{"zicbop"},
{"zicclsm", {EXT_ZICCLSM}},
{"zicntr", {EXT_ZICNTR}},
{"zicond", {EXT_ZICOND}},
{"zihpm", {EXT_ZIHPM}},
{"zilsd", {EXT_ZILSD}},
{"zclsd", {EXT_ZCLSD}, {"zilsd", "zca"}},
{"zvabd", {EXT_ZVABD}},
{"zvkb", {EXT_ZVKB}},
{"zvbb", {EXT_ZVKB, EXT_ZVBB}},
{"zvbc", {EXT_ZVBC}},
{"zvfbfmin", {EXT_ZVFBFMIN}, {"zve32f"}},
{"zvfbfwma", {EXT_ZVFBFWMA}, {"zfbfmin", "zvfbfmin"}},
{"zvkg", {EXT_ZVKG}},
{"zvkn", {EXT_ZVKB, EXT_ZVKNED, EXT_ZVKNHB}},
{"zvknc", {EXT_ZVKB, EXT_ZVBC, EXT_ZVKNED, EXT_ZVKNHB}},
{"zvkng", {EXT_ZVKB, EXT_ZVKG, EXT_ZVKNED, EXT_ZVKNHB}},
{"zvkned", {EXT_ZVKNED}},
{"zvknha", {EXT_ZVKNHA}},
{"zvknhb", {EXT_ZVKNHB}},
{"zvks", {EXT_ZVKB, EXT_ZVKSED, EXT_ZVKSH}},
{"zvksc", {EXT_ZVKB, EXT_ZVBC, EXT_ZVKSED, EXT_ZVKSH}},
{"zvksg", {EXT_ZVKB, EXT_ZVKG, EXT_ZVKSED, EXT_ZVKSH}},
{"zvksed", {EXT_ZVKSED}},
{"zvksh", {EXT_ZVKSH}},
{"zvqdotq", {EXT_ZVQDOTQ}},
{"zvqbdot8i", {EXT_ZVQBDOT8I}},
{"zvqbdot16i", {EXT_ZVQBDOT16I}},
{"zvfqbdot8f", {EXT_ZVFQBDOT8F}},
{"zvfwbdot16bf", {EXT_ZVFWBDOT16BF}},
{"zvfbdot32f", {EXT_ZVFBDOT32F}},
{"zvqldot8i", {EXT_ZVQLDOT8I}},
{"zvqldot16i", {EXT_ZVQLDOT16I}},
{"zvfqldot8f", {EXT_ZVFQLDOT8F}},
{"zvfwldot16bf", {EXT_ZVFWLDOT16BF}},
{"zvkt"},
{"zvzip", {EXT_ZVZIP}},
{"sstc", {EXT_SSTC}},
{"smcsrind", {EXT_SMCSRIND}},
{"sscsrind", {EXT_SSCSRIND}},
{"smcntrpmf", {EXT_SMCNTRPMF}},
{"smcdeleg", {EXT_SMCDELEG}},
{"ssccfg", {EXT_SSCCFG}},
{"zimop", {EXT_ZIMOP}},
{"zcmop", {EXT_ZCMOP}, {"zca"}},
{"zalasr", {EXT_ZALASR}},
{"ssqosid", {EXT_SSQOSID}},
{"zicfilp", {EXT_ZICFILP}},
{"zicfiss", {EXT_ZICFISS}, {"zaamo", "zimop"}},
{"smmpm", {EXT_SMMPM}},
{"smnpm", {EXT_SMNPM}},
{"ssnpm", {EXT_SSNPM}},
{"ssdbltrp", {EXT_SSDBLTRP}},
{"smdbltrp", {EXT_SMDBLTRP}},
{"smaia", {EXT_SMAIA, EXT_SSAIA, EXT_SMCSRIND, EXT_SSCSRIND}},
{"ssaia", {EXT_SSAIA, EXT_SSCSRIND}},
{"svvptc"},
};
static const extension_combination_t extension_combinations[] = {
{'A', {EXT_ZAAMO, EXT_ZALRSC}},
{'B', {EXT_ZBA, EXT_ZBB, EXT_ZBS}},
{EXT_ZCD, {'C', 'D'}},
{EXT_ZCMOP, {EXT_ZICFISS, EXT_ZCA}},
};
static const extension_info_t* find_extension_info(const std::string& ext)
{ {
if (ext_str == "zfh") { for (const auto& info : extension_infos)
extension_table[EXT_ZFH] = true; if (ext == info.name)
add_extension("zfhmin", str); return &info;
} else if (ext_str == "zfhmin") { return nullptr;
extension_table['F'] = true; }
extension_table[EXT_ZFHMIN] = true;
} else if (ext_str == "zvfh") { static void apply_extension_combinations(std::bitset<NUM_ISA_EXTENSIONS>& extension_table)
extension_table[EXT_ZVFH] = true; {
add_extension("zvfhmin", str); for (const auto& combination : extension_combinations) {
add_extension("zfhmin", str); if (combination.components.empty())
} else if (ext_str == "zvfhmin") { continue;
extension_table[EXT_ZVFHMIN] = true; bool has_all_components = true;
add_extension("zve32f", str); for (const auto component : combination.components) {
} else if (ext_str == "zvfbfa") { has_all_components &= extension_table[component];
extension_table[EXT_ZVFBFA] = true;
add_extension("zve32f", str);
add_extension("zfbfmin", str);
} else if (ext_str == "zvfofp4min") {
extension_table[EXT_ZVFOFP4MIN] = true;
add_extension("zve32f", str);
} else if (ext_str == "zvfofp8min") {
extension_table[EXT_ZVFOFP8MIN] = true;
add_extension("zve32f", str);
} 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 == "ziccid") {
extension_table[EXT_ZICCID] = true;
} else if (ext_str == "ziccif") {
// aligned instruction fetch is always atomic in Spike
} else if (ext_str == "zaamo") {
extension_table[EXT_ZAAMO] = true;
} else if (ext_str == "zalrsc") {
extension_table[EXT_ZALRSC] = true;
} else if (ext_str == "zacas") {
extension_table[EXT_ZACAS] = true;
extension_table[EXT_ZAAMO] = true;
} else if (ext_str == "zabha") {
extension_table[EXT_ZABHA] = true;
extension_table[EXT_ZAAMO] = true;
} else if (ext_str == "zawrs") {
extension_table[EXT_ZAWRS] = true;
extension_table[EXT_ZALRSC] = true;
} else if (ext_str == "zama16b") {
extension_table[EXT_ZAMA16B] = 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['F'] = true;
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;
extension_table[EXT_ZCE] = 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['F'] = true;
extension_table[EXT_ZCA] = true;
extension_table[EXT_ZCF] = true;
} else if (ext_str == "zcb") {
extension_table[EXT_ZCB] = true;
extension_table[EXT_ZCA] = true;
} else if (ext_str == "zcd") {
extension_table[EXT_ZCD] = true;
extension_table[EXT_ZCA] = true;
extension_table['F'] = true;
extension_table['D'] = true;
} else if (ext_str == "zcmp") {
extension_table[EXT_ZCMP] = true;
extension_table[EXT_ZCA] = true;
} else if (ext_str == "zcmt") {
extension_table[EXT_ZCMT] = true;
extension_table[EXT_ZCA] = true;
} else if (ext_str == "zibi") {
extension_table[EXT_ZIBI] = 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 == "smpmpmt") {
extension_table[EXT_SMPMPMT] = 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 == "svade") {
extension_table[EXT_SVADE] = 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 == "svukte") {
if (max_xlen != 64)
bad_isa_string(str, "'svukte' requires RV64");
extension_table[EXT_SVUKTE] = 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 == "zicclsm") {
extension_table[EXT_ZICCLSM] = true;
} 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 == "zilsd") {
if (max_xlen != 32)
bad_isa_string(str, "'Zilsd' requires RV32");
extension_table[EXT_ZILSD] = true;
} else if (ext_str == "zclsd") {
if (max_xlen != 32)
bad_isa_string(str, "'Zclsd' requires RV32");
extension_table[EXT_ZCLSD] = true;
extension_table[EXT_ZCA] = true;
extension_table[EXT_ZILSD] = true;
} else if (ext_str == "zvabd") {
extension_table[EXT_ZVABD] = true;
} else if (ext_str == "zvkb") {
extension_table[EXT_ZVKB] = true;
} else if (ext_str == "zvbb") {
extension_table[EXT_ZVKB] = true;
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;
add_extension("zve32f", str);
} else if (ext_str == "zvfbfwma") {
extension_table[EXT_ZVFBFWMA] = true;
add_extension("zfbfmin", str);
add_extension("zvfbfmin", str);
} else if (ext_str == "zvkg") {
extension_table[EXT_ZVKG] = true;
} else if (ext_str == "zvkn") {
extension_table[EXT_ZVKB] = true;
extension_table[EXT_ZVKNED] = true;
extension_table[EXT_ZVKNHB] = true;
} else if (ext_str == "zvknc") {
extension_table[EXT_ZVKB] = true;
extension_table[EXT_ZVBC] = true;
extension_table[EXT_ZVKNED] = true;
extension_table[EXT_ZVKNHB] = true;
} else if (ext_str == "zvkng") {
extension_table[EXT_ZVKB] = 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_ZVKB] = true;
extension_table[EXT_ZVKSED] = true;
extension_table[EXT_ZVKSH] = true;
} else if (ext_str == "zvksc") {
extension_table[EXT_ZVKB] = true;
extension_table[EXT_ZVBC] = true;
extension_table[EXT_ZVKSED] = true;
extension_table[EXT_ZVKSH] = true;
} else if (ext_str == "zvksg") {
extension_table[EXT_ZVKB] = 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 == "zvqdotq") {
extension_table[EXT_ZVQDOTQ] = true;
} else if (ext_str == "zvqbdot8i") {
extension_table[EXT_ZVQBDOT8I] = true;
} else if (ext_str == "zvqbdot16i") {
extension_table[EXT_ZVQBDOT16I] = true;
} else if (ext_str == "zvfqbdot8f") {
extension_table[EXT_ZVFQBDOT8F] = true;
} else if (ext_str == "zvfwbdot16bf") {
extension_table[EXT_ZVFWBDOT16BF] = true;
} else if (ext_str == "zvfbdot32f") {
extension_table[EXT_ZVFBDOT32F] = true;
} else if (ext_str == "zvqldot8i") {
extension_table[EXT_ZVQLDOT8I] = true;
} else if (ext_str == "zvqldot16i") {
extension_table[EXT_ZVQLDOT16I] = true;
} else if (ext_str == "zvfqldot8f") {
extension_table[EXT_ZVFQLDOT8F] = true;
} else if (ext_str == "zvfwldot16bf") {
extension_table[EXT_ZVFWLDOT16BF] = true;
} else if (ext_str == "zvkt") {
} else if (ext_str == "zvzip") {
extension_table[EXT_ZVZIP] = true;
} else if (ext_str == "sstc") {
extension_table[EXT_SSTC] = true;
} else if (ext_str == "smcsrind") {
extension_table[EXT_SMCSRIND] = true;
} else if (ext_str == "sscsrind") {
extension_table[EXT_SSCSRIND] = true;
} else if (ext_str == "smcntrpmf") {
extension_table[EXT_SMCNTRPMF] = true;
} else if (ext_str == "smcdeleg") {
extension_table[EXT_SMCDELEG] = true;
} else if (ext_str == "ssccfg") {
extension_table[EXT_SSCCFG] = true;
} else if (ext_str == "zimop") {
extension_table[EXT_ZIMOP] = true;
} else if (ext_str == "zcmop") {
extension_table[EXT_ZCMOP] = true;
} else if (ext_str == "zalasr") {
extension_table[EXT_ZALASR] = true;
} else if (ext_str == "ssqosid") {
extension_table[EXT_SSQOSID] = true;
} else if (ext_str == "zicfilp") {
extension_table[EXT_ZICFILP] = true;
} else if (ext_str == "zicfiss") {
extension_table[EXT_ZICFISS] = true;
extension_table[EXT_ZAAMO] = true;
extension_table[EXT_ZIMOP] = true;
} else if (ext_str == "smmpm") {
extension_table[EXT_SMMPM] = true;
} else if (ext_str == "smnpm") {
extension_table[EXT_SMNPM] = true;
} else if (ext_str == "ssnpm") {
extension_table[EXT_SSNPM] = true;
} else if (ext_str.substr(0, 3) == "zvl") {
reg_t new_vlen;
try {
new_vlen = safe_stoul(ext_str.substr(3, ext_str.size() - 4));
} catch (std::logic_error& e) {
new_vlen = 0;
} }
if ((new_vlen & (new_vlen - 1)) != 0 || new_vlen < 32 || ext_str.back() != 'b') if (has_all_components)
bad_isa_string(str, ("Invalid Zvl string: " + ext_str).c_str()); extension_table[combination.enable] = true;
vlen = std::max(vlen, new_vlen);
} else if (ext_str.substr(0, 3) == "zve") {
if (ext_str.size() != 6) {
bad_isa_string(str, ("Invalid Zve string: " + ext_str).c_str());
} }
}
} // namespace
void isa_parser_t::apply_zve_properties(const std::string& ext_str, const char* str)
{
if (ext_str.size() != 6)
bad_isa_string(str, ("Invalid Zve string: " + ext_str).c_str());
reg_t new_elen; reg_t new_elen;
try { try {
new_elen = safe_stoul(ext_str.substr(3, ext_str.size() - 4)); new_elen = safe_stoul(ext_str.substr(3, ext_str.size() - 4));
} catch (std::logic_error& e) { } catch (std::logic_error& e) {
new_elen = 0; new_elen = 0;
} }
if (ext_str.substr(5) == "d") {
switch (ext_str.back()) {
case 'd':
zvd |= true; zvd |= true;
[[fallthrough]];
case 'f':
zvf |= true; zvf |= true;
extension_table['F'] = true; break;
extension_table['D'] = true; case 'x':
} else if (ext_str.substr(5) == "f") { break;
zvf |= true; default:
extension_table['F'] = true;
} else if (ext_str.substr(5) == "x") {
/* do nothing */
} else {
new_elen = 0; new_elen = 0;
} }
if (new_elen != 32 && new_elen != 64) if (new_elen != 32 && new_elen != 64)
bad_isa_string(str, ("Invalid Zve string: " + ext_str).c_str()); bad_isa_string(str, ("Invalid Zve string: " + ext_str).c_str());
elen = std::max(elen, new_elen); elen = std::max(elen, new_elen);
vlen = std::max(vlen, new_elen); vlen = std::max(vlen, new_elen);
} else if (ext_str == "ssdbltrp") { }
extension_table[EXT_SSDBLTRP] = true;
} else if (ext_str == "smdbltrp") { void isa_parser_t::add_extension(const std::string& ext_str, const char* str)
extension_table[EXT_SMDBLTRP] = true; {
} else if (ext_str == "smaia") { if (const auto* info = find_extension_info(ext_str)) {
extension_table[EXT_SMAIA] = true; for (const auto ext : info->enables) {
extension_table[EXT_SSAIA] = true; extension_table[ext] = true;
extension_table[EXT_SMCSRIND] = true; }
extension_table[EXT_SSCSRIND] = true; for (const auto implied : info->implies) {
} else if (ext_str == "ssaia") { add_extension(implied, str);
extension_table[EXT_SSAIA] = true; }
extension_table[EXT_SSCSRIND] = true; if (ext_str.substr(0, 3) == "zve")
} else if (ext_str == "svvptc") { apply_zve_properties(ext_str, str);
} else if (ext_str[0] == 'x') { } else if (ext_str.substr(0, 3) == "zvl") {
reg_t new_vlen;
try {
new_vlen = safe_stoul(ext_str.substr(3, ext_str.size() - 4));
} catch (std::logic_error& e) {
new_vlen = 0;
}
if ((new_vlen & (new_vlen - 1)) != 0 || new_vlen < 32 || ext_str.back() != 'b')
bad_isa_string(str, ("Invalid Zvl string: " + ext_str).c_str());
vlen = std::max(vlen, new_vlen);
} else if (!ext_str.empty() && ext_str[0] == 'x') {
extension_table['X'] = true; extension_table['X'] = true;
if (ext_str.size() == 1) { if (ext_str.size() == 1) {
bad_isa_string(str, "single 'X' is not a proper name"); bad_isa_string(str, "single 'X' is not a proper name");
@ -436,23 +333,14 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
zvf = false; zvf = false;
zvd = false; zvd = false;
switch (isa_string[4]) { if (isa_string[4] == 'g') {
case 'g':
// G = IMAFD_Zicsr_Zifencei, but Spike includes the latter two // G = IMAFD_Zicsr_Zifencei, but Spike includes the latter two
// unconditionally, so they need not be explicitly added here. // unconditionally, so they need not be explicitly added here.
isa_string = isa_string.substr(0, 4) + "imafd" + isa_string.substr(5); isa_string = isa_string.substr(0, 4) + "imafd" + isa_string.substr(5);
[[fallthrough]]; } else if (isa_string[4] != 'i' && isa_string[4] != 'e') {
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()); bad_isa_string(str, ("'" + isa_string.substr(0, 4) + "' must be followed by I, E, or G").c_str());
} }
add_extension(std::string(1, isa_string[4]), str);
const char* isa_str = isa_string.c_str(); const char* isa_str = isa_string.c_str();
auto p = isa_str, subset = all_subsets; auto p = isa_str, subset = all_subsets;
@ -467,14 +355,7 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
bad_isa_string(str, ("Unsupported extension '" + std::string(1, *p) + "'").c_str()); bad_isa_string(str, ("Unsupported extension '" + std::string(1, *p) + "'").c_str());
} }
switch (*p) { add_extension(std::string(1, *p), str);
case 'v': add_extension("zve64d", str); vlen = 128;
[[fallthrough]];
case 'q': extension_table['D'] = true;
[[fallthrough]];
case 'd': extension_table['F'] = true;
}
extension_table[toupper(*p)] = true;
while (isdigit(*(p + 1))) { while (isdigit(*(p + 1))) {
++p; // skip major version, point, and minor version if presented ++p; // skip major version, point, and minor version if presented
if (*(p + 1) == 'p') ++p; if (*(p + 1) == 'p') ++p;
@ -494,25 +375,10 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
bad_isa_string(str, ("can't parse: " + std::string(p)).c_str()); bad_isa_string(str, ("can't parse: " + std::string(p)).c_str());
} }
if (extension_table['A']) { apply_extension_combinations(extension_table);
extension_table[EXT_ZAAMO] = true;
extension_table[EXT_ZALRSC] = true;
} else if (extension_table[EXT_ZAAMO] && extension_table[EXT_ZALRSC]) {
extension_table['A'] = true;
}
if (extension_table['B']) {
extension_table[EXT_ZBA] = true;
extension_table[EXT_ZBB] = true;
extension_table[EXT_ZBS] = true;
} else if (extension_table[EXT_ZBA] && extension_table[EXT_ZBB] && extension_table[EXT_ZBS]) {
extension_table['B'] = true;
}
if (extension_table['C']) { if (extension_table[EXT_ZFBFMIN] || extension_table[EXT_ZFHMIN]) {
extension_table[EXT_ZCA] = true; extension_table[EXT_INTERNAL_ZFH_MOVE] = true;
if (extension_table['D'])
extension_table[EXT_ZCD] = true;
} }
if (extension_table['C'] || extension_table[EXT_ZCE]) { if (extension_table['C'] || extension_table[EXT_ZCE]) {
@ -520,11 +386,20 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
extension_table[EXT_ZCF] = true; extension_table[EXT_ZCF] = true;
} }
if (extension_table[EXT_ZICFISS] && extension_table[EXT_ZCA]) if (extension_table[EXT_ZCF] && max_xlen != 32) {
extension_table[EXT_ZCMOP] = true; bad_isa_string(str, "'Zcf' requires RV32");
}
if (extension_table[EXT_ZFBFMIN] || extension_table[EXT_ZFHMIN]) { if (extension_table[EXT_ZCLSD] && max_xlen != 32) {
extension_table[EXT_INTERNAL_ZFH_MOVE] = true; bad_isa_string(str, "'Zclsd' requires RV32");
}
if (extension_table[EXT_ZILSD] && max_xlen != 32) {
bad_isa_string(str, "'Zilsd' requires RV32");
}
if (extension_table[EXT_SVUKTE] && max_xlen != 64) {
bad_isa_string(str, "'svukte' requires RV64");
} }
if (extension_table[EXT_ZCLSD] && extension_table[EXT_ZCF]) { if (extension_table[EXT_ZCLSD] && extension_table[EXT_ZCF]) {

1
riscv/isa_parser.h

@ -159,6 +159,7 @@ protected:
private: private:
void add_extension(const std::string&, const char*); void add_extension(const std::string&, const char*);
void apply_zve_properties(const std::string&, const char*);
}; };
#endif #endif

Loading…
Cancel
Save