diff mbox series

[1/6] powerpc sstep: Add maddhd, maddhdu, maddld instruction emulation

Message ID 2962112510464de01b24f9e1014909fde3380d52.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/apply_patch success next/apply_patch Successfully applied
snowpatch_ozlabs/checkpatch warning Test checkpatch on branch next

Commit Message

Sandipan Das Sept. 3, 2018, 3:19 p.m. UTC
This adds emulation support for the following integer instructions:
  * Multiply-Add High Doubleword (maddhd)
  * Multiply-Add High Doubleword Unsigned (maddhdu)
  * Multiply-Add Low Doubleword (maddld)

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

Comments

Segher Boessenkool Sept. 4, 2018, 10:12 p.m. UTC | #1
On Mon, Sep 03, 2018 at 08:49:33PM +0530, Sandipan Das wrote:
> +#ifdef __powerpc64__
> +	case 4:
> +		if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +			return -1;
> +
> +		switch (instr & 0x3f) {
> +		case 48:	/* maddhd */
> +			asm("maddhd %0,%1,%2,%3" : "=r" (op->val) :
> +			    "r" (regs->gpr[ra]), "r" (regs->gpr[rb]),
> +			    "r" (regs->gpr[rc]));
> +			goto compute_done;

If running maddhd does not work, will running it in kernel mode work?

I think you should *actually* emulate it.

(Same for the next patch, "darn", but emulation of that is much more
interesting).


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

On Wednesday 05 September 2018 03:42 AM, Segher Boessenkool wrote:
> On Mon, Sep 03, 2018 at 08:49:33PM +0530, Sandipan Das wrote:
>> +#ifdef __powerpc64__
>> +	case 4:
>> +		if (!cpu_has_feature(CPU_FTR_ARCH_300))
>> +			return -1;
>> +
>> +		switch (instr & 0x3f) {
>> +		case 48:	/* maddhd */
>> +			asm("maddhd %0,%1,%2,%3" : "=r" (op->val) :
>> +			    "r" (regs->gpr[ra]), "r" (regs->gpr[rb]),
>> +			    "r" (regs->gpr[rc]));
>> +			goto compute_done;
> 
> If running maddhd does not work, will running it in kernel mode work?
> 

Not sure what you meant here but one of the scenarios that I'm aware of
where this is will be used is if we place a probe at a location having
an maddhd instruction. The kernel would first attempt to emulate its
behaviour, which in this case is done by executing the same instruction
(similar to what is done for mulhd and mulhw) and if that fails, try to
execute the instruction natively.

- Sandipan
Michael Ellerman Feb. 20, 2019, 12:51 a.m. UTC | #3
Sandipan Das <sandipan@linux.ibm.com> writes:

> This adds emulation support for the following integer instructions:
>   * Multiply-Add High Doubleword (maddhd)
>   * Multiply-Add High Doubleword Unsigned (maddhdu)
>   * Multiply-Add Low Doubleword (maddld)

This doesn't build with old binutils.

    {standard input}:2089: Error: Unrecognized opcode: `maddld'
    {standard input}:2104: Error: Unrecognized opcode: `maddhdu'
    {standard input}:1141: Error: Unrecognized opcode: `maddhd'


You'll need to add hand built versions, see ppc-opcode.h for examples.

cheers

> diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
> index d81568f783e5..b40ec18515bd 100644
> --- a/arch/powerpc/lib/sstep.c
> +++ b/arch/powerpc/lib/sstep.c
> @@ -1169,7 +1169,7 @@ static nokprobe_inline int trap_compare(long v1, long v2)
>  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  		  unsigned int instr)
>  {
> -	unsigned int opcode, ra, rb, rd, spr, u;
> +	unsigned int opcode, ra, rb, rc, rd, spr, u;
>  	unsigned long int imm;
>  	unsigned long int val, val2;
>  	unsigned int mb, me, sh;
> @@ -1292,6 +1292,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  	rd = (instr >> 21) & 0x1f;
>  	ra = (instr >> 16) & 0x1f;
>  	rb = (instr >> 11) & 0x1f;
> +	rc = (instr >> 6) & 0x1f;
>  
>  	switch (opcode) {
>  #ifdef __powerpc64__
> @@ -1305,6 +1306,38 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
>  			goto trap;
>  		return 1;
>  
> +#ifdef __powerpc64__
> +	case 4:
> +		if (!cpu_has_feature(CPU_FTR_ARCH_300))
> +			return -1;
> +
> +		switch (instr & 0x3f) {
> +		case 48:	/* maddhd */
> +			asm("maddhd %0,%1,%2,%3" : "=r" (op->val) :
> +			    "r" (regs->gpr[ra]), "r" (regs->gpr[rb]),
> +			    "r" (regs->gpr[rc]));
> +			goto compute_done;
> +
> +		case 49:	/* maddhdu */
> +			asm("maddhdu %0,%1,%2,%3" : "=r" (op->val) :
> +			    "r" (regs->gpr[ra]), "r" (regs->gpr[rb]),
> +			    "r" (regs->gpr[rc]));
> +			goto compute_done;
> +
> +		case 51:	/* maddld */
> +			asm("maddld %0,%1,%2,%3" : "=r" (op->val) :
> +			    "r" (regs->gpr[ra]), "r" (regs->gpr[rb]),
> +			    "r" (regs->gpr[rc]));
> +			goto compute_done;
> +		}
> +
> +		/*
> +		 * There are other instructions from ISA 3.0 with the same
> +		 * primary opcode which do not have emulation support yet.
> +		 */
> +		return -1;
> +#endif
> +
>  	case 7:		/* mulli */
>  		op->val = regs->gpr[ra] * (short) instr;
>  		goto compute_done;
> -- 
> 2.14.4
diff mbox series

Patch

diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index d81568f783e5..b40ec18515bd 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1169,7 +1169,7 @@  static nokprobe_inline int trap_compare(long v1, long v2)
 int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 		  unsigned int instr)
 {
-	unsigned int opcode, ra, rb, rd, spr, u;
+	unsigned int opcode, ra, rb, rc, rd, spr, u;
 	unsigned long int imm;
 	unsigned long int val, val2;
 	unsigned int mb, me, sh;
@@ -1292,6 +1292,7 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 	rd = (instr >> 21) & 0x1f;
 	ra = (instr >> 16) & 0x1f;
 	rb = (instr >> 11) & 0x1f;
+	rc = (instr >> 6) & 0x1f;
 
 	switch (opcode) {
 #ifdef __powerpc64__
@@ -1305,6 +1306,38 @@  int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 			goto trap;
 		return 1;
 
+#ifdef __powerpc64__
+	case 4:
+		if (!cpu_has_feature(CPU_FTR_ARCH_300))
+			return -1;
+
+		switch (instr & 0x3f) {
+		case 48:	/* maddhd */
+			asm("maddhd %0,%1,%2,%3" : "=r" (op->val) :
+			    "r" (regs->gpr[ra]), "r" (regs->gpr[rb]),
+			    "r" (regs->gpr[rc]));
+			goto compute_done;
+
+		case 49:	/* maddhdu */
+			asm("maddhdu %0,%1,%2,%3" : "=r" (op->val) :
+			    "r" (regs->gpr[ra]), "r" (regs->gpr[rb]),
+			    "r" (regs->gpr[rc]));
+			goto compute_done;
+
+		case 51:	/* maddld */
+			asm("maddld %0,%1,%2,%3" : "=r" (op->val) :
+			    "r" (regs->gpr[ra]), "r" (regs->gpr[rb]),
+			    "r" (regs->gpr[rc]));
+			goto compute_done;
+		}
+
+		/*
+		 * There are other instructions from ISA 3.0 with the same
+		 * primary opcode which do not have emulation support yet.
+		 */
+		return -1;
+#endif
+
 	case 7:		/* mulli */
 		op->val = regs->gpr[ra] * (short) instr;
 		goto compute_done;