Linux 2.6.13-rc4
[linux-2.6/next.git] / arch / mips / lib-64 / memset.S
blob242f1976cfaf097e504a1ce86e207a3300deab03
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  */
9 #include <asm/asm.h>
10 #include <asm/offset.h>
11 #include <asm/regdef.h>
13 #define EX(insn,reg,addr,handler)                       \
14 9:      insn    reg, addr;                              \
15         .section __ex_table,"a";                        \
16         PTR     9b, handler;                            \
17         .previous
19         .macro  f_fill64 dst, offset, val, fixup
20         EX(LONG_S, \val, (\offset +  0 * LONGSIZE)(\dst), \fixup)
21         EX(LONG_S, \val, (\offset +  1 * LONGSIZE)(\dst), \fixup)
22         EX(LONG_S, \val, (\offset +  2 * LONGSIZE)(\dst), \fixup)
23         EX(LONG_S, \val, (\offset +  3 * LONGSIZE)(\dst), \fixup)
24         EX(LONG_S, \val, (\offset +  4 * LONGSIZE)(\dst), \fixup)
25         EX(LONG_S, \val, (\offset +  5 * LONGSIZE)(\dst), \fixup)
26         EX(LONG_S, \val, (\offset +  6 * LONGSIZE)(\dst), \fixup)
27         EX(LONG_S, \val, (\offset +  7 * LONGSIZE)(\dst), \fixup)
28         .endm
31  * memset(void *s, int c, size_t n)
32  *
33  * a0: start of area to clear
34  * a1: char to fill with
35  * a2: size of area to clear
36  */
37         .set    noreorder
38         .align  5
39 LEAF(memset)
40         beqz            a1, 1f
41          move           v0, a0                  /* result */
43         andi            a1, 0xff                /* spread fillword */
44         dsll            t1, a1, 8
45         or              a1, t1
46         dsll            t1, a1, 16
47         or              a1, t1
48         dsll            t1, a1, 32
49         or              a1, t1
52 FEXPORT(__bzero)
53         sltiu           t0, a2, LONGSIZE        /* very small region? */
54         bnez            t0, small_memset
55          andi           t0, a0, LONGMASK        /* aligned? */
57         beqz            t0, 1f
58          PTR_SUBU       t0, LONGSIZE            /* alignment in bytes */
60 #ifdef __MIPSEB__
61         EX(sdl, a1, (a0), first_fixup)          /* make dword aligned */
62 #endif
63 #ifdef __MIPSEL__
64         EX(sdr, a1, (a0), first_fixup)          /* make dword aligned */
65 #endif
66         PTR_SUBU        a0, t0                  /* long align ptr */
67         PTR_ADDU        a2, t0                  /* correct size */
69 1:      ori             t1, a2, 0x3f            /* # of full blocks */
70         xori            t1, 0x3f
71         beqz            t1, memset_partial      /* no block to fill */
72          andi           t0, a2, 0x38
74         PTR_ADDU        t1, a0                  /* end address */
75         .set            reorder
76 1:      PTR_ADDIU       a0, 64
77         f_fill64 a0, -64, a1, fwd_fixup
78         bne             t1, a0, 1b
79         .set            noreorder
81 memset_partial:
82         PTR_LA          t1, 2f                  /* where to start */
83         .set            noat
84         dsrl            AT, t0, 1
85         PTR_SUBU        t1, AT
86         .set            noat
87         jr              t1
88          PTR_ADDU       a0, t0                  /* dest ptr */
90         .set            push
91         .set            noreorder
92         .set            nomacro
93         f_fill64 a0, -64, a1, partial_fixup     /* ... but first do longs ... */
94 2:      .set            pop
95         andi            a2, LONGMASK            /* At most one long to go */
97         beqz            a2, 1f
98          PTR_ADDU       a0, a2                  /* What's left */
99 #ifdef __MIPSEB__
100         EX(sdr, a1, -1(a0), last_fixup)
101 #endif
102 #ifdef __MIPSEL__
103         EX(sdl, a1, -1(a0), last_fixup)
104 #endif
105 1:      jr              ra
106          move           a2, zero
108 small_memset:
109         beqz            a2, 2f
110          PTR_ADDU       t1, a0, a2
112 1:      PTR_ADDIU       a0, 1                   /* fill bytewise */
113         bne             t1, a0, 1b
114          sb             a1, -1(a0)
116 2:      jr              ra                      /* done */
117          move           a2, zero
118         END(memset)
120 first_fixup:
121         jr      ra
122          nop
124 fwd_fixup:
125         PTR_L           t0, TI_TASK($28)
126         LONG_L          t0, THREAD_BUADDR(t0)
127         andi            a2, 0x3f
128         LONG_ADDU       a2, t1
129         jr              ra
130          LONG_SUBU      a2, t0
132 partial_fixup:
133         PTR_L           t0, TI_TASK($28)
134         LONG_L          t0, THREAD_BUADDR(t0)
135         andi            a2, LONGMASK
136         LONG_ADDU       a2, t1
137         jr              ra
138          LONG_SUBU      a2, t0
140 last_fixup:
141         jr              ra
142          andi           v1, a2, LONGMASK