diff --git a/riscv/insns/pnclipiu_b.h b/riscv/insns/pnclipiu_b.h index 062ea472..fadf004d 100644 --- a/riscv/insns/pnclipiu_b.h +++ b/riscv/insns/pnclipiu_b.h @@ -1,4 +1,4 @@ require_rv32; P_NARROW_RD_RS1_ULOOP(8, 16, { - p_rd = P_USAT(8, p_rs1 >> insn.shamth()); + p_rd = P_USAT_FULL(8, (sreg_t)(p_rs1 >> insn.shamth())); }) \ No newline at end of file diff --git a/riscv/insns/pnclipiu_h.h b/riscv/insns/pnclipiu_h.h index efd46b03..ac490333 100644 --- a/riscv/insns/pnclipiu_h.h +++ b/riscv/insns/pnclipiu_h.h @@ -1,4 +1,4 @@ require_rv32; P_NARROW_RD_RS1_ULOOP(16, 32, { - p_rd = P_USAT(16, (p_rs1 >> insn.shamtw())); + p_rd = P_USAT_FULL(16, (sreg_t)(p_rs1 >> insn.shamtw())); }) \ No newline at end of file diff --git a/riscv/insns/pnclipp_b.h b/riscv/insns/pnclipp_b.h new file mode 100644 index 00000000..4f4b1a01 --- /dev/null +++ b/riscv/insns/pnclipp_b.h @@ -0,0 +1,13 @@ +require_extension('P'); +require_rv64; +reg_t rd_tmp = 0; +reg_t s_low = RS1; +reg_t s_high = RS2; +for (int i = 0; i < 8; i++) { + sreg_t s_h = (i < 4) ? P_FIELD(s_low, i, 16) : P_FIELD(s_high, i - 4, 16); + sreg_t sat_val = P_SAT(8, s_h); + if (sat_val != s_h) P.VU.vxsat->write(1); + rd_tmp = set_field(rd_tmp, make_mask64(i * 8, 8), (uint8_t)sat_val); +} +WRITE_RD(rd_tmp); + diff --git a/riscv/insns/pnclipp_h.h b/riscv/insns/pnclipp_h.h new file mode 100644 index 00000000..6eee48e0 --- /dev/null +++ b/riscv/insns/pnclipp_h.h @@ -0,0 +1,13 @@ +require_extension('P'); +require_rv64; +reg_t rd_tmp = 0; +reg_t s_low = RS1; +reg_t s_high = RS2; +for (int i = 0; i < 4; i++) { + sreg_t s_w = (i < 2) ? P_FIELD(s_low, i, 32) : P_FIELD(s_high, i - 2, 32); + sreg_t sat_val = P_SAT(16, s_w); + if (sat_val != s_w) P.VU.vxsat->write(1); + rd_tmp = set_field(rd_tmp, make_mask64(i * 16, 16), (uint16_t)sat_val); +} +WRITE_RD(rd_tmp); + diff --git a/riscv/insns/pnclipp_w.h b/riscv/insns/pnclipp_w.h new file mode 100644 index 00000000..880a72af --- /dev/null +++ b/riscv/insns/pnclipp_w.h @@ -0,0 +1,13 @@ +require_extension('P'); +require_rv64; +int64_t s1 = (int64_t)RS1; +int64_t s2 = (int64_t)RS2; + +sreg_t sat_w0 = P_SAT(32, s1); +if (sat_w0 != s1) P.VU.vxsat->write(1); + +sreg_t sat_w1 = P_SAT(32, s2); +if (sat_w1 != s2) P.VU.vxsat->write(1); + +WRITE_RD(((uint64_t)(uint32_t)sat_w1 << 32) | (uint32_t)sat_w0); + diff --git a/riscv/insns/pnclipup_b.h b/riscv/insns/pnclipup_b.h new file mode 100644 index 00000000..77e53e7b --- /dev/null +++ b/riscv/insns/pnclipup_b.h @@ -0,0 +1,13 @@ +require_extension('P'); +require_rv64; +reg_t rd_tmp = 0; +reg_t s_low = RS1; +reg_t s_high = RS2; +for (int i = 0; i < 8; i++) { + reg_t s_h = (i < 4) ? P_UFIELD(s_low, i, 16) : P_UFIELD(s_high, i - 4, 16); + reg_t sat_val = P_USAT_FULL(8, (sreg_t)s_h); + if (sat_val != s_h) P.VU.vxsat->write(1); + rd_tmp = set_field(rd_tmp, make_mask64(i * 8, 8), (uint8_t)sat_val); +} +WRITE_RD(rd_tmp); + diff --git a/riscv/insns/pnclipup_h.h b/riscv/insns/pnclipup_h.h new file mode 100644 index 00000000..e688ecf2 --- /dev/null +++ b/riscv/insns/pnclipup_h.h @@ -0,0 +1,13 @@ +require_extension('P'); +require_rv64; +reg_t rd_tmp = 0; +reg_t s_low = RS1; +reg_t s_high = RS2; +for (int i = 0; i < 4; i++) { + reg_t s_w = (i < 2) ? P_UFIELD(s_low, i, 32) : P_UFIELD(s_high, i - 2, 32); + reg_t sat_val = P_USAT_FULL(16, (sreg_t)s_w); + if (sat_val != s_w) P.VU.vxsat->write(1); + rd_tmp = set_field(rd_tmp, make_mask64(i * 16, 16), (uint16_t)sat_val); +} +WRITE_RD(rd_tmp); + diff --git a/riscv/insns/pnclipup_w.h b/riscv/insns/pnclipup_w.h new file mode 100644 index 00000000..72f8476b --- /dev/null +++ b/riscv/insns/pnclipup_w.h @@ -0,0 +1,13 @@ +require_extension('P'); +require_rv64; +uint64_t s1 = RS1; +uint64_t s2 = RS2; + +reg_t sat_w0 = P_USAT_FULL(32, (sreg_t)s1); +if (sat_w0 != s1) P.VU.vxsat->write(1); + +reg_t sat_w1 = P_USAT_FULL(32, (sreg_t)s2); +if (sat_w1 != s2) P.VU.vxsat->write(1); + +WRITE_RD(((uint64_t)(uint32_t)sat_w1 << 32) | (uint32_t)sat_w0); + diff --git a/riscv/insns/psshl_dhs.h b/riscv/insns/psshl_dhs.h new file mode 100644 index 00000000..d1fcade5 --- /dev/null +++ b/riscv/insns/psshl_dhs.h @@ -0,0 +1,19 @@ +require_rv32; +sreg_t sshamt = P_FIELD(RS2, 0, 8); +P_RD_RS1_DW_LOOP(16, 16, { + if (sshamt < 0) { + if (sshamt <= -16) + p_rd = 0; + else + p_rd = (uint16_t)p_rs1 >> (-sshamt); + } else { + uint32_t shx = (sshamt >= 16) ? ((uint32_t)(uint16_t)p_rs1 << 16) : ((uint32_t)(uint16_t)p_rs1 << sshamt); + if (shx > 0xFFFF) { + P.VU.vxsat->write(1); + p_rd = 0xFFFF; + } else { + p_rd = (uint16_t)shx; + } + } +}) + diff --git a/riscv/insns/psshl_dws.h b/riscv/insns/psshl_dws.h new file mode 100644 index 00000000..71569d2e --- /dev/null +++ b/riscv/insns/psshl_dws.h @@ -0,0 +1,19 @@ +require_rv32; +sreg_t sshamt = P_FIELD(RS2, 0, 8); +P_RD_RS1_DW_LOOP(32, 32, { + if (sshamt < 0) { + if (sshamt <= -32) + p_rd = 0; + else + p_rd = (uint32_t)p_rs1 >> (-sshamt); + } else { + uint64_t shx = (sshamt >= 32) ? ((uint64_t)(uint32_t)p_rs1 << 32) : ((uint64_t)(uint32_t)p_rs1 << sshamt); + if (shx > 0xFFFFFFFFULL) { + P.VU.vxsat->write(1); + p_rd = 0xFFFFFFFF; + } else { + p_rd = (uint32_t)shx; + } + } +}) + diff --git a/riscv/insns/psshl_hs.h b/riscv/insns/psshl_hs.h new file mode 100644 index 00000000..459289e1 --- /dev/null +++ b/riscv/insns/psshl_hs.h @@ -0,0 +1,18 @@ +sreg_t sshamt = P_FIELD(RS2, 0, 8); +P_RD_RS1_LOOP(16, 16, { + if (sshamt < 0) { + if (sshamt <= -16) + p_rd = 0; + else + p_rd = (uint16_t)p_rs1 >> (-sshamt); + } else { + uint32_t shx = (sshamt >= 16) ? ((uint32_t)(uint16_t)p_rs1 << 16) : ((uint32_t)(uint16_t)p_rs1 << sshamt); + if (shx > 0xFFFF) { + P.VU.vxsat->write(1); + p_rd = 0xFFFF; + } else { + p_rd = (uint16_t)shx; + } + } +}) + diff --git a/riscv/insns/psshl_ws.h b/riscv/insns/psshl_ws.h new file mode 100644 index 00000000..c67eddab --- /dev/null +++ b/riscv/insns/psshl_ws.h @@ -0,0 +1,19 @@ +require_rv64; +sreg_t sshamt = P_FIELD(RS2, 0, 8); +P_RD_RS1_LOOP(32, 32, { + if (sshamt < 0) { + if (sshamt <= -32) + p_rd = 0; + else + p_rd = (uint32_t)p_rs1 >> (-sshamt); + } else { + uint64_t shx = (sshamt >= 32) ? ((uint64_t)(uint32_t)p_rs1 << 32) : ((uint64_t)(uint32_t)p_rs1 << sshamt); + if (shx > 0xFFFFFFFFULL) { + P.VU.vxsat->write(1); + p_rd = 0xFFFFFFFF; + } else { + p_rd = (uint32_t)shx; + } + } +}) + diff --git a/riscv/insns/psshlr_dhs.h b/riscv/insns/psshlr_dhs.h new file mode 100644 index 00000000..d2616d6f --- /dev/null +++ b/riscv/insns/psshlr_dhs.h @@ -0,0 +1,23 @@ +require_rv32; +sreg_t sshamt = P_FIELD(RS2, 0, 8); +P_RD_RS1_DW_LOOP(16, 16, { + if (sshamt < 0) { + uint32_t shx; + if (sshamt < -16) + shx = 0; + else if (sshamt == -16) + shx = ((uint16_t)p_rs1 >> 15) & 1; + else + shx = ((uint32_t)(uint16_t)p_rs1 << 1) >> (-sshamt); + p_rd = (uint16_t)((shx + 1) >> 1); + } else { + uint32_t shx = (sshamt >= 16) ? ((uint32_t)(uint16_t)p_rs1 << 16) : ((uint32_t)(uint16_t)p_rs1 << sshamt); + if (shx > 0xFFFF) { + P.VU.vxsat->write(1); + p_rd = 0xFFFF; + } else { + p_rd = (uint16_t)shx; + } + } +}) + diff --git a/riscv/insns/psshlr_dws.h b/riscv/insns/psshlr_dws.h new file mode 100644 index 00000000..483d9d41 --- /dev/null +++ b/riscv/insns/psshlr_dws.h @@ -0,0 +1,23 @@ +require_rv32; +sreg_t sshamt = P_FIELD(RS2, 0, 8); +P_RD_RS1_DW_LOOP(32, 32, { + if (sshamt < 0) { + uint64_t shx; + if (sshamt < -32) + shx = 0; + else if (sshamt == -32) + shx = ((uint32_t)p_rs1 >> 31) & 1; + else + shx = ((uint64_t)(uint32_t)p_rs1 << 1) >> (-sshamt); + p_rd = (uint32_t)((shx + 1) >> 1); + } else { + uint64_t shx = (sshamt >= 32) ? ((uint64_t)(uint32_t)p_rs1 << 32) : ((uint64_t)(uint32_t)p_rs1 << sshamt); + if (shx > 0xFFFFFFFFULL) { + P.VU.vxsat->write(1); + p_rd = 0xFFFFFFFF; + } else { + p_rd = (uint32_t)shx; + } + } +}) + diff --git a/riscv/insns/psshlr_hs.h b/riscv/insns/psshlr_hs.h new file mode 100644 index 00000000..fd7df13d --- /dev/null +++ b/riscv/insns/psshlr_hs.h @@ -0,0 +1,22 @@ +sreg_t sshamt = P_FIELD(RS2, 0, 8); +P_RD_RS1_LOOP(16, 16, { + if (sshamt < 0) { + uint32_t shx; + if (sshamt < -16) + shx = 0; + else if (sshamt == -16) + shx = ((uint16_t)p_rs1 >> 15) & 1; + else + shx = ((uint32_t)(uint16_t)p_rs1 << 1) >> (-sshamt); + p_rd = (uint16_t)((shx + 1) >> 1); + } else { + uint32_t shx = (sshamt >= 16) ? ((uint32_t)(uint16_t)p_rs1 << 16) : ((uint32_t)(uint16_t)p_rs1 << sshamt); + if (shx > 0xFFFF) { + P.VU.vxsat->write(1); + p_rd = 0xFFFF; + } else { + p_rd = (uint16_t)shx; + } + } +}) + diff --git a/riscv/insns/psshlr_ws.h b/riscv/insns/psshlr_ws.h new file mode 100644 index 00000000..1935db20 --- /dev/null +++ b/riscv/insns/psshlr_ws.h @@ -0,0 +1,23 @@ +require_rv64; +sreg_t sshamt = P_FIELD(RS2, 0, 8); +P_RD_RS1_LOOP(32, 32, { + if (sshamt < 0) { + uint64_t shx; + if (sshamt < -32) + shx = 0; + else if (sshamt == -32) + shx = ((uint32_t)p_rs1 >> 31) & 1; + else + shx = ((uint64_t)(uint32_t)p_rs1 << 1) >> (-sshamt); + p_rd = (uint32_t)((shx + 1) >> 1); + } else { + uint64_t shx = (sshamt >= 32) ? ((uint64_t)(uint32_t)p_rs1 << 32) : ((uint64_t)(uint32_t)p_rs1 << sshamt); + if (shx > 0xFFFFFFFFULL) { + P.VU.vxsat->write(1); + p_rd = 0xFFFFFFFF; + } else { + p_rd = (uint32_t)shx; + } + } +}) + diff --git a/riscv/insns/shl.h b/riscv/insns/shl.h new file mode 100644 index 00000000..ef112422 --- /dev/null +++ b/riscv/insns/shl.h @@ -0,0 +1,15 @@ +require_extension('P'); +require_rv64; +sreg_t sshamt = P_FIELD(RS2, 0, 8); +if (sshamt < 0) { + if (sshamt <= -64) + WRITE_RD(0); + else + WRITE_RD(RS1 >> (-sshamt)); +} else { + if (sshamt >= 64) + WRITE_RD(0); + else + WRITE_RD(RS1 << sshamt); +} + diff --git a/riscv/insns/shlr.h b/riscv/insns/shlr.h new file mode 100644 index 00000000..29801fa9 --- /dev/null +++ b/riscv/insns/shlr.h @@ -0,0 +1,19 @@ +require_extension('P'); +require_rv64; +sreg_t sshamt = P_FIELD(RS2, 0, 8); +if (sshamt < 0) { + __uint128_t shx; + if (sshamt < -64) + shx = 0; + else if (sshamt == -64) + shx = (RS1 >> 63) & 1; + else + shx = ((__uint128_t)RS1 << 1) >> (-sshamt); + WRITE_RD((uint64_t)((shx + 1) >> 1)); +} else { + if (sshamt >= 64) + WRITE_RD(0); + else + WRITE_RD(RS1 << sshamt); +} + diff --git a/riscv/insns/sshl.h b/riscv/insns/sshl.h new file mode 100644 index 00000000..d2ba309d --- /dev/null +++ b/riscv/insns/sshl.h @@ -0,0 +1,18 @@ +require_extension('P'); +require_rv32; +sreg_t sshamt = P_FIELD(RS2, 0, 8); +if (sshamt < 0) { + if (sshamt <= -32) + WRITE_RD(0); + else + WRITE_RD(RS1 >> (-sshamt)); +} else { + uint64_t shx = (sshamt >= 32) ? ((uint64_t)RS1 << 32) : ((uint64_t)RS1 << sshamt); + if (shx > 0xFFFFFFFFULL) { + P.VU.vxsat->write(1); + WRITE_RD(0xFFFFFFFF); + } else { + WRITE_RD((uint32_t)shx); + } +} + diff --git a/riscv/insns/sshlr.h b/riscv/insns/sshlr.h new file mode 100644 index 00000000..d36b0052 --- /dev/null +++ b/riscv/insns/sshlr.h @@ -0,0 +1,22 @@ +require_extension('P'); +require_rv32; +sreg_t sshamt = P_FIELD(RS2, 0, 8); +if (sshamt < 0) { + uint64_t shx; + if (sshamt < -32) + shx = 0; + else if (sshamt == -32) + shx = (RS1 >> 31) & 1; + else + shx = ((uint64_t)RS1 << 1) >> (-sshamt); + WRITE_RD((uint32_t)((shx + 1) >> 1)); +} else { + uint64_t shx = (sshamt >= 32) ? ((uint64_t)RS1 << 32) : ((uint64_t)RS1 << sshamt); + if (shx > 0xFFFFFFFFULL) { + P.VU.vxsat->write(1); + WRITE_RD(0xFFFFFFFF); + } else { + WRITE_RD((uint32_t)shx); + } +} + diff --git a/riscv/overlap_list.h b/riscv/overlap_list.h index 21233d59..bf9b72e7 100644 --- a/riscv/overlap_list.h +++ b/riscv/overlap_list.h @@ -93,3 +93,5 @@ DECLARE_OVERLAP_INSN(pmqacc_w_h11, 'P') DECLARE_OVERLAP_INSN(pmqracc_w_h00, 'P') DECLARE_OVERLAP_INSN(pmqracc_w_h01, 'P') DECLARE_OVERLAP_INSN(pmqracc_w_h11, 'P') +DECLARE_OVERLAP_INSN(psshl_ws, 'P') +DECLARE_OVERLAP_INSN(psshlr_ws, 'P') diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index 0338d24d..19fa7974 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -1741,6 +1741,24 @@ riscv_insn_ext_p = \ pmq2adda_w \ pmqr2add_w \ pmqr2adda_w \ + sshl \ + sshlr \ + shl \ + shlr \ + psshl_hs \ + psshlr_hs \ + psshl_ws \ + psshlr_ws \ + psshl_dhs \ + psshlr_dhs \ + psshl_dws \ + psshlr_dws \ + pnclipp_b \ + pnclipp_h \ + pnclipp_w \ + pnclipup_b \ + pnclipup_h \ + pnclipup_w \ riscv_insn_list = \ $(riscv_insn_ext_i) \