powerpc/sstep: Check instruction validity against ISA version before emulation
We currently unconditionally try to emulate newer instructions on older
Power versions that could cause issues. Gate it.
Fixes: 350779a29f
("powerpc: Handle most loads and stores in instruction emulation code")
Signed-off-by: Ananth N Mavinakayanahalli <ananth@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/161157995977.64773.13794501093457185080.stgit@thinktux.local
This commit is contained in:
parent
4eeef098b4
commit
8813ff4960
1 changed files with 62 additions and 16 deletions
|
@ -1304,9 +1304,11 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
if ((word & 0xfe2) == 2)
|
if ((word & 0xfe2) == 2)
|
||||||
op->type = SYSCALL;
|
op->type = SYSCALL;
|
||||||
else if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) &&
|
else if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) &&
|
||||||
(word & 0xfe3) == 1)
|
(word & 0xfe3) == 1) { /* scv */
|
||||||
op->type = SYSCALL_VECTORED_0;
|
op->type = SYSCALL_VECTORED_0;
|
||||||
else
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
|
goto unknown_opcode;
|
||||||
|
} else
|
||||||
op->type = UNKNOWN;
|
op->type = UNKNOWN;
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1410,7 +1412,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
#ifdef __powerpc64__
|
#ifdef __powerpc64__
|
||||||
case 1:
|
case 1:
|
||||||
if (!cpu_has_feature(CPU_FTR_ARCH_31))
|
if (!cpu_has_feature(CPU_FTR_ARCH_31))
|
||||||
return -1;
|
goto unknown_opcode;
|
||||||
|
|
||||||
prefix_r = GET_PREFIX_R(word);
|
prefix_r = GET_PREFIX_R(word);
|
||||||
ra = GET_PREFIX_RA(suffix);
|
ra = GET_PREFIX_RA(suffix);
|
||||||
|
@ -1444,7 +1446,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
#ifdef __powerpc64__
|
#ifdef __powerpc64__
|
||||||
case 4:
|
case 4:
|
||||||
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
return -1;
|
goto unknown_opcode;
|
||||||
|
|
||||||
switch (word & 0x3f) {
|
switch (word & 0x3f) {
|
||||||
case 48: /* maddhd */
|
case 48: /* maddhd */
|
||||||
|
@ -1530,6 +1532,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
case 19:
|
case 19:
|
||||||
if (((word >> 1) & 0x1f) == 2) {
|
if (((word >> 1) & 0x1f) == 2) {
|
||||||
/* addpcis */
|
/* addpcis */
|
||||||
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
|
goto unknown_opcode;
|
||||||
imm = (short) (word & 0xffc1); /* d0 + d2 fields */
|
imm = (short) (word & 0xffc1); /* d0 + d2 fields */
|
||||||
imm |= (word >> 15) & 0x3e; /* d1 field */
|
imm |= (word >> 15) & 0x3e; /* d1 field */
|
||||||
op->val = regs->nip + (imm << 16) + 4;
|
op->val = regs->nip + (imm << 16) + 4;
|
||||||
|
@ -1842,7 +1846,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
#ifdef __powerpc64__
|
#ifdef __powerpc64__
|
||||||
case 265: /* modud */
|
case 265: /* modud */
|
||||||
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
return -1;
|
goto unknown_opcode;
|
||||||
op->val = regs->gpr[ra] % regs->gpr[rb];
|
op->val = regs->gpr[ra] % regs->gpr[rb];
|
||||||
goto compute_done;
|
goto compute_done;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1852,7 +1856,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
|
|
||||||
case 267: /* moduw */
|
case 267: /* moduw */
|
||||||
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
return -1;
|
goto unknown_opcode;
|
||||||
op->val = (unsigned int) regs->gpr[ra] %
|
op->val = (unsigned int) regs->gpr[ra] %
|
||||||
(unsigned int) regs->gpr[rb];
|
(unsigned int) regs->gpr[rb];
|
||||||
goto compute_done;
|
goto compute_done;
|
||||||
|
@ -1889,7 +1893,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
#endif
|
#endif
|
||||||
case 755: /* darn */
|
case 755: /* darn */
|
||||||
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
return -1;
|
goto unknown_opcode;
|
||||||
switch (ra & 0x3) {
|
switch (ra & 0x3) {
|
||||||
case 0:
|
case 0:
|
||||||
/* 32-bit conditioned */
|
/* 32-bit conditioned */
|
||||||
|
@ -1911,14 +1915,14 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
#ifdef __powerpc64__
|
#ifdef __powerpc64__
|
||||||
case 777: /* modsd */
|
case 777: /* modsd */
|
||||||
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
return -1;
|
goto unknown_opcode;
|
||||||
op->val = (long int) regs->gpr[ra] %
|
op->val = (long int) regs->gpr[ra] %
|
||||||
(long int) regs->gpr[rb];
|
(long int) regs->gpr[rb];
|
||||||
goto compute_done;
|
goto compute_done;
|
||||||
#endif
|
#endif
|
||||||
case 779: /* modsw */
|
case 779: /* modsw */
|
||||||
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
return -1;
|
goto unknown_opcode;
|
||||||
op->val = (int) regs->gpr[ra] %
|
op->val = (int) regs->gpr[ra] %
|
||||||
(int) regs->gpr[rb];
|
(int) regs->gpr[rb];
|
||||||
goto compute_done;
|
goto compute_done;
|
||||||
|
@ -1995,14 +1999,14 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
#endif
|
#endif
|
||||||
case 538: /* cnttzw */
|
case 538: /* cnttzw */
|
||||||
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
return -1;
|
goto unknown_opcode;
|
||||||
val = (unsigned int) regs->gpr[rd];
|
val = (unsigned int) regs->gpr[rd];
|
||||||
op->val = (val ? __builtin_ctz(val) : 32);
|
op->val = (val ? __builtin_ctz(val) : 32);
|
||||||
goto logical_done;
|
goto logical_done;
|
||||||
#ifdef __powerpc64__
|
#ifdef __powerpc64__
|
||||||
case 570: /* cnttzd */
|
case 570: /* cnttzd */
|
||||||
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
return -1;
|
goto unknown_opcode;
|
||||||
val = regs->gpr[rd];
|
val = regs->gpr[rd];
|
||||||
op->val = (val ? __builtin_ctzl(val) : 64);
|
op->val = (val ? __builtin_ctzl(val) : 64);
|
||||||
goto logical_done;
|
goto logical_done;
|
||||||
|
@ -2112,7 +2116,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
case 890: /* extswsli with sh_5 = 0 */
|
case 890: /* extswsli with sh_5 = 0 */
|
||||||
case 891: /* extswsli with sh_5 = 1 */
|
case 891: /* extswsli with sh_5 = 1 */
|
||||||
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
return -1;
|
goto unknown_opcode;
|
||||||
op->type = COMPUTE + SETREG;
|
op->type = COMPUTE + SETREG;
|
||||||
sh = rb | ((word & 2) << 4);
|
sh = rb | ((word & 2) << 4);
|
||||||
val = (signed int) regs->gpr[rd];
|
val = (signed int) regs->gpr[rd];
|
||||||
|
@ -2439,6 +2443,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 268: /* lxvx */
|
case 268: /* lxvx */
|
||||||
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
|
goto unknown_opcode;
|
||||||
op->reg = rd | ((word & 1) << 5);
|
op->reg = rd | ((word & 1) << 5);
|
||||||
op->type = MKOP(LOAD_VSX, 0, 16);
|
op->type = MKOP(LOAD_VSX, 0, 16);
|
||||||
op->element_size = 16;
|
op->element_size = 16;
|
||||||
|
@ -2448,6 +2454,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
case 269: /* lxvl */
|
case 269: /* lxvl */
|
||||||
case 301: { /* lxvll */
|
case 301: { /* lxvll */
|
||||||
int nb;
|
int nb;
|
||||||
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
|
goto unknown_opcode;
|
||||||
op->reg = rd | ((word & 1) << 5);
|
op->reg = rd | ((word & 1) << 5);
|
||||||
op->ea = ra ? regs->gpr[ra] : 0;
|
op->ea = ra ? regs->gpr[ra] : 0;
|
||||||
nb = regs->gpr[rb] & 0xff;
|
nb = regs->gpr[rb] & 0xff;
|
||||||
|
@ -2468,13 +2476,15 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
|
|
||||||
case 333: /* lxvpx */
|
case 333: /* lxvpx */
|
||||||
if (!cpu_has_feature(CPU_FTR_ARCH_31))
|
if (!cpu_has_feature(CPU_FTR_ARCH_31))
|
||||||
return -1;
|
goto unknown_opcode;
|
||||||
op->reg = VSX_REGISTER_XTP(rd);
|
op->reg = VSX_REGISTER_XTP(rd);
|
||||||
op->type = MKOP(LOAD_VSX, 0, 32);
|
op->type = MKOP(LOAD_VSX, 0, 32);
|
||||||
op->element_size = 32;
|
op->element_size = 32;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 364: /* lxvwsx */
|
case 364: /* lxvwsx */
|
||||||
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
|
goto unknown_opcode;
|
||||||
op->reg = rd | ((word & 1) << 5);
|
op->reg = rd | ((word & 1) << 5);
|
||||||
op->type = MKOP(LOAD_VSX, 0, 4);
|
op->type = MKOP(LOAD_VSX, 0, 4);
|
||||||
op->element_size = 4;
|
op->element_size = 4;
|
||||||
|
@ -2482,6 +2492,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 396: /* stxvx */
|
case 396: /* stxvx */
|
||||||
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
|
goto unknown_opcode;
|
||||||
op->reg = rd | ((word & 1) << 5);
|
op->reg = rd | ((word & 1) << 5);
|
||||||
op->type = MKOP(STORE_VSX, 0, 16);
|
op->type = MKOP(STORE_VSX, 0, 16);
|
||||||
op->element_size = 16;
|
op->element_size = 16;
|
||||||
|
@ -2491,6 +2503,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
case 397: /* stxvl */
|
case 397: /* stxvl */
|
||||||
case 429: { /* stxvll */
|
case 429: { /* stxvll */
|
||||||
int nb;
|
int nb;
|
||||||
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
|
goto unknown_opcode;
|
||||||
op->reg = rd | ((word & 1) << 5);
|
op->reg = rd | ((word & 1) << 5);
|
||||||
op->ea = ra ? regs->gpr[ra] : 0;
|
op->ea = ra ? regs->gpr[ra] : 0;
|
||||||
nb = regs->gpr[rb] & 0xff;
|
nb = regs->gpr[rb] & 0xff;
|
||||||
|
@ -2504,7 +2518,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
}
|
}
|
||||||
case 461: /* stxvpx */
|
case 461: /* stxvpx */
|
||||||
if (!cpu_has_feature(CPU_FTR_ARCH_31))
|
if (!cpu_has_feature(CPU_FTR_ARCH_31))
|
||||||
return -1;
|
goto unknown_opcode;
|
||||||
op->reg = VSX_REGISTER_XTP(rd);
|
op->reg = VSX_REGISTER_XTP(rd);
|
||||||
op->type = MKOP(STORE_VSX, 0, 32);
|
op->type = MKOP(STORE_VSX, 0, 32);
|
||||||
op->element_size = 32;
|
op->element_size = 32;
|
||||||
|
@ -2542,6 +2556,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 781: /* lxsibzx */
|
case 781: /* lxsibzx */
|
||||||
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
|
goto unknown_opcode;
|
||||||
op->reg = rd | ((word & 1) << 5);
|
op->reg = rd | ((word & 1) << 5);
|
||||||
op->type = MKOP(LOAD_VSX, 0, 1);
|
op->type = MKOP(LOAD_VSX, 0, 1);
|
||||||
op->element_size = 8;
|
op->element_size = 8;
|
||||||
|
@ -2549,6 +2565,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 812: /* lxvh8x */
|
case 812: /* lxvh8x */
|
||||||
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
|
goto unknown_opcode;
|
||||||
op->reg = rd | ((word & 1) << 5);
|
op->reg = rd | ((word & 1) << 5);
|
||||||
op->type = MKOP(LOAD_VSX, 0, 16);
|
op->type = MKOP(LOAD_VSX, 0, 16);
|
||||||
op->element_size = 2;
|
op->element_size = 2;
|
||||||
|
@ -2556,6 +2574,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 813: /* lxsihzx */
|
case 813: /* lxsihzx */
|
||||||
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
|
goto unknown_opcode;
|
||||||
op->reg = rd | ((word & 1) << 5);
|
op->reg = rd | ((word & 1) << 5);
|
||||||
op->type = MKOP(LOAD_VSX, 0, 2);
|
op->type = MKOP(LOAD_VSX, 0, 2);
|
||||||
op->element_size = 8;
|
op->element_size = 8;
|
||||||
|
@ -2569,6 +2589,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 876: /* lxvb16x */
|
case 876: /* lxvb16x */
|
||||||
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
|
goto unknown_opcode;
|
||||||
op->reg = rd | ((word & 1) << 5);
|
op->reg = rd | ((word & 1) << 5);
|
||||||
op->type = MKOP(LOAD_VSX, 0, 16);
|
op->type = MKOP(LOAD_VSX, 0, 16);
|
||||||
op->element_size = 1;
|
op->element_size = 1;
|
||||||
|
@ -2582,6 +2604,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 909: /* stxsibx */
|
case 909: /* stxsibx */
|
||||||
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
|
goto unknown_opcode;
|
||||||
op->reg = rd | ((word & 1) << 5);
|
op->reg = rd | ((word & 1) << 5);
|
||||||
op->type = MKOP(STORE_VSX, 0, 1);
|
op->type = MKOP(STORE_VSX, 0, 1);
|
||||||
op->element_size = 8;
|
op->element_size = 8;
|
||||||
|
@ -2589,6 +2613,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 940: /* stxvh8x */
|
case 940: /* stxvh8x */
|
||||||
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
|
goto unknown_opcode;
|
||||||
op->reg = rd | ((word & 1) << 5);
|
op->reg = rd | ((word & 1) << 5);
|
||||||
op->type = MKOP(STORE_VSX, 0, 16);
|
op->type = MKOP(STORE_VSX, 0, 16);
|
||||||
op->element_size = 2;
|
op->element_size = 2;
|
||||||
|
@ -2596,6 +2622,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 941: /* stxsihx */
|
case 941: /* stxsihx */
|
||||||
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
|
goto unknown_opcode;
|
||||||
op->reg = rd | ((word & 1) << 5);
|
op->reg = rd | ((word & 1) << 5);
|
||||||
op->type = MKOP(STORE_VSX, 0, 2);
|
op->type = MKOP(STORE_VSX, 0, 2);
|
||||||
op->element_size = 8;
|
op->element_size = 8;
|
||||||
|
@ -2609,6 +2637,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1004: /* stxvb16x */
|
case 1004: /* stxvb16x */
|
||||||
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
|
goto unknown_opcode;
|
||||||
op->reg = rd | ((word & 1) << 5);
|
op->reg = rd | ((word & 1) << 5);
|
||||||
op->type = MKOP(STORE_VSX, 0, 16);
|
op->type = MKOP(STORE_VSX, 0, 16);
|
||||||
op->element_size = 1;
|
op->element_size = 1;
|
||||||
|
@ -2717,12 +2747,16 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
op->type = MKOP(LOAD_FP, 0, 16);
|
op->type = MKOP(LOAD_FP, 0, 16);
|
||||||
break;
|
break;
|
||||||
case 2: /* lxsd */
|
case 2: /* lxsd */
|
||||||
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
|
goto unknown_opcode;
|
||||||
op->reg = rd + 32;
|
op->reg = rd + 32;
|
||||||
op->type = MKOP(LOAD_VSX, 0, 8);
|
op->type = MKOP(LOAD_VSX, 0, 8);
|
||||||
op->element_size = 8;
|
op->element_size = 8;
|
||||||
op->vsx_flags = VSX_CHECK_VEC;
|
op->vsx_flags = VSX_CHECK_VEC;
|
||||||
break;
|
break;
|
||||||
case 3: /* lxssp */
|
case 3: /* lxssp */
|
||||||
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
|
goto unknown_opcode;
|
||||||
op->reg = rd + 32;
|
op->reg = rd + 32;
|
||||||
op->type = MKOP(LOAD_VSX, 0, 4);
|
op->type = MKOP(LOAD_VSX, 0, 4);
|
||||||
op->element_size = 8;
|
op->element_size = 8;
|
||||||
|
@ -2752,7 +2786,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
#ifdef CONFIG_VSX
|
#ifdef CONFIG_VSX
|
||||||
case 6:
|
case 6:
|
||||||
if (!cpu_has_feature(CPU_FTR_ARCH_31))
|
if (!cpu_has_feature(CPU_FTR_ARCH_31))
|
||||||
return -1;
|
goto unknown_opcode;
|
||||||
op->ea = dqform_ea(word, regs);
|
op->ea = dqform_ea(word, regs);
|
||||||
op->reg = VSX_REGISTER_XTP(rd);
|
op->reg = VSX_REGISTER_XTP(rd);
|
||||||
op->element_size = 32;
|
op->element_size = 32;
|
||||||
|
@ -2775,6 +2809,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: /* lxv */
|
case 1: /* lxv */
|
||||||
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
|
goto unknown_opcode;
|
||||||
op->ea = dqform_ea(word, regs);
|
op->ea = dqform_ea(word, regs);
|
||||||
if (word & 8)
|
if (word & 8)
|
||||||
op->reg = rd + 32;
|
op->reg = rd + 32;
|
||||||
|
@ -2785,6 +2821,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
|
|
||||||
case 2: /* stxsd with LSB of DS field = 0 */
|
case 2: /* stxsd with LSB of DS field = 0 */
|
||||||
case 6: /* stxsd with LSB of DS field = 1 */
|
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->ea = dsform_ea(word, regs);
|
||||||
op->reg = rd + 32;
|
op->reg = rd + 32;
|
||||||
op->type = MKOP(STORE_VSX, 0, 8);
|
op->type = MKOP(STORE_VSX, 0, 8);
|
||||||
|
@ -2794,6 +2832,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
|
|
||||||
case 3: /* stxssp with LSB of DS field = 0 */
|
case 3: /* stxssp with LSB of DS field = 0 */
|
||||||
case 7: /* stxssp with LSB of DS field = 1 */
|
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->ea = dsform_ea(word, regs);
|
||||||
op->reg = rd + 32;
|
op->reg = rd + 32;
|
||||||
op->type = MKOP(STORE_VSX, 0, 4);
|
op->type = MKOP(STORE_VSX, 0, 4);
|
||||||
|
@ -2802,6 +2842,8 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5: /* stxv */
|
case 5: /* stxv */
|
||||||
|
if (!cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
|
goto unknown_opcode;
|
||||||
op->ea = dqform_ea(word, regs);
|
op->ea = dqform_ea(word, regs);
|
||||||
if (word & 8)
|
if (word & 8)
|
||||||
op->reg = rd + 32;
|
op->reg = rd + 32;
|
||||||
|
@ -2831,7 +2873,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
break;
|
break;
|
||||||
case 1: /* Prefixed instructions */
|
case 1: /* Prefixed instructions */
|
||||||
if (!cpu_has_feature(CPU_FTR_ARCH_31))
|
if (!cpu_has_feature(CPU_FTR_ARCH_31))
|
||||||
return -1;
|
goto unknown_opcode;
|
||||||
|
|
||||||
prefix_r = GET_PREFIX_R(word);
|
prefix_r = GET_PREFIX_R(word);
|
||||||
ra = GET_PREFIX_RA(suffix);
|
ra = GET_PREFIX_RA(suffix);
|
||||||
|
@ -2980,6 +3022,10 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
unknown_opcode:
|
||||||
|
op->type = UNKNOWN;
|
||||||
|
return 0;
|
||||||
|
|
||||||
logical_done:
|
logical_done:
|
||||||
if (word & 1)
|
if (word & 1)
|
||||||
set_cr0(regs, op);
|
set_cr0(regs, op);
|
||||||
|
|
Loading…
Add table
Reference in a new issue