powerpc: sstep: Add support for maddhd, maddhdu, maddld instructions
authorSandipan Das <sandipan@linux.ibm.com>
Fri, 22 Feb 2019 06:53:27 +0000 (12:23 +0530)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 25 Feb 2019 13:05:16 +0000 (00:05 +1100)
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: Sandipan Das <sandipan@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/include/asm/ppc-opcode.h
arch/powerpc/lib/sstep.c

index 87b73aa..2bc9494 100644 (file)
 #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
 /* 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)
 #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)
 #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)
index d81568f..67e69eb 100644 (file)
@@ -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;