ARM: Don't rely on undefined behavior to get arithmetic right shift.
authorGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:04 +0000 (12:58 -0500)
committerGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:04 +0000 (12:58 -0500)
Shifting to the right of a signed value when the MSB is one is technically
undefined behavior, even though in my experience it's done the "right thing"
and sign extended the value. This replaces the arithmetic right shift code in
ARM that uses that coincidence with some code that relies on bit math.

src/arch/arm/insts/static_inst.cc

index 41bfeac5970713a93104dab9fd004054e7e4c811..52811175980d0be976fdc06d2cff5219bb8bb7ca 100644 (file)
@@ -68,9 +68,9 @@ ArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt,
             return base >> shamt;
       case ASR:
         if (shamt == 0)
-            return (int32_t)base >> 31;
+            return (base >> 31) | -((base & (1 << 31)) >> 31);
         else
-            return (int32_t)base >> shamt;
+            return (base >> shamt) | -((base & (1 << 31)) >> shamt);
       case ROR:
         if (shamt == 0)
             return (cfval << 31) | (base >> 1); // RRX
@@ -106,9 +106,9 @@ ArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt,
             return base >> shamt;
       case ASR:
         if (shamt >= 32)
-            return (int32_t)base >> 31;
+            return (base >> 31) | -((base & (1 << 31)) >> 31);
         else
-            return (int32_t)base >> shamt;
+            return (base >> shamt) | -((base & (1 << 31)) >> shamt);
       case ROR:
         shamt = shamt & 0x1f;
         if (shamt == 0)