From bd5e0c1596acc85f32b846c8094793a06f9f13de Mon Sep 17 00:00:00 2001 From: Elliot Baptist Date: Tue, 13 Aug 2024 17:54:53 +0100 Subject: [PATCH] Add RVC HINT/RES/NSE encs & rework disassembly Add explicit HINT, Reserved, and NSE compressed instruction encodings from the spec. This allows Templates to more easily specify these special encodings and enables more accurate disassembly. Note that some encodings overlap. Add new instruction disassembly pretty printer functions for special cases where the operands are uninteresting or ambiguous. Rework the disassembly to account for overlapping encodings. Use XLEN, when available, and carful ordering to distinguish overlapping encodings from each other. Present both encodings when encodings overlap and XLEN is not available. Integrate new disassembly so that XLEN will be passed through when known (currently only for RVFI V2 packets). Minor errors may remain. Caution only goes so far when there are so many fiddly changes required. --- src/QuickCheckVEngine/RVFI_DII/RVFI.hs | 2 +- src/RISCV/Helpers.hs | 16 + src/RISCV/InstInspect.hs | 8 +- src/RISCV/RV_C.hs | 546 +++++++++++++++++-------- 4 files changed, 399 insertions(+), 173 deletions(-) diff --git a/src/QuickCheckVEngine/RVFI_DII/RVFI.hs b/src/QuickCheckVEngine/RVFI_DII/RVFI.hs index 1914c65..df9ece3 100644 --- a/src/QuickCheckVEngine/RVFI_DII/RVFI.hs +++ b/src/QuickCheckVEngine/RVFI_DII/RVFI.hs @@ -420,7 +420,7 @@ instance Show RVFI_Packet where (rvfi_insn tok) (privString (rvfi_mode tok)) (xlenString (rvfi_ixl tok)) - (rv_pretty (MkInstruction (toInteger (rvfi_insn tok)))) -- Inst + (rv_pretty (MkInstruction (toInteger (rvfi_insn tok))) (rvfi_ixl tok)) -- Inst -- | Return 'True' for halt 'RVFI_Packet's rvfiIsHalt :: RVFI_Packet -> Bool diff --git a/src/RISCV/Helpers.hs b/src/RISCV/Helpers.hs index f52de5d..f9b2e11 100644 --- a/src/RISCV/Helpers.hs +++ b/src/RISCV/Helpers.hs @@ -85,6 +85,7 @@ module RISCV.Helpers ( , prettyCSS , prettyCSS_F , prettyCIW +, prettyCIW_reg , prettyCL , prettyCL_F , prettyCS @@ -94,6 +95,9 @@ module RISCV.Helpers ( , prettyCB_sig , prettyCB_reg , prettyCJ +, prettyIgnr1 +, prettyIgnr2 +, prettyIgnr3 -- * Others , reg , int @@ -406,6 +410,9 @@ prettyCSS_F instr imm rs2 = -- | CIW-type 'Wide-Immediate' compressed instruction pretty printer prettyCIW instr imm rd' = concat [instr, " ", reg' rd', ", ", int imm] +-- | CIW-type (register-only variant) +prettyCIW_reg instr rd' = + concat [instr, " ", reg' rd'] -- | CL-type 'Load' compressed instruction pretty printer prettyCL instr imm rd' rs1' = @@ -439,6 +446,15 @@ prettyCB_reg instr rs1' = prettyCJ instr imm = concat [instr, " ", int $ toSigned 12 imm] +-- | Operand-swallowing instruction pretty printers. +-- | Useful for special cases, such as reserved or overlapping encodings. +prettyIgnr1 :: String -> Integer -> String +prettyIgnr1 instr _ = instr +prettyIgnr2 :: String -> Integer -> Integer -> String +prettyIgnr2 instr _ _ = instr +prettyIgnr3 :: String -> Integer -> Integer -> Integer-> String +prettyIgnr3 instr _ _ _ = instr + type ExtractedRegs = ( Bool -- ^ is_bypass , Maybe Integer -- ^ rs2 , Maybe Integer -- ^ rs1 diff --git a/src/RISCV/InstInspect.hs b/src/RISCV/InstInspect.hs index 29295cb..6ef16d5 100644 --- a/src/RISCV/InstInspect.hs +++ b/src/RISCV/InstInspect.hs @@ -74,8 +74,8 @@ import RISCV.Helpers import Text.Printf -- | RISC-V instruction pretty printer -rv_pretty :: Instruction -> String -rv_pretty instr = case decode 32 instr instList of +rv_pretty :: Instruction -> Maybe XLen-> String +rv_pretty instr ixl = case decode 32 instr instList of Nothing -> "Unknown instruction" Just i -> i where instList = rv32_i_disass ++ rv64_i_disass @@ -86,10 +86,10 @@ rv_pretty instr = case decode 32 instr instList of ++ rv32_zicsr_disass ++ rv32_zifencei_disass ++ rv32_xcheri_disass - ++ rv_c_disass + ++ rv_c_disass ixl instance Show Instruction where - show i@(MkInstruction v) = printf ".4byte 0x%08x # %s" v (rv_pretty i) + show i@(MkInstruction v) = printf ".4byte 0x%08x # %s" v (rv_pretty i Nothing) rv_extract :: Instruction -> ExtractedRegs rv_extract instr = case decode 32 instr extractList of diff --git a/src/RISCV/RV_C.hs b/src/RISCV/RV_C.hs index a102433..077b588 100644 --- a/src/RISCV/RV_C.hs +++ b/src/RISCV/RV_C.hs @@ -44,52 +44,75 @@ module RISCV.RV_C ( -- * RISC-V compressed instructions, instruction definitions c_illegal , c_addi4spn +, c_addi4spn_res , c_fld , c_lq , c_lw , c_flw , c_ld ---, c_res_a +, c_res_a , c_fsd , c_sq , c_sw , c_fsw , c_sd , c_nop +, c_nop_hint , c_addi +, c_addi_hint , c_jal , c_addiw +, c_addiw_res , c_li +, c_li_hint , c_addi16sp +, c_addi16sp_res , c_lui +, c_lui_hint +, c_lui_res , c_srli64 +, c_srli64_hint , c_srli +, c_srli_nse , c_srai64 +, c_srai64_hint , c_srai +, c_srai_nse , c_andi , c_sub , c_xor , c_or , c_and , c_subw +, c_subw_res , c_addw ---, c_res_b ---, c_res_c +, c_addw_res +, c_res_b +, c_res_c , c_j , c_beqz , c_bnez , c_slli64 +, c_slli64_hint0 +, c_slli64_hintx , c_slli +, c_slli_hint +, c_slli_nse , c_fldsp , c_lqsp , c_lwsp +, c_lwsp_res , c_flwsp , c_ldsp +, c_ldsp_res , c_jr +, c_jr_res , c_mv +, c_mv_hint , c_ebreak , c_jalr , c_add +, c_add_hint , c_fsdsp , c_sqsp , c_swsp @@ -98,66 +121,93 @@ module RISCV.RV_C ( -- * RISC-V compressed instructions, others , rv_c_disass , rv_c +, rv_c_exh ) where -import RISCV.Helpers (prettyCR, prettyCR_1op, - prettyCI, prettyCI_sig, prettyCI_F, prettyCI_reg,prettyCI_imm, prettyCI_sig_imm, +import RISCV.Helpers (XLen, + prettyCR, prettyCR_1op, + prettyCI, prettyCI_sig, prettyCI_F, prettyCI_reg, prettyCI_imm, prettyCI_sig_imm, prettyCSS, prettyCSS_F, - prettyCIW, + prettyCIW, prettyCIW_reg, prettyCL, prettyCL_F, prettyCS, prettyCS_F, prettyCA, prettyCB, prettyCB_sig, prettyCB_reg, - prettyCJ) + prettyCJ, + prettyIgnr1, prettyIgnr2, prettyIgnr3) import InstrCodec (DecodeBranch, (-->), encode, Instruction) +-- | RVC Quadrant 0 c_illegal_raw = "000 00000000 000 00" c_illegal = encode c_illegal_raw +c_addi4spn_res_raw = "000 00 0000 0 0 rd'[2:0] 00" -- REServed, nzimm==0 +c_addi4spn_res rd' = encode c_addi4spn_res_raw rd' -- REServed, nzimm==0 c_addi4spn_raw = "000 nzuimm[5:4] nzuimm[9:6] nzuimm[2] nzuimm[3] rd'[2:0] 00" c_addi4spn rd' nzuimm = encode c_addi4spn_raw nzuimm rd' -c_fld_raw = "001 uimm[5:3] rs1'[2:0] uimm[7:6] rd'[2:0] 00" -c_fld rd' rs1' uimm = encode c_fld_raw uimm rs1' rd' -c_lq_raw = "001 uimm[5:4] uimm[8] rs1'[2:0] uimm[7:6] rd'[2:0] 00" -c_lq rd' rs1' uimm = encode c_lq_raw uimm uimm rs1' rd' +c_fld_raw = "001 uimm[5:3] rs1'[2:0] uimm[7:6] rd'[2:0] 00" -- V MULTI V +c_fld rd' rs1' uimm = encode c_fld_raw uimm rs1' rd' -- RV32DC/RV64DC +c_lq_raw = "001 uimm[5:4] uimm[8] rs1'[2:0] uimm[7:6] rd'[2:0] 00" -- v +c_lq rd' rs1' uimm = encode c_lq_raw uimm uimm rs1' rd' -- RV128C c_lw_raw = "010 uimm[5:3] rs1'[2:0] uimm[2] uimm[6] rd'[2:0] 00" c_lw rd' rs1' uimm = encode c_lw_raw uimm rs1' rd' -c_flw_raw = "011 uimm[5:3] rs1'[2:0] uimm[2] uimm[6] rd'[2:0] 00" -c_flw rd' rs1' uimm = encode c_flw_raw uimm rs1' rd' -c_ld_raw = "011 uimm[5:3] rs1'[2:0] uimm[2] uimm[6] rd'[2:0] 00" -c_ld rd' rs1' uimm = encode c_ld_raw uimm rs1' rd' ---c_res_a_raw = "100 _ 00" ---c_res_a = encode c_res_a_raw -c_fsd_raw = "101 uimm[5:3] rs1'[2:0] uimm[7:6] rs2'[2:0] 00" -c_fsd rs1' rs2' uimm = encode c_fsd_raw uimm rs1' rs2' -c_sq_raw = "101 uimm[5:4] uimm[8] rs1'[2:0] uimm[7:6] rs2'[2:0] 00" -c_sq rs1' rs2' uimm = encode c_sq_raw uimm uimm rs1' rs2' +c_flw_raw = "011 uimm[5:3] rs1'[2:0] uimm[2] uimm[6] rd'[2:0] 00" -- V MULTI V +c_flw rd' rs1' uimm = encode c_flw_raw uimm rs1' rd' -- RV32FC +c_ld_raw = "011 uimm[5:3] rs1'[2:0] uimm[2] uimm[6] rd'[2:0] 00" -- v +c_ld rd' rs1' uimm = encode c_ld_raw uimm rs1' rd' -- RV64C/RV128C +c_res_a_raw = "100 ignr[10:0] 00" -- Reserved instr +c_res_a ignr = encode c_res_a_raw ignr -- Reserved instr +c_fsd_raw = "101 uimm[5:3] rs1'[2:0] uimm[7:6] rs2'[2:0] 00" -- V MULTI V +c_fsd rs1' rs2' uimm = encode c_fsd_raw uimm rs1' rs2' -- RV32DC/RV64DC +c_sq_raw = "101 uimm[5:4] uimm[8] rs1'[2:0] uimm[7:6] rs2'[2:0] 00" -- v +c_sq rs1' rs2' uimm = encode c_sq_raw uimm uimm rs1' rs2' -- RV128C c_sw_raw = "110 uimm[5:3] rs1'[2:0] uimm[2] uimm[6] rs2'[2:0] 00" c_sw rs1' rs2' uimm = encode c_sw_raw uimm rs1' rs2' -c_fsw_raw = "111 uimm[5:3] rs1'[2:0] uimm[2] uimm[6] rs2'[2:0] 00" -c_fsw rs1' rs2' uimm = encode c_fsw_raw uimm rs1' rs2' -c_sd_raw = "111 uimm[5:3] rs1'[2:0] uimm[7:6] rs2'[2:0] 00" -c_sd rs1' rs2' uimm = encode c_sd_raw uimm rs1' rs2' +c_fsw_raw = "111 uimm[5:3] rs1'[2:0] uimm[2] uimm[6] rs2'[2:0] 00" -- V MULTI V +c_fsw rs1' rs2' uimm = encode c_fsw_raw uimm rs1' rs2' -- RV32FC +c_sd_raw = "111 uimm[5:3] rs1'[2:0] uimm[7:6] rs2'[2:0] 00" -- v +c_sd rs1' rs2' uimm = encode c_sd_raw uimm rs1' rs2' -- RV64C/RV128C -c_nop_raw = "000 nzimm[5] 00000 nzimm[4:0] 01" -c_nop nzimm = encode c_nop_raw nzimm +-- | RVC Quadrant 1 +c_nop_raw = "000 0 00000 00000 01" +c_nop = encode c_nop_raw +c_nop_hint_raw = "000 nzimm[5] 00000 nzimm[4:0] 01" -- HINT, nzimm\=0 +c_nop_hint nzimm = encode c_nop_hint_raw nzimm -- HINT, nzimm\=0 +c_addi_hint_raw = "000 0 rs1_rd_nz[4:0] 00000 01" -- HINT, nzimm==0 +c_addi_hint rs1_rd_nz = encode c_addi_hint_raw rs1_rd_nz -- HINT, nzimm==0 c_addi_raw = "000 nzimm[5] rs1_rd_nz[4:0] nzimm[4:0] 01" c_addi rs1_rd_nz nzimm = encode c_addi_raw nzimm rs1_rd_nz -c_jal_raw = "001 imm[11] imm[4] imm[9:8] imm[10] imm[6] imm[7] imm[3:1] imm[5] 01" -c_jal imm = encode c_jal_raw imm -c_addiw_raw = "001 imm[5] rs1_rd_nz[4:0] imm[4:0] 01" -c_addiw rs1_rd_nz imm = encode c_addiw_raw imm rs1_rd_nz +c_jal_raw = "001 imm[11] imm[4] imm[9:8] imm[10] imm[6] imm[7] imm[3:1] imm[5] 01" -- RV32 +c_jal imm = encode c_jal_raw imm -- RV32 +c_addiw_res_raw = "001 imm[5] 00000 imm[4:0] 01" -- RV64C/RV128C; REServed, rd==0 +c_addiw_res imm = encode c_addiw_res_raw imm -- RV64C/RV128C; REServed, rd==0 +c_addiw_raw = "001 imm[5] rs1_rd_nz[4:0] imm[4:0] 01" -- RV64C/RV128C +c_addiw rs1_rd_nz imm = encode c_addiw_raw imm rs1_rd_nz -- RV64C/RV128C +c_li_hint_raw = "010 imm[5] 00000 imm[4:0] 01" -- HINT, rd==0 +c_li_hint imm = encode c_li_hint_raw imm -- HINT, rd==0 c_li_raw = "010 imm[5] rd_nz[4:0] imm[4:0] 01" c_li rd_nz imm = encode c_li_raw imm rd_nz +c_addi16sp_res_raw = "011 0 00010 0 0 00 0 01" -- REServed, nzimm==0 +c_addi16sp_res = encode c_addi16sp_res_raw -- REServed, nzimm==0 c_addi16sp_raw = "011 nzimm[9] 00010 nzimm[4] nzimm[6] nzimm[8:7] nzimm[5] 01" c_addi16sp nzimm = encode c_addi16sp_raw nzimm +c_lui_hint_raw = "011 nzimm[17] 00000 nzimm[16:12] 01" -- HINT, rd==0 +c_lui_hint nzimm = encode c_lui_hint_raw nzimm -- HINT, rd==0 +c_lui_res_raw = "011 0 rd_nz_n2[4:0] 00000 01" -- REServed, nzimm==0 +c_lui_res rd_nz_n2 = encode c_lui_res_raw rd_nz_n2 -- REServed, nzimm==0 c_lui_raw = "011 nzimm[17] rd_nz_n2[4:0] nzimm[16:12] 01" c_lui rd_nz_n2 nzimm = encode c_lui_raw nzimm rd_nz_n2 -c_srli64_raw = "100 0 00 rs1'_rd'[2:0] 00000 01" -c_srli64 rs1'_rd' = encode c_srli64_raw rs1'_rd' +c_srli64_raw = "100 0 00 rs1'_rd'[2:0] 00000 01" -- V MULTI V +c_srli64_hint rs1'_rd' = encode c_srli64_raw rs1'_rd' -- RV32C/RV64C HINT instr +c_srli64 rs1'_rd' = encode c_srli64_raw rs1'_rd' -- RV128C +c_srli_nse_raw = "100 1 00 rs1'_rd'[2:0] nzuimm[4:0] 01" -- RV32C NSE (reserved for custom extensions) +c_srli_nse rs1'_rd' nzuimm = encode c_srli_nse_raw nzuimm rs1'_rd' -- RV32C NSE (reserved for custom extensions) c_srli_raw = "100 nzuimm[5] 00 rs1'_rd'[2:0] nzuimm[4:0] 01" c_srli rs1'_rd' nzuimm = encode c_srli_raw nzuimm rs1'_rd' -c_srai64_raw = "100 0 01 rs1'_rd'[2:0] 00000 01" -c_srai64 rs1'_rd' = encode c_srai64_raw rs1'_rd' +c_srai64_raw = "100 0 01 rs1'_rd'[2:0] 00000 01" -- V MULTI V +c_srai64 rs1'_rd' = encode c_srai64_raw rs1'_rd' -- RV128C +c_srai64_hint rs1'_rd' = encode c_srai64_raw rs1'_rd' -- RV32C/RV64C HINT instr +c_srai_nse_raw = "100 1 01 rs1'_rd'[2:0] nzuimm[4:0] 01" -- RV32C NSE (reserved for custom extensions) +c_srai_nse rs1'_rd' nzuimm = encode c_srai_nse_raw rs1'_rd' nzuimm -- RV32C NSE (reserved for custom extensions) c_srai_raw = "100 nzuimm[5] 01 rs1'_rd'[2:0] nzuimm[4:0] 01" c_srai rs1'_rd' nzuimm = encode c_srai_raw nzuimm rs1'_rd' c_andi_raw = "100 imm[5] 10 rs1'_rd'[2:0] imm[4:0] 01" @@ -170,118 +220,237 @@ c_or_raw = "100 0 11 rs1'_rd'[ c_or rs1'_rd' rs2' = encode c_or_raw rs1'_rd' rs2' c_and_raw = "100 0 11 rs1'_rd'[2:0] 11 rs2'[2:0] 01" c_and rs1'_rd' rs2' = encode c_and_raw rs1'_rd' rs2' -c_subw_raw = "100 1 11 rs1'_rd'[2:0] 00 rs2'[2:0] 01" -c_subw rs1'_rd' rs2' = encode c_subw_raw rs1'_rd' rs2' -c_addw_raw = "100 1 11 rs1'_rd'[2:0] 01 rs2'[2:0] 01" -c_addw rs1'_rd' rs2' = encode c_addw_raw rs1'_rd' rs2' ---c_res_b_raw = "100 1 11 _ 10 _ 01" ---c_res_b = encode c_res_b_raw ---c_res_c_raw = "100 1 11 _ 11 _ 01" ---c_res_c = encode c_res_c_raw +c_subw_raw = "100 1 11 rs1'_rd'[2:0] 00 rs2'[2:0] 01" -- V MULTI V +c_subw rs1'_rd' rs2' = encode c_subw_raw rs1'_rd' rs2' -- RV64C/RV128C +c_subw_res rs1'_rd' rs2' = encode c_subw_raw rs1'_rd' rs2' -- RV32C REServed instr +c_addw_raw = "100 1 11 rs1'_rd'[2:0] 01 rs2'[2:0] 01" -- V MULTI V +c_addw rs1'_rd' rs2' = encode c_addw_raw rs1'_rd' rs2' -- RV64C/RV128C +c_addw_res rs1'_rd' rs2' = encode c_addw_raw rs1'_rd' rs2' -- RV32C REServed instr +c_res_b_raw = "100 1 11 ignr[5:3] 10 ignr[2:0] 01" -- Reserved instr +c_res_b ignr = encode c_res_b_raw ignr -- Reserved instr +c_res_c_raw = "100 1 11 ignr[5:3] 11 ignr[2:0] 01" -- Reserved instr +c_res_c ignr = encode c_res_c_raw ignr -- Reserved instr c_j_raw = "101 imm[11] imm[4] imm[9:8] imm[10] imm[6] imm[7] imm[3:1] imm[5] 01" c_j imm = encode c_j_raw imm c_beqz_raw = "110 imm[8] imm[4:3] rs1'[2:0] imm[7:6] imm[2:1] imm[5] 01" c_beqz rs1' imm = encode c_beqz_raw imm rs1' c_bnez_raw = "111 imm[8] imm[4:3] rs1'[2:0] imm[7:6] imm[2:1] imm[5] 01" c_bnez rs1' imm = encode c_bnez_raw imm rs1' -c_slli64_raw = "000 0 rs1_rd_nz[4:0] 00000 10" -c_slli64 rs1_rd_nz = encode c_slli64_raw rs1_rd_nz + +-- | RVC Quadrant 2 +c_slli64_hint0_raw = "000 0 00000 00000 10" -- HINT, rd==0 (overlap w/ c_slli64_hintx for RV32C/RV64C) +c_slli64_hint0 = encode c_slli64_hint0_raw -- HINT, rd==0 (overlap w/ c_slli64_hintx for RV32C/RV64C) +c_slli64_raw = "000 0 rs1_rd_nz[4:0] 00000 10" -- V MULTI V +c_slli64 rs1_rd_nz = encode c_slli64_raw rs1_rd_nz -- RV128C +c_slli64_hintx rs1_rd_nz = encode c_slli64_raw rs1_rd_nz -- RV32C/RV64C HINT instr +c_slli_hint_raw = "000 nzuimm[5] 00000 nzuimm[4:0] 10" -- HINT, rd==0 +c_slli_hint nzuimm = encode c_slli_hint_raw nzuimm -- HINT, rd==0 +c_slli_nse_raw = "000 1 rs1_rd_nz[4:0] nzuimm[4:0] 10" -- RV32C NSE (reserved for custom extensions) +c_slli_nse rs1_rd_nz nzuimm = encode c_slli_nse_raw rs1_rd_nz nzuimm -- RV32C NSE (reserved for custom extensions) c_slli_raw = "000 nzuimm[5] rs1_rd_nz[4:0] nzuimm[4:0] 10" c_slli rs1_rd_nz nzuimm = encode c_slli_raw nzuimm rs1_rd_nz -c_fldsp_raw = "001 uimm[5] rd[4:0] uimm[4:3] uimm[8:6] 10" -c_fldsp rd uimm = encode c_fldsp_raw uimm rd -c_lqsp_raw = "001 uimm[5] rd_nz[4:0] uimm[4] uimm[9:6] 10" -c_lqsp rd_nz uimm = encode c_lqsp_raw uimm rd_nz +c_fldsp_raw = "001 uimm[5] rd[4:0] uimm[4:3] uimm[8:6] 10" -- RV32DC/RV64DC +c_fldsp rd uimm = encode c_fldsp_raw uimm rd -- RV32DC/RV64DC +c_lqsp_res_raw = "001 uimm[5] 00000 uimm[4] uimm[9:6] 10" -- RV128C; REServed, rd==0 +c_lqsp_res uimm = encode c_lqsp_res_raw uimm -- RV128C; REServed, rd==0 +c_lqsp_raw = "001 uimm[5] rd_nz[4:0] uimm[4] uimm[9:6] 10" -- RV128C +c_lqsp rd_nz uimm = encode c_lqsp_raw uimm rd_nz -- RV128C +c_lwsp_res_raw = "010 uimm[5] 00000 uimm[4:2] uimm[7:6] 10" -- REServed, rd==0 +c_lwsp_res uimm = encode c_lwsp_res_raw uimm -- REServed, rd==0 c_lwsp_raw = "010 uimm[5] rd_nz[4:0] uimm[4:2] uimm[7:6] 10" c_lwsp rd_nz uimm = encode c_lwsp_raw uimm rd_nz -c_flwsp_raw = "011 uimm[5] rd[4:0] uimm[4:2] uimm[7:6] 10" -c_flwsp rd uimm = encode c_flwsp_raw uimm rd -c_ldsp_raw = "011 uimm[5] rd_nz[4:0] uimm[4:2] uimm[7:6] 10" -c_ldsp rd_nz uimm = encode c_ldsp_raw uimm rd_nz +c_flwsp_raw = "011 uimm[5] rd[4:0] uimm[4:2] uimm[7:6] 10" -- v MULTI V +c_flwsp rd uimm = encode c_flwsp_raw uimm rd -- RV32FC +c_ldsp_res_raw = "011 uimm[5] 00000 uimm[4:2] uimm[7:6] 10" -- v +c_ldsp_res uimm = encode c_ldsp_res_raw uimm -- RV64C/RV128C; REServed, rd==0 +c_ldsp_raw = "011 uimm[5] rd_nz[4:0] uimm[4:2] uimm[7:6] 10" -- v +c_ldsp rd_nz uimm = encode c_ldsp_raw uimm rd_nz -- RV64C/RV128C +c_jr_res_raw = "100 0 00000 00000 10" -- REServed, rs1==0 +c_jr_res = encode c_jr_res_raw -- REServed, rs1==0 c_jr_raw = "100 0 rs1_nz[4:0] 00000 10" c_jr rs1_nz = encode c_jr_raw rs1_nz +c_mv_hint_raw = "100 0 00000 rs2_nz[4:0] 10" -- HINT, rd==0 +c_mv_hint rs2_nz = encode c_mv_hint_raw rs2_nz -- HINT, rd==0 c_mv_raw = "100 0 rd_nz[4:0] rs2_nz[4:0] 10" c_mv rd_nz rs2_nz = encode c_mv_raw rd_nz rs2_nz c_ebreak_raw = "100 1 00000 00000 10" c_ebreak = encode c_ebreak_raw c_jalr_raw = "100 1 rs1_nz[4:0] 00000 10" c_jalr rs1_nz = encode c_jalr_raw rs1_nz +c_add_hint_raw = "100 1 00000 rs2_nz[4:0] 10" -- HINT, rd==0 +c_add_hint rs2_nz = encode c_add_hint_raw rs2_nz -- HINT, rd==0 c_add_raw = "100 1 rs1_rd_nz[4:0] rs2_nz[4:0] 10" c_add rs1_rd_nz rs2_nz = encode c_add_raw rs1_rd_nz rs2_nz -c_fsdsp_raw = "101 uimm[5:3] uimm[8:6] rs2[4:0] 10" -c_fsdsp rs2 uimm = encode c_fsdsp_raw uimm rs2 -c_sqsp_raw = "101 uimm[5:4] uimm[9:6] rs2[4:0] 10" -c_sqsp rs2 uimm = encode c_sqsp_raw uimm rs2 +c_fsdsp_raw = "101 uimm[5:3] uimm[8:6] rs2[4:0] 10" -- RV32DC/RV64DC +c_fsdsp rs2 uimm = encode c_fsdsp_raw uimm rs2 -- RV32DC/RV64DC +c_sqsp_raw = "101 uimm[5:4] uimm[9:6] rs2[4:0] 10" -- RV128C +c_sqsp rs2 uimm = encode c_sqsp_raw uimm rs2 -- RV128C c_swsp_raw = "110 uimm[5:2] uimm[7:6] rs2[4:0] 10" c_swsp rs2 uimm = encode c_swsp_raw uimm rs2 -c_fswsp_raw = "111 uimm[5:2] uimm[7:6] rs2[4:0] 10" -c_fswsp rs2 uimm = encode c_fswsp_raw uimm rs2 -c_sdsp_raw = "111 uimm[5:3] uimm[8:6] rs2[4:0] 10" -c_sdsp rs2 uimm = encode c_sdsp_raw uimm rs2 +c_fswsp_raw = "111 uimm[5:2] uimm[7:6] rs2[4:0] 10" -- RV32FC +c_fswsp rs2 uimm = encode c_fswsp_raw uimm rs2 -- RV32FC +c_sdsp_raw = "111 uimm[5:3] uimm[8:6] rs2[4:0] 10" -- RV64C/RV128C +c_sdsp rs2 uimm = encode c_sdsp_raw uimm rs2 -- RV64C/RV128C --- | Dissassembly of RISC-V compressed instructions padded to 32-bits. +-- | Disassembly of RISC-V compressed instructions padded to 32-bits. +-- | Precise across all encodings only when XLEN is specified, +-- | otherwise will show both possibilities when two encodings overlap. -- | 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 = [ pad c_illegal_raw --> "c.illegal" - , pad c_addi4spn_raw --> prettyCIW "c.addi4spn" - , pad c_fld_raw --> prettyCL_F "c.fld" - , pad c_lq_raw --> prettyCL "c.lq" - , 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_sq_raw --> prettyCS "c.sq" - , 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" ] +rv_c_disass :: Maybe XLen -> [DecodeBranch String] +rv_c_disass (Just ixl) | ixl == 1 = rv_c_32_disass + | ixl == 2 = rv_c_64_disass + | ixl == 3 = rv_c_128_disass + | otherwise = rv_c_multi_disass +rv_c_disass Nothing = rv_c_multi_disass + +-- | Precise RV32C disassembly +rv_c_32_disass :: [DecodeBranch String] +rv_c_32_disass = [ pad c_fld_raw --> prettyCL_F "c.fld" + , pad c_flw_raw --> prettyCL_F "c.flw" + , pad c_fsd_raw --> prettyCS_F "c.fsd" + , pad c_fsw_raw --> prettyCS_F "c.fsw" + + , pad c_jal_raw --> prettyCJ "c.jal" + , pad c_srli_nse_raw --> prettyCB "c.srli.nse" + , pad c_srli64_raw --> prettyCB_reg "c.srli64.hint" + , pad c_srai_nse_raw --> prettyCB "c.srai.nse" + , pad c_srai64_raw --> prettyCB_reg "c.srai64.hint" + , pad c_subw_raw --> prettyCA "c.subw.res" + , pad c_addw_raw --> prettyCA "c.addw.res" + + , pad c_slli_nse_raw --> prettyCI "c.slli.nse" + , pad c_slli64_raw --> prettyCI_reg "c.slli64.hint" + , pad c_fldsp_raw --> prettyCI_F "c.fldsp" + , pad c_flwsp_raw --> prettyCI_F "c.flwsp" + , pad c_fsdsp_raw --> prettyCSS_F "c.fsdsp" + , pad c_fswsp_raw --> prettyCSS_F "c.fswsp" + ] ++ rv_c_common_disass + +-- | Precise RV64C disassembly +rv_c_64_disass :: [DecodeBranch String] +rv_c_64_disass = [ pad c_fld_raw --> prettyCL_F "c.fld" + , pad c_ld_raw --> prettyCL "c.ld" + , pad c_fsd_raw --> prettyCS_F "c.fsd" + , pad c_sd_raw --> prettyCS "c.sd" + + , pad c_addiw_raw --> prettyCI_sig 6 "c.addiw" + , pad c_addiw_res_raw --> prettyCI_sig_imm 6 "c.addiw.res" + , pad c_srli64_raw --> prettyCB_reg "c.srli64.hint" + , pad c_srai64_raw --> prettyCB_reg "c.srai64.hint" + , pad c_subw_raw --> prettyCA "c.subw" + , pad c_addw_raw --> prettyCA "c.addw" + + , pad c_slli64_raw --> prettyCI_reg "c.slli64.hint" + , pad c_ldsp_res_raw --> prettyCI_imm "c.ldsp.res" + , pad c_ldsp_raw --> prettyCI "c.ldsp" + , pad c_fsdsp_raw --> prettyCSS_F "c.fsdsp" + , pad c_sdsp_raw --> prettyCSS "c.sdsp" + ] ++ rv_c_common_disass + +-- | Precise RV128C disassembly +rv_c_128_disass :: [DecodeBranch String] +rv_c_128_disass = [ pad c_lq_raw --> prettyCL "c.lq" + , pad c_ld_raw --> prettyCL "c.ld" + , pad c_sq_raw --> prettyCS_F "c.sq" + , pad c_sd_raw --> prettyCS "c.sd" + + , pad c_addiw_raw --> prettyCI_sig 6 "c.addiw" + , pad c_addiw_res_raw --> prettyCI_sig_imm 6 "c.addiw.res" + , pad c_srli64_raw --> prettyCB_reg "c.srli64" + , pad c_srai64_raw --> prettyCB_reg "c.srai64" + , pad c_subw_raw --> prettyCA "c.subw" + , pad c_addw_raw --> prettyCA "c.addw" + + , pad c_slli64_raw --> prettyCI_reg "c.slli64" + , pad c_lqsp_res_raw --> prettyCI_imm "c.lqsp.res" + , pad c_lqsp_raw --> prettyCI "c.lqsp" + , pad c_ldsp_res_raw --> prettyCI_imm "c.ldsp.res" + , pad c_ldsp_raw --> prettyCI "c.ldsp" + , pad c_sqsp_raw --> prettyCSS "c.sqsp" + , pad c_sdsp_raw --> prettyCSS "c.sdsp" + ] ++ rv_c_common_disass --- | List of RISC-V compressed instructions +-- | General RV32C/RV64C/RV128C disassembly +rv_c_multi_disass :: [DecodeBranch String] +rv_c_multi_disass = [ pad c_lq_raw --> prettyIgnr3 "c.fld (RV32DC/RV64DC) / c.lq (RV128C)" + , pad c_ld_raw --> prettyIgnr3 "c.flw (RV32FC) / c.ld (RV64C/RV128C)" + , pad c_sq_raw --> prettyIgnr3 "c.fsd (RV32DC/RV64DC) / c.sq (RV128C)" + , pad c_sd_raw --> prettyIgnr3 "c.fsw (RV32FC) / c.sd (RV64C/RV128C)" + + , pad c_jal_raw --> prettyIgnr1 "c.jal (RV32C) / c.addiw (RV64C/RV128C)" + , pad c_srli_nse_raw --> prettyIgnr2 "c.srli.nse (RV32C) / c.srli (RV64C/RV128C)" + , pad c_srli64_raw --> prettyCB_reg "c.srli64.hint (RV32C/RV64C) / c.srli64 (RV128C)" + , pad c_srai_nse_raw --> prettyIgnr2 "c.srai.nse (RV32C) / c.srai (RV64C/RV128C)" + , pad c_srai64_raw --> prettyCB_reg "c.srai64.hint (RV32C/RV64C) / c.srai64 (RV128C)" + , pad c_subw_raw --> prettyCA "c.subw.res (RV32C) / c.subw (RV64C/RV128C)" + , pad c_addw_raw --> prettyCA "c.addw.res (RV32C) / c.addw (RV64C/RV128C)" + + , pad c_slli_nse_raw --> prettyIgnr2 "c.slli.nse (RV32C) / c.slli (RV64C/RV128C)" + , pad c_slli64_raw --> prettyCI_reg "c.slli64.hint (RV32C/RV64C) / c.slli64 (RV128C)" + , pad c_lqsp_res_raw --> prettyIgnr1 "c.fldsp (RV32DC/RV64DC) / c.lqsp.res (RV128C)" + , pad c_lqsp_raw --> prettyIgnr2 "c.fldsp (RV32DC/RV64DC) / c.lqsp (RV128C)" + , pad c_ldsp_res_raw --> prettyIgnr1 "c.flwsp (RV32FC) / c.ldsp.res (RV64C/RV128C)" + , pad c_ldsp_raw --> prettyIgnr2 "c.flwsp (RV32FC) / c.ldsp (RV64C/RV128C)" + , pad c_sqsp_raw --> prettyIgnr2 "c.fsdsp (RV32DC/RV64DC) / c.sqsp (RV128C)" + , pad c_sdsp_raw --> prettyIgnr2 "c.fswsp (RV32FC) / c.sdsp (RV64C/RV128C)" + ] ++ rv_c_common_disass + +-- | Disassembly of the common subset of compressed instruction encodings +-- | across RV32C, RV64C, and RV128C. +-- | Should be a correct disassembly regardless of XLEN. +rv_c_common_disass :: [DecodeBranch String] +rv_c_common_disass = [ pad c_illegal_raw --> "c.illegal" + , pad c_addi4spn_raw --> prettyCIW "c.addi4spn" + , pad c_addi4spn_res_raw --> prettyCIW_reg "c.addi4spn.res" + , pad c_lw_raw --> prettyCL "c.lw" + , pad c_res_a_raw --> prettyIgnr1 "c.reserved" + , pad c_sw_raw --> prettyCS "c.sw" + + , pad c_nop_raw --> "c.nop" + , pad c_nop_hint_raw --> prettyCI_imm "c.nop.hint" + , pad c_addi_hint_raw --> prettyCI_reg "c.addi.hint" + , pad c_addi_raw --> prettyCI_sig 6 "c.addi" + , pad c_li_hint_raw --> prettyCI_sig_imm 6 "c.li.hint" + , pad c_li_raw --> prettyCI_sig 6 "c.li" + , pad c_addi16sp_res_raw --> "c.addi16sp.res" + , pad c_addi16sp_raw --> prettyCI_sig_imm 10 "c.addi16sp" + , pad c_lui_hint_raw --> prettyCI_sig_imm 18 "c.lui.hint" + , pad c_lui_res_raw --> prettyCI_reg "c.lui.res" + , pad c_lui_raw --> prettyCI_sig 18 "c.lui" + , pad c_srli_raw --> prettyCB "c.srli" + , 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_res_b_raw --> prettyIgnr1 "c.reserved" + , pad c_res_c_raw --> prettyIgnr1 "c.reserved" + , 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_hint0_raw --> "c.slli64.hint" + , pad c_slli_hint_raw --> prettyCI_imm "c.slli.hint" + , pad c_slli_raw --> prettyCI "c.slli" + , pad c_lwsp_res_raw --> prettyCI_imm "c.lwsp.res" + , pad c_lwsp_raw --> prettyCI "c.lwsp" + , pad c_jr_res_raw --> "c.jr.res" + , pad c_jr_raw --> prettyCR_1op "c.jr" + , pad c_mv_hint_raw --> prettyCR_1op "c.mv.hint" + , pad c_mv_raw --> prettyCR "c.mv" + , pad c_ebreak_raw --> "c.ebreak" + , pad c_jalr_raw --> prettyCR_1op "c.jalr" + , pad c_add_hint_raw --> prettyCR_1op "c.add.hint" + , pad c_add_raw --> prettyCR "c.add" + , pad c_swsp_raw --> prettyCSS "c.swsp" ] + +-- | List of normal RISC-V compressed instructions rv_c :: Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer @@ -291,57 +460,98 @@ rv_c imm uimm nzimm nzuimm rs1' rs1'_rd' rs1_nz rs1_rd_nz rs2 rs2' rs2_nz rd rd' rd_nz rd_nz_n2 = [ c_illegal - , c_addi4spn rd' nzuimm - , c_fld rd' rs1' uimm - , c_lq rd' rs1' uimm - , c_lw rd' rs1' uimm - , c_flw rd' rs1' uimm - , c_ld rd' rs1' uimm --- , c_res_a - , c_fsd rs1' rs2' uimm - , c_sq rs1' rs2' uimm - , c_sw rs1' rs2' uimm - , c_fsw rs1' rs2' uimm - , c_sd rs1' rs2' uimm + , c_addi4spn rd' nzuimm + , c_fld rd' rs1' uimm + , c_lq rd' rs1' uimm + , c_lw rd' rs1' uimm + , c_flw rd' rs1' uimm + , c_ld rd' rs1' uimm + , c_fsd rs1' rs2' uimm + , c_sw rs1' rs2' uimm + , c_fsw rs1' rs2' uimm + , c_sd rs1' rs2' uimm - , c_nop nzimm - , c_addi rs1_rd_nz nzimm - , c_jal imm - , c_addiw rs1_rd_nz imm - , c_li rd_nz imm - , c_addi16sp nzimm - , c_lui rd_nz_n2 nzimm - , c_srli64 rs1'_rd' - , c_srli rs1'_rd' nzuimm - , c_srai64 rs1'_rd' - , c_srai rs1'_rd' nzuimm - , c_andi rs1'_rd' imm - , c_sub rs1'_rd' rs2' - , c_xor rs1'_rd' rs2' - , c_or rs1'_rd' rs2' - , c_and rs1'_rd' rs2' - , c_subw rs1'_rd' rs2' - , c_addw rs1'_rd' rs2' --- , c_res_b --- , c_res_c - , c_j imm - , c_beqz rs1' imm - , c_bnez rs1' imm + , c_nop + , c_addi rs1_rd_nz nzimm + , c_jal imm + , c_addiw rs1_rd_nz imm + , c_li rd_nz imm + , c_addi16sp nzimm + , c_lui rd_nz_n2 nzimm + , c_srli64 rs1'_rd' + , c_srli rs1'_rd' nzuimm + , c_srai64 rs1'_rd' + , c_srai rs1'_rd' nzuimm + , c_andi rs1'_rd' imm + , c_sub rs1'_rd' rs2' + , c_xor rs1'_rd' rs2' + , c_or rs1'_rd' rs2' + , c_and rs1'_rd' rs2' + , c_subw rs1'_rd' rs2' + , c_addw rs1'_rd' rs2' + , c_j imm + , c_beqz rs1' imm + , c_bnez rs1' imm - , c_slli64 rs1_rd_nz - , c_slli rs1_rd_nz nzuimm - , c_fldsp rd uimm - , c_lqsp rd_nz uimm - , c_lwsp rd_nz uimm - , c_flwsp rd uimm - , c_ldsp rd_nz uimm - , c_jr rs1_nz - , c_mv rd_nz rs2_nz + , c_slli64 rs1_rd_nz + , c_slli rs1_rd_nz nzuimm + , c_fldsp rd uimm + , c_lqsp rd_nz uimm + , c_lwsp rd_nz uimm + , c_flwsp rd uimm + , c_ldsp rd_nz uimm + , c_jr rs1_nz + , c_mv rd_nz rs2_nz , c_ebreak - , c_jalr rs1_nz - , c_add rs1_rd_nz rs2_nz - , c_fsdsp rs2 uimm - , c_sqsp rs2 uimm - , c_swsp rs2 uimm - , c_fswsp rs2 uimm - , c_sdsp rs2 uimm ] + , c_jalr rs1_nz + , c_add rs1_rd_nz rs2_nz + , c_fsdsp rs2 uimm + , c_sqsp rs2 uimm + , c_swsp rs2 uimm + , c_fswsp rs2 uimm + , c_sdsp rs2 uimm ] + +-- | Exaustive list of RISC-V compressed instructions. +-- | Includes the normal list along with HINT, REServed, and NSE encodings. +rv_c_exh :: Integer -> Integer -> Integer -> Integer + -> Integer -> Integer -> Integer -> Integer + -> Integer -> Integer -> Integer + -> Integer -> Integer -> Integer -> Integer + -> [Instruction] +rv_c_exh imm uimm nzimm nzuimm + rs1' rs1'_rd' rs1_nz rs1_rd_nz + rs2 rs2' rs2_nz + rd rd' rd_nz rd_nz_n2 = [ c_addi4spn_res rd' + , c_res_a uimm + + , c_nop_hint nzimm + , c_addi_hint rs1_rd_nz + , c_addiw_res imm -- Reserved only for RV64C/RV128C (otherwise is c_jal) + , c_li_hint imm + , c_addi16sp_res + , c_lui_hint nzimm + , c_lui_res rd_nz_n2 + , c_srli64_hint rs1'_rd' -- HINT only for RV32C/RV64C + , c_srli_nse rs1'_rd' nzuimm -- NSE only for RV32C + , c_srai64_hint rs1'_rd' -- HINT only for RV32C/RV64C + , c_srai_nse rs1'_rd' nzuimm -- NSE only for RV32C + , c_subw_res rs1'_rd' rs2' -- Reserved only for RV32C + , c_addw_res rs1'_rd' rs2' -- Reserved only for RV32C + , c_res_b uimm + , c_res_c uimm + + , c_slli64_hint0 + , c_slli64_hintx rs1_rd_nz -- HINT only for RV32C/RV64C + , c_slli_hint nzuimm + , c_slli_nse rs1_rd_nz nzuimm -- NSE only for RV32C + , c_lqsp_res uimm -- Reserved only for RV128C and RV32C/RV64C w/o F (otherwise is c_fldsp) + , c_lwsp_res uimm + , c_ldsp_res uimm -- Reserved only for RV64C/RV128C and RV32C w/o F (otherwise is c_flwsp) + , c_jr_res + , c_mv_hint rs2_nz + , c_add_hint rs2_nz ] + + ++ rv_c imm uimm nzimm nzuimm + rs1' rs1'_rd' rs1_nz rs1_rd_nz + rs2 rs2' rs2_nz + rd rd' rd_nz rd_nz_n2