]> err.no Git - linux-2.6/commitdiff
[POWERPC] Emulate isel (Integer Select) instruction
authorKumar Gala <galak@kernel.crashing.org>
Tue, 20 Nov 2007 03:35:29 +0000 (21:35 -0600)
committerKumar Gala <galak@kernel.crashing.org>
Tue, 11 Dec 2007 19:57:16 +0000 (13:57 -0600)
isel (Integer Select) is a new user space instruction in the
PowerISA 2.04 spec.  Not all processors implement it so lets emulate
to ensure code built with isel will run everywhere.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
arch/powerpc/kernel/traps.c

index 59c464e26f38886ff0c6d9ed7f20488dc66b4740..cad64840fce49409c80d0dd0a9f970dd056ca15a 100644 (file)
@@ -622,6 +622,9 @@ static void parse_fpe(struct pt_regs *regs)
 #define INST_POPCNTB           0x7c0000f4
 #define INST_POPCNTB_MASK      0xfc0007fe
 
+#define INST_ISEL              0x7c00001e
+#define INST_ISEL_MASK         0xfc00003e
+
 static int emulate_string_inst(struct pt_regs *regs, u32 instword)
 {
        u8 rT = (instword >> 21) & 0x1f;
@@ -707,6 +710,23 @@ static int emulate_popcntb_inst(struct pt_regs *regs, u32 instword)
        return 0;
 }
 
+static int emulate_isel(struct pt_regs *regs, u32 instword)
+{
+       u8 rT = (instword >> 21) & 0x1f;
+       u8 rA = (instword >> 16) & 0x1f;
+       u8 rB = (instword >> 11) & 0x1f;
+       u8 BC = (instword >> 6) & 0x1f;
+       u8 bit;
+       unsigned long tmp;
+
+       tmp = (rA == 0) ? 0 : regs->gpr[rA];
+       bit = (regs->ccr >> (31 - BC)) & 0x1;
+
+       regs->gpr[rT] = bit ? tmp : regs->gpr[rB];
+
+       return 0;
+}
+
 static int emulate_instruction(struct pt_regs *regs)
 {
        u32 instword;
@@ -749,6 +769,11 @@ static int emulate_instruction(struct pt_regs *regs)
                return emulate_popcntb_inst(regs, instword);
        }
 
+       /* Emulate isel (Integer Select) instruction */
+       if ((instword & INST_ISEL_MASK) == INST_ISEL) {
+               return emulate_isel(regs, instword);
+       }
+
        return -EINVAL;
 }