pub mod machine; pub mod decode; pub mod print; pub mod mem_cmp; pub mod loader; pub mod interrupt; pub mod translationtable; pub mod mmu; 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; }