root/arch/sh/lib/__clear_user.S
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * __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>

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