diff --git a/arch/riscv/arch_exports.c b/arch/riscv/arch_exports.c index 11b88494c..025dcab29 100644 --- a/arch/riscv/arch_exports.c +++ b/arch/riscv/arch_exports.c @@ -163,6 +163,7 @@ void tlib_allow_additional_feature(uint32_t feature) case RISCV_FEATURE_ZICSR: case RISCV_FEATURE_ZIFENCEI: case RISCV_FEATURE_ZACAS: + case RISCV_FEATURE_ZICOND: // No dependencies break; case RISCV_FEATURE_ZCB: diff --git a/arch/riscv/cpu.h b/arch/riscv/cpu.h index 1885d03ac..5ed054546 100644 --- a/arch/riscv/cpu.h +++ b/arch/riscv/cpu.h @@ -345,6 +345,7 @@ enum riscv_additional_feature { RISCV_FEATURE_ZCB = 17, RISCV_FEATURE_ZCMP = 18, RISCV_FEATURE_ZCMT = 19, + RISCV_FEATURE_ZICOND = 20, RISCV_FEATURE_ONE_HIGHER_THAN_HIGHEST_ADDITIONAL }; diff --git a/arch/riscv/instmap.h b/arch/riscv/instmap.h index 713f3ca49..275a086ab 100644 --- a/arch/riscv/instmap.h +++ b/arch/riscv/instmap.h @@ -107,6 +107,10 @@ enum { OPC_RISC_BINV = OPC_RISC_ARITH | (0x1 << 12) | (0x34 << 25), OPC_RISC_BEXT = OPC_RISC_ARITH | (0x5 << 12) | (0x24 << 25), + /* Zicond: */ + OPC_RISC_CZERO_EQZ = OPC_RISC_ARITH | (0x5 << 12) | (0x07 << 25), + OPC_RISC_CZERO_NEZ = OPC_RISC_ARITH | (0x7 << 12) | (0x07 << 25), + /* Zbkb: */ OPC_RISC_PACK = OPC_RISC_ARITH | (0x4 << 12) | (0x4 << 25), OPC_RISC_PACKH = OPC_RISC_ARITH | (0x7 << 12) | (0x4 << 25), diff --git a/arch/riscv/translate.c b/arch/riscv/translate.c index 364f7ac09..c855acf06 100644 --- a/arch/riscv/translate.c +++ b/arch/riscv/translate.c @@ -202,6 +202,9 @@ static int ensure_additional_extension(DisasContext *dc, enum riscv_additional_f case RISCV_FEATURE_ZCMT: encoding = "cmt"; break; + case RISCV_FEATURE_ZICOND: + encoding = "icond"; + break; default: tlib_printf(LOG_LEVEL_ERROR, "Unexpected additional extension encoding: %d", ext); break; @@ -1177,6 +1180,24 @@ static void gen_arith(DisasContext *dc, uint32_t opc, int rd, int rs1, int rs2) tcg_gen_umin_i64(source1, source1, source2); #endif break; + case OPC_RISC_CZERO_EQZ: + if(!ensure_additional_extension(dc, RISCV_FEATURE_ZICOND)) { + return; + } + zeroreg = tcg_const_tl(0); + /* rd = (rs2 == 0) ? 0 : rs1 */ + tcg_gen_movcond_tl(TCG_COND_EQ, source1, source2, zeroreg, zeroreg, source1); + tcg_temp_free(zeroreg); + break; + case OPC_RISC_CZERO_NEZ: + if(!ensure_additional_extension(dc, RISCV_FEATURE_ZICOND)) { + return; + } + zeroreg = tcg_const_tl(0); + /* rd = (rs2 != 0) ? 0 : rs1 */ + tcg_gen_movcond_tl(TCG_COND_NE, source1, source2, zeroreg, zeroreg, source1); + tcg_temp_free(zeroreg); + break; case OPC_RISC_PACK: #if defined(TARGET_RISCV32) // On RV32 `pack rd, rs1, x0` is encoded the same way as `zext.h rd, rs1`