]> Git Repo - qemu.git/blobdiff - target-sparc/translate.c
sparc branch fix (Blue Swirl)
[qemu.git] / target-sparc / translate.c
index c2ba2e35cd6dfd7715e97ab9b529c9ecc76ba303..c19797e3bda4132228a685ea60f6b1a42ffe0ba6 100644 (file)
@@ -561,6 +561,32 @@ static inline void gen_movl_npc_im(target_ulong npc)
 #endif
 }
 
+static inline void gen_goto_tb(DisasContext *s, int tb_num, 
+                               target_ulong pc, target_ulong npc)
+{
+    TranslationBlock *tb;
+
+    tb = s->tb;
+    if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) &&
+        (npc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK))  {
+        /* jump to same page: we can use a direct jump */
+        if (tb_num == 0)
+            gen_op_goto_tb0(TBPARAM(tb));
+        else
+            gen_op_goto_tb1(TBPARAM(tb));
+        gen_jmp_im(pc);
+        gen_movl_npc_im(npc);
+        gen_op_movl_T0_im((long)tb + tb_num);
+        gen_op_exit_tb();
+    } else {
+        /* jump to another page: currently not optimized */
+        gen_jmp_im(pc);
+        gen_movl_npc_im(npc);
+        gen_op_movl_T0_0();
+        gen_op_exit_tb();
+    }
+}
+
 static inline void gen_branch2(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2)
 {
     int l1;
@@ -569,18 +595,10 @@ static inline void gen_branch2(DisasContext *dc, long tb, target_ulong pc1, targ
 
     gen_op_jz_T2_label(l1);
 
-    gen_op_goto_tb0(TBPARAM(tb));
-    gen_jmp_im(pc1);
-    gen_movl_npc_im(pc1 + 4);
-    gen_op_movl_T0_im((long)tb + 0);
-    gen_op_exit_tb();
+    gen_goto_tb(dc, 0, pc1, pc1 + 4);
 
     gen_set_label(l1);
-    gen_op_goto_tb1(TBPARAM(tb));
-    gen_jmp_im(pc2);
-    gen_movl_npc_im(pc2 + 4);
-    gen_op_movl_T0_im((long)tb + 1);
-    gen_op_exit_tb();
+    gen_goto_tb(dc, 1, pc2, pc2 + 4);
 }
 
 static inline void gen_branch_a(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2)
@@ -591,27 +609,15 @@ static inline void gen_branch_a(DisasContext *dc, long tb, target_ulong pc1, tar
 
     gen_op_jz_T2_label(l1);
 
-    gen_op_goto_tb0(TBPARAM(tb));
-    gen_jmp_im(pc2);
-    gen_movl_npc_im(pc1);
-    gen_op_movl_T0_im((long)tb + 0);
-    gen_op_exit_tb();
+    gen_goto_tb(dc, 0, pc2, pc1);
 
     gen_set_label(l1);
-    gen_op_goto_tb1(TBPARAM(tb));
-    gen_jmp_im(pc2 + 4);
-    gen_movl_npc_im(pc2 + 8);
-    gen_op_movl_T0_im((long)tb + 1);
-    gen_op_exit_tb();
+    gen_goto_tb(dc, 1, pc2 + 4, pc2 + 8);
 }
 
 static inline void gen_branch(DisasContext *dc, long tb, target_ulong pc, target_ulong npc)
 {
-    gen_op_goto_tb0(TBPARAM(tb));
-    gen_jmp_im(pc);
-    gen_movl_npc_im(npc);
-    gen_op_movl_T0_im((long)tb + 0);
-    gen_op_exit_tb();
+    gen_goto_tb(dc, 0, pc, npc);
 }
 
 static inline void gen_generic_branch(DisasContext *dc, target_ulong npc1, target_ulong npc2)
@@ -950,8 +956,8 @@ static void disas_sparc_insn(DisasContext * dc)
                    int cc;
 
                    target = GET_FIELD_SP(insn, 0, 18);
-                   target <<= 2;
                    target = sign_extend(target, 18);
+                   target <<= 2;
                    cc = GET_FIELD_SP(insn, 20, 21);
                    if (cc == 0)
                        do_branch(dc, target, insn, 0);
@@ -965,8 +971,8 @@ static void disas_sparc_insn(DisasContext * dc)
                {
                    target = GET_FIELD_SP(insn, 0, 13) | 
                        (GET_FIELD_SP(insn, 20, 21) >> 7);
-                   target <<= 2;
                    target = sign_extend(target, 16);
+                   target <<= 2;
                    rs1 = GET_FIELD(insn, 13, 17);
                    gen_movl_reg_T0(rs1);
                    do_branch_reg(dc, target, insn);
@@ -976,11 +982,12 @@ static void disas_sparc_insn(DisasContext * dc)
                {
                    int cc = GET_FIELD_SP(insn, 20, 21);
 #if !defined(CONFIG_USER_ONLY)
+                   save_state(dc);
                    gen_op_trap_ifnofpu();
 #endif
                    target = GET_FIELD_SP(insn, 0, 18);
-                   target <<= 2;
                    target = sign_extend(target, 19);
+                   target <<= 2;
                    do_fbranch(dc, target, insn, cc);
                    goto jmp_insn;
                }
@@ -988,19 +995,20 @@ static void disas_sparc_insn(DisasContext * dc)
            case 0x2:           /* BN+x */
                {
                    target = GET_FIELD(insn, 10, 31);
-                   target <<= 2;
                    target = sign_extend(target, 22);
+                   target <<= 2;
                    do_branch(dc, target, insn, 0);
                    goto jmp_insn;
                }
            case 0x6:           /* FBN+x */
                {
 #if !defined(CONFIG_USER_ONLY)
+                   save_state(dc);
                    gen_op_trap_ifnofpu();
 #endif
                    target = GET_FIELD(insn, 10, 31);
-                   target <<= 2;
                    target = sign_extend(target, 22);
+                   target <<= 2;
                    do_fbranch(dc, target, insn, 0);
                    goto jmp_insn;
                }
@@ -1115,7 +1123,11 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_movl_T0_reg(rd);
                     break;
                case 0x5: /* V9 rdpc */
-                   gen_op_movl_T0_im(dc->pc);
+                   if (dc->pc == (uint32_t)dc->pc) {
+                       gen_op_movl_T0_im(dc->pc);
+                   } else {
+                       gen_op_movq_T0_im64(dc->pc >> 32, dc->pc);
+                   }
                    gen_movl_T0_reg(rd);
                    break;
                case 0x6: /* V9 rdfprs */
@@ -1230,6 +1242,7 @@ static void disas_sparc_insn(DisasContext * dc)
 #endif
            } else if (xop == 0x34) {   /* FPU Operations */
 #if !defined(CONFIG_USER_ONLY)
+               save_state(dc);
                gen_op_trap_ifnofpu();
 #endif
                 rs1 = GET_FIELD(insn, 13, 17);
@@ -1418,6 +1431,7 @@ static void disas_sparc_insn(DisasContext * dc)
                int cond;
 #endif
 #if !defined(CONFIG_USER_ONLY)
+               save_state(dc);
                gen_op_trap_ifnofpu();
 #endif
                 rs1 = GET_FIELD(insn, 13, 17);
@@ -1755,6 +1769,11 @@ static void disas_sparc_insn(DisasContext * dc)
                         else
                             gen_op_addx_T1_T0();
                         break;
+#ifdef TARGET_SPARC64
+                   case 0x9: /* V9 mulx */
+                        gen_op_mulx_T1_T0();
+                        break;
+#endif
                     case 0xa:
                         gen_op_umul_T1_T0();
                         if (xop & 0x10)
@@ -1771,6 +1790,11 @@ static void disas_sparc_insn(DisasContext * dc)
                         else
                             gen_op_subx_T1_T0();
                         break;
+#ifdef TARGET_SPARC64
+                   case 0xd: /* V9 udivx */
+                        gen_op_udivx_T1_T0();
+                        break;
+#endif
                     case 0xe:
                         gen_op_udiv_T1_T0();
                         if (xop & 0x10)
@@ -1787,16 +1811,6 @@ static void disas_sparc_insn(DisasContext * dc)
                    gen_movl_T0_reg(rd);
                 } else {
                     switch (xop) {
-#ifdef TARGET_SPARC64
-                   case 0x9: /* V9 mulx */
-                        gen_op_mulx_T1_T0();
-                       gen_movl_T0_reg(rd);
-                        break;
-                   case 0xd: /* V9 udivx */
-                        gen_op_udivx_T1_T0();
-                       gen_movl_T0_reg(rd);
-                        break;
-#endif
                    case 0x20: /* taddcc */
                    case 0x21: /* tsubcc */
                    case 0x22: /* taddcctv */
@@ -1897,6 +1911,11 @@ static void disas_sparc_insn(DisasContext * dc)
 #else
                             gen_op_xor_T1_T0();
                             gen_op_wrpsr();
+                            save_state(dc);
+                            gen_op_next_insn();
+                           gen_op_movl_T0_0();
+                           gen_op_exit_tb();
+                           dc->is_br = 1;
 #endif
                         }
                         break;
@@ -1927,6 +1946,11 @@ static void disas_sparc_insn(DisasContext * dc)
                                break;
                            case 6: // pstate
                                gen_op_wrpstate();
+                                save_state(dc);
+                                gen_op_next_insn();
+                                gen_op_movl_T0_0();
+                                gen_op_exit_tb();
+                                dc->is_br = 1;
                                break;
                            case 7: // tl
                                gen_op_movl_env_T0(offsetof(CPUSPARCState, tl));
@@ -2106,7 +2130,15 @@ static void disas_sparc_insn(DisasContext * dc)
                case 0x38:      /* jmpl */
                    {
                        if (rd != 0) {
+#ifdef TARGET_SPARC64
+                            if (dc->pc == (uint32_t)dc->pc) {
+                                gen_op_movl_T1_im(dc->pc);
+                            } else {
+                                gen_op_movq_T1_im64(dc->pc >> 32, dc->pc);
+                            }
+#else
                            gen_op_movl_T1_im(dc->pc);
+#endif
                            gen_movl_T1_reg(rd);
                        }
                         gen_mov_pc_npc(dc);
@@ -2335,6 +2367,7 @@ static void disas_sparc_insn(DisasContext * dc)
 #endif
            } else if (xop >= 0x20 && xop < 0x24) {
 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
+               save_state(dc);
                gen_op_trap_ifnofpu();
 #endif
                switch (xop) {
@@ -2343,8 +2376,8 @@ static void disas_sparc_insn(DisasContext * dc)
                    gen_op_store_FT0_fpr(rd);
                    break;
                case 0x21:      /* load fsr */
+                   gen_op_ldst(ldf);
                    gen_op_ldfsr();
-                   gen_op_store_FT0_fpr(rd);
                    break;
                case 0x22:      /* load quad fpreg */
                    goto nfpu_insn;
@@ -2426,9 +2459,8 @@ static void disas_sparc_insn(DisasContext * dc)
                    gen_op_ldst(stf);
                    break;
                case 0x25: /* stfsr, V9 stxfsr */
-                    gen_op_load_fpr_FT0(rd);
-                   // XXX
                    gen_op_stfsr();
+                   gen_op_ldst(stf);
                    break;
                case 0x26: /* stdfq */
                    goto nfpu_insn;
@@ -2662,11 +2694,10 @@ CPUSPARCState *cpu_sparc_init(void)
 {
     CPUSPARCState *env;
 
-    cpu_exec_init();
-
-    if (!(env = malloc(sizeof(CPUSPARCState))))
-       return (NULL);
-    cpu_single_env = env;
+    env = qemu_mallocz(sizeof(CPUSPARCState));
+    if (!env)
+       return NULL;
+    cpu_exec_init(env);
     cpu_reset(env);
     return (env);
 }
@@ -2707,11 +2738,19 @@ void cpu_dump_state(CPUState *env, FILE *f,
         if ((i & 3) == 3)
             cpu_fprintf(f, "\n");
     }
+#ifdef TARGET_SPARC64
+    cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d\n",
+               env->pstate, GET_CCR(env), env->asi, env->tl);
+    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d cleanwin %d cwp %d\n",
+               env->cansave, env->canrestore, env->otherwin, env->wstate,
+               env->cleanwin, NWINDOWS - 1 - env->cwp);
+#else
     cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n", GET_PSR(env),
            GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
            GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
            env->psrs?'S':'-', env->psrps?'P':'-', 
            env->psret?'E':'-', env->wim);
+#endif
     cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
 }
 
This page took 0.032229 seconds and 4 git commands to generate.