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;
|
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
|
* handle an instruction that does an unaligned memory access by emulating the
|
||||||
* desired behaviour
|
* desired behaviour
|
||||||
@ -178,25 +193,13 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
|
|||||||
dst = (unsigned char*) rn;
|
dst = (unsigned char*) rn;
|
||||||
*(unsigned long*)dst = 0;
|
*(unsigned long*)dst = 0;
|
||||||
|
|
||||||
#ifdef __LITTLE_ENDIAN__
|
#if !defined(__LITTLE_ENDIAN__)
|
||||||
|
dst += 4-count;
|
||||||
|
#endif
|
||||||
if (copy_from_user(dst, src, count))
|
if (copy_from_user(dst, src, count))
|
||||||
goto fetch_fault;
|
goto fetch_fault;
|
||||||
|
|
||||||
if ((count == 2) && dst[1] & 0x80) {
|
sign_extend(count, dst);
|
||||||
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
|
|
||||||
} else {
|
} else {
|
||||||
/* to memory */
|
/* to memory */
|
||||||
src = (unsigned char*) rm;
|
src = (unsigned char*) rm;
|
||||||
@ -253,25 +256,12 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
|
|||||||
dst = (unsigned char*) rn;
|
dst = (unsigned char*) rn;
|
||||||
*(unsigned long*)dst = 0;
|
*(unsigned long*)dst = 0;
|
||||||
|
|
||||||
#ifdef __LITTLE_ENDIAN__
|
#if !defined(__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
|
|
||||||
dst += 4-count;
|
dst += 4-count;
|
||||||
|
#endif
|
||||||
if (copy_from_user(dst, src, count))
|
if (copy_from_user(dst, src, count))
|
||||||
goto fetch_fault;
|
goto fetch_fault;
|
||||||
|
sign_extend(count, dst);
|
||||||
if ((count == 2) && dst[2] & 0x80) {
|
|
||||||
dst[0] = 0xff;
|
|
||||||
dst[1] = 0xff;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -299,21 +289,9 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
|
|||||||
#if !defined(__LITTLE_ENDIAN__)
|
#if !defined(__LITTLE_ENDIAN__)
|
||||||
dst += 2;
|
dst += 2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (copy_from_user(dst, src, 2))
|
if (copy_from_user(dst, src, 2))
|
||||||
goto fetch_fault;
|
goto fetch_fault;
|
||||||
|
sign_extend(2, dst);
|
||||||
#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
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user