diff mbox series

[6/6] powerpc sstep: Add modsd, modud instruction emulation

Message ID 15e572f61bb5c74b01210b9245ce2750a31d6002.1535609090.git.sandipan@linux.ibm.com (mailing list archive)
State Changes Requested
Headers show
Series powerpc sstep: Extend instruction emulation support | expand

Checks

Context Check Description
snowpatch_ozlabs/build-ppc64le success Test build-ppc64le on branch next
snowpatch_ozlabs/apply_patch success next/apply_patch Successfully applied
snowpatch_ozlabs/checkpatch warning Test checkpatch on branch next
snowpatch_ozlabs/build-ppc64be success Test build-ppc64be on branch next
snowpatch_ozlabs/build-ppc64e success Test build-ppc64e on branch next
snowpatch_ozlabs/build-ppc32 success Test build-ppc32 on branch next

Commit Message

Sandipan Das Sept. 3, 2018, 3:19 p.m. UTC
This adds emulation support for the following integer instructions:
  * Modulo Signed Doubleword (modsd)
  * Modulo Unsigned Doubleword (modud)

Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>
---
 arch/powerpc/lib/sstep.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

Comments

Segher Boessenkool Sept. 4, 2018, 9:21 p.m. UTC | #1
On Mon, Sep 03, 2018 at 08:49:38PM +0530, Sandipan Das wrote:
> +#ifdef __powerpc64__
> +		case 265:	/* modud */
> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +				return -1;
> +			op->val = regs->gpr[ra] % regs->gpr[rb];
> +			goto compute_done;
> +#endif

The mod instruction has special cases that aren't handled by this C code,
too (divide by 0, or signed division of the most negative number by -1).
For the mod intruction the behaviour is undefined in those cases, but you
probably should force some specific behaviour.  You don't want the kernel
to execute a trap instruction, etc. :-)


Segher
Sandipan Das Sept. 5, 2018, 11:53 a.m. UTC | #2
Hi Segher,

On Wednesday 05 September 2018 02:51 AM, Segher Boessenkool wrote:
> On Mon, Sep 03, 2018 at 08:49:38PM +0530, Sandipan Das wrote:
>> +#ifdef __powerpc64__
>> +		case 265:	/* modud */
>> +			if (!cpu_has_feature(CPU_FTR_ARCH_300))
>> +				return -1;
>> +			op->val = regs->gpr[ra] % regs->gpr[rb];
>> +			goto compute_done;
>> +#endif
> 
> The mod instruction has special cases that aren't handled by this C code,
> too (divide by 0, or signed division of the most negative number by -1).
> For the mod intruction the behaviour is undefined in those cases, but you
> probably should force some specific behaviour.  You don't want the kernel
> to execute a trap instruction, etc. :-)
> 

Agreed. In that case, the same would apply to the divw, divwu, divd and divdu
instructions as well, right? Cause I don't see these cases being handled for
them currently.

Also, if I execute a modulo or division instruction for any of these special
cases in a userspace binary, I don't see any exceptions being generated. It's
just that the result is undefined (usually same as one of the source operands,
I don't remember if it was the dividend or the divisor). So, I'm wondering if
this would be necessary.

- Sandipan
diff mbox series

Patch

diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index ddc2de28e00a..b3b508d175fb 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1704,7 +1704,13 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 				(int) regs->gpr[rb];
 
 			goto arith_done;
-
+#ifdef __powerpc64__
+		case 265:	/* modud */
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
+			op->val = regs->gpr[ra] % regs->gpr[rb];
+			goto compute_done;
+#endif
 		case 266:	/* add */
 			op->val = regs->gpr[ra] + regs->gpr[rb];
 			goto arith_done;
@@ -1753,7 +1759,14 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 			}
 
 			return -1;
-
+#ifdef __powerpc64__
+		case 777:	/* modsd */
+			if (!cpu_has_feature(CPU_FTR_ARCH_300))
+				return -1;
+			op->val = (long int) regs->gpr[ra] %
+				(long int) regs->gpr[rb];
+			goto compute_done;
+#endif
 		case 779:	/* modsw */
 			if (!cpu_has_feature(CPU_FTR_ARCH_300))
 				return -1;