diff options
author | Kumar Gala <galak@kernel.crashing.org> | 2007-11-19 22:35:29 -0500 |
---|---|---|
committer | Kumar Gala <galak@kernel.crashing.org> | 2007-12-11 14:57:16 -0500 |
commit | c1469f13de275fc92b051328ea5764a32a5a43c9 (patch) | |
tree | c978f788239e97c5c49f234a130e5da8e43e9310 /arch/powerpc/kernel/traps.c | |
parent | fd351b89205bc14f79af2e0d69f4198bcea1cf6a (diff) |
[POWERPC] Emulate isel (Integer Select) instruction
isel (Integer Select) is a new user space instruction in the
PowerISA 2.04 spec. Not all processors implement it so lets emulate
to ensure code built with isel will run everywhere.
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/traps.c')
-rw-r--r-- | arch/powerpc/kernel/traps.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 59c464e26f38..cad64840fce4 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -622,6 +622,9 @@ static void parse_fpe(struct pt_regs *regs) | |||
622 | #define INST_POPCNTB 0x7c0000f4 | 622 | #define INST_POPCNTB 0x7c0000f4 |
623 | #define INST_POPCNTB_MASK 0xfc0007fe | 623 | #define INST_POPCNTB_MASK 0xfc0007fe |
624 | 624 | ||
625 | #define INST_ISEL 0x7c00001e | ||
626 | #define INST_ISEL_MASK 0xfc00003e | ||
627 | |||
625 | static int emulate_string_inst(struct pt_regs *regs, u32 instword) | 628 | static int emulate_string_inst(struct pt_regs *regs, u32 instword) |
626 | { | 629 | { |
627 | u8 rT = (instword >> 21) & 0x1f; | 630 | u8 rT = (instword >> 21) & 0x1f; |
@@ -707,6 +710,23 @@ static int emulate_popcntb_inst(struct pt_regs *regs, u32 instword) | |||
707 | return 0; | 710 | return 0; |
708 | } | 711 | } |
709 | 712 | ||
713 | static int emulate_isel(struct pt_regs *regs, u32 instword) | ||
714 | { | ||
715 | u8 rT = (instword >> 21) & 0x1f; | ||
716 | u8 rA = (instword >> 16) & 0x1f; | ||
717 | u8 rB = (instword >> 11) & 0x1f; | ||
718 | u8 BC = (instword >> 6) & 0x1f; | ||
719 | u8 bit; | ||
720 | unsigned long tmp; | ||
721 | |||
722 | tmp = (rA == 0) ? 0 : regs->gpr[rA]; | ||
723 | bit = (regs->ccr >> (31 - BC)) & 0x1; | ||
724 | |||
725 | regs->gpr[rT] = bit ? tmp : regs->gpr[rB]; | ||
726 | |||
727 | return 0; | ||
728 | } | ||
729 | |||
710 | static int emulate_instruction(struct pt_regs *regs) | 730 | static int emulate_instruction(struct pt_regs *regs) |
711 | { | 731 | { |
712 | u32 instword; | 732 | u32 instword; |
@@ -749,6 +769,11 @@ static int emulate_instruction(struct pt_regs *regs) | |||
749 | return emulate_popcntb_inst(regs, instword); | 769 | return emulate_popcntb_inst(regs, instword); |
750 | } | 770 | } |
751 | 771 | ||
772 | /* Emulate isel (Integer Select) instruction */ | ||
773 | if ((instword & INST_ISEL_MASK) == INST_ISEL) { | ||
774 | return emulate_isel(regs, instword); | ||
775 | } | ||
776 | |||
752 | return -EINVAL; | 777 | return -EINVAL; |
753 | } | 778 | } |
754 | 779 | ||