Linux-libre 4.14.82-gnu
[librecmc/linux-libre.git] / arch / metag / lib / memset.S
1 ! SPDX-License-Identifier: GPL-2.0
2 !   Copyright (C) 2008-2012 Imagination Technologies Ltd.
3
4         .text
5         .global _memset
6         .type   _memset,function
7 ! D1Ar1 dst
8 ! D0Ar2 c
9 ! D1Ar3 cnt
10 ! D0Re0 dst
11 _memset:
12         AND     D0Ar2,D0Ar2,#0xFF       ! Ensure a byte input value
13         MULW    D0Ar2,D0Ar2,#0x0101     ! Duplicate byte value into  0-15
14         ANDS    D0Ar4,D1Ar1,#7          ! Extract bottom LSBs of dst
15         LSL     D0Re0,D0Ar2,#16         ! Duplicate byte value into 16-31
16         ADD     A0.2,D0Ar2,D0Re0        ! Duplicate byte value into 4 (A0.2)
17         MOV     D0Re0,D1Ar1             ! Return dst
18         BZ      $LLongStub              ! if start address is aligned
19         ! start address is not aligned on an 8 byte boundary, so we
20         ! need the number of bytes up to the next 8 byte address
21         ! boundary, or the length of the string if less than 8, in D1Ar5
22         MOV     D0Ar2,#8                ! Need 8 - N in D1Ar5 ...
23         SUB     D1Ar5,D0Ar2,D0Ar4       !            ... subtract N
24         CMP     D1Ar3,D1Ar5
25         MOVMI   D1Ar5,D1Ar3
26         B       $LByteStub              ! dst is mis-aligned, do $LByteStub
27
28 !
29 ! Preamble to LongLoop which generates 4*8 bytes per interation (5 cycles)
30 !
31 $LLongStub:
32         LSRS    D0Ar2,D1Ar3,#5
33         AND     D1Ar3,D1Ar3,#0x1F
34         MOV     A1.2,A0.2
35         BEQ     $LLongishStub
36         SUB     TXRPT,D0Ar2,#1
37         CMP     D1Ar3,#0
38 $LLongLoop:
39         SETL    [D1Ar1++],A0.2,A1.2
40         SETL    [D1Ar1++],A0.2,A1.2
41         SETL    [D1Ar1++],A0.2,A1.2
42         SETL    [D1Ar1++],A0.2,A1.2
43         BR      $LLongLoop
44         BZ      $Lexit
45 !
46 ! Preamble to LongishLoop which generates 1*8 bytes per interation (2 cycles)
47 !
48 $LLongishStub:
49         LSRS    D0Ar2,D1Ar3,#3
50         AND     D1Ar3,D1Ar3,#0x7
51         MOV     D1Ar5,D1Ar3
52         BEQ     $LByteStub
53         SUB     TXRPT,D0Ar2,#1
54         CMP     D1Ar3,#0
55 $LLongishLoop:
56         SETL    [D1Ar1++],A0.2,A1.2
57         BR      $LLongishLoop
58         BZ      $Lexit
59 !
60 ! This does a byte structured burst of up to 7 bytes
61 !
62 !       D1Ar1 should point to the location required
63 !       D1Ar3 should be the remaining total byte count
64 !       D1Ar5 should be burst size (<= D1Ar3)
65 !
66 $LByteStub:
67         SUBS    D1Ar3,D1Ar3,D1Ar5       ! Reduce count
68         ADD     D1Ar1,D1Ar1,D1Ar5       ! Advance pointer to end of area
69         MULW    D1Ar5,D1Ar5,#4          ! Scale to (1*4), (2*4), (3*4)
70         SUB     D1Ar5,D1Ar5,#(8*4)      ! Rebase to -(7*4), -(6*4), -(5*4), ...
71         MOV     A1.2,D1Ar5
72         SUB     PC,CPC1,A1.2            ! Jump into table below
73         SETB    [D1Ar1+#(-7)],A0.2
74         SETB    [D1Ar1+#(-6)],A0.2
75         SETB    [D1Ar1+#(-5)],A0.2
76         SETB    [D1Ar1+#(-4)],A0.2
77         SETB    [D1Ar1+#(-3)],A0.2
78         SETB    [D1Ar1+#(-2)],A0.2
79         SETB    [D1Ar1+#(-1)],A0.2
80 !
81 ! Return if all data has been output, otherwise do $LLongStub
82 !
83         BNZ     $LLongStub
84 $Lexit:
85         MOV     PC,D1RtP
86         .size _memset,.-_memset
87