Merge mulgrave-w:git/scsi-misc-2.6
[pandora-kernel.git] / arch / powerpc / kernel / traps.c
index e4d1713..d9f10f2 100644 (file)
@@ -585,19 +585,22 @@ static void parse_fpe(struct pt_regs *regs)
 #define INST_MFSPR_PVR_MASK    0xfc1fffff
 
 #define INST_DCBA              0x7c0005ec
-#define INST_DCBA_MASK         0x7c0007fe
+#define INST_DCBA_MASK         0xfc0007fe
 
 #define INST_MCRXR             0x7c000400
-#define INST_MCRXR_MASK                0x7c0007fe
+#define INST_MCRXR_MASK                0xfc0007fe
 
 #define INST_STRING            0x7c00042a
-#define INST_STRING_MASK       0x7c0007fe
-#define INST_STRING_GEN_MASK   0x7c00067e
+#define INST_STRING_MASK       0xfc0007fe
+#define INST_STRING_GEN_MASK   0xfc00067e
 #define INST_LSWI              0x7c0004aa
 #define INST_LSWX              0x7c00042a
 #define INST_STSWI             0x7c0005aa
 #define INST_STSWX             0x7c00052a
 
+#define INST_POPCNTB           0x7c0000f4
+#define INST_POPCNTB_MASK      0xfc0007fe
+
 static int emulate_string_inst(struct pt_regs *regs, u32 instword)
 {
        u8 rT = (instword >> 21) & 0x1f;
@@ -666,6 +669,23 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword)
        return 0;
 }
 
+static int emulate_popcntb_inst(struct pt_regs *regs, u32 instword)
+{
+       u32 ra,rs;
+       unsigned long tmp;
+
+       ra = (instword >> 16) & 0x1f;
+       rs = (instword >> 21) & 0x1f;
+
+       tmp = regs->gpr[rs];
+       tmp = tmp - ((tmp >> 1) & 0x5555555555555555ULL);
+       tmp = (tmp & 0x3333333333333333ULL) + ((tmp >> 2) & 0x3333333333333333ULL);
+       tmp = (tmp + (tmp >> 4)) & 0x0f0f0f0f0f0f0f0fULL;
+       regs->gpr[ra] = tmp;
+
+       return 0;
+}
+
 static int emulate_instruction(struct pt_regs *regs)
 {
        u32 instword;
@@ -703,6 +723,11 @@ static int emulate_instruction(struct pt_regs *regs)
        if ((instword & INST_STRING_GEN_MASK) == INST_STRING)
                return emulate_string_inst(regs, instword);
 
+       /* Emulate the popcntb (Population Count Bytes) instruction. */
+       if ((instword & INST_POPCNTB_MASK) == INST_POPCNTB) {
+               return emulate_popcntb_inst(regs, instword);
+       }
+
        return -EINVAL;
 }