microblaze: Improve addkc

* Optimize handling when carry is not updated.
* Optimize handling for adds with nop semantics.
* Move code from helper_addkc to the translator making
  helper_addkc PURE and CONST.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
diff --git a/target-microblaze/helper.h b/target-microblaze/helper.h
index 11ad1b6..4871406 100644
--- a/target-microblaze/helper.h
+++ b/target-microblaze/helper.h
@@ -2,7 +2,7 @@
 
 DEF_HELPER_1(raise_exception, void, i32)
 DEF_HELPER_0(debug, void)
-DEF_HELPER_4(addkc, i32, i32, i32, i32, i32)
+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)
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index 97461ae..eb5a8b7 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -128,26 +128,14 @@
     return t;
 }
 
-uint32_t helper_addkc(uint32_t a, uint32_t b, uint32_t k, uint32_t c)
+uint32_t helper_addkc(uint32_t a, uint32_t b, uint32_t cf)
 {
-    uint32_t d, cf = 0, ncf;
+    uint32_t d, ncf;
 
-    if (c)
-        cf = env->sregs[SR_MSR] >> 31;
-    assert(cf == 0 || cf == 1);
     d = a + b + cf;
 
-    if (!k) {
-        ncf = compute_carry(a, b, 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;
+    ncf = compute_carry(a, b, cf);
+    return ncf;
 }
 
 uint32_t helper_subkc(uint32_t a, uint32_t b, uint32_t k, uint32_t c)
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index dd2865c..d983c8b 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -193,6 +193,7 @@
 static void dec_add(DisasContext *dc)
 {
     unsigned int k, c;
+    TCGv cf;
 
     k = dc->opcode & 4;
     c = dc->opcode & 2;
@@ -201,17 +202,47 @@
             dc->type_b ? "i" : "", k ? "k" : "", c ? "c" : "",
             dc->rd, dc->ra, dc->rb);
 
-    if (k && !c && dc->rd)
-        tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
-    else if (dc->rd)
-        gen_helper_addkc(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)),
-                         tcg_const_tl(k), tcg_const_tl(c));
-    else {
-        TCGv d = tcg_temp_new();
-        gen_helper_addkc(d, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
-                         tcg_const_tl(k), tcg_const_tl(c));
-        tcg_temp_free(d);
+    /* 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_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
+
+            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.  */
+    cf = tcg_temp_new();
+    if (c) {
+        read_carry(dc, cf);
+    } else {
+        tcg_gen_movi_tl(cf, 0);
+    }
+
+    if (dc->rd) {
+        TCGv ncf = tcg_temp_new();
+        gen_helper_addkc(ncf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf);
+        tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(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, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
+                         tcg_const_tl(cf));
+        write_carry(dc, cf);
+    }
+    tcg_temp_free(cf);
 }
 
 static void dec_sub(DisasContext *dc)