Commit 930d6288 authored by Sandipan Das's avatar Sandipan Das Committed by Michael Ellerman
Browse files

powerpc: sstep: Add support for maddhd, maddhdu, maddld instructions



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)

As suggested by Michael, this uses a raw .long for specifying the
instruction word when using inline assembly to retain compatibility
with older binutils.

Signed-off-by: default avatarSandipan Das <sandipan@linux.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent d608898a
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -335,6 +335,9 @@
#define PPC_INST_MULLW			0x7c0001d6
#define PPC_INST_MULHWU			0x7c000016
#define PPC_INST_MULLI			0x1c000000
#define PPC_INST_MADDHD			0x10000030
#define PPC_INST_MADDHDU		0x10000031
#define PPC_INST_MADDLD			0x10000033
#define PPC_INST_DIVWU			0x7c000396
#define PPC_INST_DIVD			0x7c0003d2
#define PPC_INST_RLWINM			0x54000000
@@ -377,6 +380,7 @@
/* macros to insert fields into opcodes */
#define ___PPC_RA(a)	(((a) & 0x1f) << 16)
#define ___PPC_RB(b)	(((b) & 0x1f) << 11)
#define ___PPC_RC(c)	(((c) & 0x1f) << 6)
#define ___PPC_RS(s)	(((s) & 0x1f) << 21)
#define ___PPC_RT(t)	___PPC_RS(t)
#define ___PPC_R(r)	(((r) & 0x1) << 16)
@@ -396,7 +400,7 @@
#define __PPC_WS(w)	(((w) & 0x1f) << 11)
#define __PPC_SH(s)	__PPC_WS(s)
#define __PPC_SH64(s)	(__PPC_SH(s) | (((s) & 0x20) >> 4))
#define __PPC_MB(s)	(((s) & 0x1f) << 6)
#define __PPC_MB(s)	___PPC_RC(s)
#define __PPC_ME(s)	(((s) & 0x1f) << 1)
#define __PPC_MB64(s)	(__PPC_MB(s) | ((s) & 0x20))
#define __PPC_ME64(s)	__PPC_MB64(s)
@@ -438,6 +442,15 @@
#define PPC_STQCX(t, a, b)	stringify_in_c(.long PPC_INST_STQCX | \
					___PPC_RT(t) | ___PPC_RA(a) | \
					___PPC_RB(b))
#define PPC_MADDHD(t, a, b, c)	stringify_in_c(.long PPC_INST_MADDHD | \
					___PPC_RT(t) | ___PPC_RA(a)  | \
					___PPC_RB(b) | ___PPC_RC(c))
#define PPC_MADDHDU(t, a, b, c)	stringify_in_c(.long PPC_INST_MADDHDU | \
					___PPC_RT(t) | ___PPC_RA(a)   | \
					___PPC_RB(b) | ___PPC_RC(c))
#define PPC_MADDLD(t, a, b, c)	stringify_in_c(.long PPC_INST_MADDLD | \
					___PPC_RT(t) | ___PPC_RA(a)  | \
					___PPC_RB(b) | ___PPC_RC(c))
#define PPC_MSGSND(b)		stringify_in_c(.long PPC_INST_MSGSND | \
					___PPC_RB(b))
#define PPC_MSGSYNC		stringify_in_c(.long PPC_INST_MSGSYNC)
+34 −1
Original line number Diff line number Diff line
@@ -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 volatile(PPC_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 volatile(PPC_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 volatile(PPC_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;