Commit f1bbb99f authored by Paul Mackerras's avatar Paul Mackerras Committed by Michael Ellerman

powerpc: Fix emulation of the isel instruction

The case added for the isel instruction was added inside a switch
statement which uses the 10-bit minor opcode field in the 0x7fe
bits of the instruction word.  However, for the isel instruction,
the minor opcode field is only the 0x3e bits, and the 0x7c0 bits
are used for the "BC" field, which indicates which CR bit to use
to select the result.

Therefore, for the isel emulation to work correctly when BC != 0,
we need to match on ((instr >> 1) & 0x1f) == 15).  To do this, we
pull the isel case out of the switch statement and put it in an
if statement of its own.

Fixes: e27f71e5 ("powerpc/lib/sstep: Add isel instruction emulation")
Signed-off-by: default avatarPaul Mackerras <paulus@ozlabs.org>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent d120cdbc
...@@ -1216,6 +1216,16 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -1216,6 +1216,16 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
return 0; return 0;
case 31: case 31:
/* isel occupies 32 minor opcodes */
if (((instr >> 1) & 0x1f) == 15) {
mb = (instr >> 6) & 0x1f; /* bc field */
val = (regs->ccr >> (31 - mb)) & 1;
val2 = (ra) ? regs->gpr[ra] : 0;
op->val = (val) ? val2 : regs->gpr[rb];
goto compute_done;
}
switch ((instr >> 1) & 0x3ff) { switch ((instr >> 1) & 0x3ff) {
case 4: /* tw */ case 4: /* tw */
if (rd == 0x1f || if (rd == 0x1f ||
...@@ -1441,14 +1451,6 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, ...@@ -1441,14 +1451,6 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
/* /*
* Logical instructions * Logical instructions
*/ */
case 15: /* isel */
mb = (instr >> 6) & 0x1f; /* bc */
val = (regs->ccr >> (31 - mb)) & 1;
val2 = (ra) ? regs->gpr[ra] : 0;
op->val = (val) ? val2 : regs->gpr[rb];
goto compute_done;
case 26: /* cntlzw */ case 26: /* cntlzw */
op->val = __builtin_clz((unsigned int) regs->gpr[rd]); op->val = __builtin_clz((unsigned int) regs->gpr[rd]);
goto logical_done; goto logical_done;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment