pub mod machine;
pub mod decode;
pub mod print;
pub mod mem_cmp;
pub mod loader;
pub mod interrupt;

pub mod global {

    #![allow(dead_code)]
    #![allow(unused_variables)]
    // Instructions type:
    // - R: Register / register
    // - I: Immediate
    // - U: Upper-Immediate
    // - S: Store
    // - B: Branch (conditional branches...)
    // - J: Jump

    // xlen = i64::MAX_VALUE on rv64 and i32::MAX_VALUE on rv32

    /// Type: U
    /// 
    /// Load upper immediate
    /// 
    /// `LUI rd, imm31_12` => `rd <- imm31_12 << 12`
    /// 
    pub const RISCV_LUI: u8 = 0x37;
    /// Type: U
    /// 
    /// Add upper immediate to PC
    /// 
    /// `AUIP rd, imm31_12` => `rd <- PC + imm31_12 << 12`
    pub const RISCV_AUIPC: u8 = 0x17;
    /// Type: J
    /// 
    /// Jump and link
    /// 
    /// `JAL rd, imm20(rs1)` => `rd <- pc + 4; pc <- rs1 + imm12`
    pub const RISCV_JAL: u8 = 0x6f;
    /// type: J
    /// 
    /// Jump and link register
    /// 
    /// `JALR rd, imm12(rs1)` => `rd <- pc + 4; pc <- rs1 + imm12`
    pub const RISCV_JALR: u8 = 0x67;
    pub const RISCV_BR: u8 = 0x63;

    /// Load instructions
    /// 
    /// See func3 to know the type of instruction (LD, LW, LH, LB, LWU, LHU, LBU)
    pub const RISCV_LD: u8 = 0x3;
    // Store instructions
    pub const RISCV_ST: u8 = 0x23;
    // immediate Arithmetic operations
    pub const RISCV_OPI: u8 = 0x13;
    // Arithmetic operations
    pub const RISCV_OP: u8 = 0x33;
    /// Immediate arithmetic operations for rv64i
    pub const RISCV_OPIW: u8 = 0x1b;
    // Arithmetic operations for rv64i
    pub const RISCV_OPW: u8 = 0x3b;

    /// Type: B
    /// 
    /// Branch equal
    /// 
    /// `BEQ rs1, rs2, imm12` => `if rs1 = rs2 then pc <- pc + imm12`
    pub const RISCV_BR_BEQ: u8 = 0x0;
    /// Type: B
    /// 
    /// Branch not equal
    /// 
    /// `BNE rs1, rs2, imm12` => `if rs1 != rs2 then pc <- pc + imm12`
    pub const RISCV_BR_BNE: u8 = 0x1;
    /// Type: B
    /// 
    /// Branch less than
    /// 
    /// `BLT rs1, rs2, imm12` => `if rs1 < rs2 then pc <- pc + imm12`
    pub const RISCV_BR_BLT: u8 = 0x4;
    /// Type: B
    /// 
    /// Branch greater than or equal
    /// 
    /// `BGE rs1, rs2, imm12` => `if rs1 >= rs2 then pc <- pc + imm12`
    pub const RISCV_BR_BGE: u8 = 0x5;
    /// Type: B
    /// 
    /// Branch less than unsigned
    /// 
    /// Same as BLT but for unsigned values
    pub const RISCV_BR_BLTU: u8 = 0x6;
    /// Type: B
    /// 
    /// Greater than or equal unsigned
    /// 
    /// Same as BGE but for unsigned values
    pub const RISCV_BR_BGEU: u8 = 0x7;

    /// Type: I
    /// 
    /// Load byte (8 bits word)
    /// 
    /// `LB rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
    pub const RISCV_LD_LB: u8 = 0x0;
    /// Type: I
    /// 
    /// Load halfword (16 bits word)
    /// 
    /// `LH rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
    pub const RISCV_LD_LH: u8 = 0x1;
    /// Type: I
    /// 
    /// Load word (32 bits word)
    /// 
    /// `LW rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
    pub const RISCV_LD_LW: u8 = 0x2;
    /// Type: I
    /// 
    /// Load doubleword (64-bits word)
    /// 
    /// `LD rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
    pub const RISCV_LD_LD: u8 = 0x3;
    /// Type: I
    /// 
    /// Load byte unsigned
    /// 
    /// `LBU rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
    pub const RISCV_LD_LBU: u8 = 0x4;
    /// Type: I
    /// 
    /// Load halfword unsigned
    /// 
    /// `LHU rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
    pub const RISCV_LD_LHU: u8 = 0x5;
    /// Type: I
    /// 
    /// Load word unsigned (64 bits word)
    /// 
    /// `LW rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
    pub const RISCV_LD_LWU: u8 = 0x6;

    /// Type: S
    /// 
    /// Store halfword (SH) (16 bits)
    /// 
    /// In case of overflow (rs2 is a 64 bits reg), only the first 16 bits values are stored
    /// 
    /// `SH rs2, imm12(rs1)` => `rs2 -> mem[rs1 + imm12]`
    pub const RISCV_ST_STH: u8 = 0x1;
    /// Type: S
    /// 
    /// Store word (SW) (32 bits)
    /// 
    /// In case of overflow (rs2 is a 64 bits reg), only the first 32 bits values are stored
    /// 
    /// `SW rs2, imm12(rs1)` => `rs2 -> mem[rs1 + imm12]`
    pub const RISCV_ST_STW: u8 = 0x2;
    /// Type: S
    /// 
    /// Store byte (SB) (8 bits)
    /// 
    /// In case of overflow (rs2 is a 64 bits reg), only the first 8 bits values are stored
    /// 
    /// `SB rs2, imm12(rs1)` => `rs2 -> mem[rs1 + imm12]`
    pub const RISCV_ST_STB: u8 = 0x0;
    /// Type: S
    /// 
    /// Store doubleword (SD) (64 bits)
    /// 
    /// `SD rs2, imm12(rs1)` => `rs2 -> mem[rs1 + imm12]`
    pub const RISCV_ST_STD: u8 = 0x3;

    /// Type: I
    /// 
    /// Add immediate
    /// 
    /// `addi rd, rs1, imm12` => `rd <- rs1 + imm12`
    pub const RISCV_OPI_ADDI: u8 = 0x0;
    /// Type: I
    /// 
    /// Set less than immediate: set rd to 1 if rs1 < imm12, 0 otherwise
    /// 
    /// `SLT rd, rs1, imm12` => `rd <- rs1 < imm12 ? 1 : 0`
    pub const RISCV_OPI_SLTI: u8 = 0x2;
    /// Type: I
    /// 
    /// Set less than immediate unsigned : same than SLTI but for unsigned values
    pub const RISCV_OPI_SLTIU: u8 = 0x3;
    /// Type: I
    /// 
    /// XOR immediate instruction
    /// 
    /// `XORI rd, rs1, imm12` => `rd <- rs1 ^ imm12`
    pub const RISCV_OPI_XORI: u8 = 0x4;
    /// Type: I
    /// 
    /// OR immediate instruction
    /// 
    /// `ORI rd, rs1, imm12` => `rd <- rs1 | imm12`
    pub const RISCV_OPI_ORI: u8 = 0x6;
    /// Type: I
    /// 
    /// AND immediate instruction
    /// 
    /// `ANDI rd, rs1, imm12` => `rd <- rs1 & imm12`
    pub const RISCV_OPI_ANDI: u8 = 0x7;
    /// Type: I
    /// 
    /// Shift left logical immediate
    /// 
    /// `SLLI rd, rs1, shamt` => `rd <- rs1 >> shamt`
    pub const RISCV_OPI_SLLI: u8 = 0x1;
    /// Shift right immediate, may be SRAI or SRLI
    pub const RISCV_OPI_SRI: u8 = 0x5;
    /// type: I
    /// 
    /// Shift right arithmetic immediate
    /// 
    /// `SRAI rd, rs1, shamt` => `rd <- rs1 >> shamt`
    pub const RISCV_OPI_SRI_SRAI: u8 = 0x20;
    /// type: I
    /// 
    /// Shift right logical immediate
    /// 
    /// `SRLI rd, rs1, shamt` => `rd <- rs1 >> shamt`
    pub const RISCV_OPI_SRI_SRLI: u8 = 0x0;

    /// Type: R
    /// 
    /// Add or sub (see RISCV_OP_ADD_ADD or RISCV_OP_ADD_SUB) depending of func7 value
    pub const RISCV_OP_ADD: u8 = 0x0;
    /// Type: R
    /// 
    /// Shift left logical, add a 0 on right of the word
    /// 
    /// `SLL rd, rs1, rs2` => `rs <- rs1 << rs2`
    pub const RISCV_OP_SLL: u8 = 0x1;
    /// Type: R
    /// 
    /// Set less than : set rd to 1 if rs1 < rs2, 0 otherwise
    /// 
    /// `SLT rd, rs1, rs2` => `rd <- rs1 < rs2 ? 1 : 0`
    pub const RISCV_OP_SLT: u8 = 0x2;
    /// Type: R
    /// 
    /// Set less than unsigned : same than SLT but for unsigned values
    pub const RISCV_OP_SLTU: u8 = 0x3;
    /// Type: R
    /// 
    /// XOR instruction
    /// 
    /// `XOR rd, rs1, rs2` => `rd <- rs1 ^ rs2`
    pub const RISCV_OP_XOR: u8 = 0x4;
    pub const RISCV_OP_SR: u8 = 0x5;
    /// Type: R
    /// 
    /// OR instruction
    /// 
    /// `OR rd, rs1, rs2` => `rd <- rs1 | rs2`
    pub const RISCV_OP_OR: u8 = 0x6;
    /// Type: R
    /// 
    /// AND instruction
    /// 
    /// `AND rd, rs1, rs2` => `rd <- rs1 & rs2`
    pub const RISCV_OP_AND: u8 = 0x7;
    /// Type : R
    /// 
    /// Addition
    /// 
    /// `ADD rd, rs1, rs2` => `rd <- rs1 + rs2`
    pub const RISCV_OP_ADD_ADD: u8 = 0x0;
    /// Type: R
    /// 
    /// Substract
    /// 
    /// `SUB rd, rs1, rs2` => `rd <- rs1 - rs2`
    pub const RISCV_OP_ADD_SUB: u8 = 0x20;
    /// Type: R
    /// 
    /// Shift right logical, add a 0 at the left of the word (should not used for signed values in most cases)
    /// 
    /// `SRL rd, rs1, rs2` => `rd <- rs1 >> rs2`
    pub const RISCV_OP_SR_SRL: u8 = 0x0;
    /// Type: R
    /// 
    /// Shift right arithmetic, add a 1 at the left of the word(useful for signed values bacause it keep signed value)
    /// 
    /// `SRA rd, rs1, rs2` => `rd <- rs1 >> rs2`
    pub const RISCV_OP_SR_SRA: u8 = 0x20;

    // ECALL or EBREAK from base instructions
    /// or instructions from Ricsr extension 
    pub const RISCV_SYSTEM: u8 = 0x73;

    /// Type: I
    /// 
    /// Add immediate word (RV64I only)
    /// 
    /// `ADDIW rd, rs1, imm12` => `rd <- rs1 + imm12`
    pub const RISCV_OPIW_ADDIW: u8 = 0x0;
    /// Type: I
    /// 
    /// Shift right logical immediate word (RV64I only)
    /// 
    /// `SLLIW rd, rs1, imm12` => `rd <- rs1 >> shamt`
    pub const RISCV_OPIW_SLLIW: u8 = 0x1;
    
    /// Shift right immediate instructions (logical or arithmetic depend of func7)
    pub const RISCV_OPIW_SRW: u8 = 0x5;
    /// Type: I
    /// 
    /// Shift right logical immediate word (RV64I only)
    /// 
    /// `SRLIW rd, rs1, imm12` => `rd <- rs1 >> shamt`
    /// 
    /// Complete left bits by a zero, should be used with an unsigned value in most case
    pub const RISCV_OPIW_SRW_SRLIW: u8 = 0x0;
    /// Type: I
    /// 
    /// Shift right arithmetic immediate word (RV64I only)
    /// 
    /// `SRAIW rd, rs1, imm12` => `rd <- rs1 >> shamt`
    /// 
    /// Keep sign bit
    pub const RISCV_OPIW_SRW_SRAIW: u8 = 0x20;

    // ADD or SUB immediate instructions, depend of func7 value
    pub const RISCV_OPW_ADDSUBW: u8 = 0x0;
    /// Type: R
    /// 
    /// Shift left logical word (RV64I only)
    /// 
    /// `SLLW rd, rs1, rs2` => `rd <- rs1 << rs2`
    pub const RISCV_OPW_SLLW: u8 = 0x1;
    /// Shift right word instructions (logical or arithmetic depend of func3)
    pub const RISCV_OPW_SRW: u8 = 0x5;
    /// Type: R
    /// 
    /// Add word (rv64I only)
    /// 
    /// `ADDW rd, rs1, rs2` => `rd <- rs1 + rs2`
    pub const RISCV_OPW_ADDSUBW_ADDW: u8 = 0x0;
    /// Type: R
    /// 
    /// Subtract word (rv64I only)
    /// 
    /// `SUBW rd, rs1, rs2` => `rd <- rs1 - rs2`
    pub const RISCV_OPW_ADDSUBW_SUBW: u8 = 0x20;
    /// Type: R
    /// 
    /// Shift right logical word (rv64I only)
    /// 
    /// rd <- rs1 >> rs2
    /// 
    /// Complete left bits by a 0, should be used with an unsigned value
    pub const RISCV_OPW_SRW_SRLW: u8 = 0x0;
    /// Type: R
    /// 
    /// Shift right arithmetic word (rv64I only)
    /// 
    /// `SRAW rd, rs1, rs2` => `rd <- rs1 >> rs2`
    /// 
    /// Keep sign bit
    pub const RISCV_OPW_SRW_SRAW: u8 = 0x20;

    pub const RISCV_SYSTEM_ENV: u8 = 0x0;
    pub const RISCV_SYSTEM_ENV_ECALL: u8 = 0x0;
    pub const RISCV_SYSTEM_ENV_EBREAK: u8 = 0x1;
    pub const RISCV_SYSTEM_CSRRS: u8 = 0x2;
    pub const RISCV_SYSTEM_CSRRW: u8 = 0x1;
    pub const RISCV_SYSTEM_CSRRC: u8 = 0x3;
    pub const RISCV_SYSTEM_CSRRWI: u8 = 0x5;
    pub const RISCV_SYSTEM_CSRRSI: u8 = 0x6;
    pub const RISCV_SYSTEM_CSRRCI: u8 = 0x7;

    pub const RISCV_FLW: u8 = 0x07;
    pub const RISCV_FSW: u8 = 0x27;
    pub const RISCV_FMADD: u8 = 0x43;
    pub const RISCV_FMSUB: u8 = 0x47;
    pub const RISCV_FNMSUB: u8 = 0x4b;
    pub const RISCV_FNMADD: u8 = 0x4f;

    /// Simple floating point extension
    pub const RISCV_FP: u8 = 0x53;

    /// Type: R
    /// 
    /// Simple precision floating point addition
    /// 
    /// `FADD.S rd, rs1, rs2` => `rd <- rs1 + rs2`
    pub const RISCV_FP_ADD: u8 = 0x0;
    /// Type: R
    /// 
    /// Simple precision floating point substraction
    /// 
    /// `FSUB.S rd, rs1, rs2` => `rd <- rs1 - rs2`
    pub const RISCV_FP_SUB: u8 = 0x4;
    /// Type: R
    /// 
    /// Simple precision floating point multiplication
    /// 
    /// `fmul.s rd, rs1, rs2` => `rd <- rs1 * rs2`
    pub const RISCV_FP_MUL: u8 = 0x8;
    /// Type : R
    /// 
    /// Simple precision floating point division
    /// 
    /// `fdiv.s rd, rs1, rs2` => `rd <- rs1 / rs2`
    pub const RISCV_FP_DIV: u8 = 0xc;
    /// Type: R
    /// 
    /// Simple precision square root
    /// 
    /// `fsqrt.s rd, rs1` => `rd <- sqrt(rs1)`
    pub const RISCV_FP_SQRT: u8 = 0x2c;
    /// FSGN instructions
    pub const RISCV_FP_FSGN: u8 = 0x10;
    // fmin or fmax instructions
    pub const RISCV_FP_MINMAX: u8 = 0x14;
    /// fcvt.w instructions
    /// 
    /// convert fp to integer
    pub const RISCV_FP_FCVTW: u8 = 0x60;
    /// fmv.x.w or fclass.s instruction
    pub const RISCV_FP_FMVXFCLASS: u8 = 0x70;
    /// floating points comparaison instructions
    pub const RISCV_FP_FCMP: u8 = 0x50;
    pub const RISCV_FP_FEQS: u8 = 0x53;
    /// fcvt.s instructions
    /// 
    /// Convert integer to fp
    pub const RISCV_FP_FCVTS: u8 = 0x68;
    pub const RISCV_FP_FCVTDS: u8 = 0x21;

    /// Type: R
    /// 
    /// Take all bits except sign bit from rs1. sign is rs2's sign bit
    /// 
    /// `fsgnj.s rd, rs1, rs2` => `rd <- {rs2[31], rs1[30:0]}`
    pub const RISCV_FP_FSGN_J: u8 = 0x0;
    /// Type: R
    /// 
    /// Take all bits except sign bit from rs1, sign is opposite of rs2's sign bit
    /// 
    /// `fsgnjs.s rd, rs1, rs2` => `rd <- {rs2[31], rs[30:0]}`
    pub const RISCV_FP_FSGN_JN: u8 = 0x1;
    /// Type: R
    /// 
    /// Take all bits except sign bit from rs1, sign is XOR of sign bit of rs1 and rs2
    /// 
    /// `fsgnjx.s rd, rs1, rs2` => `rd <- {rs1[31] ^ rs2[31], rs1[30:0]}` 
    pub const RISCV_FP_FSGN_JX: u8 = 0x2;

    /// Type: R
    /// 
    /// write the smaller number between rs1 and rs2 to rd
    /// 
    /// `fmin.s rd, rs1, rs2` => `rd <- min(rs1, rs2)`
    pub const RISCV_FP_MINMAX_MIN: u8 = 0x0;
    /// type: R
    /// 
    /// Write the larger number between rs1 and rs2 to rd
    /// 
    /// `fmax.s rd, rs1, rs2` => `rd <- max(rs1, rs2)`
    pub const RISCV_FP_MINMAX_MAX: u8 = 0x1;
    
    /// Type: R
    /// 
    /// Convert a floating point number in register to a signed 32-bit integer and write it in integer register
    /// 
    /// `fcvt.w.s rd, rs1` => `rd <- rs1_f32 as i32`
    /// 
    /// rd is integer register and rs1 is floating point register
    pub const RISCV_FP_FCVTW_W: u8 = 0x0;
    /// Type: R
    /// 
    /// Convert a floating point number in register to a unsigned 32 bit integer and write it in integer register
    /// 
    /// `fcvt.wu.s rd, rs1` => `rd <- rs1_f32 as u32`
    pub const RISCV_FP_FCVTW_WU: u8 = 0x1;

    /// Type : R
    /// 
    /// Convert signed 32 bit integer in register to a floating point number and write it in fp register
    /// 
    /// `fcvt.s.w rd, rs1` => `rd <- rs1_s32 as f32`
    pub const RISCV_FP_FCVTS_W: u8 = 0x0;
    /// Type: R
    /// 
    /// Convert unsigned 32 bit integer in register to a floating point number and write it in fp register
    /// 
    /// `fcvt.s.wu rd, rs1` => `rd <- rs1_u32 as f32`
    pub const RISCV_FP_FCVTS_WU: u8 = 0x1;
    /// Type: R
    /// 
    /// Move floating point value in register to integer register, bits value aren't modified during the process
    /// 
    /// On rv64, the lower 32 bits of the integer register are transfered, for the upper 32 bits, values are filles with copies of the floating point number's sign bit 
    /// 
    /// `fmv.x.w rd ,rs1` => `rd[31,0] <- rs1; rd[63:32] <- rs[31]`
    pub const RISCV_FP_FMVXFCLASS_FMVX: u8 = 0x0;
    ///  Type: R
    /// 
    /// examine the value given in fp register rs1 and writes to integer register rd a 10 bit mask that indicates the class of the fp number.
    /// Format is described here: 
    /// 
    /// | rd bit | meaning                            |
    /// |--------|------------------------------------|
    /// | 0      | rs1 is -infinite                   |
    /// | 1      | rs1 is a negative normal number    |
    /// | 2      | rs1 is a negative subnormal number |
    /// | 3      | rs1 is -0                          |
    /// | 4      | rs1 is +0                          |
    /// | 5      | rs1 is a positive subnormal number |
    /// | 6      | rs1 is a positive normal number    |
    /// | 7      | rs1 is +infinite                   |
    /// | 8      | rs1 is a signaling NaN             |
    /// | 9      | rs1 is a quiet NaN                 |
    /// 
    /// All others bit in rd are cleared
    pub const RISCV_FP_FMVXFCLASS_FCLASS: u8 = 0x1;

    /// Type: R
    /// 
    /// Quiet equal comparaison, NaN cause an invalid operation exception
    /// 
    /// `feq.s rd, rs1, rs2` => `rd <- rs1 == rs2`
    pub const RISCV_FP_FCMP_FEQ: u8 = 2;
    /// Type: R
    /// 
    /// Quiet less comparaison, NaN cause an invalid operation exception
    /// 
    /// `flt.s rd, rs1, rs2` => `rdf <- rs1 < rs2`
    pub const RISCV_FP_FCMP_FLT: u8 = 1;
    /// Type: R
    /// 
    /// Quiet less or equal comparaison, NaN cause an invalid operation exception
    /// 
    /// `fle.s rd, rs1, rs2` => `rd <- rs1 <= rs2`
    pub const RISCV_FP_FCMP_FLE: u8 = 0;

    /// Type : R
    /// 
    /// Move floating point value in integer register to the fp register. Bits aren't modified in the transfer
    /// 
    /// On rv64, only the lower 32 bits in the integer register are transfered.
    /// 
    /// `fmv.w.x rd, rs1` => `rd <- rs1[31:0]`
    pub const RISCV_FP_FMVW: u8 = 0x78;

    /// Integer, multiplication and division extension
    pub const RISCV_OP_M: u8 = 0x1;

    /// Type: R
    /// 
    /// Multiply
    /// 
    /// `MUL rd, rs1, rs2` => `rd <- rs1 * rs2`
    pub const RISCV_OP_M_MUL: u8 = 0x0;
    /// Type: R
    /// 
    /// Multiply high signed signed
    /// 
    /// `MULH rd, rs1, rs2` => `rd <- (rs1 * rs2) >> xlen`
    /// 
    /// rs1 and rs2 signed
    pub const RISCV_OP_M_MULH: u8 = 0x1;
    /// Type: R
    /// 
    /// Multiply high signed unsigned
    /// 
    /// `MULHSU rd, rs1, rs2` => `rd <- (rs1 x rs2) >> xlen`
    /// 
    /// rs1 is signed and rs2 is unsigned
    pub const RISCV_OP_M_MULHSU: u8 = 0x2;
    /// Type: R
    /// 
    /// Multiply high unsigned unsigned
    /// 
    /// `MULHU rd, rs1, rs2` => `rd <- (rs1 × rs2) >> xlen`
    /// 
    /// rs1 and rs2 unsigned
    pub const RISCV_OP_M_MULHU: u8 = 0x3;
    /// Type: R
    /// 
    /// Divide signed
    /// 
    /// `DIV rd, rs1, rs2` => `rd <- r1 / rs2`
    pub const RISCV_OP_M_DIV: u8 = 0x4;
    /// Type: R
    /// 
    /// Divide unsigned
    /// 
    /// `DIVU rd, rs1, rs2` => `rd <- rs1 / rs2`
    pub const RISCV_OP_M_DIVU: u8 = 0x5;
    /// Type: R
    /// 
    /// Remainder signed
    /// 
    /// `REM rd, rs1, rs2` => `rd <- rs1 % rs2`
    pub const RISCV_OP_M_REM: u8 = 0x6;
    /// Type: R
    /// 
    /// Remaindder unsigned
    /// 
    /// `REMU rd, rs1, rs2` => `rd <- rs1 % rs2`
    pub const RISCV_OP_M_REMU: u8 = 0x7;

    /// Type: R
    /// 
    /// Multiply Word (rv64M only)
    /// 
    /// `MULW rd, rs1, rs2` => `rd <- rs1 * rs2`
    pub const RISCV_OPW_M_MULW: u8 = 0x0;
    /// Type: R
    /// 
    /// Divide signed word (RV64M only)
    /// 
    /// `DIVW rd, rs1, rs2` => `rd <- rs1 / rs2`
    pub const RISCV_OPW_M_DIVW: u8 = 0x4;
    /// Type: R
    /// 
    /// Divide unsigned word
    /// 
    /// `DIVUW rd, rs1, rs2` => `red <- rs1 / rs2`
    pub const RISCV_OPW_M_DIVUW: u8 = 0x5;
    /// Type: R
    /// 
    /// Remainder signed word (RV64M only)
    /// 
    /// `REMW rd, rs1, rs2` => `rd <- rs1 % rs2`
    pub const RISCV_OPW_M_REMW: u8 = 0x6;
    /// Type: R
    /// 
    /// Remainder unsigned word (RV64M only)
    /// 
    /// `REMUW rd, rs1, rs2` => `rd <- rs1 % rs2`
    pub const RISCV_OPW_M_REMUW: u8 = 0x7;

    /// Instruction from Zifencei extension
    pub const RISCV_FENCE: u8 = 0x0f;

    /// Atomic instructions extension
    pub const RISCV_ATOM: u8 = 0x2f;
    pub const RISCV_ATOM_LR: u8 = 0x2;
    pub const RISCV_ATOM_SC: u8 = 0x3;
    pub const RISCV_ATOM_SWAP: u8 = 0x1;
    pub const RISCV_ATOM_ADD: u8 = 0;
    pub const RISCV_ATOM_XOR: u8 = 0x4;
    pub const RISCV_ATOM_AND: u8 = 0xc;
    pub const RISCV_ATOM_OR: u8 = 0x8;
    pub const RISCV_ATOM_MIN: u8 = 0x10;
    pub const RISCV_ATOM_MAX: u8 = 0x14;
    pub const RISCV_ATOM_MINU: u8 = 0x18;
    pub const RISCV_ATOM_MAXU: u8 = 0x1c;

}