]> git.proxmox.com Git - qemu.git/commitdiff
more complete ARM shift fix
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Wed, 8 Dec 2004 23:40:14 +0000 (23:40 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Wed, 8 Dec 2004 23:40:14 +0000 (23:40 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1168 c046a42c-6fe2-441c-8c8c-71466251a162

target-arm/op.c
target-arm/translate.c

index 7545bb0f13b5b2b07e941b31395de8717f8a22c6..6596de76fa8325004c12105945026bc8255fabd9 100644 (file)
@@ -463,6 +463,7 @@ void OPPROTO op_swpl_T0_T1(void)
 /* shifts */
 
 /* T1 based */
+
 void OPPROTO op_shll_T1_im(void)
 {
     T1 = T1 << PARAM1;
@@ -473,11 +474,21 @@ void OPPROTO op_shrl_T1_im(void)
     T1 = (uint32_t)T1 >> PARAM1;
 }
 
+void OPPROTO op_shrl_T1_0(void)
+{
+    T1 = 0;
+}
+
 void OPPROTO op_sarl_T1_im(void)
 {
     T1 = (int32_t)T1 >> PARAM1;
 }
 
+void OPPROTO op_sarl_T1_0(void)
+{
+    T1 = (int32_t)T1 >> 31;
+}
+
 void OPPROTO op_rorl_T1_im(void)
 {
     int shift;
@@ -503,12 +514,24 @@ void OPPROTO op_shrl_T1_im_cc(void)
     T1 = (uint32_t)T1 >> PARAM1;
 }
 
+void OPPROTO op_shrl_T1_0_cc(void)
+{
+    env->CF = (T1 >> 31) & 1;
+    T1 = 0;
+}
+
 void OPPROTO op_sarl_T1_im_cc(void)
 {
     env->CF = (T1 >> (PARAM1 - 1)) & 1;
     T1 = (int32_t)T1 >> PARAM1;
 }
 
+void OPPROTO op_sarl_T1_0_cc(void)
+{
+    env->CF = (T1 >> 31) & 1;
+    T1 = (int32_t)T1 >> 31;
+}
+
 void OPPROTO op_rorl_T1_im_cc(void)
 {
     int shift;
@@ -536,11 +559,21 @@ void OPPROTO op_shrl_T2_im(void)
     T2 = (uint32_t)T2 >> PARAM1;
 }
 
+void OPPROTO op_shrl_T2_0(void)
+{
+    T2 = 0;
+}
+
 void OPPROTO op_sarl_T2_im(void)
 {
     T2 = (int32_t)T2 >> PARAM1;
 }
 
+void OPPROTO op_sarl_T2_0(void)
+{
+    T2 = (int32_t)T2 >> 31;
+}
+
 void OPPROTO op_rorl_T2_im(void)
 {
     int shift;
@@ -548,6 +581,11 @@ void OPPROTO op_rorl_T2_im(void)
     T2 = ((uint32_t)T2 >> shift) | (T2 << (32 - shift));
 }
 
+void OPPROTO op_rrxl_T2(void)
+{
+    T2 = ((uint32_t)T2 >> 1) | ((uint32_t)env->CF << 31);
+}
+
 /* T1 based, use T0 as shift count */
 
 void OPPROTO op_shll_T1_T0(void)
index 18caa81212fe74e20bf0971f809f94982fcc8e50..56efa41e10ed6f8e6683ee5fcca29f841fa495dc 100644 (file)
@@ -94,6 +94,13 @@ static GenOpFunc1 *gen_shift_T1_im[4] = {
     gen_op_rorl_T1_im,
 };
 
+static GenOpFunc *gen_shift_T1_0[4] = {
+    NULL,
+    gen_op_shrl_T1_0,
+    gen_op_sarl_T1_0,
+    gen_op_rrxl_T1,
+};
+
 static GenOpFunc1 *gen_shift_T2_im[4] = {
     gen_op_shll_T2_im,
     gen_op_shrl_T2_im,
@@ -101,6 +108,13 @@ static GenOpFunc1 *gen_shift_T2_im[4] = {
     gen_op_rorl_T2_im,
 };
 
+static GenOpFunc *gen_shift_T2_0[4] = {
+    NULL,
+    gen_op_shrl_T2_0,
+    gen_op_sarl_T2_0,
+    gen_op_rrxl_T2,
+};
+
 static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
     gen_op_shll_T1_im_cc,
     gen_op_shrl_T1_im_cc,
@@ -108,6 +122,13 @@ static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
     gen_op_rorl_T1_im_cc,
 };
 
+static GenOpFunc *gen_shift_T1_0_cc[4] = {
+    NULL,
+    gen_op_shrl_T1_0_cc,
+    gen_op_sarl_T1_0_cc,
+    gen_op_rrxl_T1_cc,
+};
+
 static GenOpFunc *gen_shift_T1_T0[4] = {
     gen_op_shll_T1_T0,
     gen_op_shrl_T1_T0,
@@ -272,7 +293,7 @@ static inline void gen_movl_reg_T1(DisasContext *s, int reg)
 
 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
 {
-    int val, rm, shift;
+    int val, rm, shift, shiftop;
 
     if (!(insn & (1 << 25))) {
         /* immediate */
@@ -286,8 +307,11 @@ static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
         rm = (insn) & 0xf;
         shift = (insn >> 7) & 0x1f;
         gen_movl_T2_reg(s, rm);
+        shiftop = (insn >> 5) & 3;
         if (shift != 0) {
-            gen_shift_T2_im[(insn >> 5) & 3](shift);
+            gen_shift_T2_im[shiftop](shift);
+        } else if (shiftop != 0) {
+            gen_shift_T2_0[shiftop]();
         }
         if (!(insn & (1 << 23)))
             gen_op_subl_T1_T2();
@@ -365,11 +389,12 @@ static void disas_arm_insn(DisasContext *s)
                     } else {
                         gen_shift_T1_im[shiftop](shift);
                     }
-                } else if (shiftop == 3) {
-                    if (logic_cc)
-                        gen_op_rrxl_T1_cc();
-                    else
-                        gen_op_rrxl_T1();
+                } else if (shiftop != 0) {
+                    if (logic_cc) {
+                        gen_shift_T1_0_cc[shiftop]();
+                    } else {
+                        gen_shift_T1_0[shiftop]();
+                    }
                 }
             } else {
                 rs = (insn >> 8) & 0xf;