target/mips: MXU: Add handler for an align instruction

Add translation handler for S32ALNI MXU instruction.

Backports commit 79f5fee7a3c53494c7ca4bc18c72944f5e2d5c2f from qemu
This commit is contained in:
Aleksandar Markovic 2019-01-05 08:00:06 -05:00 committed by Lioncash
parent 94956d81f6
commit 5729c803a7
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -25266,6 +25266,200 @@ static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
} }
/*
* MXU instruction category: align
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* S32ALN S32ALNI
*/
/*
* S32ALNI XRc, XRb, XRa, optn3
* Arrange bytes from XRb and XRc according to one of five sets of
* rules determined by optn3, and place the result in XRa.
*
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
* +-----------+-----+---+-----+-------+-------+-------+-----------+
* | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
* +-----------+-----+---+-----+-------+-------+-------+-----------+
*
*/
static void gen_mxu_S32ALNI(DisasContext *ctx)
{
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
uint32_t optn3, pad, XRc, XRb, XRa;
optn3 = extract32(ctx->opcode, 23, 3);
pad = extract32(ctx->opcode, 21, 2);
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 all 0s */
tcg_gen_movi_i32(tcg_ctx, tcg_ctx->mxu_gpr[XRa - 1], 0);
} else if (unlikely(XRb == 0)) {
/* XRb zero register -> just appropriatelly shift XRc into XRa */
switch (optn3) {
case MXU_OPTN3_PTN0:
tcg_gen_movi_i32(tcg_ctx, tcg_ctx->mxu_gpr[XRa - 1], 0);
break;
case MXU_OPTN3_PTN1:
case MXU_OPTN3_PTN2:
case MXU_OPTN3_PTN3:
tcg_gen_shri_i32(tcg_ctx, tcg_ctx->mxu_gpr[XRa - 1], tcg_ctx->mxu_gpr[XRc - 1],
8 * (4 - optn3));
break;
case MXU_OPTN3_PTN4:
tcg_gen_mov_i32(tcg_ctx, tcg_ctx->mxu_gpr[XRa - 1], tcg_ctx->mxu_gpr[XRc - 1]);
break;
}
} else if (unlikely(XRc == 0)) {
/* XRc zero register -> just appropriatelly shift XRb into XRa */
switch (optn3) {
case MXU_OPTN3_PTN0:
tcg_gen_mov_i32(tcg_ctx, tcg_ctx->mxu_gpr[XRa - 1], tcg_ctx->mxu_gpr[XRb - 1]);
break;
case MXU_OPTN3_PTN1:
case MXU_OPTN3_PTN2:
case MXU_OPTN3_PTN3:
tcg_gen_shri_i32(tcg_ctx, tcg_ctx->mxu_gpr[XRa - 1], tcg_ctx->mxu_gpr[XRb - 1], 8 * optn3);
break;
case MXU_OPTN3_PTN4:
tcg_gen_movi_i32(tcg_ctx, tcg_ctx->mxu_gpr[XRa - 1], 0);
break;
}
} else if (unlikely(XRb == XRc)) {
/* both operands same -> just rotation or moving from any of them */
switch (optn3) {
case MXU_OPTN3_PTN0:
case MXU_OPTN3_PTN4:
tcg_gen_mov_i32(tcg_ctx, tcg_ctx->mxu_gpr[XRa - 1], tcg_ctx->mxu_gpr[XRb - 1]);
break;
case MXU_OPTN3_PTN1:
case MXU_OPTN3_PTN2:
case MXU_OPTN3_PTN3:
tcg_gen_rotli_i32(tcg_ctx, tcg_ctx->mxu_gpr[XRa - 1], tcg_ctx->mxu_gpr[XRb - 1], 8 * optn3);
break;
}
} else {
/* the most general case */
switch (optn3) {
case MXU_OPTN3_PTN0:
{
/* */
/* XRb XRc */
/* +---------------+ */
/* | A B C D | E F G H */
/* +-------+-------+ */
/* | */
/* XRa */
/* */
tcg_gen_mov_i32(tcg_ctx, tcg_ctx->mxu_gpr[XRa - 1], tcg_ctx->mxu_gpr[XRb - 1]);
}
break;
case MXU_OPTN3_PTN1:
{
/* */
/* XRb XRc */
/* +-------------------+ */
/* A | B C D E | F G H */
/* +---------+---------+ */
/* | */
/* XRa */
/* */
TCGv_i32 t0 = tcg_temp_new(tcg_ctx);
TCGv_i32 t1 = tcg_temp_new(tcg_ctx);
tcg_gen_andi_i32(tcg_ctx, t0, tcg_ctx->mxu_gpr[XRb - 1], 0x00FFFFFF);
tcg_gen_shli_i32(tcg_ctx, t0, t0, 8);
tcg_gen_andi_i32(tcg_ctx, t1, tcg_ctx->mxu_gpr[XRc - 1], 0xFF000000);
tcg_gen_shri_i32(tcg_ctx, t1, t1, 24);
tcg_gen_or_i32(tcg_ctx, tcg_ctx->mxu_gpr[XRa - 1], t0, t1);
tcg_temp_free(tcg_ctx, t1);
tcg_temp_free(tcg_ctx, t0);
}
break;
case MXU_OPTN3_PTN2:
{
/* */
/* XRb XRc */
/* +-------------------+ */
/* A B | C D E F | G H */
/* +---------+---------+ */
/* | */
/* XRa */
/* */
TCGv_i32 t0 = tcg_temp_new(tcg_ctx);
TCGv_i32 t1 = tcg_temp_new(tcg_ctx);
tcg_gen_andi_i32(tcg_ctx, t0, tcg_ctx->mxu_gpr[XRb - 1], 0x0000FFFF);
tcg_gen_shli_i32(tcg_ctx, t0, t0, 16);
tcg_gen_andi_i32(tcg_ctx, t1, tcg_ctx->mxu_gpr[XRc - 1], 0xFFFF0000);
tcg_gen_shri_i32(tcg_ctx, t1, t1, 16);
tcg_gen_or_i32(tcg_ctx, tcg_ctx->mxu_gpr[XRa - 1], t0, t1);
tcg_temp_free(tcg_ctx, t1);
tcg_temp_free(tcg_ctx, t0);
}
break;
case MXU_OPTN3_PTN3:
{
/* */
/* XRb XRc */
/* +-------------------+ */
/* A B C | D E F G | H */
/* +---------+---------+ */
/* | */
/* XRa */
/* */
TCGv_i32 t0 = tcg_temp_new(tcg_ctx);
TCGv_i32 t1 = tcg_temp_new(tcg_ctx);
tcg_gen_andi_i32(tcg_ctx, t0, tcg_ctx->mxu_gpr[XRb - 1], 0x000000FF);
tcg_gen_shli_i32(tcg_ctx, t0, t0, 24);
tcg_gen_andi_i32(tcg_ctx, t1, tcg_ctx->mxu_gpr[XRc - 1], 0xFFFFFF00);
tcg_gen_shri_i32(tcg_ctx, t1, t1, 8);
tcg_gen_or_i32(tcg_ctx, tcg_ctx->mxu_gpr[XRa - 1], t0, t1);
tcg_temp_free(tcg_ctx, t1);
tcg_temp_free(tcg_ctx, t0);
}
break;
case MXU_OPTN3_PTN4:
{
/* */
/* XRb XRc */
/* +---------------+ */
/* A B C D | E F G H | */
/* +-------+-------+ */
/* | */
/* XRa */
/* */
tcg_gen_mov_i32(tcg_ctx, tcg_ctx->mxu_gpr[XRa - 1], tcg_ctx->mxu_gpr[XRc - 1]);
}
break;
}
}
}
/* /*
* Decoding engine for MXU * Decoding engine for MXU
* ======================= * =======================
@ -25928,9 +26122,7 @@ static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
generate_exception_end(ctx, EXCP_RI); generate_exception_end(ctx, EXCP_RI);
break; break;
case OPC_MXU_S32ALNI: case OPC_MXU_S32ALNI:
/* TODO: Implement emulation of S32ALNI instruction. */ gen_mxu_S32ALNI(ctx);
MIPS_INVAL("OPC_MXU_S32ALNI");
generate_exception_end(ctx, EXCP_RI);
break; break;
case OPC_MXU_S32LUI: case OPC_MXU_S32LUI:
/* TODO: Implement emulation of S32LUI instruction. */ /* TODO: Implement emulation of S32LUI instruction. */