diff mbox series

[v3,13/40] target/mips: Add emulation of misc nanoMIPS instructions (pool32a0)

Message ID 1532004912-13899-14-git-send-email-stefan.markovic@rt-rk.com
State New
Headers show
Series Add nanoMIPS support to QEMU | expand

Commit Message

Stefan Markovic July 19, 2018, 12:54 p.m. UTC
From: Yongbok Kim <yongbok.kim@mips.com>

Add emulation of nanoMIPS instructions that are situated in pool32a0.

Signed-off-by: Yongbok Kim <yongbok.kim@mips.com>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Signed-off-by: Stefan Markovic <smarkovic@wavecomp.com>
Reviewed-by: Aleksandar Markovic <amarkovic@wavecomp.com>
---
 target/mips/translate.c | 190 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 190 insertions(+)

Comments

Richard Henderson July 19, 2018, 7:08 p.m. UTC | #1
On 07/19/2018 05:54 AM, Stefan Markovic wrote:
> From: Yongbok Kim <yongbok.kim@mips.com>
> 
> Add emulation of nanoMIPS instructions that are situated in pool32a0.
> 
> Signed-off-by: Yongbok Kim <yongbok.kim@mips.com>
> Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
> Signed-off-by: Stefan Markovic <smarkovic@wavecomp.com>
> Reviewed-by: Aleksandar Markovic <amarkovic@wavecomp.com>
> ---
>  target/mips/translate.c | 190 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 190 insertions(+)
> 
> diff --git a/target/mips/translate.c b/target/mips/translate.c
> index 2c7f62e..81c2950 100644
> --- a/target/mips/translate.c
> +++ b/target/mips/translate.c
> @@ -16588,6 +16588,186 @@ static void gen_pool16c_nanomips_insn(DisasContext *ctx)
>      }
>  }
>  
> +static void gen_pool32a0_nanomips_insn(DisasContext *ctx)
> +{
> +    int rt = (ctx->opcode >> 21) & 0x1f;
> +    int rs = (ctx->opcode >> 16) & 0x1f;
> +    int rd = (ctx->opcode >> 11) & 0x1f;

extract32.

> +    case NM_SOV:
> +    {
> +        TCGv t0 = tcg_temp_local_new();
> +        TCGv t1 = tcg_temp_new();
> +        TCGv t2 = tcg_temp_new();
> +        TCGLabel *l1 = gen_new_label();
> +
> +        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);
> +
> +        tcg_gen_movi_tl(t0, 0);
> +        tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);

tcg_gen_setcondi_tl.


r~
Aleksandar Markovic July 25, 2018, 3:38 p.m. UTC | #2
Hi, Richard.

> > +    case NM_SOV:
> > +    {
> > +        TCGv t0 = tcg_temp_local_new();
> > +        TCGv t1 = tcg_temp_new();
> > +        TCGv t2 = tcg_temp_new();
> > +        TCGLabel *l1 = gen_new_label();
> > +
> > +        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);
> > +
> > +        tcg_gen_movi_tl(t0, 0);
> > +        tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
> 
> tcg_gen_setcondi_tl.
> 

Would here the correct simplification be:

Replace code segment

tcg_gen_movi_tl(t0, 0);
tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
tcg_gen_movi_tl(t0, 1);
gen_set_label(l1);

with

tcg_gen_setcondi_tl(TCG_COND_GE, t0, t1, 0);
(plus deleting the declaration of l1 of course)

Regards,
Aleksandar M.
Richard Henderson July 25, 2018, 7:07 p.m. UTC | #3
On 07/25/2018 08:38 AM, Aleksandar Markovic wrote:
> Hi, Richard.
> 
>>> +    case NM_SOV:
>>> +    {
>>> +        TCGv t0 = tcg_temp_local_new();
>>> +        TCGv t1 = tcg_temp_new();
>>> +        TCGv t2 = tcg_temp_new();
>>> +        TCGLabel *l1 = gen_new_label();
>>> +
>>> +        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);
>>> +
>>> +        tcg_gen_movi_tl(t0, 0);
>>> +        tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
>>
>> tcg_gen_setcondi_tl.
>>
> 
> Would here the correct simplification be:
> 
> Replace code segment
> 
> tcg_gen_movi_tl(t0, 0);
> tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
> tcg_gen_movi_tl(t0, 1);
> gen_set_label(l1);
> 
> with
> 
> tcg_gen_setcondi_tl(TCG_COND_GE, t0, t1, 0);
> (plus deleting the declaration of l1 of course)

Nearly.  You're branching over a move of 1, and so computing the inverse of the
condition.  So the correct replacement is

  tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);


r~
diff mbox series

Patch

diff --git a/target/mips/translate.c b/target/mips/translate.c
index 2c7f62e..81c2950 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -16588,6 +16588,186 @@  static void gen_pool16c_nanomips_insn(DisasContext *ctx)
     }
 }
 
+static void gen_pool32a0_nanomips_insn(DisasContext *ctx)
+{
+    int rt = (ctx->opcode >> 21) & 0x1f;
+    int rs = (ctx->opcode >> 16) & 0x1f;
+    int rd = (ctx->opcode >> 11) & 0x1f;
+
+    switch ((ctx->opcode >> 3) & 0x7f) {
+    case NM_P_TRAP:
+        switch ((ctx->opcode >> 10) & 0x1) {
+        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 ((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 ((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_local_new();
+        TCGv t1 = tcg_temp_new();
+        TCGv t2 = tcg_temp_new();
+        TCGLabel *l1 = gen_new_label();
+
+        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);
+
+        tcg_gen_movi_tl(t0, 0);
+        tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
+        /* operands of same sign, result different sign */
+
+        tcg_gen_movi_tl(t0, 1);
+        gen_set_label(l1);
+        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, (ctx->opcode >> 11) & 0x7);
+        break;
+    case NM_MTC0:
+        check_cp0_enabled(ctx);
+        {
+            TCGv t0 = tcg_temp_new();
+
+            gen_load_gpr(t0, rt);
+            gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
+            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;
@@ -16952,6 +17132,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) {