linux/arch/sh/lib/clear_page.S
Stuart Menefy fea966f756 sh: Remove implicit sign extension from assembler immediates
The SH instruction set has several instructions which accept an 8 bit
immediate operand. For logical instructions this operand is zero extended,
for arithmetic instructions the operand is sign extended. After adding an
option to the assembler to check this, it was found that several pieces
of assembly code were assuming this behaviour, and in one case
getting it wrong.

So this patch explicitly sign extends any immediate operands, which makes
it obvious what is happening, and fixes the one case which got it wrong.

Signed-off-by: Stuart Menefy <stuart.menefy@st.com>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
2009-08-24 17:09:53 +09:00

155 lines
2.3 KiB
ArmAsm

/*
* __clear_user_page, __clear_user, clear_page implementation of SuperH
*
* Copyright (C) 2001 Kaz Kojima
* Copyright (C) 2001, 2002 Niibe Yutaka
* Copyright (C) 2006 Paul Mundt
*/
#include <linux/linkage.h>
#include <asm/page.h>
/*
* clear_page
* @to: P1 address
*
* void clear_page(void *to)
*/
/*
* r0 --- scratch
* r4 --- to
* r5 --- to + PAGE_SIZE
*/
ENTRY(clear_page)
mov r4,r5
mov.l .Llimit,r0
add r0,r5
mov #0,r0
!
1:
#if defined(CONFIG_CPU_SH4)
movca.l r0,@r4
mov r4,r1
#else
mov.l r0,@r4
#endif
add #32,r4
mov.l r0,@-r4
mov.l r0,@-r4
mov.l r0,@-r4
mov.l r0,@-r4
mov.l r0,@-r4
mov.l r0,@-r4
mov.l r0,@-r4
#if defined(CONFIG_CPU_SH4)
ocbwb @r1
#endif
cmp/eq r5,r4
bf/s 1b
add #28,r4
!
rts
nop
.balign 4
.Llimit: .long (PAGE_SIZE-28)
ENTRY(__clear_user)
!
mov #0, r0
mov #0xffffffe0, r1
!
! r4..(r4+31)&~32 -------- not aligned [ Area 0 ]
! (r4+31)&~32..(r4+r5)&~32 -------- aligned [ Area 1 ]
! (r4+r5)&~32..r4+r5 -------- not aligned [ Area 2 ]
!
! Clear area 0
mov r4, r2
!
tst r1, r5 ! length < 32
bt .Larea2 ! skip to remainder
!
add #31, r2
and r1, r2
cmp/eq r4, r2
bt .Larea1
mov r2, r3
sub r4, r3
mov r3, r7
mov r4, r2
!
.L0: dt r3
0: mov.b r0, @r2
bf/s .L0
add #1, r2
!
sub r7, r5
mov r2, r4
.Larea1:
mov r4, r3
add r5, r3
and r1, r3
cmp/hi r2, r3
bf .Larea2
!
! Clear area 1
#if defined(CONFIG_CPU_SH4)
1: movca.l r0, @r2
#else
1: mov.l r0, @r2
#endif
add #4, r2
2: mov.l r0, @r2
add #4, r2
3: mov.l r0, @r2
add #4, r2
4: mov.l r0, @r2
add #4, r2
5: mov.l r0, @r2
add #4, r2
6: mov.l r0, @r2
add #4, r2
7: mov.l r0, @r2
add #4, r2
8: mov.l r0, @r2
add #4, r2
cmp/hi r2, r3
bt/s 1b
nop
!
! Clear area 2
.Larea2:
mov r4, r3
add r5, r3
cmp/hs r3, r2
bt/s .Ldone
sub r2, r3
.L2: dt r3
9: mov.b r0, @r2
bf/s .L2
add #1, r2
!
.Ldone: rts
mov #0, r0 ! return 0 as normal return
! return the number of bytes remained
.Lbad_clear_user:
mov r4, r0
add r5, r0
rts
sub r2, r0
.section __ex_table,"a"
.align 2
.long 0b, .Lbad_clear_user
.long 1b, .Lbad_clear_user
.long 2b, .Lbad_clear_user
.long 3b, .Lbad_clear_user
.long 4b, .Lbad_clear_user
.long 5b, .Lbad_clear_user
.long 6b, .Lbad_clear_user
.long 7b, .Lbad_clear_user
.long 8b, .Lbad_clear_user
.long 9b, .Lbad_clear_user
.previous