diff options
author | Phil Edworthy <Phil.Edworthy@renesas.com> | 2011-08-24 06:43:59 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2011-08-29 02:32:10 -0400 |
commit | 34f7145a63211eb7ecfcafa6c2a8db5646baf953 (patch) | |
tree | daaa5fe82c1d80c806c6da6cb69cd96218f27072 /arch | |
parent | 0710b91c516ffd448db6e80e9026f11778a80d45 (diff) |
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')
-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, | |||
316 | break; | 316 | break; |
317 | } | 317 | } |
318 | break; | 318 | break; |
319 | |||
320 | case 9: /* mov.w @(disp,PC),Rn */ | ||
321 | srcu = (unsigned char __user *)regs->pc; | ||
322 | srcu += 4; | ||
323 | srcu += (instruction & 0x00FF) << 1; | ||
324 | dst = (unsigned char *)rn; | ||
325 | *(unsigned long *)dst = 0; | ||
326 | |||
327 | #if !defined(__LITTLE_ENDIAN__) | ||
328 | dst += 2; | ||
329 | #endif | ||
330 | |||
331 | if (ma->from(dst, srcu, 2)) | ||
332 | goto fetch_fault; | ||
333 | sign_extend(2, dst); | ||
334 | ret = 0; | ||
335 | break; | ||
336 | |||
337 | case 0xd: /* mov.l @(disp,PC),Rn */ | ||
338 | srcu = (unsigned char __user *)(regs->pc & ~0x3); | ||
339 | srcu += 4; | ||
340 | srcu += (instruction & 0x00FF) << 2; | ||
341 | dst = (unsigned char *)rn; | ||
342 | *(unsigned long *)dst = 0; | ||
343 | |||
344 | if (ma->from(dst, srcu, 4)) | ||
345 | goto fetch_fault; | ||
346 | ret = 0; | ||
347 | break; | ||
319 | } | 348 | } |
320 | return ret; | 349 | return ret; |
321 | 350 | ||
@@ -496,6 +525,9 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, | |||
496 | } | 525 | } |
497 | break; | 526 | break; |
498 | 527 | ||
528 | case 0x9000: /* mov.w @(disp,Rm),Rn */ | ||
529 | goto simple; | ||
530 | |||
499 | case 0xA000: /* bra label */ | 531 | case 0xA000: /* bra label */ |
500 | ret = handle_delayslot(regs, instruction, ma); | 532 | ret = handle_delayslot(regs, instruction, ma); |
501 | if (ret==0) | 533 | if (ret==0) |
@@ -509,6 +541,9 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, | |||
509 | regs->pc += SH_PC_12BIT_OFFSET(instruction); | 541 | regs->pc += SH_PC_12BIT_OFFSET(instruction); |
510 | } | 542 | } |
511 | break; | 543 | break; |
544 | |||
545 | case 0xD000: /* mov.l @(disp,Rm),Rn */ | ||
546 | goto simple; | ||
512 | } | 547 | } |
513 | return ret; | 548 | return ret; |
514 | 549 | ||