]> git.proxmox.com Git - qemu.git/commitdiff
microblaze: Improve subkc
authorEdgar E. Iglesias <edgar.iglesias@gmail.com>
Sat, 22 Jan 2011 11:39:16 +0000 (12:39 +0100)
committerEdgar E. Iglesias <edgar.iglesias@gmail.com>
Sat, 22 Jan 2011 11:39:16 +0000 (12:39 +0100)
Move code from the helper into the translator. The remaining
helper parts can reuse helper_addkc, making it possible to
remove helper_subkc entirely.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
target-microblaze/helper.h
target-microblaze/op_helper.c
target-microblaze/translate.c

index 4871406f8ffe6705ad21e31483c5422b8480f008..9c2a1e4b6d11a64747636cca815a252805f596f6 100644 (file)
@@ -3,7 +3,6 @@
 DEF_HELPER_1(raise_exception, void, i32)
 DEF_HELPER_0(debug, void)
 DEF_HELPER_FLAGS_3(addkc, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32, i32)
-DEF_HELPER_4(subkc, i32, i32, i32, i32, i32)
 DEF_HELPER_2(cmp, i32, i32, i32)
 DEF_HELPER_2(cmpu, i32, i32, i32)
 
index eb5a8b7df32d65704345bd47826aad2a0d77d8cc..59e4674ded765c32558cd59fe05876aecae677c3 100644 (file)
@@ -138,28 +138,6 @@ uint32_t helper_addkc(uint32_t a, uint32_t b, uint32_t cf)
     return ncf;
 }
 
-uint32_t helper_subkc(uint32_t a, uint32_t b, uint32_t k, uint32_t c)
-{
-    uint32_t d, cf = 1, ncf;
-
-    if (c)
-        cf = env->sregs[SR_MSR] >> 31; 
-    assert(cf == 0 || cf == 1);
-    d = b + ~a + cf;
-
-    if (!k) {
-        ncf = compute_carry(b, ~a, cf);
-        assert(ncf == 0 || ncf == 1);
-        if (ncf)
-            env->sregs[SR_MSR] |= MSR_C | MSR_CC;
-        else
-            env->sregs[SR_MSR] &= ~(MSR_C | MSR_CC);
-    }
-    D(qemu_log("%x = %x + %x cf=%d ncf=%d k=%d c=%d\n",
-               d, a, b, cf, ncf, k, c));
-    return d;
-}
-
 static inline int div_prepare(uint32_t a, uint32_t b)
 {
     if (b == 0) {
index 264395b74c2f4aa55031aab7ff3c79f1a8faf333..0c5edc3583b70b88a6cf646d8c8eeec8a8f8c3e6 100644 (file)
@@ -247,6 +247,7 @@ static void dec_add(DisasContext *dc)
 static void dec_sub(DisasContext *dc)
 {
     unsigned int u, cmp, k, c;
+    TCGv cf, na;
 
     u = dc->imm & 2;
     k = dc->opcode & 4;
@@ -261,24 +262,57 @@ static void dec_sub(DisasContext *dc)
             else
                 gen_helper_cmp(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
         }
-    } else {
-        LOG_DIS("sub%s%s r%d, r%d r%d\n",
-                 k ? "k" : "",  c ? "c" : "", dc->rd, dc->ra, dc->rb);
+        return;
+    }
 
-        if (!k || c) {
-            TCGv t;
-            t = tcg_temp_new();
-            if (dc->rd)
-                gen_helper_subkc(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)),
-                                 tcg_const_tl(k), tcg_const_tl(c));
-            else
-                gen_helper_subkc(t, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
-                                 tcg_const_tl(k), tcg_const_tl(c));
-            tcg_temp_free(t);
-        }
-        else if (dc->rd)
+    LOG_DIS("sub%s%s r%d, r%d r%d\n",
+             k ? "k" : "",  c ? "c" : "", dc->rd, dc->ra, dc->rb);
+
+    /* Take care of the easy cases first.  */
+    if (k) {
+        /* k - keep carry, no need to update MSR.  */
+        /* If rd == r0, it's a nop.  */
+        if (dc->rd) {
             tcg_gen_sub_tl(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
+
+            if (c) {
+                /* c - Add carry into the result.  */
+                cf = tcg_temp_new();
+
+                read_carry(dc, cf);
+                tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
+                tcg_temp_free(cf);
+            }
+        }
+        return;
+    }
+
+    /* From now on, we can assume k is zero.  So we need to update MSR.  */
+    /* Extract carry. And complement a into na.  */
+    cf = tcg_temp_new();
+    na = tcg_temp_new();
+    if (c) {
+        read_carry(dc, cf);
+    } else {
+        tcg_gen_movi_tl(cf, 1);
+    }
+
+    /* d = b + ~a + c. carry defaults to 1.  */
+    tcg_gen_not_tl(na, cpu_R[dc->ra]);
+
+    if (dc->rd) {
+        TCGv ncf = tcg_temp_new();
+        gen_helper_addkc(ncf, na, *(dec_alu_op_b(dc)), cf);
+        tcg_gen_add_tl(cpu_R[dc->rd], na, *(dec_alu_op_b(dc)));
+        tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
+        write_carry(dc, ncf);
+        tcg_temp_free(ncf);
+    } else {
+        gen_helper_addkc(cf, na, *(dec_alu_op_b(dc)), cf);
+        write_carry(dc, cf);
     }
+    tcg_temp_free(cf);
+    tcg_temp_free(na);
 }
 
 static void dec_pattern(DisasContext *dc)