[Qemu-devel] [PATCH v5 19/76] target/mips: Add emulation of nanoMIPS 16-bit arithmetic instructions

Aleksandar Markovic posted 76 patches 7 years, 3 months ago
There is a newer version of this series
[Qemu-devel] [PATCH v5 19/76] target/mips: Add emulation of nanoMIPS 16-bit arithmetic instructions
Posted by Aleksandar Markovic 7 years, 3 months ago
From: Yongbok Kim <yongbok.kim@mips.com>

Add emulation of nanoMIPS 16-bit arithmetic instructions.

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>
---
 target/mips/translate.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 124 insertions(+)

diff --git a/target/mips/translate.c b/target/mips/translate.c
index aba42be..7e13df0 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -16522,6 +16522,130 @@ static inline int decode_gpr_gpr4_zero(int r)
 
 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
 {
+    uint32_t op;
+    int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
+    int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
+    int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode));
+
+    /* make sure instructions are on a halfword boundary */
+    if (ctx->base.pc_next & 0x1) {
+        TCGv tmp = tcg_const_tl(ctx->base.pc_next);
+        tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
+        tcg_temp_free(tmp);
+        generate_exception_end(ctx, EXCP_AdEL);
+        return 2;
+    }
+
+    op = extract32(ctx->opcode, 10, 6);
+    switch (op) {
+    case NM_P16_MV:
+        break;
+    case NM_P16_SHIFT:
+        break;
+    case NM_P16C:
+        break;
+    case NM_P16_A1:
+        switch (extract32(ctx->opcode, 6, 1)) {
+        case NM_ADDIUR1SP:
+            gen_arith_imm(ctx, OPC_ADDIU, rt, 29,
+                          extract32(ctx->opcode, 0, 6) << 2);
+            break;
+        default:
+            generate_exception_end(ctx, EXCP_RI);
+            break;
+        }
+        break;
+    case NM_P16_A2:
+        switch (extract32(ctx->opcode, 3, 1)) {
+        case NM_ADDIUR2:
+            rd = extract32(ctx->opcode, 0, 3) << 2;
+            gen_arith_imm(ctx, OPC_ADDIU, rt, rs, rd);
+            break;
+        case NM_P_ADDIURS5:
+            rt = extract32(ctx->opcode, 5, 5);
+            if (rt != 0) {
+                rs = (sextract32(ctx->opcode, 4, 1) << 3) |
+                      extract32(ctx->opcode, 0, 3);
+                /* s = sign_extend( s[3] . s[2:0] , from_nbits = 4)*/
+                gen_arith_imm(ctx, OPC_ADDIU, rt, rt, rs);
+            }
+            break;
+        }
+        break;
+    case NM_P16_ADDU:
+        switch (ctx->opcode & 0x1) {
+        case NM_ADDU16:
+            gen_arith(ctx, OPC_ADDU, rd, rs, rt);
+            break;
+        case NM_SUBU16:
+            gen_arith(ctx, OPC_SUBU, rd, rs, rt);
+            break;
+        }
+        break;
+    case NM_P16_4X4:
+        rt = (extract32(ctx->opcode, 9, 1) << 3) |
+              extract32(ctx->opcode, 5, 3);
+        rs = (extract32(ctx->opcode, 4, 1) << 3) |
+              extract32(ctx->opcode, 0, 3);
+        rt = decode_gpr_gpr4(rt);
+        rs = decode_gpr_gpr4(rs);
+        switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
+                (extract32(ctx->opcode, 3, 1))) {
+        case NM_ADDU4X4:
+            gen_arith(ctx, OPC_ADDU, rt, rs, rt);
+            break;
+        case NM_MUL4X4:
+            gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
+            break;
+        default:
+            generate_exception_end(ctx, EXCP_RI);
+            break;
+        }
+        break;
+    case NM_LI16:
+        break;
+    case NM_ANDI16:
+        break;
+    case NM_P16_LB:
+        break;
+    case NM_P16_LH:
+        break;
+    case NM_LW16:
+        break;
+    case NM_LWSP16:
+        break;
+    case NM_LW4X4:
+        break;
+    case NM_SW4X4:
+        break;
+    case NM_LWGP16:
+        break;
+    case NM_SWSP16:
+        break;
+    case NM_SW16:
+        break;
+    case NM_SWGP16:
+        break;
+    case NM_BC16:
+        break;
+    case NM_BALC16:
+        break;
+    case NM_BEQZC16:
+        break;
+    case NM_BNEZC16:
+        break;
+    case NM_P16_BR:
+        break;
+    case NM_P16_SR:
+        break;
+    case NM_MOVEP:
+        break;
+    case NM_MOVEPREV:
+        break;
+    default:
+        break;
+    }
+
     return 2;
 }
 
-- 
2.7.4


Re: [Qemu-devel] [PATCH v5 19/76] target/mips: Add emulation of nanoMIPS 16-bit arithmetic instructions
Posted by Richard Henderson 7 years, 3 months ago
On 07/30/2018 12:11 PM, Aleksandar Markovic wrote:
> +    case NM_P16_A2:
> +        switch (extract32(ctx->opcode, 3, 1)) {
> +        case NM_ADDIUR2:
> +            rd = extract32(ctx->opcode, 0, 3) << 2;
> +            gen_arith_imm(ctx, OPC_ADDIU, rt, rs, rd);
> +            break;
> +        case NM_P_ADDIURS5:
> +            rt = extract32(ctx->opcode, 5, 5);
> +            if (rt != 0) {
> +                rs = (sextract32(ctx->opcode, 4, 1) << 3) |
> +                      extract32(ctx->opcode, 0, 3);
> +                /* s = sign_extend( s[3] . s[2:0] , from_nbits = 4)*/
> +                gen_arith_imm(ctx, OPC_ADDIU, rt, rt, rs);
> +            }
> +            break;
> +        }

Now, these re-uses of RD and RS variables are misleading.
These are immediates that you are extracting, not register numbers.

I suggest a "target_long imm;" at the top of the function to handle all such
that will be required when this function is filled out.


r~

Re: [Qemu-devel] [PATCH v5 19/76] target/mips: Add emulation of nanoMIPS 16-bit arithmetic instructions
Posted by Aleksandar Markovic 7 years, 3 months ago
Hi, Richard.

> > +    case NM_P16_A2:
> > +        switch (extract32(ctx->opcode, 3, 1)) {
> > +        case NM_ADDIUR2:
> > +            rd = extract32(ctx->opcode, 0, 3) << 2;
> > +            gen_arith_imm(ctx, OPC_ADDIU, rt, rs, rd);
> > +            break;
> > +        case NM_P_ADDIURS5:
> > +            rt = extract32(ctx->opcode, 5, 5);
> > +            if (rt != 0) {
> > +                rs = (sextract32(ctx->opcode, 4, 1) << 3) |
> > +                      extract32(ctx->opcode, 0, 3);
> > +                /* s = sign_extend( s[3] . s[2:0] , from_nbits = 4)*/
> > +                gen_arith_imm(ctx, OPC_ADDIU, rt, rt, rs);
> > +            }
> > +            break;
> > +        }
> 
> Now, these re-uses of RD and RS variables are misleading.
> These are immediates that you are extracting, not register numbers.
> 
> I suggest a "target_long imm;" at the top of the function to handle all such
> that will be required when this function is filled out.

gen_arith_imm() and similar functions have "int" as the type of offset/imm parameter (in this case the last parameter) - shouldn't "int" be more appropriate type for local variable than "target_long"?

Aleksandar M.

Re: [Qemu-devel] [PATCH v5 19/76] target/mips: Add emulation of nanoMIPS 16-bit arithmetic instructions
Posted by Richard Henderson 7 years, 3 months ago
On 08/01/2018 12:02 PM, Aleksandar Markovic wrote:
>> I suggest a "target_long imm;" at the top of the function to handle all such
>> that will be required when this function is filled out.
> 
> gen_arith_imm() and similar functions have "int" as the type of offset/imm parameter (in this case the last parameter) - shouldn't "int" be more appropriate type for local variable than "target_long"?
Fair enough.  It certainly fits all of the immediates that nanomips can generate.

If you eventually split up gen_arith_imm etc as previously suggested, I suggest
changing to target_long though.  That would allow e.g. the decode for the
MIPS64R6 DATI and DAHI instructions to use the basic gen_daddiu expander with
the immediate already shifted into place in the high 32 bits.


r~