Merge branches 'x86/apic', 'x86/cleanups', 'x86/mm', 'x86/pat', 'x86/setup' and ...
[linux-2.6] / arch / mips / lib / memset.S
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 1998, 1999, 2000 by Ralf Baechle
7  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
8  * Copyright (C) 2007  Maciej W. Rozycki
9  */
10 #include <asm/asm.h>
11 #include <asm/asm-offsets.h>
12 #include <asm/regdef.h>
13
14 #if LONGSIZE == 4
15 #define LONG_S_L swl
16 #define LONG_S_R swr
17 #else
18 #define LONG_S_L sdl
19 #define LONG_S_R sdr
20 #endif
21
22 #define EX(insn,reg,addr,handler)                       \
23 9:      insn    reg, addr;                              \
24         .section __ex_table,"a";                        \
25         PTR     9b, handler;                            \
26         .previous
27
28         .macro  f_fill64 dst, offset, val, fixup
29         EX(LONG_S, \val, (\offset +  0 * LONGSIZE)(\dst), \fixup)
30         EX(LONG_S, \val, (\offset +  1 * LONGSIZE)(\dst), \fixup)
31         EX(LONG_S, \val, (\offset +  2 * LONGSIZE)(\dst), \fixup)
32         EX(LONG_S, \val, (\offset +  3 * LONGSIZE)(\dst), \fixup)
33         EX(LONG_S, \val, (\offset +  4 * LONGSIZE)(\dst), \fixup)
34         EX(LONG_S, \val, (\offset +  5 * LONGSIZE)(\dst), \fixup)
35         EX(LONG_S, \val, (\offset +  6 * LONGSIZE)(\dst), \fixup)
36         EX(LONG_S, \val, (\offset +  7 * LONGSIZE)(\dst), \fixup)
37 #if LONGSIZE == 4
38         EX(LONG_S, \val, (\offset +  8 * LONGSIZE)(\dst), \fixup)
39         EX(LONG_S, \val, (\offset +  9 * LONGSIZE)(\dst), \fixup)
40         EX(LONG_S, \val, (\offset + 10 * LONGSIZE)(\dst), \fixup)
41         EX(LONG_S, \val, (\offset + 11 * LONGSIZE)(\dst), \fixup)
42         EX(LONG_S, \val, (\offset + 12 * LONGSIZE)(\dst), \fixup)
43         EX(LONG_S, \val, (\offset + 13 * LONGSIZE)(\dst), \fixup)
44         EX(LONG_S, \val, (\offset + 14 * LONGSIZE)(\dst), \fixup)
45         EX(LONG_S, \val, (\offset + 15 * LONGSIZE)(\dst), \fixup)
46 #endif
47         .endm
48
49 /*
50  * memset(void *s, int c, size_t n)
51  *
52  * a0: start of area to clear
53  * a1: char to fill with
54  * a2: size of area to clear
55  */
56         .set    noreorder
57         .align  5
58 LEAF(memset)
59         beqz            a1, 1f
60          move           v0, a0                  /* result */
61
62         andi            a1, 0xff                /* spread fillword */
63         LONG_SLL                t1, a1, 8
64         or              a1, t1
65         LONG_SLL                t1, a1, 16
66 #if LONGSIZE == 8
67         or              a1, t1
68         LONG_SLL                t1, a1, 32
69 #endif
70         or              a1, t1
71 1:
72
73 FEXPORT(__bzero)
74         sltiu           t0, a2, LONGSIZE        /* very small region? */
75         bnez            t0, .Lsmall_memset
76          andi           t0, a0, LONGMASK        /* aligned? */
77
78 #ifndef CONFIG_CPU_DADDI_WORKAROUNDS
79         beqz            t0, 1f
80          PTR_SUBU       t0, LONGSIZE            /* alignment in bytes */
81 #else
82         .set            noat
83         li              AT, LONGSIZE
84         beqz            t0, 1f
85          PTR_SUBU       t0, AT                  /* alignment in bytes */
86         .set            at
87 #endif
88
89         R10KCBARRIER(0(ra))
90 #ifdef __MIPSEB__
91         EX(LONG_S_L, a1, (a0), .Lfirst_fixup)   /* make word/dword aligned */
92 #endif
93 #ifdef __MIPSEL__
94         EX(LONG_S_R, a1, (a0), .Lfirst_fixup)   /* make word/dword aligned */
95 #endif
96         PTR_SUBU        a0, t0                  /* long align ptr */
97         PTR_ADDU        a2, t0                  /* correct size */
98
99 1:      ori             t1, a2, 0x3f            /* # of full blocks */
100         xori            t1, 0x3f
101         beqz            t1, .Lmemset_partial    /* no block to fill */
102          andi           t0, a2, 0x40-LONGSIZE
103
104         PTR_ADDU        t1, a0                  /* end address */
105         .set            reorder
106 1:      PTR_ADDIU       a0, 64
107         R10KCBARRIER(0(ra))
108         f_fill64 a0, -64, a1, .Lfwd_fixup
109         bne             t1, a0, 1b
110         .set            noreorder
111
112 .Lmemset_partial:
113         R10KCBARRIER(0(ra))
114         PTR_LA          t1, 2f                  /* where to start */
115 #if LONGSIZE == 4
116         PTR_SUBU        t1, t0
117 #else
118         .set            noat
119         LONG_SRL                AT, t0, 1
120         PTR_SUBU        t1, AT
121         .set            at
122 #endif
123         jr              t1
124          PTR_ADDU       a0, t0                  /* dest ptr */
125
126         .set            push
127         .set            noreorder
128         .set            nomacro
129         f_fill64 a0, -64, a1, .Lpartial_fixup   /* ... but first do longs ... */
130 2:      .set            pop
131         andi            a2, LONGMASK            /* At most one long to go */
132
133         beqz            a2, 1f
134          PTR_ADDU       a0, a2                  /* What's left */
135         R10KCBARRIER(0(ra))
136 #ifdef __MIPSEB__
137         EX(LONG_S_R, a1, -1(a0), .Llast_fixup)
138 #endif
139 #ifdef __MIPSEL__
140         EX(LONG_S_L, a1, -1(a0), .Llast_fixup)
141 #endif
142 1:      jr              ra
143          move           a2, zero
144
145 .Lsmall_memset:
146         beqz            a2, 2f
147          PTR_ADDU       t1, a0, a2
148
149 1:      PTR_ADDIU       a0, 1                   /* fill bytewise */
150         R10KCBARRIER(0(ra))
151         bne             t1, a0, 1b
152          sb             a1, -1(a0)
153
154 2:      jr              ra                      /* done */
155          move           a2, zero
156         END(memset)
157
158 .Lfirst_fixup:
159         jr      ra
160          nop
161
162 .Lfwd_fixup:
163         PTR_L           t0, TI_TASK($28)
164         LONG_L          t0, THREAD_BUADDR(t0)
165         andi            a2, 0x3f
166         LONG_ADDU       a2, t1
167         jr              ra
168          LONG_SUBU      a2, t0
169
170 .Lpartial_fixup:
171         PTR_L           t0, TI_TASK($28)
172         LONG_L          t0, THREAD_BUADDR(t0)
173         andi            a2, LONGMASK
174         LONG_ADDU       a2, t1
175         jr              ra
176          LONG_SUBU      a2, t0
177
178 .Llast_fixup:
179         jr              ra
180          andi           v1, a2, LONGMASK