All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yongbok Kim <yongbok.kim@imgtec.com>
To: qemu-devel@nongnu.org
Cc: leon.alrae@imgtec.com, aurelien@aurel32.net
Subject: [Qemu-devel] [PATCH 07/13] target-mips: microMIPS32 R6 branches and jumps
Date: Fri, 12 Jun 2015 15:02:17 +0100	[thread overview]
Message-ID: <1434117743-53520-8-git-send-email-yongbok.kim@imgtec.com> (raw)
In-Reply-To: <1434117743-53520-1-git-send-email-yongbok.kim@imgtec.com>

add new microMIPS32 Release 6 branch and jump instructions.

Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
---
 target-mips/translate.c |  209 ++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 181 insertions(+), 28 deletions(-)

diff --git a/target-mips/translate.c b/target-mips/translate.c
index fa81448..0efaa02 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -8198,7 +8198,8 @@ static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
 
 /* R6 CP1 Branches */
 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
-                                   int32_t ft, int32_t offset)
+                                   int32_t ft, int32_t offset,
+                                   int delayslot_size)
 {
     target_ulong btarget;
     const char *opn = "cp1 cond branch";
@@ -8241,7 +8242,15 @@ static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
     MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
                ctx->hflags, btarget);
     ctx->btarget = btarget;
-    ctx->hflags |= MIPS_HFLAG_BDS32;
+
+    switch (delayslot_size) {
+    case 2:
+        ctx->hflags |= MIPS_HFLAG_BDS16;
+        break;
+    case 4:
+        ctx->hflags |= MIPS_HFLAG_BDS32;
+        break;
+    }
 
 out:
     tcg_temp_free_i64(t0);
@@ -10766,7 +10775,8 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
         ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
         if (rs <= rt && rs == 0) {
             /* OPC_BEQZALC, OPC_BNEZALC */
-            tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
+            tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 +
+                    !!(ctx->hflags & MIPS_HFLAG_M16));
         }
         break;
     case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
@@ -10781,7 +10791,8 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
         if (rs == 0 || rs == rt) {
             /* OPC_BLEZALC, OPC_BGEZALC */
             /* OPC_BGTZALC, OPC_BLTZALC */
-            tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
+            tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 +
+                    !!(ctx->hflags & MIPS_HFLAG_M16));
         }
         gen_load_gpr(t0, rs);
         gen_load_gpr(t1, rt);
@@ -10821,13 +10832,15 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
         /* Uncoditional compact branch */
         switch (opc) {
         case OPC_JIALC:
-            tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
+            tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 +
+                    !!(ctx->hflags & MIPS_HFLAG_M16));
             /* Fallthrough */
         case OPC_JIC:
             ctx->hflags |= MIPS_HFLAG_BR;
             break;
         case OPC_BALC:
-            tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
+            tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 +
+                    !!(ctx->hflags & MIPS_HFLAG_M16));
             /* Fallthrough */
         case OPC_BC:
             ctx->hflags |= MIPS_HFLAG_B;
@@ -13169,8 +13182,13 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
         switch (minor) {
         case JALR:
         case JALR_HB:
-            gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
-            ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
+            /* JALRC */
+            if (ctx->insn_flags & ISA_MIPS32R6) {
+                gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
+            } else {
+                gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
+                ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
+            }
             break;
         case JALRS:
         case JALRS_HB:
@@ -14144,11 +14162,25 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
 
             /* Traps */
         case TLTI:
-            mips32_op = OPC_TLTI;
-            goto do_trapi;
+            /* BC1EQZC */
+            if (ctx->insn_flags & ISA_MIPS32R6) {
+                check_cp1_enabled(ctx);
+                gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
+            } else {
+                mips32_op = OPC_TLTI;
+                goto do_trapi;
+            }
+            break;
         case TGEI:
-            mips32_op = OPC_TGEI;
-            goto do_trapi;
+            /* BC1NEZC */
+            if (ctx->insn_flags & ISA_MIPS32R6) {
+                check_cp1_enabled(ctx);
+                gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
+            } else {
+                mips32_op = OPC_TGEI;
+                goto do_trapi;
+            }
+            break;
         case TLTIU:
             check_insn_opc_removed(ctx, ISA_MIPS32R6);
             mips32_op = OPC_TLTIU;
@@ -14351,26 +14383,75 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
         ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
         break;
     case JALS32:
-        offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
-        gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
-        ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
+        /* BOVC, BEQC, BEQZALC */
+        if (ctx->insn_flags & ISA_MIPS32R6) {
+            if (rs >= rt) {
+                /* BOVC */
+                mips32_op = OPC_BOVC;
+            } else if (rs < rt && rs == 0) {
+                /* BEQZALC */
+                mips32_op = OPC_BEQZALC;
+            } else {
+                /* BEQC */
+                mips32_op = OPC_BEQC;
+            }
+            gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
+        } else {
+            offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
+            gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
+            ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
+        }
         break;
     case BEQ32:
-        gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
+        /* BC */
+        if (ctx->insn_flags & ISA_MIPS32R6) {
+            gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
+                                       sextract32(ctx->opcode << 1, 0, 27));
+        } else {
+            gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
+        }
         break;
     case BNE32:
-        gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
+        /* BALC */
+        if (ctx->insn_flags & ISA_MIPS32R6) {
+            gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
+                                       sextract32(ctx->opcode << 1, 0, 27));
+        } else {
+            gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
+        }
         break;
     case J32:
-        check_insn_opc_removed(ctx, ISA_MIPS32R6);
-        gen_compute_branch(ctx, OPC_J, 4, rt, rs,
-                           (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
+        /* BGTZC, BLTZC, BLTC */
+        if (ctx->insn_flags & ISA_MIPS32R6) {
+            if (rs == 0 && rt != 0) {
+                mips32_op = OPC_BGTZC;
+            } else if (rs != 0 && rt != 0 && rs == rt) {
+                mips32_op = OPC_BLTZC;
+            } else {
+                mips32_op = OPC_BLTC;
+            }
+            gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
+        } else {
+            gen_compute_branch(ctx, OPC_J, 4, rt, rs,
+                               (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
+        }
         break;
     case JAL32:
-        check_insn_opc_removed(ctx, ISA_MIPS32R6);
-        gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
-                           (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
-        ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
+        /* BLEZC, BGEZC, BGEC */
+        if (ctx->insn_flags & ISA_MIPS32R6) {
+            if (rs == 0 && rt != 0) {
+                mips32_op = OPC_BLEZC;
+            } else if (rs != 0 && rt != 0 && rs == rt) {
+                mips32_op = OPC_BGEZC;
+            } else {
+                mips32_op = OPC_BGEC;
+            }
+            gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
+        } else {
+            gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
+                               (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
+            ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
+        }
         break;
         /* Floating point (COP1) */
     case LWC132:
@@ -14395,6 +14476,65 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
             gen_addiupc(ctx, reg, offset, 0, 0);
         }
         break;
+    case BNVC:
+        /* BNEC, BNEZALC */
+        check_insn(ctx, ISA_MIPS32R6);
+        if (rs >= rt) {
+            /* BNVC */
+            mips32_op = OPC_BNVC;
+        } else if (rs < rt && rs == 0) {
+            /* BNEZALC */
+            mips32_op = OPC_BNEZALC;
+        } else {
+            /* BNEC */
+            mips32_op = OPC_BNEC;
+        }
+        gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
+        break;
+    case R6_BNEZC:
+        /* JIALC */
+        check_insn(ctx, ISA_MIPS32R6);
+        if (rt != 0) {
+            gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
+                                       sextract32(ctx->opcode << 1, 0, 22));
+        } else {
+            gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
+        }
+        break;
+    case R6_BEQZC:
+        /* JIC */
+        check_insn(ctx, ISA_MIPS32R6);
+        if (rt != 0) {
+            gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
+                                       sextract32(ctx->opcode << 1, 0, 22));
+        } else {
+            gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
+        }
+        break;
+    case BLEZALC:
+        /* BGEZALC, BGEUC */
+        check_insn(ctx, ISA_MIPS32R6);
+        if (rs == 0 && rt != 0) {
+            mips32_op = OPC_BLEZALC;
+        } else if (rs != 0 && rt != 0 && rs == rt) {
+            mips32_op = OPC_BGEZALC;
+        } else {
+            mips32_op = OPC_BGEUC;
+        }
+        gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
+        break;
+    case BGTZALC:
+        /* BLTZALC, BLTUC */
+        check_insn(ctx, ISA_MIPS32R6);
+        if (rs == 0 && rt != 0) {
+            mips32_op = OPC_BGTZALC;
+        } else if (rs != 0 && rt != 0 && rs == rt) {
+            mips32_op = OPC_BLTZALC;
+        } else {
+            mips32_op = OPC_BLTUC;
+        }
+        gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
+        break;
         /* Loads and stores */
     case LB32:
         mips32_op = OPC_LB;
@@ -14673,14 +14813,20 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
         }
         break;
     case B16:
+        /* BC16 */
         gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
-                           SIMM(ctx->opcode, 0, 10) << 1, 4);
+                           SIMM(ctx->opcode, 0, 10) << 1,
+                           (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
         break;
     case BNEZ16:
+        /* BNEZC16 */
     case BEQZ16:
+        /* BEQZC16 */
         gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
                            mmreg(uMIPS_RD(ctx->opcode)),
-                           0, SIMM(ctx->opcode, 0, 7) << 1, 4);
+                           0, SIMM(ctx->opcode, 0, 7) << 1,
+                           (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
+
         break;
     case LI16:
         {
@@ -19047,7 +19193,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
             if (ctx->insn_flags & ISA_MIPS32R6) {
                 /* OPC_BC1EQZ */
                 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
-                                rt, imm << 2);
+                                       rt, imm << 2, 4);
             } else {
                 /* OPC_BC1ANY2 */
                 check_cop1x(ctx);
@@ -19060,7 +19206,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
             check_cp1_enabled(ctx);
             check_insn(ctx, ISA_MIPS32R6);
             gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
-                            rt, imm << 2);
+                                   rt, imm << 2, 4);
             break;
         case OPC_BC1ANY4:
             check_cp1_enabled(ctx);
@@ -19451,6 +19597,13 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
                    forbidden slot */
                 is_slot = 1;
             }
+            if ((ctx.hflags & MIPS_HFLAG_M16) &&
+                (ctx.insn_flags & ISA_MIPS32R6) &&
+                (ctx.hflags & MIPS_HFLAG_FBNSLOT)) {
+                /* Force to generate branch as microMIPS R6 doesn't restrict
+                   branches in the forbidden slot. */
+                is_slot = 1;
+            }
         }
         if (is_slot) {
             gen_branch(&ctx, insn_bytes);
-- 
1.7.5.4

  parent reply	other threads:[~2015-06-12 14:03 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-06-12 14:02 [Qemu-devel] [PATCH 00/13] target-mips: add microMIPS32 R6 Instruction Set support Yongbok Kim
2015-06-12 14:02 ` [Qemu-devel] [PATCH 01/13] target-mips: fix {D, W}RGPR in microMIPS Yongbok Kim
2015-06-15 11:16   ` Aurelien Jarno
2015-06-15 16:19   ` Leon Alrae
2015-06-12 14:02 ` [Qemu-devel] [PATCH 02/13] target-mips: add microMIPS TLBINV, TLBINVF Yongbok Kim
2015-06-15 11:50   ` Aurelien Jarno
2015-06-15 16:19   ` Leon Alrae
2015-06-12 14:02 ` [Qemu-devel] [PATCH 03/13] target-mips: refactor {D}LSA, {D}ALIGN, {D}BITSWAP Yongbok Kim
2015-06-15 11:32   ` Leon Alrae
2015-06-12 14:02 ` [Qemu-devel] [PATCH 04/13] target-mips: rearrange gen_compute_compact_branch Yongbok Kim
2015-06-15 16:19   ` Leon Alrae
2015-06-12 14:02 ` [Qemu-devel] [PATCH 05/13] target-mips: signal RI for removed instructions in microMIPS R6 Yongbok Kim
2015-06-15 16:18   ` Leon Alrae
2015-06-12 14:02 ` [Qemu-devel] [PATCH 06/13] target-mips: add microMIPS32 R6 opcode enum Yongbok Kim
2015-06-12 14:02 ` Yongbok Kim [this message]
2015-06-12 14:02 ` [Qemu-devel] [PATCH 08/13] target-mips: microMIPS32 R6 POOL32A{XF} instructions Yongbok Kim
2015-06-16 15:24   ` Leon Alrae
2015-06-12 14:02 ` [Qemu-devel] [PATCH 09/13] target-mips: microMIPS32 R6 POOL32F instructions Yongbok Kim
2015-06-17 15:50   ` Leon Alrae
2015-06-12 14:02 ` [Qemu-devel] [PATCH 10/13] target-mips: microMIPS32 R6 POOL32{I, C} instructions Yongbok Kim
2015-06-16 13:13   ` Leon Alrae
2015-06-12 14:02 ` [Qemu-devel] [PATCH 11/13] target-mips: microMIPS32 R6 Major instructions Yongbok Kim
2015-06-16 13:07   ` Leon Alrae
2015-06-12 14:02 ` [Qemu-devel] [PATCH 12/13] target-mips: microMIPS32 R6 POOL16{A, C} instructions Yongbok Kim
2015-06-12 14:02 ` [Qemu-devel] [PATCH 13/13] target-mips: add mips32r6-generic CPU definition Yongbok Kim

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1434117743-53520-8-git-send-email-yongbok.kim@imgtec.com \
    --to=yongbok.kim@imgtec.com \
    --cc=aurelien@aurel32.net \
    --cc=leon.alrae@imgtec.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.