[5/5] powerpc/lib/sstep: Add isel instruction emulation

Message ID 20170713032548.451-5-matthew.brown.dev@gmail.com
State Superseded
Headers show

Commit Message

Matt Brown July 13, 2017, 3:25 a.m.
This add emulation for the isel instruction.

Signed-off-by: Matt Brown <matthew.brown.dev@gmail.com>
---
 arch/powerpc/lib/sstep.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

Comments

Segher Boessenkool July 13, 2017, 7:47 a.m. | #1
On Thu, Jul 13, 2017 at 01:25:48PM +1000, Matt Brown wrote:
> +		case 585:	/* isel */

The secondary opcode for isel is only 5 bits, not 10 like most other
insns have.

> +			mb = (instr >> 6) & 0x1f; /* bc */
> +			val = (regs->ccr >> (mb + 32)) & 1;

regs->ccr >> (31 - mb)  ?

> +
> +			if (val)
> +				regs->gpr[rd] = regs->gpr[ra];

You need to treat ra=0 separately (as 0, not reg 0).

> +			else
> +				regs->gpr[rd] = regs->gpr[rb];
> +			goto logical_done;


Segher
Matt Brown July 14, 2017, 12:49 a.m. | #2
On Thu, Jul 13, 2017 at 5:47 PM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
> On Thu, Jul 13, 2017 at 01:25:48PM +1000, Matt Brown wrote:
>> +             case 585:       /* isel */
>
> The secondary opcode for isel is only 5 bits, not 10 like most other
> insns have.

Yet another conversion mistake, I'll get there one day!

>
>> +                     mb = (instr >> 6) & 0x1f; /* bc */
>> +                     val = (regs->ccr >> (mb + 32)) & 1;
>
> regs->ccr >> (31 - mb)  ?
>
>> +
>> +                     if (val)
>> +                             regs->gpr[rd] = regs->gpr[ra];
>
> You need to treat ra=0 separately (as 0, not reg 0).
>
Ah I missed that. The wording in the ISA doesn't make that completely obvious.

Thanks,
Matt

>> +                     else
>> +                             regs->gpr[rd] = regs->gpr[rb];
>> +                     goto logical_done;
>
>
> Segher

Patch

diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 3228783..bb0e301 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1297,6 +1297,16 @@  int analyse_instr(struct instruction_op *op, struct pt_regs *regs,
 			regs->gpr[ra] = ~(regs->gpr[rd] & regs->gpr[rb]);
 			goto logical_done;
 
+		case 585:	/* isel */
+			mb = (instr >> 6) & 0x1f; /* bc */
+			val = (regs->ccr >> (mb + 32)) & 1;
+
+			if (val)
+				regs->gpr[rd] = regs->gpr[ra];
+			else
+				regs->gpr[rd] = regs->gpr[rb];
+			goto logical_done;
+
 		case 922:	/* extsh */
 			regs->gpr[ra] = (signed short) regs->gpr[rd];
 			goto logical_done;