#ifndef __RISCV__
#define __RISCV__

#include "../common/cpu.h"

struct extension {
  int id;
  char* str;
};

#define RISCV_ISA_EXT_NAME_LEN_MAX 32
#define RISCV_ISA_EXT_BASE         26

// https://elixir.bootlin.com/linux/latest/source/arch/riscv/include/asm/hwcap.h
// This enum represent the logical ID for multi-letter RISC-V ISA extensions.
// The logical ID should start from RISCV_ISA_EXT_BASE
enum riscv_isa_ext_id {
  RISCV_ISA_EXT_SSCOFPMF = RISCV_ISA_EXT_BASE,
  RISCV_ISA_EXT_SSTC,
  RISCV_ISA_EXT_SVINVAL,
  RISCV_ISA_EXT_SVPBMT,
  RISCV_ISA_EXT_ZBB,
  RISCV_ISA_EXT_ZICBOM,
  RISCV_ISA_EXT_ZIHINTPAUSE,
  RISCV_ISA_EXT_SVNAPOT,
  RISCV_ISA_EXT_ZICBOZ,
  RISCV_ISA_EXT_SMAIA,
  RISCV_ISA_EXT_SSAIA,
  RISCV_ISA_EXT_ZBA,
  RISCV_ISA_EXT_ZBS,
  RISCV_ISA_EXT_ZICNTR,
  RISCV_ISA_EXT_ZICSR,
  RISCV_ISA_EXT_ZIFENCEI,
  RISCV_ISA_EXT_ZIHPM,
  RISCV_ISA_EXT_SMSTATEEN,
  RISCV_ISA_EXT_ZICOND,
  RISCV_ISA_EXT_ZBC,
  RISCV_ISA_EXT_ZBKB,
  RISCV_ISA_EXT_ZBKC,
  RISCV_ISA_EXT_ZBKX,
  RISCV_ISA_EXT_ZKND,
  RISCV_ISA_EXT_ZKNE,
  RISCV_ISA_EXT_ZKNH,
  RISCV_ISA_EXT_ZKR,
  RISCV_ISA_EXT_ZKSED,
  RISCV_ISA_EXT_ZKSH,
  RISCV_ISA_EXT_ZKT,
  RISCV_ISA_EXT_ZVBB,
  RISCV_ISA_EXT_ZVBC,
  RISCV_ISA_EXT_ZVKB,
  RISCV_ISA_EXT_ZVKG,
  RISCV_ISA_EXT_ZVKNED,
  RISCV_ISA_EXT_ZVKNHA,
  RISCV_ISA_EXT_ZVKNHB,
  RISCV_ISA_EXT_ZVKSED,
  RISCV_ISA_EXT_ZVKSH,
  RISCV_ISA_EXT_ZVKT,
  RISCV_ISA_EXT_ZFH,
  RISCV_ISA_EXT_ZFHMIN,
  RISCV_ISA_EXT_ZIHINTNTL,
  RISCV_ISA_EXT_ZVFH,
  RISCV_ISA_EXT_ZVFHMIN,
  RISCV_ISA_EXT_ZFA,
  RISCV_ISA_EXT_ZTSO,
  RISCV_ISA_EXT_ZACAS,
  RISCV_ISA_EXT_ZVE32X,
  RISCV_ISA_EXT_ZVE32F,
  RISCV_ISA_EXT_ZVE64X,
  RISCV_ISA_EXT_ZVE64F,
  RISCV_ISA_EXT_ZVE64D,
  RISCV_ISA_EXT_ZIMOP,
  RISCV_ISA_EXT_ZCA,
  RISCV_ISA_EXT_ZCB,
  RISCV_ISA_EXT_ZCD,
  RISCV_ISA_EXT_ZCF,
  RISCV_ISA_EXT_ZCMOP,
  RISCV_ISA_EXT_ZAWRS,
  RISCV_ISA_EXT_SVVPTC,
  RISCV_ISA_EXT_SMMPM,
  RISCV_ISA_EXT_SMNPM,
  RISCV_ISA_EXT_SSNPM,
  RISCV_ISA_EXT_ZABHA,
  RISCV_ISA_EXT_ZICCRSE,
  RISCV_ISA_EXT_SVADE,
  RISCV_ISA_EXT_SVADU,
  RISCV_ISA_EXT_ZFBFMIN,
  RISCV_ISA_EXT_ZVFBFMIN,
  RISCV_ISA_EXT_ZVFBFWMA,
  RISCV_ISA_EXT_ZAAMO,
  RISCV_ISA_EXT_ZALRSC,
  RISCV_ISA_EXT_ZICBOP,
  RISCV_ISA_EXT_IME,      // This is not in the kernel! but it was seen on a Muse Pi Pro board
  RISCV_ISA_EXT_ID_MAX
};

// https://five-embeddev.com/riscv-isa-manual/latest/preface.html#preface
// https://en.wikichip.org/wiki/risc-v/standard_extensions
// (Zicbop) https://github.com/riscv/riscv-CMOs/blob/master/cmobase/Zicbop.adoc
// https://raw.githubusercontent.com/riscv/riscv-CMOs/master/specifications/cmobase-v1.0.1.pdf
// https://www.kernel.org/doc/Documentation/devicetree/bindings/riscv/extensions.yaml
// https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Options.html
// (Ime) https://github.com/riscv/integrated-matrix-extension (not confirmed, just a guess...)
// Included all except for G
static const struct extension extension_list[] = {
  { 'i' - 'a', "(I) Integer Instruction Set" },
  { 'm' - 'a', "(M) Integer Multiplication and Division" },
  { 'a' - 'a', "(A) Atomic Instructions" },
  { 'f' - 'a', "(F) Single-Precision Floating-Point" },
  { 'd' - 'a', "(D) Double-Precision Floating-Point" },
  { 'q' - 'a', "(Q) Quad-Precision Floating-Point" },
  { 'l' - 'a', "(L) Decimal Floating-Point" },
  { 'c' - 'a', "(C) Compressed Instructions" },
  { 'b' - 'a', "(B) Double-Precision Floating-Point" },
  { 'j' - 'a', "(J) Dynamically Translated Languages" },
  { 't' - 'a', "(T) Transactional Memory" },
  { 'p' - 'a', "(P) Packed-SIMD Instructions" },
  { 'v' - 'a', "(V) Vector Operations" },
  { 'n' - 'a', "(N) User-Level Interrupts" },
  { 'h' - 'a', "(H) Hypervisor" },
  // multi-letter extensions
  { RISCV_ISA_EXT_SSCOFPMF,    "(Sscofpmf) Count OverFlow and Privilege Mode Filtering" },
  { RISCV_ISA_EXT_SSTC,        "(Sstc) S and VS level Time Compare" },
  { RISCV_ISA_EXT_SVINVAL,     "(Svinval) Fast TLB Invalidation" },
  { RISCV_ISA_EXT_SVPBMT,      "(Svpbmt) Page-based Memory Types" },
  { RISCV_ISA_EXT_ZBB,         "(Zbb) Basic bit-manipulation" },
  { RISCV_ISA_EXT_ZICBOM,      "(Zicbom) Cache Block Management Operations" },
  { RISCV_ISA_EXT_ZIHINTPAUSE, "(Zihintpause) Pause Hint" },
  { RISCV_ISA_EXT_SVNAPOT,     "(Svnapot) Naturally Aligned Power of Two Pages" },
  { RISCV_ISA_EXT_ZICBOZ,      "(Zicboz) Cache Block Zero Operations" },
  { RISCV_ISA_EXT_ZICBOP,      "(Zicbop) Cache Block Prefetch Operations" },
  { RISCV_ISA_EXT_SMAIA,       "(Smaia) Advanced Interrupt Architecture" },
  { RISCV_ISA_EXT_SSAIA,       "(Ssaia) Advanced Interrupt Architecture" },
  { RISCV_ISA_EXT_ZBA,         "(Zba) Address Generation" },
  { RISCV_ISA_EXT_ZBS,         "(Zbs) Single-bit Instructions" },
  { RISCV_ISA_EXT_ZICNTR,      "(Zicntr) Base Counters and Timers" },
  { RISCV_ISA_EXT_ZICSR,       "(Zicsr) Control and Status Register" },
  { RISCV_ISA_EXT_ZIFENCEI,    "(Zifencei) Instruction-Fetch Fence" },
  { RISCV_ISA_EXT_ZIHPM,       "(Zihpm) Hardware Performance Counters" },
  { RISCV_ISA_EXT_SMSTATEEN,   "(Smstateen) Supervisor/Hypervisor State Enable" },
  { RISCV_ISA_EXT_ZICOND,      "(Zicond) Integer Conditional Operations" },
  { RISCV_ISA_EXT_ZBC,         "(Zbc) Carry-Less Multiplication" },
  { RISCV_ISA_EXT_ZBKB,        "(Zbkb) Bit-Manipulation for Cryptography (Byte ops)" },
  { RISCV_ISA_EXT_ZBKC,        "(Zbkc) Bit-Manipulation for Cryptography (Carry-less ops)" },
  { RISCV_ISA_EXT_ZBKX,        "(Zbkx) Bit-Manipulation for Cryptography (Crossbar ops)" },
  { RISCV_ISA_EXT_ZKND,        "(Zknd) NIST AES Decryption Instructions" },
  { RISCV_ISA_EXT_ZKNE,        "(Zkne) NIST AES Encryption Instructions" },
  { RISCV_ISA_EXT_ZKNH,        "(Zknh) NIST Hash (SHA-2/SHA-3) Instructions" },
  { RISCV_ISA_EXT_ZKR,         "(Zkr) Entropy Source Reading (Random)" },
  { RISCV_ISA_EXT_ZKSED,       "(Zksed) SM4 Block Cipher Decryption" },
  { RISCV_ISA_EXT_ZKSH,        "(Zksh) SM3 Hash Instructions" },
  { RISCV_ISA_EXT_ZKT,         "(Zkt) Data-Independent Execution Latency" },
  { RISCV_ISA_EXT_ZVBB,        "(Zvbb) Vector Basic Bit-Manipulation" },
  { RISCV_ISA_EXT_ZVBC,        "(Zvbc) Vector Carry-Less Multiplication" },
  { RISCV_ISA_EXT_ZVKB,        "(Zvkb) Vector Cryptography (Byte ops)" },
  { RISCV_ISA_EXT_ZVKG,        "(Zvkg) Vector GCM/GMAC Instructions" },
  { RISCV_ISA_EXT_ZVKNED,      "(Zvkned) Vector AES Decryption" },
  { RISCV_ISA_EXT_ZVKNHA,      "(Zvknha) Vector SHA-2 Hash (A variant)" },
  { RISCV_ISA_EXT_ZVKNHB,      "(Zvknhb) Vector SHA-2 Hash (B variant)" },
  { RISCV_ISA_EXT_ZVKSED,      "(Zvksed) Vector SM4 Block Cipher Decryption" },
  { RISCV_ISA_EXT_ZVKSH,       "(Zvksh) Vector SM3 Hash Instructions" },
  { RISCV_ISA_EXT_ZVKT,        "(Zvkt) Vector Data-Independent Execution Latency" },
  { RISCV_ISA_EXT_ZFH,         "(Zfh) Half-Precision Floating Point" },
  { RISCV_ISA_EXT_ZFHMIN,      "(Zfhmin) Minimal Half-Precision Floating Point" },
  { RISCV_ISA_EXT_ZIHINTNTL,   "(Zihintntl) Non-Temporal Load/Store Hints" },
  { RISCV_ISA_EXT_ZVFH,        "(Zvfh) Vector Half-Precision Floating Point" },
  { RISCV_ISA_EXT_ZVFHMIN,     "(Zvfhmin) Minimal Vector Half-Precision Floating Point" },
  { RISCV_ISA_EXT_ZFA,         "(Zfa) Additional Floating-Point Instructions" },
  { RISCV_ISA_EXT_ZTSO,        "(Ztso) Total Store Ordering Memory Model" },
  { RISCV_ISA_EXT_ZACAS,       "(Zacas) Atomic Compare-and-Swap" },
  { RISCV_ISA_EXT_ZVE32X,      "(Zve32x) Embedded Vector Integer (32-bit elements)" },
  { RISCV_ISA_EXT_ZVE32F,      "(Zve32f) Embedded Vector Floating Point (f32)" },
  { RISCV_ISA_EXT_ZVE64X,      "(Zve64x) Embedded Vector Integer (64-bit elements)" },
  { RISCV_ISA_EXT_ZVE64F,      "(Zve64f) Embedded Vector Floating Point (f64)" },
  { RISCV_ISA_EXT_ZVE64D,      "(Zve64d) Embedded Vector Double-Precision FP (f64)" },
  { RISCV_ISA_EXT_ZIMOP,       "(Zimop) Integer Multiply-Only Instructions" },
  { RISCV_ISA_EXT_ZCA,         "(Zca) Compressed Integer Instructions" },
  { RISCV_ISA_EXT_ZCB,         "(Zcb) Compressed Bit-Manipulation Instructions" },
  { RISCV_ISA_EXT_ZCD,         "(Zcd) Compressed Double-Precision FP Instructions" },
  { RISCV_ISA_EXT_ZCF,         "(Zcf) Compressed Single-Precision FP Instructions" },
  { RISCV_ISA_EXT_ZCMOP,       "(Zcmop) Compressed Multiply-Only Instructions" },
  { RISCV_ISA_EXT_ZAWRS,       "(Zawrs) Wait-on-Reservation-Set Instruction" },
  { RISCV_ISA_EXT_SVVPTC,      "(Svvptc) Supervisor Virtual Page Table Cache Control" },
  { RISCV_ISA_EXT_SMMPM,       "(Smmpm) Supervisor Memory Protection Modification" },
  { RISCV_ISA_EXT_SMNPM,       "(Smnpm) Supervisor Non-Privileged Memory Access Control" },
  { RISCV_ISA_EXT_SSNPM,       "(Ssnpm) Supervisor Secure Non-Privileged Memory" },
  { RISCV_ISA_EXT_ZABHA,       "(Zabha) Atomic Byte/Halfword Operations" },
  { RISCV_ISA_EXT_ZICCRSE,     "(Ziccrse) Cache Control Range Start/End Operations" },
  { RISCV_ISA_EXT_SVADE,       "(Svade) Supervisor Virtual Address Deferred Exception" },
  { RISCV_ISA_EXT_SVADU,       "(Svadu) Supervisor Virtual Address Dirty Update" },
  { RISCV_ISA_EXT_ZFBFMIN,     "(Zfbfmin) Minimal BFloat16 Floating Point" },
  { RISCV_ISA_EXT_ZVFBFMIN,    "(Zvfbfmin) Vector Minimal BFloat16 Floating Point" },
  { RISCV_ISA_EXT_ZVFBFWMA,    "(Zvfbfwma) Vector BFloat16 Widening Multiply-Accumulate" },
  { RISCV_ISA_EXT_ZAAMO,       "(Zaamo) Atomic Memory Operation (AMO) Instructions" },
  { RISCV_ISA_EXT_ZALRSC,      "(Zalrsc) Atomic Load-Reserved/Store-Conditional" },
  { RISCV_ISA_EXT_ZICBOP,      "(Zicbop) Cache Block Prefetch/Zero Operations" },
  { RISCV_ISA_EXT_IME,         "(Ime) Integrated Matrix Extension" },
};

struct cpuInfo* get_cpu_info(void);
char* get_str_topology(struct cpuInfo* cpu, struct topology* topo);
char* get_str_extensions(struct cpuInfo* cpu);
uint32_t get_num_extensions(bool* mask);
void print_debug(struct cpuInfo* cpu);

#endif
