aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/traps.c
diff options
context:
space:
mode:
authorKumar Gala <galak@kernel.crashing.org>2009-02-10 15:10:44 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-02-22 18:48:56 -0500
commit16c57b3620d77e0bc981da5ef32beae730512684 (patch)
tree115045916a264f56f55751ce2948d59e03b16c0c /arch/powerpc/kernel/traps.c
parentbb9b903527eb16c8fdad59a562c29e89f5dcf233 (diff)
powerpc: Unify opcode definitions and support
Create a new header that becomes a single location for defining PowerPC opcodes used by code that is either generationg instructions at runtime (fixups, debug, etc.), emulating instructions, or just compiling instructions old assemblers don't know about. We currently don't handle the floating point emulation or alignment decode as both are better handled by the specific decode support they already have. Added support for the new dcbzl, dcbal, msgsnd, tlbilx, & wait instructions since older assemblers don't know about them. Signed-off-by: Kumar Gala <galak@kernel.crashing.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/traps.c')
-rw-r--r--arch/powerpc/kernel/traps.c58
1 files changed, 18 insertions, 40 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 5457e957568..970d66ec465 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -52,6 +52,7 @@
52#include <asm/processor.h> 52#include <asm/processor.h>
53#endif 53#endif
54#include <asm/kexec.h> 54#include <asm/kexec.h>
55#include <asm/ppc-opcode.h>
55 56
56#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) 57#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
57int (*__debugger)(struct pt_regs *regs); 58int (*__debugger)(struct pt_regs *regs);
@@ -637,29 +638,6 @@ static void parse_fpe(struct pt_regs *regs)
637 * bits is faster and easier. 638 * bits is faster and easier.
638 * 639 *
639 */ 640 */
640#define INST_MFSPR_PVR 0x7c1f42a6
641#define INST_MFSPR_PVR_MASK 0xfc1fffff
642
643#define INST_DCBA 0x7c0005ec
644#define INST_DCBA_MASK 0xfc0007fe
645
646#define INST_MCRXR 0x7c000400
647#define INST_MCRXR_MASK 0xfc0007fe
648
649#define INST_STRING 0x7c00042a
650#define INST_STRING_MASK 0xfc0007fe
651#define INST_STRING_GEN_MASK 0xfc00067e
652#define INST_LSWI 0x7c0004aa
653#define INST_LSWX 0x7c00042a
654#define INST_STSWI 0x7c0005aa
655#define INST_STSWX 0x7c00052a
656
657#define INST_POPCNTB 0x7c0000f4
658#define INST_POPCNTB_MASK 0xfc0007fe
659
660#define INST_ISEL 0x7c00001e
661#define INST_ISEL_MASK 0xfc00003e
662
663static int emulate_string_inst(struct pt_regs *regs, u32 instword) 641static int emulate_string_inst(struct pt_regs *regs, u32 instword)
664{ 642{
665 u8 rT = (instword >> 21) & 0x1f; 643 u8 rT = (instword >> 21) & 0x1f;
@@ -670,20 +648,20 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword)
670 int pos = 0; 648 int pos = 0;
671 649
672 /* Early out if we are an invalid form of lswx */ 650 /* Early out if we are an invalid form of lswx */
673 if ((instword & INST_STRING_MASK) == INST_LSWX) 651 if ((instword & PPC_INST_STRING_MASK) == PPC_INST_LSWX)
674 if ((rT == rA) || (rT == NB_RB)) 652 if ((rT == rA) || (rT == NB_RB))
675 return -EINVAL; 653 return -EINVAL;
676 654
677 EA = (rA == 0) ? 0 : regs->gpr[rA]; 655 EA = (rA == 0) ? 0 : regs->gpr[rA];
678 656
679 switch (instword & INST_STRING_MASK) { 657 switch (instword & PPC_INST_STRING_MASK) {
680 case INST_LSWX: 658 case PPC_INST_LSWX:
681 case INST_STSWX: 659 case PPC_INST_STSWX:
682 EA += NB_RB; 660 EA += NB_RB;
683 num_bytes = regs->xer & 0x7f; 661 num_bytes = regs->xer & 0x7f;
684 break; 662 break;
685 case INST_LSWI: 663 case PPC_INST_LSWI:
686 case INST_STSWI: 664 case PPC_INST_STSWI:
687 num_bytes = (NB_RB == 0) ? 32 : NB_RB; 665 num_bytes = (NB_RB == 0) ? 32 : NB_RB;
688 break; 666 break;
689 default: 667 default:
@@ -695,9 +673,9 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword)
695 u8 val; 673 u8 val;
696 u32 shift = 8 * (3 - (pos & 0x3)); 674 u32 shift = 8 * (3 - (pos & 0x3));
697 675
698 switch ((instword & INST_STRING_MASK)) { 676 switch ((instword & PPC_INST_STRING_MASK)) {
699 case INST_LSWX: 677 case PPC_INST_LSWX:
700 case INST_LSWI: 678 case PPC_INST_LSWI:
701 if (get_user(val, (u8 __user *)EA)) 679 if (get_user(val, (u8 __user *)EA))
702 return -EFAULT; 680 return -EFAULT;
703 /* first time updating this reg, 681 /* first time updating this reg,
@@ -706,8 +684,8 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword)
706 regs->gpr[rT] = 0; 684 regs->gpr[rT] = 0;
707 regs->gpr[rT] |= val << shift; 685 regs->gpr[rT] |= val << shift;
708 break; 686 break;
709 case INST_STSWI: 687 case PPC_INST_STSWI:
710 case INST_STSWX: 688 case PPC_INST_STSWX:
711 val = regs->gpr[rT] >> shift; 689 val = regs->gpr[rT] >> shift;
712 if (put_user(val, (u8 __user *)EA)) 690 if (put_user(val, (u8 __user *)EA))
713 return -EFAULT; 691 return -EFAULT;
@@ -775,18 +753,18 @@ static int emulate_instruction(struct pt_regs *regs)
775 return -EFAULT; 753 return -EFAULT;
776 754
777 /* Emulate the mfspr rD, PVR. */ 755 /* Emulate the mfspr rD, PVR. */
778 if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) { 756 if ((instword & PPC_INST_MFSPR_PVR_MASK) == PPC_INST_MFSPR_PVR) {
779 rd = (instword >> 21) & 0x1f; 757 rd = (instword >> 21) & 0x1f;
780 regs->gpr[rd] = mfspr(SPRN_PVR); 758 regs->gpr[rd] = mfspr(SPRN_PVR);
781 return 0; 759 return 0;
782 } 760 }
783 761
784 /* Emulating the dcba insn is just a no-op. */ 762 /* Emulating the dcba insn is just a no-op. */
785 if ((instword & INST_DCBA_MASK) == INST_DCBA) 763 if ((instword & PPC_INST_DCBA_MASK) == PPC_INST_DCBA)
786 return 0; 764 return 0;
787 765
788 /* Emulate the mcrxr insn. */ 766 /* Emulate the mcrxr insn. */
789 if ((instword & INST_MCRXR_MASK) == INST_MCRXR) { 767 if ((instword & PPC_INST_MCRXR_MASK) == PPC_INST_MCRXR) {
790 int shift = (instword >> 21) & 0x1c; 768 int shift = (instword >> 21) & 0x1c;
791 unsigned long msk = 0xf0000000UL >> shift; 769 unsigned long msk = 0xf0000000UL >> shift;
792 770
@@ -796,16 +774,16 @@ static int emulate_instruction(struct pt_regs *regs)
796 } 774 }
797 775
798 /* Emulate load/store string insn. */ 776 /* Emulate load/store string insn. */
799 if ((instword & INST_STRING_GEN_MASK) == INST_STRING) 777 if ((instword & PPC_INST_STRING_GEN_MASK) == PPC_INST_STRING)
800 return emulate_string_inst(regs, instword); 778 return emulate_string_inst(regs, instword);
801 779
802 /* Emulate the popcntb (Population Count Bytes) instruction. */ 780 /* Emulate the popcntb (Population Count Bytes) instruction. */
803 if ((instword & INST_POPCNTB_MASK) == INST_POPCNTB) { 781 if ((instword & PPC_INST_POPCNTB_MASK) == PPC_INST_POPCNTB) {
804 return emulate_popcntb_inst(regs, instword); 782 return emulate_popcntb_inst(regs, instword);
805 } 783 }
806 784
807 /* Emulate isel (Integer Select) instruction */ 785 /* Emulate isel (Integer Select) instruction */
808 if ((instword & INST_ISEL_MASK) == INST_ISEL) { 786 if ((instword & PPC_INST_ISEL_MASK) == PPC_INST_ISEL) {
809 return emulate_isel(regs, instword); 787 return emulate_isel(regs, instword);
810 } 788 }
811 789