#![allow(dead_code)] #![allow(unused_variables)] use crate::decode::Instruction; pub const RISCV_LUI: u8 = 0x37; pub const RISCV_AUIPC: u8 = 0x17; pub const RISCV_JAL: u8 = 0x6f; pub const RISCV_JALR: u8 = 0x67; pub const RISCV_BR: u8 = 0x63; 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; pub const RISCV_LD_LB: u8 = 0x0; pub const RISCV_LD_LH: u8 = 0x1; pub const RISCV_LD_LW: u8 = 0x2; pub const RISCV_LD_LD: u8 = 0x3; pub const RISCV_LD_LBU: u8 = 0x4; pub const RISCV_LD_LHU: u8 = 0x5; pub const RISCV_LD_LWU: u8 = 0x6; pub const RISCV_ST_STH: u8 = 0x1; pub const RISCV_ST_STW: u8 = 0x2; pub const RISCV_ST_STB: u8 = 0x0; pub const RISCV_ST_STD: u8 = 0x3; pub const RISCV_OPI_ADDI: u8 = 0x0; pub const RISCV_OPI_SLTI: u8 = 0x2; pub const RISCV_OPI_SLTIU: u8 = 0x3; pub const RISCV_OPI_XORI: u8 = 0x4; pub const RISCV_OPI_ORI: u8 = 0x6; pub const RISCV_OPI_ANDI: u8 = 0x7; pub const RISCV_OPI_SLLI: u8 = 0x1; pub const RISCV_OPI_SRI: u8 = 0x5; pub const RISCV_OPI_SRI_SRAI: u8 = 0x20; pub const RISCV_OPI_SRI_SRLI: u8 = 0x0; pub const RISCV_OP_ADD: u8 = 0x0; pub const RISCV_OP_SLL: u8 = 0x1; pub const RISCV_OP_SLT: u8 = 0x2; pub const RISCV_OP_SLTU: u8 = 0x3; pub const RISCV_OP_XOR: u8 = 0x4; pub const RISCV_OP_SR: u8 = 0x5; pub const RISCV_OP_OR: u8 = 0x6; pub const RISCV_OP_AND: u8 = 0x7; pub const RISCV_OP_ADD_ADD: u8 = 0x0; pub const RISCV_OP_ADD_SUB: u8 = 0x20; pub const RISCV_OP_SR_SRL: u8 = 0x0; 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; 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", "", ""]; // Register name mapping const reg_x: [&str; 32] = ["zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "fp", "s1", // fp ou s0 ? "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"]; const _reg_f: [&str; 32] = ["ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7", "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7", "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11"]; pub fn print(ins: Instruction, pc: i32) -> String { //TODO pc should be u64 let rd = ins.rd as usize; let rs1 = ins.rs1 as usize; let rs2 = ins.rs2 as usize; match ins.opcode { RISCV_OP => { let name: &str; if ins.funct7 == 1 { // Use mul array 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"; } else { name = "sra"; } } else { name = names_op[ins.funct3 as usize]; } } format!("{} {}, {}, {}", name.to_string(), reg_x[rd], reg_x[rs1], reg_x[rs2]) }, RISCV_OPI => { // SHAMT OR IMM if ins.funct3 == RISCV_OPI_SRI { if ins.funct7 == RISCV_OPI_SRI_SRLI { format!("slrii {}, {}, {}", reg_x[rd], reg_x[rs1], ins.shamt.to_string()) } else { format!("srai {}, {}, {}", reg_x[rd], reg_x[rs1], ins.shamt.to_string()) } } else if ins.funct3 == RISCV_OPI_SLLI { format!("{} {}, {}, {}", names_opi[ins.funct3 as usize], reg_x[rd], reg_x[rs1], ins.shamt.to_string()) } else { format!("{} {}, {}, {}", names_opi[ins.funct3 as usize], reg_x[rd], reg_x[rs1], ins.imm12_I_signed.to_string()) } }, RISCV_LUI => { format!("lui {}, 0x{:X}", reg_x[rd], ins.imm31_12) }, RISCV_AUIPC => { format!("auipc {}, {:X}", reg_x[rd], ins.imm31_12) }, RISCV_JAL => { if ins.rd == 0 { format!("j {}", ins.imm31_12.to_string()) } else { format!("jal {}, {:X}", reg_x[rd], (pc - 4 + ins.imm21_1_signed)) } }, RISCV_JALR => { if ins.rd == 0 { if ins.rs1 == 1 { "ret".to_string() } else { format!("jr {:X}", ins.imm31_12) } } else { format!("jalr {}, ({})", ins.imm12_I_signed.to_string(), reg_x[rs1]) } }, RISCV_BR => { format!("{} {}, {}, {}", names_br[ins.funct3 as usize].to_string(), reg_x[rs1], reg_x[rs2], ins.imm13_signed.to_string()) }, RISCV_LD => { format!("{} {}, {}({})", names_ld[ins.funct3 as usize].to_string(), reg_x[rd], ins.imm12_I_signed.to_string(), reg_x[rs1]) }, RISCV_ST => { format!("{} {}, {}({})", names_st[ins.funct3 as usize].to_string(), reg_x[rs2], ins.imm12_S_signed.to_string(), reg_x[rs1]) }, RISCV_OPIW => { if ins.funct3 == RISCV_OPIW_SRW { if ins.funct7 == RISCV_OPIW_SRW_SRLIW { format!("srlwi {}, {}, {}", reg_x[rd], reg_x[rs1], reg_x[rs2]) } else { format!("srawi {}, {}, {}", reg_x[rd], reg_x[rs1], reg_x[rs2]) } } else if ins.funct3 == RISCV_OPIW_SLLIW { format!("{} {}, {}, {}", names_opi[ins.funct3 as usize], reg_x[rd], reg_x[rs1], reg_x[rs2]) } else { format!("{} {}, {}, {}", names_opiw[ins.funct3 as usize], reg_x[rd], reg_x[rs1], ins.imm12_I_signed.to_string()) } }, RISCV_OPW => { if ins.funct7 == 1 { format!("{}w {}, {}, {}", names_mul[ins.funct3 as usize].to_string(), 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 {}, {}, {}", reg_x[rd], reg_x[rs1], reg_x[rs2]) } else { format!("subw {}, {}, {}", reg_x[rd], reg_x[rs1], reg_x[rs2]) } } else if ins.funct3 == RISCV_OPW_SRW { if ins.funct7 == RISCV_OPW_SRW_SRLW { format!("srlw {}, {}, {}", reg_x[rd], reg_x[rs1], reg_x[rs2]) } else { format!("sraw {}, {}, {}", reg_x[rd], reg_x[rs1], reg_x[rs2]) } } else { format!("{} {}, {}, {}", names_opw[ins.funct3 as usize], reg_x[rd], reg_x[rs1], reg_x[rs2]) } } }, RISCV_SYSTEM => { "ecall".to_string() }, _ => "Unknown".to_string() // Error } } #[cfg(test)] mod test { use crate::{print, decode}; #[test] 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); assert_eq!("sub t3, a7, a6", print::print(sub, 0)); assert_eq!("xor t3, a7, a6", print::print(xor, 0)); assert_eq!("srl t3, a7, a6", print::print(slr, 0)); assert_eq!("sra t3, a7, a6", print::print(sra, 0)); assert_eq!("add t3, a7, a6", print::print(add, 0)); } #[test] fn test_opi() { let addi = decode::decode(0b0000000000_10001_000_11100_0010011); 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); let andi = decode::decode(0b000000000000_10001_111_11100_0010011); assert_eq!("andi t3, a7, 0", print::print(andi, 0)); assert_eq!("addi t3, a7, 0", print::print(addi, 0)); assert_eq!("slli t3, a7, 0", print::print(slli, 0)); assert_eq!("slti t3, a7, 0", print::print(slti, 0)); assert_eq!("sltiu t3, a7, 0", print::print(sltiu, 0)); assert_eq!("xori t3, a7, 0", print::print(xori, 0)); assert_eq!("ori t3, a7, 0", print::print(ori, 0)); } #[test] fn test_lui() { let lui = decode::decode(0b01110001000011111000_11100_0110111); let lui_negatif = decode::decode(0b11110001000011111000_11100_0110111); assert_eq!("lui t3, 0x710F8000", print::print(lui, 0)); assert_eq!("lui t3, 0xF10F8000", print::print(lui_negatif, 0)); } #[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); // TODO: imm négatif produit une erreur assert_eq!("lb t3, 1520(a7)", print::print(lb, 0)); assert_eq!("lh t3, 1520(a7)", print::print(lh, 0)); assert_eq!("lw t3, 1520(a7)", print::print(lw, 0)); assert_eq!("lbu t3, 1520(a7)", print::print(lbu, 0)); assert_eq!("lhu t3, 1520(a7)", print::print(lhu, 0)); assert_eq!("ld t3, 1520(a7)", print::print(ld, 0)); assert_eq!("lwu t3, 1520(a7)", print::print(lwu, 0)); } #[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); assert_eq!("addw t3, a7, a6", print::print(addw, 0)); assert_eq!("sllw t3, a7, a6", print::print(sllw, 0)); assert_eq!("srlw t3, a7, a6", print::print(srlw, 0)); assert_eq!("sraw t3, a7, a6", print::print(sraw, 0)); } #[test] fn test_opwi() { let addiw: decode::Instruction =decode::decode(0b000000000000_10001_000_11100_0011011); let slliw: decode::Instruction = decode::decode(0b0000000_10000_10001_001_11100_0011011); let srai: decode::Instruction = decode::decode(0b010000010001_10001_101_11100_0010011); assert_eq!("addiw t3, a7, 0", print::print(addiw, 0)); assert_eq!("slli t3, a7, a6", print::print(slliw, 0)); assert_eq!("srai t3, a7, 17", print::print(srai, 0)); } #[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); assert_eq!("blt a7, a6, 0", print::print(blt, 0)); assert_eq!("bge a7, a6, 0", print::print(bge, 0)); assert_eq!("bltu a7, a6, 0", print::print(bltu, 0)); assert_eq!("bgeu a7, a6, 0", print::print(bgeu, 0)); assert_eq!("bne a7, a6, 0", print::print(bne, 0)); assert_eq!("beq a7, a6, 0", print::print(beq, 0)); } }