ARM: Add a findLsbSet function and use it to implement clz.
authorGabe Black <gblack@eecs.umich.edu>
Thu, 2 Jul 2009 05:16:36 +0000 (22:16 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Thu, 2 Jul 2009 05:16:36 +0000 (22:16 -0700)
src/arch/arm/isa/decoder.isa
src/base/bitfield.hh

index 9d2c90b4c29b634c085f9b8a0404ba596fb23db1..8c9f7aa50000c53c2bb14ed2fbb074e5d02b0223 100644 (file)
@@ -270,18 +270,8 @@ format DataOp {
                 0x1: decode OPCODE {
                     0x9: BranchExchange::bx({{ }});
                     0xb: PredOp::clz({{
-                        if (Rm == 0)
-                            Rd = 32;
-                        else
-                        {
-                            int i;
-                            for (i = 0; i < 32; i++)
-                            {
-                                if (Rm & (1<<(31-i)))
-                                break;
-                            }
-                            Rd = i;
-                        }
+                        unsigned lsb = findLsbSet(Rm);
+                        Rd = (lsb > 31) ? 32 : lsb;
                     }});
                 }
                 0x2: decode OPCODE {
index 28093a5d44e45e8732f885eefcfdd56b0b98b666..cc3695159e639dc030c055ff82aa9d3a245dbf6a 100644 (file)
@@ -161,4 +161,21 @@ findMsbSet(uint64_t val) {
     return msb;
 }
 
+/**
+ * Returns the bit position of the LSB that is set in the input
+ */
+inline int
+findLsbSet(uint64_t val) {
+    int lsb = 0;
+    if (!val)
+        return sizeof(val) * 8;
+    if (!bits(val, 31,0)) { lsb += 32; val >>= 32; }
+    if (!bits(val, 15,0)) { lsb += 16; val >>= 16; }
+    if (!bits(val, 7,0))  { lsb += 8;  val >>= 8;  }
+    if (!bits(val, 3,0))  { lsb += 4;  val >>= 4;  }
+    if (!bits(val, 1,0))  { lsb += 2;  val >>= 2;  }
+    if (!bits(val, 0,0))  { lsb += 1; }
+    return lsb;
+}
+
 #endif // __BASE_BITFIELD_HH__