qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Siarhei Volkau <lis8215@gmail.com>
To: qemu-devel@nongnu.org
Cc: "Aleksandar Rikalo" <aleksandar.rikalo@syrmia.com>,
	"Philippe Mathieu-Daudé" <philmd@linaro.org>,
	"Aurelien Jarno" <aurelien@aurel32.net>,
	"Stefan Markovic" <smarkovic@wavecomp.com>,
	"Aleksandar Markovic" <amarkovic@wavecomp.com>,
	"Jiaxun Yang" <jiaxun.yang@flygoat.com>,
	"Siarhei Volkau" <lis8215@gmail.com>
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	[thread overview]
Message-ID: <20230608104222.1520143-8-lis8215@gmail.com> (raw)
In-Reply-To: <20230608104222.1520143-1-lis8215@gmail.com>

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



  parent reply	other threads:[~2023-06-08 13:19 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-08 10:41 [PATCH 00/33] target/mips: Finalise the Ingenic MXU ASE support Siarhei Volkau
2023-06-08 10:41 ` [PATCH 01/33] target/mips: Add emulation of MXU instructions for 32-bit load/store Siarhei Volkau
2023-06-08 10:41 ` [PATCH 02/33] Add support of two XBurst CPUs Siarhei Volkau
2023-06-08 10:41 ` [PATCH 03/33] target/mips: Add emulation of LXW LXB LXH LXBU LXHU instructions Siarhei Volkau
2023-06-08 10:41 ` [PATCH 04/33] target/mips: Add emulation of S32MADD/MADDU/MSUB/MSUBU instructions Siarhei Volkau
2023-06-08 10:41 ` [PATCH 05/33] target/mips: Add emulation of Q8SLT Q8SLTU instructions Siarhei Volkau
2023-06-08 10:41 ` [PATCH 06/33] target/mips: fix MXU D16MAX D16MIN Q8MAX Q8MIN instructions Siarhei Volkau
2023-06-08 10:41 ` Siarhei Volkau [this message]
2023-06-08 10:41 ` [PATCH 08/33] target/mips: Add emulation of Q8ADD instruction Siarhei Volkau
2023-06-08 10:41 ` [PATCH 09/33] target/mips: Add emulation of MXU S32CPS D16CPS Q8ABD Q16SAT insns Siarhei Volkau
2023-06-08 10:41 ` [PATCH 10/33] target/mips: Add emulation of MXU D16MULF D16MULE instructions Siarhei Volkau
2023-06-08 10:42 ` [PATCH 11/33] target/mips: Add emulation of MXU D16MACF D16MACE instructions Siarhei Volkau
2023-06-08 10:42 ` [PATCH 12/33] target/mips: Add emulation of MXU D16MADL instruction Siarhei Volkau
2023-06-08 10:42 ` [PATCH 13/33] target/mips: Add emulation of MXU S16MAD instruction Siarhei Volkau
2023-06-08 10:42 ` [PATCH 14/33] target/mips: Add emulation of MXU Q16ADD instruction Siarhei Volkau
2023-06-08 10:42 ` [PATCH 15/33] target/mips: Add emulation of MXU D32ADD instruction Siarhei Volkau
2023-06-08 10:42 ` [PATCH 16/33] target/mips: Add emulation of MXU D32ACC D32ACCM D32ASUM instructions Siarhei Volkau
2023-06-08 10:42 ` [PATCH 17/33] target/mips: Add emulation of MXU D32ADDC instruction Siarhei Volkau
2023-06-08 10:42 ` [PATCH 18/33] target/mips: Add emulation of MXU Q16ACC Q16ACCM D16ASUM instructions Siarhei Volkau
2023-06-08 10:42 ` [PATCH 19/33] target/mips: Add emulation of MXU Q8ADDE Q8ACCE D8SUM D8SUMC instructions Siarhei Volkau
2023-06-08 10:42 ` [PATCH 20/33] target/mips: Add emulation of MXU S8STD S8LDI S8SDI instructions Siarhei Volkau
2023-06-08 10:42 ` [PATCH 21/33] target/mips: Add emulation of MXU S16LDD S16STD S16LDI S16SDI instructions Siarhei Volkau
2023-06-08 10:42 ` [PATCH 22/33] target/mips: Add emulation of MXU S32MUL S32MULU S32EXTR S32EXTRV insns Siarhei Volkau
2023-06-08 10:42 ` [PATCH 23/33] target/mips: Add emulation of MXU S32ALN S32LUI insns Siarhei Volkau
2023-06-08 10:42 ` [PATCH 24/33] target/mips: Add emulation of MXU D32SARL D32SARW instructions Siarhei Volkau
2023-06-08 10:42 ` [PATCH 25/33] target/mips: Add emulation of MXU D32SLL D32SLR D32SAR instructions Siarhei Volkau
2023-06-08 10:42 ` [PATCH 26/33] target/mips: Add emulation of MXU Q16SLL Q16SLR Q16SAR instructions Siarhei Volkau
2023-06-08 10:42 ` [PATCH 27/33] target/mips: Add emulation of MXU D32/Q16- SLLV/SLRV/SARV instructions Siarhei Volkau
2023-06-08 10:42 ` [PATCH 28/33] target/mips: Add emulation of MXU S32/D16/Q8- MOVZ/MOVN instructions Siarhei Volkau
2023-06-08 10:42 ` [PATCH 29/33] target/mips: Add emulation of MXU Q8MAC Q8MACSU instructions Siarhei Volkau
2023-06-08 10:42 ` [PATCH 30/33] target/mips: Add emulation of MXU Q16SCOP instruction Siarhei Volkau
2023-06-08 10:42 ` [PATCH 31/33] target/mips: Add emulation of MXU Q8MADL instruction Siarhei Volkau
2023-06-08 10:42 ` [PATCH 32/33] target/mips: Add emulation of MXU S32SFL instruction Siarhei Volkau
2023-06-08 10:42 ` [PATCH 33/33] target/mips: Add emulation of MXU Q8SAD instruction Siarhei Volkau
2023-07-10 19:28 ` [PATCH 00/33] target/mips: Finalise the Ingenic MXU ASE support Philippe Mathieu-Daudé
2023-07-20 16:12   ` Siarhei Volkau

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230608104222.1520143-8-lis8215@gmail.com \
    --to=lis8215@gmail.com \
    --cc=aleksandar.rikalo@syrmia.com \
    --cc=amarkovic@wavecomp.com \
    --cc=aurelien@aurel32.net \
    --cc=jiaxun.yang@flygoat.com \
    --cc=philmd@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=smarkovic@wavecomp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).