2022-11-09 15:06:22 +01:00
#![ allow(dead_code) ]
#![ allow(unused_variables) ]
2023-01-11 14:58:12 +01:00
use super ::decode ::{ Instruction } ;
2022-10-26 13:31:40 +02:00
2023-01-18 22:15:06 +01:00
// Instructions type:
// - R: Register / register
// - I: Immediate
// - U: Upper-Immediate
// - S: Store
// - B: Branch (conditional branches...)
// - J: Jump
/// Type: U
///
/// Load upper immediate
///
/// `LUI rd, imm31_12` => `rd <- imm31_12 << 12`
///
2022-11-16 15:48:46 +01:00
pub const RISCV_LUI : u8 = 0x37 ;
2023-01-18 22:15:06 +01:00
/// Type: U
///
/// Add upper immediate to PC
///
/// `AUIP rd, imm31_12` => `rd <- PC + imm31_12 << 12`
2022-11-16 15:48:46 +01:00
pub const RISCV_AUIPC : u8 = 0x17 ;
pub const RISCV_JAL : u8 = 0x6f ;
pub const RISCV_JALR : u8 = 0x67 ;
pub const RISCV_BR : u8 = 0x63 ;
2023-01-18 22:15:06 +01:00
/// Load instruction
///
/// See func3 to know the type of instruction (LD, LW, LH, LB, LWU, LHU, LBU)
2022-11-16 15:48:46 +01:00
pub const RISCV_LD : u8 = 0x3 ;
pub const RISCV_ST : u8 = 0x23 ;
pub const RISCV_OPI : u8 = 0x13 ;
pub const RISCV_OP : u8 = 0x33 ;
pub const RISCV_OPIW : u8 = 0x1b ;
pub const RISCV_OPW : u8 = 0x3b ;
pub const RISCV_BR_BEQ : u8 = 0x0 ;
pub const RISCV_BR_BNE : u8 = 0x1 ;
pub const RISCV_BR_BLT : u8 = 0x4 ;
pub const RISCV_BR_BGE : u8 = 0x5 ;
pub const RISCV_BR_BLTU : u8 = 0x6 ;
pub const RISCV_BR_BGEU : u8 = 0x7 ;
2023-01-18 22:15:06 +01:00
/// Type: I
///
/// Load byte (8 bits word)
///
/// `LB rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
2022-11-16 15:48:46 +01:00
pub const RISCV_LD_LB : u8 = 0x0 ;
2023-01-18 22:15:06 +01:00
/// Type: I
///
/// Load halfword (16 bits word)
///
/// `LH rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
2022-11-16 15:48:46 +01:00
pub const RISCV_LD_LH : u8 = 0x1 ;
2023-01-18 22:15:06 +01:00
/// Type: I
///
/// Load word (32 bits word)
///
/// `LW rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
2022-11-16 15:48:46 +01:00
pub const RISCV_LD_LW : u8 = 0x2 ;
2023-01-18 22:15:06 +01:00
/// Type: I
///
/// Load doubleword (64-bits word)
///
/// `LD rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
2022-11-16 15:48:46 +01:00
pub const RISCV_LD_LD : u8 = 0x3 ;
2023-01-18 22:15:06 +01:00
/// Type: I
///
/// Load byte unsigned
///
/// `LBU rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
2022-11-16 15:48:46 +01:00
pub const RISCV_LD_LBU : u8 = 0x4 ;
2023-01-18 22:15:06 +01:00
/// Type: I
///
/// Load halfword unsigned
///
/// `LHU rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
2022-11-16 15:48:46 +01:00
pub const RISCV_LD_LHU : u8 = 0x5 ;
2023-01-18 22:15:06 +01:00
/// Type: I
///
/// Load word unsigned (64 bits word)
///
/// `LW rd, imm12(rs1)` => `rd <- mem[rs1 + imm12]`
2022-11-16 15:48:46 +01:00
pub const RISCV_LD_LWU : u8 = 0x6 ;
2023-01-18 22:15:06 +01:00
/// 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]`
2022-11-16 15:48:46 +01:00
pub const RISCV_ST_STH : u8 = 0x1 ;
2023-01-18 22:15:06 +01:00
/// 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]`
2022-11-16 15:48:46 +01:00
pub const RISCV_ST_STW : u8 = 0x2 ;
2023-01-18 22:15:06 +01:00
/// 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]`
2022-11-16 15:48:46 +01:00
pub const RISCV_ST_STB : u8 = 0x0 ;
2023-01-18 22:15:06 +01:00
/// Type: S
///
/// Store doubleword (SD) (64 bits)
///
/// `SD rs2, imm12(rs1` => `rs2 -> mem[rs1 + imm12]`
2022-11-16 15:48:46 +01:00
pub const RISCV_ST_STD : u8 = 0x3 ;
2023-01-18 22:15:06 +01:00
/// Type: I
///
/// Add immediate
///
/// `addi rd, rs1, imm12` => `rd <- rs1 + imm12`
2022-11-16 15:48:46 +01:00
pub const RISCV_OPI_ADDI : u8 = 0x0 ;
2023-01-18 22:15:06 +01:00
/// Type: I
///
/// Set less than immediate: set rd to 1 if rs1 < imm12, 0 otherwise
///
/// `SLT rd, rs1, imm12` => `rd <- rs1 < imm12 ? 1 : 0`
2022-11-16 15:48:46 +01:00
pub const RISCV_OPI_SLTI : u8 = 0x2 ;
2023-01-18 22:15:06 +01:00
/// Type: I
///
/// Set less than immediate unsigned : same than SLTI but for unsigned values
2022-11-16 15:48:46 +01:00
pub const RISCV_OPI_SLTIU : u8 = 0x3 ;
2023-01-18 22:15:06 +01:00
/// Type: I
///
/// XOR immediate instruction
///
/// `XORI rd, rs1, imm12` => `rd <- rs1 ^ imm12`
2022-11-16 15:48:46 +01:00
pub const RISCV_OPI_XORI : u8 = 0x4 ;
2023-01-18 22:15:06 +01:00
/// Type: I
///
/// OR immediate instruction
///
/// `ORI rd, rs1, imm12` => `rd <- rs1 | imm12`
2022-11-16 15:48:46 +01:00
pub const RISCV_OPI_ORI : u8 = 0x6 ;
2023-01-18 22:15:06 +01:00
/// Type: I
///
/// AND immediate instruction
///
/// `ANDI rd, rs1, imm12` => `rd <- rs1 & imm12`
2022-11-16 15:48:46 +01:00
pub const RISCV_OPI_ANDI : u8 = 0x7 ;
2023-01-18 22:15:06 +01:00
/// Type: I
///
/// Shift left logical immediate
///
/// `SLLI rd, rs1, shamt` => `rd <- rs1 >> shamt`
2022-11-16 15:48:46 +01:00
pub const RISCV_OPI_SLLI : u8 = 0x1 ;
2023-01-18 22:15:06 +01:00
/// Shift right immediate, may be SRAI or SRLI
2022-11-16 15:48:46 +01:00
pub const RISCV_OPI_SRI : u8 = 0x5 ;
2023-01-18 22:15:06 +01:00
/// type: I
///
/// Shift right arithmetic immediate
///
/// `SRAI rd, rs1, shamt` => `rd <- rs1 >> shamt`
2022-11-16 15:48:46 +01:00
pub const RISCV_OPI_SRI_SRAI : u8 = 0x20 ;
2023-01-18 22:15:06 +01:00
/// type: I
///
/// Shift right logical immediate
///
/// `SRLI rd, rs1, shamt` => `rd <- rs1 >> shamt`
2022-11-16 15:48:46 +01:00
pub const RISCV_OPI_SRI_SRLI : u8 = 0x0 ;
2023-01-18 22:15:06 +01:00
/// Type: R
///
/// Add or sub (see RISCV_OP_ADD_ADD or RISCV_OP_ADD_SUB) depending of func7 value
2022-11-16 15:48:46 +01:00
pub const RISCV_OP_ADD : u8 = 0x0 ;
2023-01-18 22:15:06 +01:00
/// Type: R
///
/// Shift left logical, add a 0 on right of the word
///
/// `SLL rd, rs1, rs2` => `rs <- rs1 << rs2`
2022-11-16 15:48:46 +01:00
pub const RISCV_OP_SLL : u8 = 0x1 ;
2023-01-18 22:15:06 +01:00
/// Type: R
///
/// Set less than : set rd to 1 if rs1 < rs2, 0 otherwise
///
/// `SLT rd, rs1, rs2` => `rd <- rs1 < rs2 ? 1 : 0`
2022-11-16 15:48:46 +01:00
pub const RISCV_OP_SLT : u8 = 0x2 ;
2023-01-18 22:15:06 +01:00
/// Type: R
///
/// Set less than unsigned : same than SLT but for unsigned values
2022-11-16 15:48:46 +01:00
pub const RISCV_OP_SLTU : u8 = 0x3 ;
2023-01-18 22:15:06 +01:00
/// Type: R
///
/// XOR instruction
///
/// `XOR rd, rs1, rs2` => `rd <- rs1 ^ rs2`
2022-11-16 15:48:46 +01:00
pub const RISCV_OP_XOR : u8 = 0x4 ;
pub const RISCV_OP_SR : u8 = 0x5 ;
2023-01-18 22:15:06 +01:00
/// Type: R
///
/// OR instruction
///
/// `OR rd, rs1, rs2` => `rd <- rs1 | rs2`
2022-11-16 15:48:46 +01:00
pub const RISCV_OP_OR : u8 = 0x6 ;
2023-01-18 22:15:06 +01:00
/// Type: R
///
/// AND instruction
///
/// `AND rd, rs1, rs2` => `rd <- rs1 & rs2`
2022-11-16 15:48:46 +01:00
pub const RISCV_OP_AND : u8 = 0x7 ;
2023-01-18 22:15:06 +01:00
/// Type : R
///
/// Addition
///
/// `ADD rd, rs1, rs2` => `rd <- rs1 + rs2`
2022-11-16 15:48:46 +01:00
pub const RISCV_OP_ADD_ADD : u8 = 0x0 ;
2023-01-18 22:15:06 +01:00
/// Type: R
///
/// Substract
///
/// `SUB rd, rs1, rs2` => `rd <- rs1 - rs2`
2022-11-16 15:48:46 +01:00
pub const RISCV_OP_ADD_SUB : u8 = 0x20 ;
2023-01-18 22:15:06 +01:00
/// 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`
2022-11-16 15:48:46 +01:00
pub const RISCV_OP_SR_SRL : u8 = 0x0 ;
2023-01-18 22:15:06 +01:00
/// 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`
2022-11-16 15:48:46 +01:00
pub const RISCV_OP_SR_SRA : u8 = 0x20 ;
pub const RISCV_SYSTEM : u8 = 0x73 ;
pub const RISCV_OPIW_ADDIW : u8 = 0x0 ;
pub const RISCV_OPIW_SLLIW : u8 = 0x1 ;
pub const RISCV_OPIW_SRW : u8 = 0x5 ;
pub const RISCV_OPIW_SRW_SRLIW : u8 = 0x0 ;
pub const RISCV_OPIW_SRW_SRAIW : u8 = 0x20 ;
pub const RISCV_OPW_ADDSUBW : u8 = 0x0 ;
pub const RISCV_OPW_SLLW : u8 = 0x1 ;
pub const RISCV_OPW_SRW : u8 = 0x5 ;
pub const RISCV_OPW_ADDSUBW_ADDW : u8 = 0x0 ;
pub const RISCV_OPW_ADDSUBW_SUBW : u8 = 0x20 ;
pub const RISCV_OPW_SRW_SRLW : u8 = 0x0 ;
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 ;
pub const RISCV_FP : u8 = 0x53 ;
pub const RISCV_FP_ADD : u8 = 0x0 ;
pub const RISCV_FP_SUB : u8 = 0x4 ;
pub const RISCV_FP_MUL : u8 = 0x8 ;
pub const RISCV_FP_DIV : u8 = 0xc ;
pub const RISCV_FP_SQRT : u8 = 0x2c ;
pub const RISCV_FP_FSGN : u8 = 0x10 ;
pub const RISCV_FP_MINMAX : u8 = 0x14 ;
pub const RISCV_FP_FCVTW : u8 = 0x60 ;
pub const RISCV_FP_FMVXFCLASS : u8 = 0x70 ;
pub const RISCV_FP_FCMP : u8 = 0x50 ;
pub const RISCV_FP_FEQS : u8 = 0x53 ;
pub const RISCV_FP_FCVTS : u8 = 0x68 ;
pub const RISCV_FP_FCVTDS : u8 = 0x21 ;
pub const RISCV_FP_FSGN_J : u8 = 0x0 ;
pub const RISCV_FP_FSGN_JN : u8 = 0x1 ;
pub const RISCV_FP_FSGN_JX : u8 = 0x2 ;
pub const RISCV_FP_MINMAX_MIN : u8 = 0x0 ;
pub const RISCV_FP_MINMAX_MAX : u8 = 0x1 ;
pub const RISCV_FP_FCVTW_W : u8 = 0x0 ;
pub const RISCV_FP_FCVTW_WU : u8 = 0x1 ;
pub const RISCV_FP_FCVTS_W : u8 = 0x0 ;
pub const RISCV_FP_FCVTS_WU : u8 = 0x1 ;
pub const RISCV_FP_FMVXFCLASS_FMVX : u8 = 0x0 ;
pub const RISCV_FP_FMVXFCLASS_FCLASS : u8 = 0x1 ;
pub const RISCV_FP_FCMP_FEQ : u8 = 2 ;
pub const RISCV_FP_FCMP_FLT : u8 = 1 ;
pub const RISCV_FP_FCMP_FLE : u8 = 0 ;
pub const RISCV_FP_FMVW : u8 = 0x78 ;
2022-10-26 13:31:40 +02:00
2022-11-16 17:59:09 +01:00
pub const RISCV_OP_M : u8 = 0x1 ;
pub const RISCV_OP_M_MUL : u8 = 0x0 ;
pub const RISCV_OP_M_MULH : u8 = 0x1 ;
pub const RISCV_OP_M_MULHSU : u8 = 0x2 ;
pub const RISCV_OP_M_MULHU : u8 = 0x3 ;
pub const RISCV_OP_M_DIV : u8 = 0x4 ;
pub const RISCV_OP_M_DIVU : u8 = 0x5 ;
pub const RISCV_OP_M_REM : u8 = 0x6 ;
pub const RISCV_OP_M_REMU : u8 = 0x7 ;
pub const RISCV_OPW_M_MULW : u8 = 0x0 ;
pub const RISCV_OPW_M_DIVW : u8 = 0x4 ;
pub const RISCV_OPW_M_DIVUW : u8 = 0x5 ;
pub const RISCV_OPW_M_REMW : u8 = 0x6 ;
pub const RISCV_OPW_M_REMUW : u8 = 0x7 ;
pub const RISCV_FENCE : u8 = 0x0f ;
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 ;
2022-10-26 13:31:40 +02:00
2023-01-11 15:31:52 +01:00
const NAMES_OP : [ & str ; 8 ] = [ " add " , " sll " , " slt " , " sltu " , " xor " , " sr " , " or " , " and " ] ;
const NAMES_OPI : [ & str ; 8 ] = [ " addi " , " slli " , " slti " , " sltiu " , " xori " , " slri " , " ori " , " andi " ] ;
const NAMES_MUL : [ & str ; 8 ] = [ " mpylo " , " mpyhi " , " mpyhi " , " mpyhi " , " divhi " , " divhi " , " divlo " , " divlo " ] ;
const NAMES_BR : [ & str ; 8 ] = [ " beq " , " bne " , " " , " " , " blt " , " bge " , " bltu " , " bgeu " ] ;
const NAMES_ST : [ & str ; 4 ] = [ " sb " , " sh " , " sw " , " sd " ] ;
const NAMES_LD : [ & str ; 7 ] = [ " lb " , " lh " , " lw " , " ld " , " lbu " , " lhu " , " lwu " ] ;
const NAMES_OPW : [ & str ; 8 ] = [ " addw " , " sllw " , " " , " " , " " , " srw " , " " , " " ] ;
const NAMES_OPIW : [ & str ; 8 ] = [ " addiw " , " slliw " , " " , " " , " " , " sri " , " " , " " ] ;
2022-10-26 13:31:40 +02:00
2022-11-16 17:24:20 +01:00
// Register name mapping
2023-01-11 15:31:52 +01:00
const REG_X : [ & str ; 32 ] = [ " zero " , " ra " , " sp " , " gp " , " tp " , " t0 " , " t1 " , " t2 " , " fp " , " s1 " , // fp ou s0 ?
2022-11-16 17:24:20 +01:00
" a0 " , " a1 " , " a2 " , " a3 " , " a4 " , " a5 " , " a6 " , " a7 " ,
" s2 " , " s3 " , " s4 " , " s5 " , " s6 " , " s7 " , " s8 " , " s9 " , " s10 " , " s11 " ,
" t3 " , " t4 " , " t5 " , " t6 " ] ;
2023-01-11 15:31:52 +01:00
const REG_F : [ & str ; 32 ] = [ " ft0 " , " ft1 " , " ft2 " , " ft3 " , " ft4 " , " ft5 " , " ft6 " , " ft7 " , " fs0 " , " fs1 " ,
2022-11-16 17:24:20 +01:00
" fa0 " , " fa1 " , " fa2 " , " fa3 " , " fa4 " , " fa5 " , " fa6 " , " fa7 " ,
" fs2 " , " fs3 " , " fs4 " , " fs5 " , " fs6 " , " fs7 " , " fs8 " , " fs9 " , " fs10 " , " fs11 " ,
" ft8 " , " ft9 " , " ft10 " , " ft11 " ] ;
2022-10-26 13:31:40 +02:00
pub fn print ( ins : Instruction , pc : i32 ) -> String { //TODO pc should be u64
2022-11-16 17:24:20 +01:00
let rd = ins . rd as usize ;
let rs1 = ins . rs1 as usize ;
let rs2 = ins . rs2 as usize ;
2022-10-26 13:31:40 +02:00
match ins . opcode {
RISCV_OP = > {
let name : & str ;
if ins . funct7 = = 1 { // Use mul array
2023-01-11 15:31:52 +01:00
name = NAMES_MUL [ ins . funct3 as usize ]
} else if ins . funct3 = = RISCV_OP_ADD {
// Add or Sub
if ins . funct7 = = RISCV_OP_ADD_ADD {
name = " add " ;
} else {
name = " sub " ;
}
} else if ins . funct3 = = RISCV_OP_SR {
// Srl or Sra
if ins . funct7 = = RISCV_OP_SR_SRL {
name = " srl " ;
2022-11-09 14:37:19 +01:00
} else {
2023-01-11 15:31:52 +01:00
name = " sra " ;
2022-11-09 14:37:19 +01:00
}
2023-01-11 15:31:52 +01:00
} else {
name = NAMES_OP [ ins . funct3 as usize ] ;
2022-10-26 13:31:40 +02:00
}
2023-01-11 15:31:52 +01:00
format! ( " {} \t {} , {} , {} " , name , REG_X [ rd ] , REG_X [ rs1 ] , REG_X [ rs2 ] )
2022-10-26 13:31:40 +02:00
} ,
RISCV_OPI = > {
// SHAMT OR IMM
if ins . funct3 = = RISCV_OPI_SRI {
if ins . funct7 = = RISCV_OPI_SRI_SRLI {
2023-01-18 22:15:06 +01:00
format! ( " srli \t {} , {} , {} " , REG_X [ rd ] , REG_X [ rs1 ] , ins . shamt )
2022-10-26 13:31:40 +02:00
} else {
2023-01-11 15:31:52 +01:00
format! ( " srai \t {} , {} , {} " , REG_X [ rd ] , REG_X [ rs1 ] , ins . shamt )
2022-10-26 13:31:40 +02:00
}
} else if ins . funct3 = = RISCV_OPI_SLLI {
2023-01-11 15:31:52 +01:00
format! ( " {} \t {} , {} , {} " , NAMES_OPI [ ins . funct3 as usize ] , REG_X [ rd ] , REG_X [ rs1 ] , ins . shamt )
2022-10-26 13:31:40 +02:00
} else {
2023-01-11 15:31:52 +01:00
format! ( " {} \t {} , {} , {} " , NAMES_OPI [ ins . funct3 as usize ] , REG_X [ rd ] , REG_X [ rs1 ] , ins . imm12_I_signed )
2022-10-26 13:31:40 +02:00
}
} ,
RISCV_LUI = > {
2023-01-11 15:31:52 +01:00
format! ( " lui \t {} , 0x {:X} " , REG_X [ rd ] , ins . imm31_12 )
2022-10-26 13:31:40 +02:00
} ,
RISCV_AUIPC = > {
2023-01-11 15:31:52 +01:00
format! ( " auipc \t {} , {:X} " , REG_X [ rd ] , ins . imm31_12 )
2022-10-26 13:31:40 +02:00
} ,
RISCV_JAL = > {
if ins . rd = = 0 {
2023-01-11 15:31:52 +01:00
format! ( " j \t {} " , ins . imm31_12 )
2022-10-26 13:31:40 +02:00
} else {
2023-01-11 15:31:52 +01:00
format! ( " jal \t {} , {:X} " , REG_X [ rd ] , ( pc - 4 + ins . imm21_1_signed ) )
2022-10-26 13:31:40 +02:00
}
} ,
RISCV_JALR = > {
if ins . rd = = 0 {
if ins . rs1 = = 1 {
" ret " . to_string ( )
} else {
2022-11-16 17:37:04 +01:00
format! ( " jr \t {:X} " , ins . imm31_12 )
2022-10-26 13:31:40 +02:00
}
} else {
2023-01-11 15:31:52 +01:00
format! ( " jalr \t {} , ( {} ) " , ins . imm12_I_signed , REG_X [ rs1 ] )
2022-10-26 13:31:40 +02:00
}
} ,
RISCV_BR = > {
2023-01-11 15:31:52 +01:00
format! ( " {} \t {} , {} , {} " , NAMES_BR [ ins . funct3 as usize ] , REG_X [ rs1 ] , REG_X [ rs2 ] , ins . imm13_signed )
2022-10-26 13:31:40 +02:00
} ,
RISCV_LD = > {
2023-01-11 15:31:52 +01:00
format! ( " {} \t {} , {} ( {} ) " , NAMES_LD [ ins . funct3 as usize ] , REG_X [ rd ] , ins . imm12_I_signed , REG_X [ rs1 ] )
2022-10-26 13:31:40 +02:00
} ,
RISCV_ST = > {
2023-01-11 15:31:52 +01:00
format! ( " {} \t {} , {} ( {} ) " , NAMES_ST [ ins . funct3 as usize ] , REG_X [ rs2 ] , ins . imm12_S_signed , REG_X [ rs1 ] )
2022-10-26 13:31:40 +02:00
} ,
RISCV_OPIW = > {
if ins . funct3 = = RISCV_OPIW_SRW {
if ins . funct7 = = RISCV_OPIW_SRW_SRLIW {
2023-01-11 15:31:52 +01:00
format! ( " srlwi \t {} , {} , {} " , REG_X [ rd ] , REG_X [ rs1 ] , REG_X [ rs2 ] )
2022-10-26 13:31:40 +02:00
} else {
2023-01-11 15:31:52 +01:00
format! ( " srawi \t {} , {} , {} " , REG_X [ rd ] , REG_X [ rs1 ] , REG_X [ rs2 ] )
2022-10-26 13:31:40 +02:00
}
} else if ins . funct3 = = RISCV_OPIW_SLLIW {
2023-01-11 15:31:52 +01:00
format! ( " {} \t {} , {} , {} " , NAMES_OPI [ ins . funct3 as usize ] , REG_X [ rd ] , REG_X [ rs1 ] , REG_X [ rs2 ] )
2022-10-26 13:31:40 +02:00
} else {
2023-01-11 15:31:52 +01:00
format! ( " {} \t {} , {} , {} " , NAMES_OPIW [ ins . funct3 as usize ] , REG_X [ rd ] , REG_X [ rs1 ] , ins . imm12_I_signed )
2022-10-26 13:31:40 +02:00
}
} ,
RISCV_OPW = > {
if ins . funct7 = = 1 {
2023-01-11 15:31:52 +01:00
format! ( " {} w \t {} , {} , {} " , NAMES_MUL [ ins . funct3 as usize ] , REG_X [ rd ] , REG_X [ rs1 ] , REG_X [ rs2 ] )
} else if ins . funct3 = = RISCV_OP_ADD {
if ins . funct7 = = RISCV_OPW_ADDSUBW_ADDW {
format! ( " addw \t {} , {} , {} " , REG_X [ rd ] , REG_X [ rs1 ] , REG_X [ rs2 ] )
2022-10-26 13:31:40 +02:00
} else {
2023-01-11 15:31:52 +01:00
format! ( " subw \t {} , {} , {} " , REG_X [ rd ] , REG_X [ rs1 ] , REG_X [ rs2 ] )
2022-10-26 13:31:40 +02:00
}
2023-01-11 15:31:52 +01:00
} else if ins . funct3 = = RISCV_OPW_SRW {
if ins . funct7 = = RISCV_OPW_SRW_SRLW {
format! ( " srlw \t {} , {} , {} " , REG_X [ rd ] , REG_X [ rs1 ] , REG_X [ rs2 ] )
} else {
format! ( " sraw \t {} , {} , {} " , REG_X [ rd ] , REG_X [ rs1 ] , REG_X [ rs2 ] )
}
} else {
format! ( " {} \t {} , {} , {} " , NAMES_OPW [ ins . funct3 as usize ] , REG_X [ rd ] , REG_X [ rs1 ] , REG_X [ rs2 ] )
2022-10-26 13:31:40 +02:00
}
} ,
RISCV_SYSTEM = > {
" ecall " . to_string ( )
} ,
2023-01-18 22:15:06 +01:00
_ = > todo! ( " Unknown or currently unsupported opcode " ) // Change todo! to panic! in the future, I put todo! because there's a lot of opcode currently not implemented
2022-10-26 13:31:40 +02:00
}
2022-11-09 15:06:22 +01:00
}
#[ cfg(test) ]
2022-11-09 15:54:01 +01:00
mod test {
2023-01-11 15:31:52 +01:00
#![ allow(clippy::unusual_byte_groupings) ]
2023-01-11 14:58:12 +01:00
use crate ::simulator ::{ decode , print } ;
2022-11-09 16:38:50 +01:00
2022-11-09 15:06:22 +01:00
#[ test ]
2022-11-09 15:54:01 +01:00
fn test_op ( ) {
let sub = decode ::decode ( 0b0100000_10000_10001_000_11100_0110011 ) ;
let add = decode ::decode ( 0b0000000_10000_10001_000_11100_0110011 ) ;
let xor = decode ::decode ( 0b0000000_10000_10001_100_11100_0110011 ) ;
let slr = decode ::decode ( 0b0000000_10000_10001_101_11100_0110011 ) ;
let sra = decode ::decode ( 0b0100000_10000_10001_101_11100_0110011 ) ;
2022-11-09 15:06:22 +01:00
2022-11-16 17:37:04 +01:00
assert_eq! ( " sub \t t3, a7, a6 " , print ::print ( sub , 0 ) ) ;
assert_eq! ( " xor \t t3, a7, a6 " , print ::print ( xor , 0 ) ) ;
assert_eq! ( " srl \t t3, a7, a6 " , print ::print ( slr , 0 ) ) ;
assert_eq! ( " sra \t t3, a7, a6 " , print ::print ( sra , 0 ) ) ;
assert_eq! ( " add \t t3, a7, a6 " , print ::print ( add , 0 ) ) ;
2022-11-09 15:06:22 +01:00
}
2022-11-09 15:54:01 +01:00
#[ test ]
fn test_opi ( ) {
let addi = decode ::decode ( 0b0000000000_10001_000_11100_0010011 ) ;
2022-11-09 16:38:50 +01:00
let slli = decode ::decode ( 0b0000000000_10001_001_11100_0010011 ) ;
let slti = decode ::decode ( 0b0000000000_10001_010_11100_0010011 ) ;
let sltiu = decode ::decode ( 0b0000000000_10001_011_11100_0010011 ) ;
let xori = decode ::decode ( 0b_0000000000010001_100_11100_0010011 ) ;
let ori = decode ::decode ( 0b00000000000_10001_110_11100_0010011 ) ;
2022-11-10 00:08:06 +01:00
let andi = decode ::decode ( 0b000000000000_10001_111_11100_0010011 ) ;
2022-11-16 17:37:04 +01:00
assert_eq! ( " andi \t t3, a7, 0 " , print ::print ( andi , 0 ) ) ;
assert_eq! ( " addi \t t3, a7, 0 " , print ::print ( addi , 0 ) ) ;
assert_eq! ( " slli \t t3, a7, 0 " , print ::print ( slli , 0 ) ) ;
assert_eq! ( " slti \t t3, a7, 0 " , print ::print ( slti , 0 ) ) ;
assert_eq! ( " sltiu \t t3, a7, 0 " , print ::print ( sltiu , 0 ) ) ;
assert_eq! ( " xori \t t3, a7, 0 " , print ::print ( xori , 0 ) ) ;
assert_eq! ( " ori \t t3, a7, 0 " , print ::print ( ori , 0 ) ) ;
2022-11-09 15:54:01 +01:00
}
2022-11-09 16:08:51 +01:00
#[ test ]
fn test_lui ( ) {
let lui = decode ::decode ( 0b01110001000011111000_11100_0110111 ) ;
2022-11-09 17:31:14 +01:00
let lui_negatif = decode ::decode ( 0b11110001000011111000_11100_0110111 ) ;
2022-11-16 17:37:04 +01:00
assert_eq! ( " lui \t t3, 0x710F8000 " , print ::print ( lui , 0 ) ) ;
assert_eq! ( " lui \t t3, 0xF10F8000 " , print ::print ( lui_negatif , 0 ) ) ;
2022-11-09 16:08:51 +01:00
}
#[ test ]
fn test_ld ( ) {
// imm rs1 f3 rd opcode
let lb = decode ::decode ( 0b010111110000_10001_000_11100_0000011 ) ;
let lh = decode ::decode ( 0b010111110000_10001_001_11100_0000011 ) ;
let lw = decode ::decode ( 0b010111110000_10001_010_11100_0000011 ) ;
let lbu = decode ::decode ( 0b010111110000_10001_100_11100_0000011 ) ;
let lhu = decode ::decode ( 0b010111110000_10001_101_11100_0000011 ) ;
let ld = decode ::decode ( 0b010111110000_10001_011_11100_0000011 ) ;
let lwu = decode ::decode ( 0b010111110000_10001_110_11100_0000011 ) ;
2022-11-16 17:37:04 +01:00
assert_eq! ( " lb \t t3, 1520(a7) " , print ::print ( lb , 0 ) ) ;
assert_eq! ( " lh \t t3, 1520(a7) " , print ::print ( lh , 0 ) ) ;
assert_eq! ( " lw \t t3, 1520(a7) " , print ::print ( lw , 0 ) ) ;
assert_eq! ( " lbu \t t3, 1520(a7) " , print ::print ( lbu , 0 ) ) ;
assert_eq! ( " lhu \t t3, 1520(a7) " , print ::print ( lhu , 0 ) ) ;
assert_eq! ( " ld \t t3, 1520(a7) " , print ::print ( ld , 0 ) ) ;
assert_eq! ( " lwu \t t3, 1520(a7) " , print ::print ( lwu , 0 ) ) ;
2022-11-09 16:08:51 +01:00
}
2022-11-10 00:16:21 +01:00
#[ test ]
fn test_opw ( ) {
let addw : decode ::Instruction = decode ::decode ( 0b0000000_10000_10001_000_11100_0111011 ) ;
let sllw : decode ::Instruction = decode ::decode ( 0b0000000_10000_10001_001_11100_0111011 ) ;
let srlw : decode ::Instruction = decode ::decode ( 0b0000000_10000_10001_101_11100_0111011 ) ;
let sraw : decode ::Instruction = decode ::decode ( 0b0100000_10000_10001_101_11100_0111011 ) ;
2022-11-16 17:37:04 +01:00
assert_eq! ( " addw \t t3, a7, a6 " , print ::print ( addw , 0 ) ) ;
assert_eq! ( " sllw \t t3, a7, a6 " , print ::print ( sllw , 0 ) ) ;
assert_eq! ( " srlw \t t3, a7, a6 " , print ::print ( srlw , 0 ) ) ;
assert_eq! ( " sraw \t t3, a7, a6 " , print ::print ( sraw , 0 ) ) ;
2022-11-10 00:16:21 +01:00
}
2022-11-10 00:08:06 +01:00
2022-11-10 00:39:11 +01:00
#[ test ]
fn test_opwi ( ) {
2022-11-16 17:24:20 +01:00
let addiw : decode ::Instruction = decode ::decode ( 0b000000000000_10001_000_11100_0011011 ) ;
let slliw : decode ::Instruction = decode ::decode ( 0b0000000_10000_10001_001_11100_0011011 ) ;
2022-11-10 00:39:11 +01:00
let srai : decode ::Instruction = decode ::decode ( 0b010000010001_10001_101_11100_0010011 ) ;
2022-11-16 17:37:04 +01:00
assert_eq! ( " addiw \t t3, a7, 0 " , print ::print ( addiw , 0 ) ) ;
assert_eq! ( " slli \t t3, a7, a6 " , print ::print ( slliw , 0 ) ) ;
assert_eq! ( " srai \t t3, a7, 17 " , print ::print ( srai , 0 ) ) ;
2022-11-10 00:39:11 +01:00
}
2022-11-10 00:08:06 +01:00
2022-11-10 00:47:32 +01:00
#[ test ]
fn test_br ( ) {
let beq : decode ::Instruction = decode ::decode ( 0b0000000_10000_10001_000_00000_1100011 ) ;
let bne : decode ::Instruction = decode ::decode ( 0b0000000_10000_10001_001_00000_1100011 ) ;
let blt : decode ::Instruction = decode ::decode ( 0b0000000_10000_10001_100_00000_1100011 ) ;
let bge : decode ::Instruction = decode ::decode ( 0b0000000_10000_10001_101_00000_1100011 ) ;
let bltu : decode ::Instruction = decode ::decode ( 0b0000000_10000_10001_110_00000_1100011 ) ;
let bgeu : decode ::Instruction = decode ::decode ( 0b0000000_10000_10001_111_00000_1100011 ) ;
2022-11-16 17:37:04 +01:00
assert_eq! ( " blt \t a7, a6, 0 " , print ::print ( blt , 0 ) ) ;
assert_eq! ( " bge \t a7, a6, 0 " , print ::print ( bge , 0 ) ) ;
assert_eq! ( " bltu \t a7, a6, 0 " , print ::print ( bltu , 0 ) ) ;
assert_eq! ( " bgeu \t a7, a6, 0 " , print ::print ( bgeu , 0 ) ) ;
assert_eq! ( " bne \t a7, a6, 0 " , print ::print ( bne , 0 ) ) ;
assert_eq! ( " beq \t a7, a6, 0 " , print ::print ( beq , 0 ) ) ;
2022-11-10 00:47:32 +01:00
}
2022-10-26 13:31:40 +02:00
}