diff options
author | Phil Edworthy <Phil.Edworthy@renesas.com> | 2011-08-24 12:43:59 +0200 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2011-08-29 08:32:10 +0200 |
commit | 34f7145a63211eb7ecfcafa6c2a8db5646baf953 (patch) | |
tree | daaa5fe82c1d80c806c6da6cb69cd96218f27072 /arch/sh/kernel | |
parent | sh: Fix unaligned memory access for branches without delay slots (diff) | |
download | linux-34f7145a63211eb7ecfcafa6c2a8db5646baf953.tar.xz linux-34f7145a63211eb7ecfcafa6c2a8db5646baf953.zip |
sh: Add unaligned memory access for PC relative intructions
This adds unaligned memory access support for the following instructions:
mov.w @(disp,PC),Rn
mov.l @(disp,PC),Rn
These instructions are often used on SH2A toolchains.
Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r-- | arch/sh/kernel/traps_32.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index 61fa4a5bc72b..7bbef95c9d1b 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c @@ -316,6 +316,35 @@ static int handle_unaligned_ins(insn_size_t instruction, struct pt_regs *regs, break; } break; + + case 9: /* mov.w @(disp,PC),Rn */ + srcu = (unsigned char __user *)regs->pc; + srcu += 4; + srcu += (instruction & 0x00FF) << 1; + dst = (unsigned char *)rn; + *(unsigned long *)dst = 0; + +#if !defined(__LITTLE_ENDIAN__) + dst += 2; +#endif + + if (ma->from(dst, srcu, 2)) + goto fetch_fault; + sign_extend(2, dst); + ret = 0; + break; + + case 0xd: /* mov.l @(disp,PC),Rn */ + srcu = (unsigned char __user *)(regs->pc & ~0x3); + srcu += 4; + srcu += (instruction & 0x00FF) << 2; + dst = (unsigned char *)rn; + *(unsigned long *)dst = 0; + + if (ma->from(dst, srcu, 4)) + goto fetch_fault; + ret = 0; + break; } return ret; @@ -496,6 +525,9 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, } break; + case 0x9000: /* mov.w @(disp,Rm),Rn */ + goto simple; + case 0xA000: /* bra label */ ret = handle_delayslot(regs, instruction, ma); if (ret==0) @@ -509,6 +541,9 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, regs->pc += SH_PC_12BIT_OFFSET(instruction); } break; + + case 0xD000: /* mov.l @(disp,Rm),Rn */ + goto simple; } return ret; |