|
|
|
@ -28,18 +28,16 @@ static void bad_priv_string(const char* priv) |
|
|
|
} |
|
|
|
|
|
|
|
isa_parser_t::isa_parser_t(const char* str, const char *priv) |
|
|
|
: extension_table(256, false) |
|
|
|
{ |
|
|
|
isa_string = strtolower(str); |
|
|
|
const char* all_subsets = "mafdqchpv"; |
|
|
|
|
|
|
|
max_isa = reg_t(2) << 62; |
|
|
|
// enable zicntr and zihpm unconditionally for backward compatibility
|
|
|
|
extension_table[EXT_ZICNTR] = true; |
|
|
|
extension_table[EXT_ZIHPM] = true; |
|
|
|
|
|
|
|
if (isa_string.compare(0, 4, "rv32") == 0) |
|
|
|
max_xlen = 32, max_isa = reg_t(1) << 30; |
|
|
|
max_xlen = 32; |
|
|
|
else if (isa_string.compare(0, 4, "rv64") == 0) |
|
|
|
max_xlen = 64; |
|
|
|
else |
|
|
|
@ -52,11 +50,11 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) |
|
|
|
isa_string = isa_string.substr(0, 4) + "imafd" + isa_string.substr(5); |
|
|
|
// Fall through
|
|
|
|
case 'i': |
|
|
|
max_isa |= 1L << ('i' - 'a'); |
|
|
|
extension_table['I'] = true; |
|
|
|
break; |
|
|
|
|
|
|
|
case 'e': |
|
|
|
max_isa |= 1L << ('e' - 'a'); |
|
|
|
extension_table['E'] = true; |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
@ -82,11 +80,10 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) |
|
|
|
extension_table[EXT_ZPSFOPERAND] = true; |
|
|
|
extension_table[EXT_ZMMUL] = true; break; |
|
|
|
case 'v': // even rv32iv implies double float
|
|
|
|
case 'q': max_isa |= 1L << ('d' - 'a'); |
|
|
|
case 'q': extension_table['D'] = true; |
|
|
|
// Fall through
|
|
|
|
case 'd': max_isa |= 1L << ('f' - 'a'); |
|
|
|
case 'd': extension_table['F'] = true; |
|
|
|
} |
|
|
|
max_isa |= 1L << (*p - 'a'); |
|
|
|
extension_table[toupper(*p)] = true; |
|
|
|
while (isdigit(*(p + 1))) { |
|
|
|
++p; // skip major version, point, and minor version if presented
|
|
|
|
@ -101,13 +98,13 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) |
|
|
|
do ++end; while (*end && *end != '_'); |
|
|
|
auto ext_str = std::string(p, end); |
|
|
|
if (ext_str == "zfh" || ext_str == "zfhmin") { |
|
|
|
if (!((max_isa >> ('f' - 'a')) & 1)) |
|
|
|
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 (!((max_isa >> ('v' - 'a')) & 1)) |
|
|
|
if (!extension_table['V']) |
|
|
|
bad_isa_string(str, ("'" + ext_str + "' extension requires 'V'").c_str()); |
|
|
|
|
|
|
|
extension_table[EXT_ZVFHMIN] = true; |
|
|
|
@ -225,8 +222,7 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) |
|
|
|
} else if (ext_str == "sstc") { |
|
|
|
extension_table[EXT_SSTC] = true; |
|
|
|
} else if (ext_str[0] == 'x') { |
|
|
|
max_isa |= 1L << ('x' - 'a'); |
|
|
|
extension_table[toupper('x')] = true; |
|
|
|
extension_table['X'] = true; |
|
|
|
if (ext_str == "xbitmanip") { |
|
|
|
extension_table[EXT_XZBP] = true; |
|
|
|
extension_table[EXT_XZBS] = true; |
|
|
|
@ -278,7 +274,7 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) |
|
|
|
extension_table[EXT_ZCD] = true; |
|
|
|
} |
|
|
|
|
|
|
|
if (extension_table[EXT_ZFINX] && ((max_isa >> ('f' - 'a')) & 1)) { |
|
|
|
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")); |
|
|
|
} |
|
|
|
|
|
|
|
@ -311,16 +307,15 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) |
|
|
|
else |
|
|
|
bad_priv_string(priv); |
|
|
|
|
|
|
|
if (user) { |
|
|
|
max_isa |= reg_t(user) << ('u' - 'a'); |
|
|
|
extension_table['U'] = true; |
|
|
|
} |
|
|
|
|
|
|
|
if (supervisor) { |
|
|
|
max_isa |= reg_t(supervisor) << ('s' - 'a'); |
|
|
|
extension_table['S'] = true; |
|
|
|
} |
|
|
|
extension_table['U'] = user; |
|
|
|
extension_table['S'] = supervisor; |
|
|
|
|
|
|
|
if (((max_isa >> ('h' - 'a')) & 1) && !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'); |
|
|
|
} |
|
|
|
} |
|
|
|
|