aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/traps_32.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2008-11-26 13:06:04 +0900
committerPaul Mundt <lethal@linux-sh.org>2008-12-22 18:43:49 +0900
commitedfd6da0405520b147ab1473ad183a5b32be7082 (patch)
tree3b97d63cda99bf19f305a16e6f86bf5da68d8935 /arch/sh/kernel/traps_32.c
parentsh: Re-add support for best fit ISA tuning if none is available. (diff)
downloadlinux-dev-edfd6da0405520b147ab1473ad183a5b32be7082.tar.xz
linux-dev-edfd6da0405520b147ab1473ad183a5b32be7082.zip
sh: Add a few more branch types to the branch emulator.
This plugs in some extra encodings for matching more bsr/bsrf/jsr branches. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel/traps_32.c')
-rw-r--r--arch/sh/kernel/traps_32.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c
index 1e5c74efbacc..f2497585cac0 100644
--- a/arch/sh/kernel/traps_32.c
+++ b/arch/sh/kernel/traps_32.c
@@ -689,7 +689,7 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
}
#ifdef CONFIG_SH_FPU_EMU
-static int emulate_branch(unsigned short inst, struct pt_regs* regs)
+static int emulate_branch(unsigned short inst, struct pt_regs *regs)
{
/*
* bfs: 8fxx: PC+=d*2+4;
@@ -702,27 +702,32 @@ static int emulate_branch(unsigned short inst, struct pt_regs* regs)
* jsr: 4x0b: PC=Rn after PR=PC+4;
* rts: 000b: PC=PR;
*/
- if ((inst & 0xfd00) == 0x8d00) {
+ if (((inst & 0xf000) == 0xb000) || /* bsr */
+ ((inst & 0xf0ff) == 0x0003) || /* bsrf */
+ ((inst & 0xf0ff) == 0x400b)) /* jsr */
+ regs->pr = regs->pc + 4;
+
+ if ((inst & 0xfd00) == 0x8d00) { /* bfs, bts */
regs->pc += SH_PC_8BIT_OFFSET(inst);
return 0;
}
- if ((inst & 0xe000) == 0xa000) {
+ if ((inst & 0xe000) == 0xa000) { /* bra, bsr */
regs->pc += SH_PC_12BIT_OFFSET(inst);
return 0;
}
- if ((inst & 0xf0df) == 0x0003) {
+ if ((inst & 0xf0df) == 0x0003) { /* braf, bsrf */
regs->pc += regs->regs[(inst & 0x0f00) >> 8] + 4;
return 0;
}
- if ((inst & 0xf0df) == 0x400b) {
+ if ((inst & 0xf0df) == 0x400b) { /* jmp, jsr */
regs->pc = regs->regs[(inst & 0x0f00) >> 8];
return 0;
}
- if ((inst & 0xffff) == 0x000b) {
+ if ((inst & 0xffff) == 0x000b) { /* rts */
regs->pc = regs->pr;
return 0;
}