target/mips/mxu: Add S32ALN S32LUI insns

These instructions are part of pool16, see the grand opcode organization
tree on top of the file.

Signed-off-by: Siarhei Volkau <lis8215@gmail.com>
Message-Id: <20230608104222.1520143-24-lis8215@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
This commit is contained in:
Siarhei Volkau 2023-06-08 13:42:12 +03:00 committed by Philippe Mathieu-Daudé
parent 29059e72b0
commit 5925963476
1 changed files with 121 additions and 1 deletions

View File

@ -492,7 +492,9 @@ enum {
* MXU pool 16
*/
enum {
OPC_MXU_S32ALN = 0x01,
OPC_MXU_S32ALNI = 0x02,
OPC_MXU_S32LUI = 0x03,
OPC_MXU_S32NOR = 0x04,
OPC_MXU_S32AND = 0x05,
OPC_MXU_S32OR = 0x06,
@ -3066,7 +3068,7 @@ static void gen_mxu_d32asum(DisasContext *ctx)
* MXU instruction category: Miscellaneous
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* S32EXTR
* S32EXTR S32LUI
* S32EXTRV
* Q16SAT
*/
@ -3182,6 +3184,59 @@ static void gen_mxu_s32extrv(DisasContext *ctx)
gen_store_mxu_gpr(t0, XRa);
}
/*
* S32LUI XRa, S8, optn3
* Permutate the immediate S8 value to form a word
* to update XRa.
*/
static void gen_mxu_s32lui(DisasContext *ctx)
{
uint32_t XRa, s8, optn3, pad;
XRa = extract32(ctx->opcode, 6, 4);
s8 = extract32(ctx->opcode, 10, 8);
pad = extract32(ctx->opcode, 21, 2);
optn3 = extract32(ctx->opcode, 23, 3);
if (unlikely(pad != 0)) {
/* opcode padding incorrect -> do nothing */
} else if (unlikely(XRa == 0)) {
/* destination is zero register -> do nothing */
} else {
uint32_t s16;
TCGv t0 = tcg_temp_new();
switch (optn3) {
case 0:
tcg_gen_movi_tl(t0, s8);
break;
case 1:
tcg_gen_movi_tl(t0, s8 << 8);
break;
case 2:
tcg_gen_movi_tl(t0, s8 << 16);
break;
case 3:
tcg_gen_movi_tl(t0, s8 << 24);
break;
case 4:
tcg_gen_movi_tl(t0, (s8 << 16) | s8);
break;
case 5:
tcg_gen_movi_tl(t0, (s8 << 24) | (s8 << 8));
break;
case 6:
s16 = (uint16_t)(int16_t)(int8_t)s8;
tcg_gen_movi_tl(t0, (s16 << 16) | s16);
break;
case 7:
tcg_gen_movi_tl(t0, (s8 << 24) | (s8 << 16) | (s8 << 8) | s8);
break;
}
gen_store_mxu_gpr(t0, XRa);
}
}
/*
* Q16SAT XRa, XRb, XRc
* Packs four 16-bit signed integers in XRb and XRc to
@ -3461,6 +3516,65 @@ static void gen_mxu_S32ALNI(DisasContext *ctx)
}
}
/*
* S32ALN XRc, XRb, XRa, rs
* Arrange bytes from XRb and XRc according to one of five sets of
* rules determined by rs[2:0], and place the result in XRa.
*/
static void gen_mxu_S32ALN(DisasContext *ctx)
{
uint32_t rs, XRc, XRb, XRa;
rs = 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(XRa == 0)) {
/* destination is zero register -> do nothing */
} else if (unlikely((XRb == 0) && (XRc == 0))) {
/* both operands zero registers -> just set destination to all 0s */
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();
TCGLabel *l_exit = gen_new_label();
TCGLabel *l_b_only = gen_new_label();
TCGLabel *l_c_only = gen_new_label();
gen_load_mxu_gpr(t0, XRb);
gen_load_mxu_gpr(t1, XRc);
gen_load_gpr(t2, rs);
tcg_gen_andi_tl(t2, t2, 0x07);
/* do nothing for undefined cases */
tcg_gen_brcondi_tl(TCG_COND_GE, t2, 5, l_exit);
tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l_b_only);
tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 4, l_c_only);
tcg_gen_shli_tl(t2, t2, 3);
tcg_gen_subfi_tl(t3, 32, t2);
tcg_gen_shl_tl(t0, t0, t2);
tcg_gen_shr_tl(t1, t1, t3);
tcg_gen_or_tl(mxu_gpr[XRa - 1], t0, t1);
tcg_gen_br(l_exit);
gen_set_label(l_b_only);
gen_store_mxu_gpr(t0, XRa);
tcg_gen_br(l_exit);
gen_set_label(l_c_only);
gen_store_mxu_gpr(t1, XRa);
gen_set_label(l_exit);
}
}
/*
* S32MADD XRa, XRd, rb, rc
* 32 to 64 bit signed multiply with subsequent add
@ -3889,9 +4003,15 @@ static void decode_opc_mxu__pool16(DisasContext *ctx)
uint32_t opcode = extract32(ctx->opcode, 18, 3);
switch (opcode) {
case OPC_MXU_S32ALN:
gen_mxu_S32ALN(ctx);
break;
case OPC_MXU_S32ALNI:
gen_mxu_S32ALNI(ctx);
break;
case OPC_MXU_S32LUI:
gen_mxu_s32lui(ctx);
break;
case OPC_MXU_S32NOR:
gen_mxu_S32NOR(ctx);
break;