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 } ;
2023-01-20 18:21:32 +01:00
use super ::global ::* ;
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-20 18:21:32 +01:00
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
}