Merge tag 'powerpc-5.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[linux-2.6-microblaze.git] / arch / powerpc / lib / sstep.c
index ede093e..bb5c20d 100644 (file)
@@ -1306,9 +1306,11 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                if ((word & 0xfe2) == 2)
                        op->type = SYSCALL;
                else if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) &&
-                               (word & 0xfe3) == 1)
+                               (word & 0xfe3) == 1) {  /* scv */
                        op->type = SYSCALL_VECTORED_0;
-               else
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
+               } else
                        op->type = UNKNOWN;
                return 0;
 #endif
@@ -1412,7 +1414,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 #ifdef __powerpc64__
        case 1:
                if (!cpu_has_feature(CPU_FTR_ARCH_31))
-                       return -1;
+                       goto unknown_opcode;
 
                prefix_r = GET_PREFIX_R(word);
                ra = GET_PREFIX_RA(suffix);
@@ -1445,8 +1447,13 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 
 #ifdef __powerpc64__
        case 4:
+               /*
+                * There are very many instructions with this primary opcode
+                * introduced in the ISA as early as v2.03. However, the ones
+                * we currently emulate were all introduced with ISA 3.0
+                */
                if (!cpu_has_feature(CPU_FTR_ARCH_300))
-                       return -1;
+                       goto unknown_opcode;
 
                switch (word & 0x3f) {
                case 48:        /* maddhd */
@@ -1472,7 +1479,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                 * There are other instructions from ISA 3.0 with the same
                 * primary opcode which do not have emulation support yet.
                 */
-               return -1;
+               goto unknown_opcode;
 #endif
 
        case 7:         /* mulli */
@@ -1532,6 +1539,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
        case 19:
                if (((word >> 1) & 0x1f) == 2) {
                        /* addpcis */
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
                        imm = (short) (word & 0xffc1);  /* d0 + d2 fields */
                        imm |= (word >> 15) & 0x3e;     /* d1 field */
                        op->val = regs->nip + (imm << 16) + 4;
@@ -1844,7 +1853,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 #ifdef __powerpc64__
                case 265:       /* modud */
                        if (!cpu_has_feature(CPU_FTR_ARCH_300))
-                               return -1;
+                               goto unknown_opcode;
                        op->val = regs->gpr[ra] % regs->gpr[rb];
                        goto compute_done;
 #endif
@@ -1854,7 +1863,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 
                case 267:       /* moduw */
                        if (!cpu_has_feature(CPU_FTR_ARCH_300))
-                               return -1;
+                               goto unknown_opcode;
                        op->val = (unsigned int) regs->gpr[ra] %
                                (unsigned int) regs->gpr[rb];
                        goto compute_done;
@@ -1891,7 +1900,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 #endif
                case 755:       /* darn */
                        if (!cpu_has_feature(CPU_FTR_ARCH_300))
-                               return -1;
+                               goto unknown_opcode;
                        switch (ra & 0x3) {
                        case 0:
                                /* 32-bit conditioned */
@@ -1909,18 +1918,18 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                                goto compute_done;
                        }
 
-                       return -1;
+                       goto unknown_opcode;
 #ifdef __powerpc64__
                case 777:       /* modsd */
                        if (!cpu_has_feature(CPU_FTR_ARCH_300))
-                               return -1;
+                               goto unknown_opcode;
                        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;
+                               goto unknown_opcode;
                        op->val = (int) regs->gpr[ra] %
                                (int) regs->gpr[rb];
                        goto compute_done;
@@ -1997,14 +2006,14 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 #endif
                case 538:       /* cnttzw */
                        if (!cpu_has_feature(CPU_FTR_ARCH_300))
-                               return -1;
+                               goto unknown_opcode;
                        val = (unsigned int) regs->gpr[rd];
                        op->val = (val ? __builtin_ctz(val) : 32);
                        goto logical_done;
 #ifdef __powerpc64__
                case 570:       /* cnttzd */
                        if (!cpu_has_feature(CPU_FTR_ARCH_300))
-                               return -1;
+                               goto unknown_opcode;
                        val = regs->gpr[rd];
                        op->val = (val ? __builtin_ctzl(val) : 64);
                        goto logical_done;
@@ -2114,7 +2123,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                case 890:       /* extswsli with sh_5 = 0 */
                case 891:       /* extswsli with sh_5 = 1 */
                        if (!cpu_has_feature(CPU_FTR_ARCH_300))
-                               return -1;
+                               goto unknown_opcode;
                        op->type = COMPUTE + SETREG;
                        sh = rb | ((word & 2) << 4);
                        val = (signed int) regs->gpr[rd];
@@ -2441,6 +2450,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                        break;
 
                case 268:       /* lxvx */
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
                        op->reg = rd | ((word & 1) << 5);
                        op->type = MKOP(LOAD_VSX, 0, 16);
                        op->element_size = 16;
@@ -2450,6 +2461,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                case 269:       /* lxvl */
                case 301: {     /* lxvll */
                        int nb;
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
                        op->reg = rd | ((word & 1) << 5);
                        op->ea = ra ? regs->gpr[ra] : 0;
                        nb = regs->gpr[rb] & 0xff;
@@ -2470,13 +2483,15 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 
                case 333:       /* lxvpx */
                        if (!cpu_has_feature(CPU_FTR_ARCH_31))
-                               return -1;
+                               goto unknown_opcode;
                        op->reg = VSX_REGISTER_XTP(rd);
                        op->type = MKOP(LOAD_VSX, 0, 32);
                        op->element_size = 32;
                        break;
 
                case 364:       /* lxvwsx */
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
                        op->reg = rd | ((word & 1) << 5);
                        op->type = MKOP(LOAD_VSX, 0, 4);
                        op->element_size = 4;
@@ -2484,6 +2499,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                        break;
 
                case 396:       /* stxvx */
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
                        op->reg = rd | ((word & 1) << 5);
                        op->type = MKOP(STORE_VSX, 0, 16);
                        op->element_size = 16;
@@ -2493,6 +2510,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                case 397:       /* stxvl */
                case 429: {     /* stxvll */
                        int nb;
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
                        op->reg = rd | ((word & 1) << 5);
                        op->ea = ra ? regs->gpr[ra] : 0;
                        nb = regs->gpr[rb] & 0xff;
@@ -2506,7 +2525,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                }
                case 461:       /* stxvpx */
                        if (!cpu_has_feature(CPU_FTR_ARCH_31))
-                               return -1;
+                               goto unknown_opcode;
                        op->reg = VSX_REGISTER_XTP(rd);
                        op->type = MKOP(STORE_VSX, 0, 32);
                        op->element_size = 32;
@@ -2544,6 +2563,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                        break;
 
                case 781:       /* lxsibzx */
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
                        op->reg = rd | ((word & 1) << 5);
                        op->type = MKOP(LOAD_VSX, 0, 1);
                        op->element_size = 8;
@@ -2551,6 +2572,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                        break;
 
                case 812:       /* lxvh8x */
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
                        op->reg = rd | ((word & 1) << 5);
                        op->type = MKOP(LOAD_VSX, 0, 16);
                        op->element_size = 2;
@@ -2558,6 +2581,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                        break;
 
                case 813:       /* lxsihzx */
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
                        op->reg = rd | ((word & 1) << 5);
                        op->type = MKOP(LOAD_VSX, 0, 2);
                        op->element_size = 8;
@@ -2571,6 +2596,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                        break;
 
                case 876:       /* lxvb16x */
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
                        op->reg = rd | ((word & 1) << 5);
                        op->type = MKOP(LOAD_VSX, 0, 16);
                        op->element_size = 1;
@@ -2584,6 +2611,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                        break;
 
                case 909:       /* stxsibx */
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
                        op->reg = rd | ((word & 1) << 5);
                        op->type = MKOP(STORE_VSX, 0, 1);
                        op->element_size = 8;
@@ -2591,6 +2620,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                        break;
 
                case 940:       /* stxvh8x */
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
                        op->reg = rd | ((word & 1) << 5);
                        op->type = MKOP(STORE_VSX, 0, 16);
                        op->element_size = 2;
@@ -2598,6 +2629,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                        break;
 
                case 941:       /* stxsihx */
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
                        op->reg = rd | ((word & 1) << 5);
                        op->type = MKOP(STORE_VSX, 0, 2);
                        op->element_size = 8;
@@ -2611,6 +2644,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                        break;
 
                case 1004:      /* stxvb16x */
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
                        op->reg = rd | ((word & 1) << 5);
                        op->type = MKOP(STORE_VSX, 0, 16);
                        op->element_size = 1;
@@ -2719,12 +2754,16 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                        op->type = MKOP(LOAD_FP, 0, 16);
                        break;
                case 2:         /* lxsd */
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
                        op->reg = rd + 32;
                        op->type = MKOP(LOAD_VSX, 0, 8);
                        op->element_size = 8;
                        op->vsx_flags = VSX_CHECK_VEC;
                        break;
                case 3:         /* lxssp */
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
                        op->reg = rd + 32;
                        op->type = MKOP(LOAD_VSX, 0, 4);
                        op->element_size = 8;
@@ -2754,7 +2793,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 #ifdef CONFIG_VSX
        case 6:
                if (!cpu_has_feature(CPU_FTR_ARCH_31))
-                       return -1;
+                       goto unknown_opcode;
                op->ea = dqform_ea(word, regs);
                op->reg = VSX_REGISTER_XTP(rd);
                op->element_size = 32;
@@ -2777,6 +2816,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                        break;
 
                case 1:         /* lxv */
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
                        op->ea = dqform_ea(word, regs);
                        if (word & 8)
                                op->reg = rd + 32;
@@ -2787,6 +2828,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 
                case 2:         /* stxsd with LSB of DS field = 0 */
                case 6:         /* stxsd with LSB of DS field = 1 */
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
                        op->ea = dsform_ea(word, regs);
                        op->reg = rd + 32;
                        op->type = MKOP(STORE_VSX, 0, 8);
@@ -2796,6 +2839,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 
                case 3:         /* stxssp with LSB of DS field = 0 */
                case 7:         /* stxssp with LSB of DS field = 1 */
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
                        op->ea = dsform_ea(word, regs);
                        op->reg = rd + 32;
                        op->type = MKOP(STORE_VSX, 0, 4);
@@ -2804,6 +2849,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                        break;
 
                case 5:         /* stxv */
+                       if (!cpu_has_feature(CPU_FTR_ARCH_300))
+                               goto unknown_opcode;
                        op->ea = dqform_ea(word, regs);
                        if (word & 8)
                                op->reg = rd + 32;
@@ -2833,7 +2880,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                break;
        case 1: /* Prefixed instructions */
                if (!cpu_has_feature(CPU_FTR_ARCH_31))
-                       return -1;
+                       goto unknown_opcode;
 
                prefix_r = GET_PREFIX_R(word);
                ra = GET_PREFIX_RA(suffix);
@@ -2972,6 +3019,20 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 
        }
 
+       if (OP_IS_LOAD_STORE(op->type) && (op->type & UPDATE)) {
+               switch (GETTYPE(op->type)) {
+               case LOAD:
+                       if (ra == rd)
+                               goto unknown_opcode;
+                       fallthrough;
+               case STORE:
+               case LOAD_FP:
+               case STORE_FP:
+                       if (ra == 0)
+                               goto unknown_opcode;
+               }
+       }
+
 #ifdef CONFIG_VSX
        if ((GETTYPE(op->type) == LOAD_VSX ||
             GETTYPE(op->type) == STORE_VSX) &&
@@ -2982,6 +3043,10 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 
        return 0;
 
+ unknown_opcode:
+       op->type = UNKNOWN;
+       return 0;
+
  logical_done:
        if (word & 1)
                set_cr0(regs, op);