diff --git a/src/riscv/riscv.c b/src/riscv/riscv.c index a069916..6d7bf83 100644 --- a/src/riscv/riscv.c +++ b/src/riscv/riscv.c @@ -28,6 +28,27 @@ int64_t get_peak_performance(struct cpuInfo* cpu) { return flops; } +// Returns the length of the multi-letter +// extension, or -1 if an error occurs +int parse_multi_letter_extension(struct extensions* ext, char* e) { + if(*e != '_') return -1; + char* multi_letter_extension_end = strstr(e+1, "_"); + if(multi_letter_extension_end == NULL) { + // This is the last extension, find the end + // of the string + multi_letter_extension_end = e + strlen(e); + } + + int multi_letter_extension_len = multi_letter_extension_end-(e+1); + + // TODO: Parse extension and fill ext struct + char* multi_letter_extension = emalloc(multi_letter_extension_len); + strncpy(multi_letter_extension, e+1, multi_letter_extension_len); + printWarn("Not parsed multi-letter extension: %s", multi_letter_extension); + + return multi_letter_extension_len; +} + struct extensions* get_extensions_from_str(char* str) { struct extensions* ext = emalloc(sizeof(struct extensions)); ext->mask = 0; @@ -42,7 +63,7 @@ struct extensions* get_extensions_from_str(char* str) { memset(ext->str, 0, len); strncpy(ext->str, str, sizeof(char) * len); - // Code inspired in Linux kernel: + // Code inspired in Linux kernel (riscv_fill_hwcap): // https://elixir.bootlin.com/linux/v6.2.10/source/arch/riscv/kernel/cpufeature.c char* isa = str; if (!strncmp(isa, "rv32", 4)) @@ -55,8 +76,18 @@ struct extensions* get_extensions_from_str(char* str) { } for(char* e = isa; *e != '\0'; e++) { - int n = *e - 'a'; - ext->mask |= 1UL << n; + if(*e == '_') { + // Multi-letter extension + int multi_letter_extension_len = parse_multi_letter_extension(ext, e); + if(multi_letter_extension_len == -1) { + return ext; + } + e += multi_letter_extension_len; + } + else { + int n = *e - 'a'; + ext->mask |= 1UL << n; + } } return ext;