[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 07/33] target/mips: Add emulation of MXU S32SLT D16SLT D16AVG[R]
From: |
Siarhei Volkau |
Subject: |
[PATCH 07/33] target/mips: Add emulation of MXU S32SLT D16SLT D16AVG[R] Q8AVG[R] insns |
Date: |
Thu, 8 Jun 2023 13:41:56 +0300 |
These instructions are part of pool1, see the grand tree above
in the file. Q8ADD is part of pool1 too but belong to another
category of instructions, thus will be made in later patches.
Signed-off-by: Siarhei Volkau <lis8215@gmail.com>
---
target/mips/tcg/mxu_translate.c | 244 +++++++++++++++++++++++++++++++-
1 file changed, 243 insertions(+), 1 deletion(-)
diff --git a/target/mips/tcg/mxu_translate.c b/target/mips/tcg/mxu_translate.c
index 984d826c36..2c1d7f139e 100644
--- a/target/mips/tcg/mxu_translate.c
+++ b/target/mips/tcg/mxu_translate.c
@@ -360,6 +360,7 @@ enum {
OPC_MXU__POOL00 = 0x03,
OPC_MXU_S32MSUB = 0x04,
OPC_MXU_S32MSUBU = 0x05,
+ OPC_MXU__POOL01 = 0x06,
OPC_MXU_D16MUL = 0x08,
OPC_MXU_D16MAC = 0x0A,
OPC_MXU__POOL04 = 0x10,
@@ -393,6 +394,18 @@ enum {
OPC_MXU_Q8SLTU = 0x07,
};
+/*
+ * MXU pool 01
+ */
+enum {
+ OPC_MXU_S32SLT = 0x00,
+ OPC_MXU_D16SLT = 0x01,
+ OPC_MXU_D16AVG = 0x02,
+ OPC_MXU_D16AVGR = 0x03,
+ OPC_MXU_Q8AVG = 0x04,
+ OPC_MXU_Q8AVGR = 0x05,
+};
+
/*
* MXU pool 04 05 06 07 08 09 10 11
*/
@@ -1154,11 +1167,15 @@ static void gen_mxu_S32XOR(DisasContext *ctx)
/*
- * MXU instruction category max/min
+ * MXU instruction category max/min/avg
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* S32MAX D16MAX Q8MAX
* S32MIN D16MIN Q8MIN
+ * S32SLT D16SLT Q8SLT
+ * Q8SLTU
+ * D16AVG Q8AVG
+ * D16AVGR Q8AVGR
*/
/*
@@ -1464,6 +1481,199 @@ static void gen_mxu_q8slt(DisasContext *ctx, bool sltu)
}
}
+/*
+ * S32SLT
+ * Update XRa with the signed "set less than" comparison of XRb and XRc.
+ * a.k.a. XRa = XRb < XRc ? 1 : 0;
+ */
+static void gen_mxu_S32SLT(DisasContext *ctx)
+{
+ uint32_t pad, XRc, XRb, XRa;
+
+ pad = extract32(ctx->opcode, 21, 5);
+ XRc = extract32(ctx->opcode, 14, 4);
+ XRb = extract32(ctx->opcode, 10, 4);
+ XRa = extract32(ctx->opcode, 6, 4);
+
+ if (unlikely(pad != 0)) {
+ /* opcode padding incorrect -> do nothing */
+ } else if (unlikely(XRa == 0)) {
+ /* destination is zero register -> do nothing */
+ } else if (unlikely((XRb == 0) && (XRc == 0))) {
+ /* both operands zero registers -> just set destination to zero */
+ tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
+ } else if (unlikely(XRb == XRc)) {
+ /* both operands same registers -> just set destination to zero */
+ tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
+ } else {
+ /* the most general case */
+ tcg_gen_setcond_tl(TCG_COND_LT, mxu_gpr[XRa - 1],
+ mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
+ }
+}
+
+/*
+ * D16SLT
+ * Update XRa with the signed "set less than" comparison of XRb and XRc
+ * on per-word basis.
+ * a.k.a. XRa[0..1] = XRb[0..1] < XRc[0..1] ? 1 : 0;
+ */
+static void gen_mxu_D16SLT(DisasContext *ctx)
+{
+ uint32_t pad, XRc, XRb, XRa;
+
+ pad = extract32(ctx->opcode, 21, 5);
+ XRc = extract32(ctx->opcode, 14, 4);
+ XRb = extract32(ctx->opcode, 10, 4);
+ XRa = extract32(ctx->opcode, 6, 4);
+
+ if (unlikely(pad != 0)) {
+ /* opcode padding incorrect -> do nothing */
+ } else if (unlikely(XRa == 0)) {
+ /* destination is zero register -> do nothing */
+ } else if (unlikely((XRb == 0) && (XRc == 0))) {
+ /* both operands zero registers -> just set destination to zero */
+ tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
+ } else if (unlikely(XRb == XRc)) {
+ /* both operands same registers -> just set destination to zero */
+ tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
+ } else {
+ /* the most general case */
+ TCGv t0 = tcg_temp_new();
+ TCGv t1 = tcg_temp_new();
+ TCGv t2 = tcg_temp_new();
+ TCGv t3 = tcg_temp_new();
+ TCGv t4 = tcg_temp_new();
+
+ gen_load_mxu_gpr(t3, XRb);
+ gen_load_mxu_gpr(t4, XRc);
+ tcg_gen_sextract_tl(t0, t3, 16, 16);
+ tcg_gen_sextract_tl(t1, t4, 16, 16);
+ tcg_gen_setcond_tl(TCG_COND_LT, t0, t0, t1);
+ tcg_gen_shli_tl(t2, t0, 16);
+ tcg_gen_sextract_tl(t0, t3, 0, 16);
+ tcg_gen_sextract_tl(t1, t4, 0, 16);
+ tcg_gen_setcond_tl(TCG_COND_LT, t0, t0, t1);
+ tcg_gen_or_tl(mxu_gpr[XRa - 1], t2, t0);
+ }
+}
+
+/*
+ * D16AVG
+ * Update XRa with the signed average of XRb and XRc
+ * on per-word basis, rounding down.
+ * a.k.a. XRa[0..1] = (XRb[0..1] + XRc[0..1]) >> 1;
+ *
+ * D16AVGR
+ * Update XRa with the signed average of XRb and XRc
+ * on per-word basis, math rounding 4/5.
+ * a.k.a. XRa[0..1] = (XRb[0..1] + XRc[0..1] + 1) >> 1;
+ */
+static void gen_mxu_d16avg(DisasContext *ctx, bool round45)
+{
+ uint32_t pad, XRc, XRb, XRa;
+
+ pad = extract32(ctx->opcode, 21, 5);
+ XRc = extract32(ctx->opcode, 14, 4);
+ XRb = extract32(ctx->opcode, 10, 4);
+ XRa = extract32(ctx->opcode, 6, 4);
+
+ if (unlikely(pad != 0)) {
+ /* opcode padding incorrect -> do nothing */
+ } else if (unlikely(XRa == 0)) {
+ /* destination is zero register -> do nothing */
+ } else if (unlikely((XRb == 0) && (XRc == 0))) {
+ /* both operands zero registers -> just set destination to zero */
+ tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
+ } else if (unlikely(XRb == XRc)) {
+ /* both operands same registers -> just set destination to same */
+ tcg_gen_mov_tl(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
+ } else {
+ /* the most general case */
+ TCGv t0 = tcg_temp_new();
+ TCGv t1 = tcg_temp_new();
+ TCGv t2 = tcg_temp_new();
+ TCGv t3 = tcg_temp_new();
+ TCGv t4 = tcg_temp_new();
+
+ gen_load_mxu_gpr(t3, XRb);
+ gen_load_mxu_gpr(t4, XRc);
+ tcg_gen_sextract_tl(t0, t3, 16, 16);
+ tcg_gen_sextract_tl(t1, t4, 16, 16);
+ tcg_gen_add_tl(t0, t0, t1);
+ if (round45) {
+ tcg_gen_addi_tl(t0, t0, 1);
+ }
+ tcg_gen_shli_tl(t2, t0, 15);
+ tcg_gen_andi_tl(t2, t2, 0xffff0000);
+ tcg_gen_sextract_tl(t0, t3, 0, 16);
+ tcg_gen_sextract_tl(t1, t4, 0, 16);
+ tcg_gen_add_tl(t0, t0, t1);
+ if (round45) {
+ tcg_gen_addi_tl(t0, t0, 1);
+ }
+ tcg_gen_shri_tl(t0, t0, 1);
+ tcg_gen_deposit_tl(t2, t2, t0, 0, 16);
+ gen_store_mxu_gpr(t2, XRa);
+ }
+}
+
+/*
+ * Q8AVG
+ * Update XRa with the signed average of XRb and XRc
+ * on per-byte basis, rounding down.
+ * a.k.a. XRa[0..3] = (XRb[0..3] + XRc[0..3]) >> 1;
+ *
+ * Q8AVGR
+ * Update XRa with the signed average of XRb and XRc
+ * on per-word basis, math rounding 4/5.
+ * a.k.a. XRa[0..3] = (XRb[0..3] + XRc[0..3] + 1) >> 1;
+ */
+static void gen_mxu_q8avg(DisasContext *ctx, bool round45)
+{
+ uint32_t pad, XRc, XRb, XRa;
+
+ pad = extract32(ctx->opcode, 21, 5);
+ XRc = extract32(ctx->opcode, 14, 4);
+ XRb = extract32(ctx->opcode, 10, 4);
+ XRa = extract32(ctx->opcode, 6, 4);
+
+ if (unlikely(pad != 0)) {
+ /* opcode padding incorrect -> do nothing */
+ } else if (unlikely(XRa == 0)) {
+ /* destination is zero register -> do nothing */
+ } else if (unlikely((XRb == 0) && (XRc == 0))) {
+ /* both operands zero registers -> just set destination to zero */
+ tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
+ } else if (unlikely(XRb == XRc)) {
+ /* both operands same registers -> just set destination to same */
+ tcg_gen_mov_tl(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
+ } else {
+ /* the most general case */
+ TCGv t0 = tcg_temp_new();
+ TCGv t1 = tcg_temp_new();
+ TCGv t2 = tcg_temp_new();
+ TCGv t3 = tcg_temp_new();
+ TCGv t4 = tcg_temp_new();
+
+ gen_load_mxu_gpr(t3, XRb);
+ gen_load_mxu_gpr(t4, XRc);
+ tcg_gen_movi_tl(t2, 0);
+
+ for (int i = 0; i < 4; i++) {
+ tcg_gen_extract_tl(t0, t3, 8 * i, 8);
+ tcg_gen_extract_tl(t1, t4, 8 * i, 8);
+ tcg_gen_add_tl(t0, t0, t1);
+ if (round45) {
+ tcg_gen_addi_tl(t0, t0, 1);
+ }
+ tcg_gen_shri_tl(t0, t0, 1);
+ tcg_gen_deposit_tl(t2, t2, t0, 8 * i, 8);
+ }
+ gen_store_mxu_gpr(t2, XRa);
+ }
+}
+
/*
* MXU instruction category: align
@@ -1771,6 +1981,35 @@ static bool decode_opc_mxu_s32madd_sub(DisasContext *ctx)
return true;
}
+static void decode_opc_mxu__pool01(DisasContext *ctx)
+{
+ uint32_t opcode = extract32(ctx->opcode, 18, 3);
+
+ switch (opcode) {
+ case OPC_MXU_S32SLT:
+ gen_mxu_S32SLT(ctx);
+ break;
+ case OPC_MXU_D16SLT:
+ gen_mxu_D16SLT(ctx);
+ break;
+ case OPC_MXU_D16AVG:
+ gen_mxu_d16avg(ctx, false);
+ break;
+ case OPC_MXU_D16AVGR:
+ gen_mxu_d16avg(ctx, true);
+ break;
+ case OPC_MXU_Q8AVG:
+ gen_mxu_q8avg(ctx, false);
+ break;
+ case OPC_MXU_Q8AVGR:
+ gen_mxu_q8avg(ctx, true);
+ break;
+ default:
+ MIPS_INVAL("decode_opc_mxu");
+ gen_reserved_instruction(ctx);
+ break;
+ }
+}
static void decode_opc_mxu__pool04(DisasContext *ctx)
{
uint32_t reversed = extract32(ctx->opcode, 20, 1);
@@ -2017,6 +2256,9 @@ bool decode_ase_mxu(DisasContext *ctx, uint32_t insn)
case OPC_MXU_D16MAC:
gen_mxu_d16mac(ctx);
break;
+ case OPC_MXU__POOL01:
+ decode_opc_mxu__pool01(ctx);
+ break;
case OPC_MXU__POOL04:
decode_opc_mxu__pool04(ctx);
break;
--
2.40.0
- [PATCH 00/33] target/mips: Finalise the Ingenic MXU ASE support, Siarhei Volkau, 2023/06/08
- [PATCH 03/33] target/mips: Add emulation of LXW LXB LXH LXBU LXHU instructions, Siarhei Volkau, 2023/06/08
- [PATCH 12/33] target/mips: Add emulation of MXU D16MADL instruction, Siarhei Volkau, 2023/06/08
- [PATCH 15/33] target/mips: Add emulation of MXU D32ADD instruction, Siarhei Volkau, 2023/06/08
- [PATCH 04/33] target/mips: Add emulation of S32MADD/MADDU/MSUB/MSUBU instructions, Siarhei Volkau, 2023/06/08
- [PATCH 05/33] target/mips: Add emulation of Q8SLT Q8SLTU instructions, Siarhei Volkau, 2023/06/08
- [PATCH 06/33] target/mips: fix MXU D16MAX D16MIN Q8MAX Q8MIN instructions, Siarhei Volkau, 2023/06/08
- [PATCH 11/33] target/mips: Add emulation of MXU D16MACF D16MACE instructions, Siarhei Volkau, 2023/06/08
- [PATCH 02/33] Add support of two XBurst CPUs, Siarhei Volkau, 2023/06/08
- [PATCH 01/33] target/mips: Add emulation of MXU instructions for 32-bit load/store, Siarhei Volkau, 2023/06/08
- [PATCH 07/33] target/mips: Add emulation of MXU S32SLT D16SLT D16AVG[R] Q8AVG[R] insns,
Siarhei Volkau <=
- [PATCH 13/33] target/mips: Add emulation of MXU S16MAD instruction, Siarhei Volkau, 2023/06/08
- [PATCH 16/33] target/mips: Add emulation of MXU D32ACC D32ACCM D32ASUM instructions, Siarhei Volkau, 2023/06/08
- [PATCH 18/33] target/mips: Add emulation of MXU Q16ACC Q16ACCM D16ASUM instructions, Siarhei Volkau, 2023/06/08
- [PATCH 19/33] target/mips: Add emulation of MXU Q8ADDE Q8ACCE D8SUM D8SUMC instructions, Siarhei Volkau, 2023/06/08
- [PATCH 22/33] target/mips: Add emulation of MXU S32MUL S32MULU S32EXTR S32EXTRV insns, Siarhei Volkau, 2023/06/08
- [PATCH 08/33] target/mips: Add emulation of Q8ADD instruction, Siarhei Volkau, 2023/06/08
- [PATCH 09/33] target/mips: Add emulation of MXU S32CPS D16CPS Q8ABD Q16SAT insns, Siarhei Volkau, 2023/06/08
- [PATCH 10/33] target/mips: Add emulation of MXU D16MULF D16MULE instructions, Siarhei Volkau, 2023/06/08
- [PATCH 23/33] target/mips: Add emulation of MXU S32ALN S32LUI insns, Siarhei Volkau, 2023/06/08
- [PATCH 27/33] target/mips: Add emulation of MXU D32/Q16- SLLV/SLRV/SARV instructions, Siarhei Volkau, 2023/06/08