Merge commit 'gnu/master' into test
[qemu] / target-arm / translate.c
index f73f5d4..0a1ac27 100644 (file)
@@ -191,14 +191,6 @@ static void store_reg(DisasContext *s, int reg, TCGv var)
     dead_tmp(var);
 }
 
-/* Variant of store_reg which uses branch&exchange logic when storing
-   to r15 in ARM architecture v7 and above. The source must be a temporary
-   and will be marked as dead. */
-#define store_reg_bx(dc, reg, var) \
-    if ((reg) == 15 && ENABLE_ARCH_7) \
-        gen_bx((dc), (var)); \
-    else \
-        store_reg((dc), (reg), (var));
 
 /* Basic operations.  */
 #define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
@@ -215,7 +207,6 @@ static void store_reg(DisasContext *s, int reg, TCGv var)
 #define gen_op_subl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[0], cpu_T[1])
 #define gen_op_sbcl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
 #define gen_op_rsbl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[1], cpu_T[0])
-#define gen_op_rscl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[1], cpu_T[0])
 
 #define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
 #define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
@@ -829,6 +820,19 @@ static inline void gen_bx_T0(DisasContext *s)
     gen_bx(s, tmp);
 }
 
+/* Variant of store_reg which uses branch&exchange logic when storing
+   to r15 in ARM architecture v7 and above. The source must be a temporary
+   and will be marked as dead. */
+static inline void store_reg_bx(CPUState *env, DisasContext *s,
+                                int reg, TCGv var)
+{
+    if (reg == 15 && ENABLE_ARCH_7) {
+        gen_bx(s, var);
+    } else {
+        store_reg(s, reg, var);
+    }
+}
+
 static inline TCGv gen_ld8s(TCGv addr, int index)
 {
     TCGv tmp = new_tmp();
@@ -6116,12 +6120,14 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
             /* immediate operand */
             val = insn & 0xff;
             shift = ((insn >> 8) & 0xf) * 2;
-            if (shift)
+            if (shift) {
                 val = (val >> shift) | (val << (32 - shift));
+            }
             tmp2 = new_tmp();
             tcg_gen_movi_i32(tmp2, val);
-            if (logic_cc && shift)
+            if (logic_cc && shift) {
                 gen_set_CF_bit31(tmp2);
+            }
         } else {
             /* register */
             rm = (insn) & 0xf;
@@ -6139,71 +6145,81 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
         if (op1 != 0x0f && op1 != 0x0d) {
             rn = (insn >> 16) & 0xf;
             tmp = load_reg(s, rn);
-        } else
-            tmp = new_tmp();
+        } else {
+            TCGV_UNUSED(tmp);
+        }
         rd = (insn >> 12) & 0xf;
         switch(op1) {
         case 0x00:
             tcg_gen_and_i32(tmp, tmp, tmp2);
-            if (logic_cc)
+            if (logic_cc) {
                 gen_logic_CC(tmp);
-            store_reg_bx(s, rd, tmp);
+            }
+            store_reg_bx(env, s, rd, tmp);
             break;
         case 0x01:
             tcg_gen_xor_i32(tmp, tmp, tmp2);
-            if (logic_cc)
+            if (logic_cc) {
                 gen_logic_CC(tmp);
-            store_reg_bx(s, rd, tmp);
+            }
+            store_reg_bx(env, s, rd, tmp);
             break;
         case 0x02:
             if (set_cc && rd == 15) {
                 /* SUBS r15, ... is used for exception return.  */
-                if (IS_USER(s))
+                if (IS_USER(s)) {
                     goto illegal_op;
+                }
                 gen_helper_sub_cc(tmp, tmp, tmp2);
                 gen_exception_return(s, tmp);
             } else {
-                if (set_cc)
+                if (set_cc) {
                     gen_helper_sub_cc(tmp, tmp, tmp2);
-                else
+                } else {
                     tcg_gen_sub_i32(tmp, tmp, tmp2);
-                store_reg_bx(s, rd, tmp);
+                }
+                store_reg_bx(env, s, rd, tmp);
             }
             break;
         case 0x03:
-            if (set_cc)
+            if (set_cc) {
                 gen_helper_sub_cc(tmp, tmp2, tmp);
-            else
+            } else {
                 tcg_gen_sub_i32(tmp, tmp2, tmp);
-            store_reg_bx(s, rd, tmp);
+            }
+            store_reg_bx(env, s, rd, tmp);
             break;
         case 0x04:
-            if (set_cc)
+            if (set_cc) {
                 gen_helper_add_cc(tmp, tmp, tmp2);
-            else
+            } else {
                 tcg_gen_add_i32(tmp, tmp, tmp2);
-            store_reg_bx(s, rd, tmp);
+            }
+            store_reg_bx(env, s, rd, tmp);
             break;
         case 0x05:
-            if (set_cc)
+            if (set_cc) {
                 gen_helper_adc_cc(tmp, tmp, tmp2);
-            else
+            } else {
                 gen_add_carry(tmp, tmp, tmp2);
-            store_reg_bx(s, rd, tmp);
+            }
+            store_reg_bx(env, s, rd, tmp);
             break;
         case 0x06:
-            if (set_cc)
+            if (set_cc) {
                 gen_helper_sbc_cc(tmp, tmp, tmp2);
-            else
+            } else {
                 gen_sub_carry(tmp, tmp, tmp2);
-            store_reg_bx(s, rd, tmp);
+            }
+            store_reg_bx(env, s, rd, tmp);
             break;
         case 0x07:
-            if (set_cc)
+            if (set_cc) {
                 gen_helper_sbc_cc(tmp, tmp2, tmp);
-            else
+            } else {
                 gen_sub_carry(tmp, tmp2, tmp);
-            store_reg_bx(s, rd, tmp);
+            }
+            store_reg_bx(env, s, rd, tmp);
             break;
         case 0x08:
             if (set_cc) {
@@ -6220,49 +6236,57 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
             dead_tmp(tmp);
             break;
         case 0x0a:
-            if (set_cc)
+            if (set_cc) {
                 gen_helper_sub_cc(tmp, tmp, tmp2);
+            }
             dead_tmp(tmp);
             break;
         case 0x0b:
-            if (set_cc)
+            if (set_cc) {
                 gen_helper_add_cc(tmp, tmp, tmp2);
+            }
             dead_tmp(tmp);
             break;
         case 0x0c:
             tcg_gen_or_i32(tmp, tmp, tmp2);
-            if (logic_cc)
+            if (logic_cc) {
                 gen_logic_CC(tmp);
-            store_reg_bx(s, rd, tmp);
+            }
+            store_reg_bx(env, s, rd, tmp);
             break;
         case 0x0d:
-            tcg_gen_mov_i32(tmp, tmp2);
             if (logic_cc && rd == 15) {
                 /* MOVS r15, ... is used for exception return.  */
-                if (IS_USER(s))
+                if (IS_USER(s)) {
                     goto illegal_op;
-                gen_exception_return(s, tmp);
+                }
+                gen_exception_return(s, tmp2);
             } else {
-                store_reg_bx(s, rd, tmp);
-                if (logic_cc)
+                if (logic_cc) {
                     gen_logic_CC(tmp2);
+                }
+                store_reg_bx(env, s, rd, tmp2);
             }
             break;
         case 0x0e:
             tcg_gen_bic_i32(tmp, tmp, tmp2);
-            if (logic_cc)
+            if (logic_cc) {
                 gen_logic_CC(tmp);
-            store_reg_bx(s, rd, tmp);
+            }
+            store_reg_bx(env, s, rd, tmp);
             break;
         default:
         case 0x0f:
-            tcg_gen_not_i32(tmp, tmp2);
-            if (logic_cc)
-                gen_logic_CC(tmp);
-            store_reg_bx(s, rd, tmp);
+            tcg_gen_not_i32(tmp2, tmp2);
+            if (logic_cc) {
+                gen_logic_CC(tmp2);
+            }
+            store_reg_bx(env, s, rd, tmp2);
             break;
         }
-        dead_tmp(tmp2);
+        if (op1 != 0x0f && op1 != 0x0d) {
+            dead_tmp(tmp2);
+        }
     } else {
         /* other instructions */
         op1 = (insn >> 24) & 0xf;
@@ -7359,7 +7383,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
             gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
             if (logic_cc)
                 gen_logic_CC(tmp);
-            store_reg(s, rd, tmp);
+            store_reg_bx(env, s, rd, tmp);
             break;
         case 1: /* Sign/zero extend.  */
             tmp = load_reg(s, rm);