From: Andrew Waterman Date: Sun, 31 May 2015 23:38:24 +0000 (-0700) Subject: Add rest of RV32C instructions X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=56701b230823f52c252ce6ab69c18639daa02a14;p=riscv-isa-sim.git Add rest of RV32C instructions --- diff --git a/riscv/decode.h b/riscv/decode.h index 4f57656..91ad73e 100644 --- a/riscv/decode.h +++ b/riscv/decode.h @@ -85,6 +85,7 @@ public: int64_t rvc_ld_imm() { return (x(10, 3) << 3) + (x(5, 2) << 6); } int64_t rvc_j_imm() { return (x(3, 4) << 1) + (x(2, 1) << 5) + (xs(7, 6) << 6); } int64_t rvc_b_imm() { return (x(3, 4) << 1) + (x(2, 1) << 5) + (xs(10, 3) << 6); } + int64_t rvc_simm3() { return x(10, 3); } uint64_t rvc_rd() { return rd(); } uint64_t rvc_rs1() { return rd(); } uint64_t rvc_rs2() { return x(2, 5); } diff --git a/riscv/encoding.h b/riscv/encoding.h index cfe8b38..a95f463 100644 --- a/riscv/encoding.h +++ b/riscv/encoding.h @@ -266,7 +266,7 @@ #define MATCH_C_SLLI 0x1 #define MASK_C_SLLI 0xe003 #define MATCH_C_SLLIW 0x8001 -#define MASK_C_SLLIW 0xf003 +#define MASK_C_SLLIW 0xe003 #define MATCH_C_SRAI 0x2000 #define MASK_C_SRAI 0xe003 #define MATCH_C_SRLI 0x2001 diff --git a/riscv/insns/c_addiw.h b/riscv/insns/c_addiw.h index 27ffd8f..ae4980e 100644 --- a/riscv/insns/c_addiw.h +++ b/riscv/insns/c_addiw.h @@ -1,4 +1,7 @@ require_extension('C'); -require_rv64; -require(insn.rvc_rd() != 0); -WRITE_RD(sext32(RVC_RS1 + insn.rvc_imm())); +if (xlen == 32) { + WRITE_RD(RVC_RS1 & insn.rvc_imm()); // c.andi +} else { + require(insn.rvc_rd() != 0); + WRITE_RD(sext32(RVC_RS1 + insn.rvc_imm())); +} diff --git a/riscv/insns/c_ldsp.h b/riscv/insns/c_ldsp.h index 7047d53..aa98f33 100644 --- a/riscv/insns/c_ldsp.h +++ b/riscv/insns/c_ldsp.h @@ -1,4 +1,8 @@ require_extension('C'); -require_rv64; -require(insn.rvc_rd() != 0); -WRITE_RD(MMU.load_int64(RVC_SP + insn.rvc_ldsp_imm())); +if (xlen == 32) { + if (sreg_t(RVC_RS1S) >= 0) // c.bgez + set_pc(pc + insn.rvc_b_imm()); +} else { + require(insn.rvc_rd() != 0); + WRITE_RD(MMU.load_int64(RVC_SP + insn.rvc_ldsp_imm())); +} diff --git a/riscv/insns/c_sd.h b/riscv/insns/c_sd.h index 9262d04..4551ced 100644 --- a/riscv/insns/c_sd.h +++ b/riscv/insns/c_sd.h @@ -1,3 +1,38 @@ require_extension('C'); -require_rv64; -MMU.store_uint64(RVC_RS1S + insn.rvc_ld_imm(), RVC_RS2S); +if (xlen == 32) { + int32_t res; + switch ((insn.bits() >> 10) & 7) { + case 0: + switch ((insn.bits() >> 5) & 3) { + case 0: res = RVC_RS1S ^ RVC_RS2S; // c.xor + case 1: res = int32_t(RVC_RS1S) >> (RVC_RS2S & 0x1f); // c.sra + default: require(0); + } + WRITE_RVC_RS1S(res); + break; + + case 1: + switch ((insn.bits() >> 5) & 3) { + case 0: res = RVC_RS1S << (RVC_RS2S & 0x1f); // c.sll + case 1: res = uint32_t(RVC_RS1S) >> (RVC_RS2S & 0x1f); // c.srl + case 2: res = int32_t(RVC_RS1S) < int32_t(RVC_RS2S); // c.slt + case 3: res = uint32_t(RVC_RS1S) < uint32_t(RVC_RS2S); // c.sltu + } + WRITE_RVC_RS1S(res); + break; + + case 3: + switch ((insn.bits() >> 5) & 3) { + case 0: res = RVC_RS1S << (RVC_RS2S & 0x1f); // c.sllr + case 1: res = uint32_t(RVC_RS1S) >> (RVC_RS2S & 0x1f); // c.srlr + case 2: res = int32_t(RVC_RS1S) < int32_t(RVC_RS2S); // c.sltr + case 3: res = uint32_t(RVC_RS1S) < uint32_t(RVC_RS2S); // c.sltur + } + WRITE_RVC_RS2S(res); + break; + + default: require(0); + } +} else { + MMU.store_uint64(RVC_RS1S + insn.rvc_ld_imm(), RVC_RS2S); +} diff --git a/riscv/insns/c_sdsp.h b/riscv/insns/c_sdsp.h index e59e00b..db504ec 100644 --- a/riscv/insns/c_sdsp.h +++ b/riscv/insns/c_sdsp.h @@ -1,3 +1,7 @@ require_extension('C'); -require_rv64; -MMU.store_uint64(RVC_SP + insn.rvc_sdsp_imm(), RVC_RS2); +if (xlen == 32) { + if (sreg_t(RVC_RS1S) < 0) // c.bltz + set_pc(pc + insn.rvc_b_imm()); +} else { + MMU.store_uint64(RVC_SP + insn.rvc_sdsp_imm(), RVC_RS2); +} diff --git a/riscv/insns/c_slliw.h b/riscv/insns/c_slliw.h index 87a5901..643bf74 100644 --- a/riscv/insns/c_slliw.h +++ b/riscv/insns/c_slliw.h @@ -1,5 +1,13 @@ require_extension('C'); -require_rv64; -require(insn.rvc_rd() != 0); -require(insn.rvc_imm() < 32); -WRITE_RD(sext32(RVC_RS1 << insn.rvc_imm())); +if (xlen == 32) { + switch ((insn.bits() >> 5) & 3) { + case 0: WRITE_RVC_RS2S(sext_xlen(RVC_RS1S + insn.rvc_simm3())); // c.addin + case 1: WRITE_RVC_RS2S(sext_xlen(RVC_RS1S ^ insn.rvc_simm3())); // c.xorin + case 2: WRITE_RVC_RS2S(sext_xlen(RVC_RS1S | insn.rvc_simm3())); // c.orin + case 3: WRITE_RVC_RS2S(sext_xlen(RVC_RS1S & insn.rvc_simm3())); // c.andin + } +} else { + require(insn.rvc_rd() != 0); + require(insn.rvc_imm() < 32); + WRITE_RD(sext32(RVC_RS1 << insn.rvc_imm())); +}