mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 17:25:27 +00:00
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:
parent
94956d81f6
commit
5729c803a7
|
@ -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. */
|
||||||
|
|
Loading…
Reference in a new issue