]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
target-arm: Add ARM UDIV/SDIV support
authorPeter Maydell <peter.maydell@linaro.org>
Wed, 19 Oct 2011 16:14:06 +0000 (16:14 +0000)
committerPeter Maydell <peter.maydell@linaro.org>
Wed, 19 Oct 2011 16:14:06 +0000 (16:14 +0000)
Add support for UDIV and SDIV in ARM mode. This is a new optional
feature for A profile cores (Thumb mode has had UDIV and SDIV for
M profile cores for some time).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
target-arm/cpu.h
target-arm/helper.c
target-arm/translate.c

index 00e012e5408b36ad645f306c8ccc01d38b3c7055..af3904d2bbcfa1f565d9a0dbc432dc6e6ffbb3d4 100644 (file)
@@ -375,6 +375,7 @@ enum arm_features {
     ARM_FEATURE_V5,
     ARM_FEATURE_STRONGARM,
     ARM_FEATURE_VAPA, /* cp15 VA to PA lookups */
+    ARM_FEATURE_ARM_DIV, /* divide supported in ARM encoding */
 };
 
 static inline int arm_feature(CPUARMState *env, int feature)
index faf0283b2da05a3d0c650236cd26d078401da028..3a51fd73cf825f6cfb9586cbdf810fe482c7abfe 100644 (file)
@@ -207,7 +207,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         set_feature(env, ARM_FEATURE_VFP_FP16);
         set_feature(env, ARM_FEATURE_NEON);
         set_feature(env, ARM_FEATURE_THUMB2EE);
-        set_feature(env, ARM_FEATURE_THUMB_DIV);
+        set_feature(env, ARM_FEATURE_ARM_DIV);
         set_feature(env, ARM_FEATURE_V7MP);
         break;
     case ARM_CPUID_TI915T:
@@ -261,6 +261,9 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     if (arm_feature(env, ARM_FEATURE_V7)) {
         set_feature(env, ARM_FEATURE_VAPA);
     }
+    if (arm_feature(env, ARM_FEATURE_ARM_DIV)) {
+        set_feature(env, ARM_FEATURE_THUMB_DIV);
+    }
 }
 
 void cpu_reset(CPUARMState *env)
index deb0bcfba7489083f55f4e95d367100a529ca352..812a9e7be4d107c18d2070dbbb15d71c09c16266 100644 (file)
@@ -7639,6 +7639,25 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                             store_reg(s, rn, tmp);
                         }
                         break;
+                    case 1:
+                    case 3:
+                        /* SDIV, UDIV */
+                        if (!arm_feature(env, ARM_FEATURE_ARM_DIV)) {
+                            goto illegal_op;
+                        }
+                        if (((insn >> 5) & 7) || (rd != 15)) {
+                            goto illegal_op;
+                        }
+                        tmp = load_reg(s, rm);
+                        tmp2 = load_reg(s, rs);
+                        if (insn & (1 << 21)) {
+                            gen_helper_udiv(tmp, tmp, tmp2);
+                        } else {
+                            gen_helper_sdiv(tmp, tmp, tmp2);
+                        }
+                        tcg_temp_free_i32(tmp2);
+                        store_reg(s, rn, tmp);
+                        break;
                     default:
                         goto illegal_op;
                     }