From f5cee0ce57f08c954ab5ca49508670a05bfd46bd Mon Sep 17 00:00:00 2001 From: Elliot Baptist Date: Fri, 2 Aug 2024 11:17:36 +0100 Subject: [PATCH] Add RV_C disassembly Implement basic disassembly for RV_C (compressed instructions). Only the compressed instruction and given operands are shown in the printed output. No expansion to non-compressed instructions or insertion of implicit operands is performed. Simplicity was the aim, given the high number array of special cases. --- src/RISCV/Helpers.hs | 113 +++++++++++++++++++++++++++++++++++++++ src/RISCV/InstInspect.hs | 2 + src/RISCV/RV_C.hs | 73 +++++++++++++++++++++++-- 3 files changed, 185 insertions(+), 3 deletions(-) diff --git a/src/RISCV/Helpers.hs b/src/RISCV/Helpers.hs index c023ee0..f52de5d 100644 --- a/src/RISCV/Helpers.hs +++ b/src/RISCV/Helpers.hs @@ -74,6 +74,26 @@ module RISCV.Helpers ( , prettyR_rm , prettyR4_rm , prettyS_F +, prettyCR +, prettyCR_1op +, prettyCI +, prettyCI_sig +, prettyCI_F +, prettyCI_reg +, prettyCI_imm +, prettyCI_sig_imm +, prettyCSS +, prettyCSS_F +, prettyCIW +, prettyCL +, prettyCL_F +, prettyCS +, prettyCS_F +, prettyCA +, prettyCB +, prettyCB_sig +, prettyCB_reg +, prettyCJ -- * Others , reg , int @@ -204,6 +224,28 @@ toSigned :: (Ord a, Num a) => Int -> a -> a toSigned w x | x >= 0 = if x >= 2^(w-1) then x - 2^w else x | otherwise = error $ "cannot toSigned on negative number" +-- | RVC compressed integer register pretty printer +reg' :: Integer -> String +reg' = cIntReg + +-- | Gives a RISCV register name 'String' when provided an RVC compressed +-- integer register index +cIntReg :: Integer -> String +cIntReg i + | i >= 0 && i < 8 = intReg (i + 8) + | otherwise = "unknownCompressedRegIdx" ++ show i + +-- | RVC compressed floating-point register pretty printer +fpReg' :: Integer -> String +fpReg' = cFpReg + +-- | Gives a RISCV floating point register name 'String' when provided an +-- RVC compressed floating-point register index +cFpReg :: Integer -> String +cFpReg i + | i >= 0 && i < 8 = fpReg (i + 8) + | otherwise = "unknownCompressedRegIdx" ++ show i + -- ** Instructions @@ -326,6 +368,77 @@ prettyR4_rm instr rs3 rs2 rs1 rm rd = prettyS_F instr imm rs2 rs1 = concat [instr, " ", fpReg rs2, ", ", reg rs1, "(", int imm, ")"] +-- ** Compressed Instructions + +-- | CR-type 'Register' compressed instruction pretty printer +prettyCR instr rs2 rs1_rd = + concat [instr, " ", reg rs1_rd, ", ", reg rs2] +-- | CR-type (single-operand variant) +prettyCR_1op instr rs1_rd = + concat [instr, " ", reg rs1_rd] + +-- | CI-type 'Immediate' compressed instruction pretty printer +prettyCI instr imm rs1_rd = + concat [instr, " ", reg rs1_rd, ", ", int imm] +-- | CI-type (signed variant) +prettyCI_sig ise instr imm rs1_rd = + concat [instr, " ", reg rs1_rd, ", ", int $ toSigned ise imm] +-- | CI-type (floating-point variant) +prettyCI_F instr imm rs1_rd = + concat [instr, " ", fpReg rs1_rd, ", ", int imm] +-- | CI-type (register-only variant) +prettyCI_reg instr rs1_rd = + concat [instr, " ", reg rs1_rd] +-- | CI-type (immediate-only variant) +prettyCI_imm instr imm = + concat [instr, " ", int imm] +-- | CI-type (signed immediate-only variant) +prettyCI_sig_imm ise instr imm = + concat [instr, " ", int $ toSigned ise imm] + +-- | CSS-type 'Stack-relative Store' compressed instruction pretty printer +prettyCSS instr imm rs2 = + concat [instr, " ", reg rs2, ", ", int imm] +-- | CSS-type (floating-point variant) +prettyCSS_F instr imm rs2 = + concat [instr, " ", fpReg rs2, ", ", int imm] + +-- | CIW-type 'Wide-Immediate' compressed instruction pretty printer +prettyCIW instr imm rd' = + concat [instr, " ", reg' rd', ", ", int imm] + +-- | CL-type 'Load' compressed instruction pretty printer +prettyCL instr imm rd' rs1' = + concat [instr, " ", reg' rd', ", ", reg' rs1', "[", int imm, "]"] +-- | CL-type (floating-point variant) +prettyCL_F instr imm rd' rs1' = + concat [instr, " ", fpReg' rd', ", ", reg' rs1', "[", int imm, "]"] + +-- | CS-type 'Store' compressed instruction pretty printer +prettyCS instr imm rs1' rs2' = + concat [instr, " ", reg' rs2', ", ", reg' rs1', "[", int imm, "]"] +-- | CS-type (floating-point variant) +prettyCS_F instr imm rs1' rs2' = + concat [instr, " ", fpReg' rs2', ", ", reg' rs1', "[", int imm, "]"] + +-- | CA-type 'Arithmetic' compressed instruction pretty printer +prettyCA instr rs1_rd' rs2' = + concat [instr, " ", reg' rs1_rd', ", ", reg' rs2'] + +-- | CB-type 'Branch' compressed instruction pretty printer +prettyCB instr imm rs1' = + concat [instr, " ", reg' rs1', ", ", int imm] +-- | CB-type (signed variant) +prettyCB_sig ise instr imm rs1' = + concat [instr, " ", reg' rs1', ", ", int $ toSigned ise imm] +-- | CB-type (register-only variant) +prettyCB_reg instr rs1' = + concat [instr, " ", reg' rs1'] + +-- | CJ-type 'Jump' compressed instruction pretty printer +prettyCJ instr imm = + concat [instr, " ", int $ toSigned 12 imm] + type ExtractedRegs = ( Bool -- ^ is_bypass , Maybe Integer -- ^ rs2 , Maybe Integer -- ^ rs1 diff --git a/src/RISCV/InstInspect.hs b/src/RISCV/InstInspect.hs index ac3eaba..29295cb 100644 --- a/src/RISCV/InstInspect.hs +++ b/src/RISCV/InstInspect.hs @@ -68,6 +68,7 @@ import RISCV.RV64_M import RISCV.RV64_A import RISCV.RV64_F import RISCV.RV64_D +import RISCV.RV_C import RISCV.Helpers import Text.Printf @@ -85,6 +86,7 @@ rv_pretty instr = case decode 32 instr instList of ++ rv32_zicsr_disass ++ rv32_zifencei_disass ++ rv32_xcheri_disass + ++ rv_c_disass instance Show Instruction where show i@(MkInstruction v) = printf ".4byte 0x%08x # %s" v (rv_pretty i) diff --git a/src/RISCV/RV_C.hs b/src/RISCV/RV_C.hs index dc09df4..74dc69d 100644 --- a/src/RISCV/RV_C.hs +++ b/src/RISCV/RV_C.hs @@ -100,6 +100,15 @@ module RISCV.RV_C ( , rv_c ) where +import RISCV.Helpers (prettyCR, prettyCR_1op, + prettyCI, prettyCI_sig, prettyCI_F, prettyCI_reg,prettyCI_imm, prettyCI_sig_imm, + prettyCSS, prettyCSS_F, + prettyCIW, + prettyCL, prettyCL_F, + prettyCS, prettyCS_F, + prettyCA, + prettyCB, prettyCB_sig, prettyCB_reg, + prettyCJ) import InstrCodec (DecodeBranch, (-->), encode, Instruction) c_illegal_raw = "000 00000000 000 00" @@ -210,11 +219,69 @@ c_fswsp rs2 uimm = encode c_fswsp_raw uimm c_sdsp_raw = "111 uimm[5:3] uimm[8:6] rs2[4:0] 10" c_sdsp rs2 uimm = encode c_sdsp_raw uimm rs2 --- | TODO Dissassembly of RISC-V compressed instructions +-- | Dissassembly of RISC-V compressed instructions padded to 32-bits. +-- | No instruction expansion or implicit operands are shown. +-- | +-- | Note: left-shifting of RV_C immediates is done in `decode`, +-- | not in the pretty printing functions. +pad :: String -> String +pad = (++) "0000000000000000" rv_c_disass :: [DecodeBranch String] -rv_c_disass = [] +rv_c_disass = [ pad c_illegal_raw --> "c.illegal" + , pad c_addi4spn_raw --> prettyCIW "c.addi4spn" + , pad c_fld_raw --> prettyCL_F "c.fld" + , pad c_flq_raw --> prettyCL_F "c.flq" + , pad c_lw_raw --> prettyCL "c.lw" + , pad c_flw_raw --> prettyCL_F "c.flw" + , pad c_ld_raw --> prettyCL "c.ld" +-- , c_res_a_raw + , pad c_fsd_raw --> prettyCS_F "c.fsd" + , pad c_fsq_raw --> prettyCS_F "c.fsq" + , pad c_sw_raw --> prettyCS "c.sw" + , pad c_fsw_raw --> prettyCS_F "c.fsw" + , pad c_sd_raw --> prettyCS "c.sd" + , pad c_nop_raw --> prettyCI_imm "c.nop" + , pad c_addi_raw --> prettyCI_sig 6 "c.addi" + , pad c_jal_raw --> prettyCJ "c.jal" + , pad c_addiw_raw --> prettyCI_sig 6 "c.addiw" + , pad c_li_raw --> prettyCI_sig 6 "c.li" + , pad c_addi16sp_raw --> prettyCI_sig_imm 10 "c.addi16sp" + , pad c_lui_raw --> prettyCI_sig 18 "c.lui" + , pad c_srli64_raw --> prettyCB_reg "c.srli64" + , pad c_srli_raw --> prettyCB "c.srli" + , pad c_srai64_raw --> prettyCB_reg "c.srai64" + , pad c_srai_raw --> prettyCB "c.srai" + , pad c_andi_raw --> prettyCB_sig 6 "c.andi" + , pad c_sub_raw --> prettyCA "c.sub" + , pad c_xor_raw --> prettyCA "c.xor" + , pad c_or_raw --> prettyCA "c.or" + , pad c_and_raw --> prettyCA "c.and" + , pad c_subw_raw --> prettyCA "c.subw" + , pad c_addw_raw --> prettyCA "c.addw" +-- , c_res_b_raw +-- , c_res_c_raw + , pad c_j_raw --> prettyCJ "c.j" + , pad c_beqz_raw --> prettyCB_sig 9 "c.beqz" + , pad c_bnez_raw --> prettyCB_sig 9 "c.bnez" + , pad c_slli64_raw --> prettyCI_reg "c.slli64" + , pad c_slli_raw --> prettyCI "c.slli" + , pad c_fldsp_raw --> prettyCI_F "c.fldsp" + , pad c_lqsp_raw --> prettyCI "c.lqsp" + , pad c_lwsp_raw --> prettyCI "c.lwsp" + , pad c_flwsp_raw --> prettyCI_F "c.flwsp" + , pad c_ldsp_raw --> prettyCI "c.ldsp" + , pad c_jr_raw --> prettyCR_1op "c.jr" + , pad c_mv_raw --> prettyCR "c.mv" + , pad c_ebreak_raw --> "c.ebreak" + , pad c_jalr_raw --> prettyCR_1op "c.jalr" + , pad c_add_raw --> prettyCR "c.add" + , pad c_fsdsp_raw --> prettyCSS_F "c.fsdsp" + , pad c_sqsp_raw --> prettyCSS "c.sqsp" + , pad c_swsp_raw --> prettyCSS "c.swsp" + , pad c_fswsp_raw --> prettyCSS_F "c.fswsp" + , pad c_sdsp_raw --> prettyCSS "c.sdsp" ] --- | TODO List of RISC-V compressed instructions +-- | List of RISC-V compressed instructions rv_c :: Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer