target/mips/mxu: Add D32/Q16- SLLV/SLRV/SARV instructions

These instructions are counterparts for D32/Q16-SLL/SLR/SAR with
difference that the shift amount placed into GPR.

Signed-off-by: Siarhei Volkau <lis8215@gmail.com>
Message-Id: <20230608104222.1520143-28-lis8215@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
This commit is contained in:
Siarhei Volkau 2023-06-08 13:42:16 +03:00 committed by Philippe Mathieu-Daudé
parent 52fe25d445
commit 07c92895d7
1 changed files with 162 additions and 4 deletions

View File

@ -318,10 +318,10 @@
* 110001 OPC_MXU_D32SLR 20..18
* 110010 OPC_MXU_D32SARL 000 OPC_MXU_D32SLLV
* 110011 OPC_MXU_D32SAR 001 OPC_MXU_D32SLRV
* 110100 OPC_MXU_Q16SLL 010 OPC_MXU_D32SARV
* 110101 OPC_MXU_Q16SLR 011 OPC_MXU_Q16SLLV
* 100 OPC_MXU_Q16SLRV
* 110110 OPC_MXU__POOL18 101 OPC_MXU_Q16SARV
* 110100 OPC_MXU_Q16SLL 011 OPC_MXU_D32SARV
* 110101 OPC_MXU_Q16SLR 100 OPC_MXU_Q16SLLV
* 101 OPC_MXU_Q16SLRV
* 110110 OPC_MXU__POOL18 111 OPC_MXU_Q16SARV
*
* 110111 OPC_MXU_Q16SAR
* 23..22
@ -400,6 +400,7 @@ enum {
OPC_MXU_D32SAR = 0x33,
OPC_MXU_Q16SLL = 0x34,
OPC_MXU_Q16SLR = 0x35,
OPC_MXU__POOL18 = 0x36,
OPC_MXU_Q16SAR = 0x37,
OPC_MXU__POOL19 = 0x38,
};
@ -520,6 +521,18 @@ enum {
OPC_MXU_LXHU = 0x05,
};
/*
* MXU pool 18
*/
enum {
OPC_MXU_D32SLLV = 0x00,
OPC_MXU_D32SLRV = 0x01,
OPC_MXU_D32SARV = 0x03,
OPC_MXU_Q16SLLV = 0x04,
OPC_MXU_Q16SLRV = 0x05,
OPC_MXU_Q16SARV = 0x07,
};
/*
* MXU pool 19
*/
@ -1750,6 +1763,50 @@ static void gen_mxu_d32sxx(DisasContext *ctx, bool right, bool arithmetic)
gen_store_mxu_gpr(t1, XRd);
}
/*
* D32SLLV XRa, XRd, rs
* Dual 32-bit shift left from XRa and XRd to rs[3:0]
* bits. Store back to XRa and XRd respectively.
* D32SLRV XRa, XRd, rs
* Dual 32-bit shift logic right from XRa and XRd to rs[3:0]
* bits. Store back to XRa and XRd respectively.
* D32SARV XRa, XRd, rs
* Dual 32-bit shift arithmetic right from XRa and XRd to rs[3:0]
* bits. Store back to XRa and XRd respectively.
*/
static void gen_mxu_d32sxxv(DisasContext *ctx, bool right, bool arithmetic)
{
uint32_t XRa, XRd, rs;
XRa = extract32(ctx->opcode, 10, 4);
XRd = extract32(ctx->opcode, 14, 4);
rs = extract32(ctx->opcode, 21, 5);
TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
TCGv t2 = tcg_temp_new();
gen_load_mxu_gpr(t0, XRa);
gen_load_mxu_gpr(t1, XRd);
gen_load_gpr(t2, rs);
tcg_gen_andi_tl(t2, t2, 0x0f);
if (right) {
if (arithmetic) {
tcg_gen_sar_tl(t0, t0, t2);
tcg_gen_sar_tl(t1, t1, t2);
} else {
tcg_gen_shr_tl(t0, t0, t2);
tcg_gen_shr_tl(t1, t1, t2);
}
} else {
tcg_gen_shl_tl(t0, t0, t2);
tcg_gen_shl_tl(t1, t1, t2);
}
gen_store_mxu_gpr(t0, XRa);
gen_store_mxu_gpr(t1, XRd);
}
/*
* D32SARL XRa, XRb, XRc, SFT4
* Dual shift arithmetic right 32-bit integers in XRb and XRc
@ -1858,6 +1915,74 @@ static void gen_mxu_q16sxx(DisasContext *ctx, bool right, bool arithmetic)
gen_store_mxu_gpr(t2, XRd);
}
/*
* Q16SLLV XRa, XRd, rs
* Quad 16-bit shift left from XRa and XRd to rs[3:0]
* bits. Store to XRa and XRd respectively.
* Q16SLRV XRa, XRd, rs
* Quad 16-bit shift logic right from XRa and XRd to rs[3:0]
* bits. Store to XRa and XRd respectively.
* Q16SARV XRa, XRd, rs
* Quad 16-bit shift arithmetic right from XRa and XRd to rs[3:0]
* bits. Store to XRa and XRd respectively.
*/
static void gen_mxu_q16sxxv(DisasContext *ctx, bool right, bool arithmetic)
{
uint32_t XRa, XRd, rs;
XRa = extract32(ctx->opcode, 10, 4);
XRd = extract32(ctx->opcode, 14, 4);
rs = extract32(ctx->opcode, 21, 5);
TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
TCGv t2 = tcg_temp_new();
TCGv t3 = tcg_temp_new();
TCGv t5 = tcg_temp_new();
gen_load_mxu_gpr(t0, XRa);
gen_load_mxu_gpr(t2, XRd);
gen_load_gpr(t5, rs);
tcg_gen_andi_tl(t5, t5, 0x0f);
if (arithmetic) {
tcg_gen_sextract_tl(t1, t0, 16, 16);
tcg_gen_sextract_tl(t0, t0, 0, 16);
tcg_gen_sextract_tl(t3, t2, 16, 16);
tcg_gen_sextract_tl(t2, t2, 0, 16);
} else {
tcg_gen_extract_tl(t1, t0, 16, 16);
tcg_gen_extract_tl(t0, t0, 0, 16);
tcg_gen_extract_tl(t3, t2, 16, 16);
tcg_gen_extract_tl(t2, t2, 0, 16);
}
if (right) {
if (arithmetic) {
tcg_gen_sar_tl(t0, t0, t5);
tcg_gen_sar_tl(t1, t1, t5);
tcg_gen_sar_tl(t2, t2, t5);
tcg_gen_sar_tl(t3, t3, t5);
} else {
tcg_gen_shr_tl(t0, t0, t5);
tcg_gen_shr_tl(t1, t1, t5);
tcg_gen_shr_tl(t2, t2, t5);
tcg_gen_shr_tl(t3, t3, t5);
}
} else {
tcg_gen_shl_tl(t0, t0, t5);
tcg_gen_shl_tl(t1, t1, t5);
tcg_gen_shl_tl(t2, t2, t5);
tcg_gen_shl_tl(t3, t3, t5);
}
tcg_gen_deposit_tl(t0, t0, t1, 16, 16);
tcg_gen_deposit_tl(t2, t2, t3, 16, 16);
gen_store_mxu_gpr(t0, XRa);
gen_store_mxu_gpr(t2, XRd);
}
/*
* MXU instruction category max/min/avg
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -4236,6 +4361,36 @@ static void decode_opc_mxu__pool17(DisasContext *ctx)
}
}
static void decode_opc_mxu__pool18(DisasContext *ctx)
{
uint32_t opcode = extract32(ctx->opcode, 18, 3);
switch (opcode) {
case OPC_MXU_D32SLLV:
gen_mxu_d32sxxv(ctx, false, false);
break;
case OPC_MXU_D32SLRV:
gen_mxu_d32sxxv(ctx, true, false);
break;
case OPC_MXU_D32SARV:
gen_mxu_d32sxxv(ctx, true, true);
break;
case OPC_MXU_Q16SLLV:
gen_mxu_q16sxxv(ctx, false, false);
break;
case OPC_MXU_Q16SLRV:
gen_mxu_q16sxxv(ctx, true, false);
break;
case OPC_MXU_Q16SARV:
gen_mxu_q16sxxv(ctx, true, true);
break;
default:
MIPS_INVAL("decode_opc_mxu");
gen_reserved_instruction(ctx);
break;
}
}
static void decode_opc_mxu__pool19(DisasContext *ctx)
{
uint32_t opcode = extract32(ctx->opcode, 22, 2);
@ -4400,6 +4555,9 @@ bool decode_ase_mxu(DisasContext *ctx, uint32_t insn)
case OPC_MXU_Q16SLL:
gen_mxu_q16sxx(ctx, false, false);
break;
case OPC_MXU__POOL18:
decode_opc_mxu__pool18(ctx);
break;
case OPC_MXU_Q16SLR:
gen_mxu_q16sxx(ctx, true, false);
break;