diff options
author | Magnus Damm <magnus.damm@gmail.com> | 2008-02-07 00:02:50 +0900 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2008-02-14 14:22:07 +0900 |
commit | 86c0179c9307bd600a96a44d623814c33bdbe0f0 (patch) | |
tree | 6651026da498831b60c4c3694781b8ac9d44facf /arch/sh/kernel/traps_32.c | |
parent | 1cfb629cfa4a8d9b65c0f60c65ec731bde82d60c (diff) | |
download | lwn-86c0179c9307bd600a96a44d623814c33bdbe0f0.tar.gz lwn-86c0179c9307bd600a96a44d623814c33bdbe0f0.zip |
sh: break out unaligned sign extension code
Break out the sign extension code since it's used in multiple places.
Signed-off-by: Magnus Damm <damm@igel.co.jp>
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.c | 68 |
1 files changed, 23 insertions, 45 deletions
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index 2e58f7a6b746..7154a7b2135b 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c @@ -147,6 +147,21 @@ static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err) return -EFAULT; } +static inline void sign_extend(unsigned int count, unsigned char *dst) +{ +#ifdef __LITTLE_ENDIAN__ + if ((count == 2) && dst[1] & 0x80) { + dst[2] = 0xff; + dst[3] = 0xff; + } +#else + if ((count == 2) && dst[2] & 0x80) { + dst[0] = 0xff; + dst[1] = 0xff; + } +#endif +} + /* * handle an instruction that does an unaligned memory access by emulating the * desired behaviour @@ -178,25 +193,13 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) dst = (unsigned char*) rn; *(unsigned long*)dst = 0; -#ifdef __LITTLE_ENDIAN__ - if (copy_from_user(dst, src, count)) - goto fetch_fault; - - if ((count == 2) && dst[1] & 0x80) { - dst[2] = 0xff; - dst[3] = 0xff; - } -#else +#if !defined(__LITTLE_ENDIAN__) dst += 4-count; - - if (__copy_user(dst, src, count)) +#endif + if (copy_from_user(dst, src, count)) goto fetch_fault; - if ((count == 2) && dst[2] & 0x80) { - dst[0] = 0xff; - dst[1] = 0xff; - } -#endif + sign_extend(count, dst); } else { /* to memory */ src = (unsigned char*) rm; @@ -253,25 +256,12 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) dst = (unsigned char*) rn; *(unsigned long*)dst = 0; -#ifdef __LITTLE_ENDIAN__ - if (copy_from_user(dst, src, count)) - goto fetch_fault; - - if ((count == 2) && dst[1] & 0x80) { - dst[2] = 0xff; - dst[3] = 0xff; - } -#else +#if !defined(__LITTLE_ENDIAN__) dst += 4-count; - +#endif if (copy_from_user(dst, src, count)) goto fetch_fault; - - if ((count == 2) && dst[2] & 0x80) { - dst[0] = 0xff; - dst[1] = 0xff; - } -#endif + sign_extend(count, dst); ret = 0; break; @@ -299,21 +289,9 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) #if !defined(__LITTLE_ENDIAN__) dst += 2; #endif - if (copy_from_user(dst, src, 2)) goto fetch_fault; - -#ifdef __LITTLE_ENDIAN__ - if (dst[1] & 0x80) { - dst[2] = 0xff; - dst[3] = 0xff; - } -#else - if (dst[2] & 0x80) { - dst[0] = 0xff; - dst[1] = 0xff; - } -#endif + sign_extend(2, dst); ret = 0; break; } |