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>
This commit is contained in:
parent
1cfb629cfa
commit
86c0179c93
|
@ -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 !defined(__LITTLE_ENDIAN__)
|
||||
dst += 4-count;
|
||||
#endif
|
||||
if (copy_from_user(dst, src, count))
|
||||
goto fetch_fault;
|
||||
|
||||
if ((count == 2) && dst[1] & 0x80) {
|
||||
dst[2] = 0xff;
|
||||
dst[3] = 0xff;
|
||||
}
|
||||
#else
|
||||
dst += 4-count;
|
||||
|
||||
if (__copy_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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue