target/mips: Add emulation of misc nanoMIPS instructions (pool32a0)

Add emulation of nanoMIPS instructions that are situated in pool32a0.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Signed-off-by: Stefan Markovic <smarkovic@wavecomp.com>
This commit is contained in:
Yongbok Kim 2018-08-02 16:16:17 +02:00 committed by Aleksandar Markovic
parent 579b8ea97a
commit e0cf0e6586

View file

@ -16859,6 +16859,181 @@ static void gen_pool16c_nanomips_insn(DisasContext *ctx)
}
}
static void gen_pool32a0_nanomips_insn(DisasContext *ctx)
{
int rt = extract32(ctx->opcode, 21, 5);
int rs = extract32(ctx->opcode, 16, 5);
int rd = extract32(ctx->opcode, 11, 5);
switch (extract32(ctx->opcode, 3, 7)) {
case NM_P_TRAP:
switch (extract32(ctx->opcode, 10, 1)) {
case NM_TEQ:
gen_trap(ctx, OPC_TEQ, rs, rt, -1);
break;
case NM_TNE:
gen_trap(ctx, OPC_TNE, rs, rt, -1);
break;
}
break;
case NM_RDHWR:
gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
break;
case NM_SEB:
gen_bshfl(ctx, OPC_SEB, rs, rt);
break;
case NM_SEH:
gen_bshfl(ctx, OPC_SEH, rs, rt);
break;
case NM_SLLV:
gen_shift(ctx, OPC_SLLV, rd, rt, rs);
break;
case NM_SRLV:
gen_shift(ctx, OPC_SRLV, rd, rt, rs);
break;
case NM_SRAV:
gen_shift(ctx, OPC_SRAV, rd, rt, rs);
break;
case NM_ROTRV:
gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
break;
case NM_ADD:
gen_arith(ctx, OPC_ADD, rd, rs, rt);
break;
case NM_ADDU:
gen_arith(ctx, OPC_ADDU, rd, rs, rt);
break;
case NM_SUB:
gen_arith(ctx, OPC_SUB, rd, rs, rt);
break;
case NM_SUBU:
gen_arith(ctx, OPC_SUBU, rd, rs, rt);
break;
case NM_P_CMOVE:
switch (extract32(ctx->opcode, 10, 1)) {
case NM_MOVZ:
gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
break;
case NM_MOVN:
gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
break;
}
break;
case NM_AND:
gen_logic(ctx, OPC_AND, rd, rs, rt);
break;
case NM_OR:
gen_logic(ctx, OPC_OR, rd, rs, rt);
break;
case NM_NOR:
gen_logic(ctx, OPC_NOR, rd, rs, rt);
break;
case NM_XOR:
gen_logic(ctx, OPC_XOR, rd, rs, rt);
break;
case NM_SLT:
gen_slt(ctx, OPC_SLT, rd, rs, rt);
break;
case NM_P_SLTU:
if (rd == 0) {
/* P_DVP */
#ifndef CONFIG_USER_ONLY
TCGv t0 = tcg_temp_new();
switch (extract32(ctx->opcode, 10, 1)) {
case NM_DVP:
if (ctx->vp) {
check_cp0_enabled(ctx);
gen_helper_dvp(t0, cpu_env);
gen_store_gpr(t0, rt);
}
break;
case NM_EVP:
if (ctx->vp) {
check_cp0_enabled(ctx);
gen_helper_evp(t0, cpu_env);
gen_store_gpr(t0, rt);
}
break;
}
tcg_temp_free(t0);
#endif
} else {
gen_slt(ctx, OPC_SLTU, rd, rs, rt);
}
break;
case NM_SOV:
{
TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
TCGv t2 = tcg_temp_new();
gen_load_gpr(t1, rs);
gen_load_gpr(t2, rt);
tcg_gen_add_tl(t0, t1, t2);
tcg_gen_ext32s_tl(t0, t0);
tcg_gen_xor_tl(t1, t1, t2);
tcg_gen_xor_tl(t2, t0, t2);
tcg_gen_andc_tl(t1, t2, t1);
/* operands of same sign, result different sign */
tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
gen_store_gpr(t0, rd);
tcg_temp_free(t0);
tcg_temp_free(t1);
tcg_temp_free(t2);
}
break;
case NM_MUL:
gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
break;
case NM_MUH:
gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
break;
case NM_MULU:
gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
break;
case NM_MUHU:
gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
break;
case NM_DIV:
gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
break;
case NM_MOD:
gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
break;
case NM_DIVU:
gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
break;
case NM_MODU:
gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
break;
#ifndef CONFIG_USER_ONLY
case NM_MFC0:
check_cp0_enabled(ctx);
if (rt == 0) {
/* Treat as NOP. */
break;
}
gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
break;
case NM_MTC0:
check_cp0_enabled(ctx);
{
TCGv t0 = tcg_temp_new();
gen_load_gpr(t0, rt);
gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
tcg_temp_free(t0);
}
break;
#endif
default:
generate_exception_end(ctx, EXCP_RI);
break;
}
}
static void gen_pool32f_nanomips_insn(DisasContext *ctx)
{
int rt, rs, rd;
@ -17224,6 +17399,16 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
}
break;
case NM_POOL32A:
switch (ctx->opcode & 0x07) {
case NM_POOL32A0:
gen_pool32a0_nanomips_insn(ctx);
break;
case NM_POOL32A7:
break;
default:
generate_exception_end(ctx, EXCP_RI);
break;
}
break;
case NM_P_GP_W:
switch (ctx->opcode & 0x03) {