Home | History | Annotate | Download | only in lib
      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 by Maciej W. Rozycki
      9  * Copyright (C) 2011, 2012 MIPS Technologies, Inc.
     10  */
     11 #include <asm/asm.h>
     12 #include <asm/asm-offsets.h>
     13 #include <asm/regdef.h>
     14 
     15 #if LONGSIZE == 4
     16 #define LONG_S_L swl
     17 #define LONG_S_R swr
     18 #else
     19 #define LONG_S_L sdl
     20 #define LONG_S_R sdr
     21 #endif
     22 
     23 #ifdef CONFIG_CPU_MICROMIPS
     24 #define STORSIZE (LONGSIZE * 2)
     25 #define STORMASK (STORSIZE - 1)
     26 #define FILL64RG t8
     27 #define FILLPTRG t7
     28 #undef  LONG_S
     29 #define LONG_S LONG_SP
     30 #else
     31 #define STORSIZE LONGSIZE
     32 #define STORMASK LONGMASK
     33 #define FILL64RG a1
     34 #define FILLPTRG t0
     35 #endif
     36 
     37 #define EX(insn,reg,addr,handler)			\
     38 9:	insn	reg, addr;				\
     39 	.section __ex_table,"a";			\
     40 	PTR	9b, handler;				\
     41 	.previous
     42 
     43 	.macro	f_fill64 dst, offset, val, fixup
     44 	EX(LONG_S, \val, (\offset +  0 * STORSIZE)(\dst), \fixup)
     45 	EX(LONG_S, \val, (\offset +  1 * STORSIZE)(\dst), \fixup)
     46 	EX(LONG_S, \val, (\offset +  2 * STORSIZE)(\dst), \fixup)
     47 	EX(LONG_S, \val, (\offset +  3 * STORSIZE)(\dst), \fixup)
     48 #if ((defined(CONFIG_CPU_MICROMIPS) && (LONGSIZE == 4)) || !defined(CONFIG_CPU_MICROMIPS))
     49 	EX(LONG_S, \val, (\offset +  4 * STORSIZE)(\dst), \fixup)
     50 	EX(LONG_S, \val, (\offset +  5 * STORSIZE)(\dst), \fixup)
     51 	EX(LONG_S, \val, (\offset +  6 * STORSIZE)(\dst), \fixup)
     52 	EX(LONG_S, \val, (\offset +  7 * STORSIZE)(\dst), \fixup)
     53 #endif
     54 #if (!defined(CONFIG_CPU_MICROMIPS) && (LONGSIZE == 4))
     55 	EX(LONG_S, \val, (\offset +  8 * STORSIZE)(\dst), \fixup)
     56 	EX(LONG_S, \val, (\offset +  9 * STORSIZE)(\dst), \fixup)
     57 	EX(LONG_S, \val, (\offset + 10 * STORSIZE)(\dst), \fixup)
     58 	EX(LONG_S, \val, (\offset + 11 * STORSIZE)(\dst), \fixup)
     59 	EX(LONG_S, \val, (\offset + 12 * STORSIZE)(\dst), \fixup)
     60 	EX(LONG_S, \val, (\offset + 13 * STORSIZE)(\dst), \fixup)
     61 	EX(LONG_S, \val, (\offset + 14 * STORSIZE)(\dst), \fixup)
     62 	EX(LONG_S, \val, (\offset + 15 * STORSIZE)(\dst), \fixup)
     63 #endif
     64 	.endm
     65 
     66 /*
     67  * memset(void *s, int c, size_t n)
     68  *
     69  * a0: start of area to clear
     70  * a1: char to fill with
     71  * a2: size of area to clear
     72  */
     73 	.set	noreorder
     74 	.align	5
     75 LEAF(memset)
     76 	beqz		a1, 1f
     77 	 move		v0, a0			/* result */
     78 
     79 	andi		a1, 0xff		/* spread fillword */
     80 	LONG_SLL		t1, a1, 8
     81 	or		a1, t1
     82 	LONG_SLL		t1, a1, 16
     83 #if LONGSIZE == 8
     84 	or		a1, t1
     85 	LONG_SLL		t1, a1, 32
     86 #endif
     87 	or		a1, t1
     88 1:
     89 
     90 FEXPORT(__bzero)
     91 	sltiu		t0, a2, STORSIZE	/* very small region? */
     92 	bnez		t0, .Lsmall_memset
     93 	 andi		t0, a0, STORMASK	/* aligned? */
     94 
     95 #ifdef CONFIG_CPU_MICROMIPS
     96 	move		t8, a1			/* used by 'swp' instruction */
     97 	move		t9, a1
     98 #endif
     99 #ifndef CONFIG_CPU_DADDI_WORKAROUNDS
    100 	beqz		t0, 1f
    101 	 PTR_SUBU	t0, STORSIZE		/* alignment in bytes */
    102 #else
    103 	.set		noat
    104 	li		AT, STORSIZE
    105 	beqz		t0, 1f
    106 	 PTR_SUBU	t0, AT			/* alignment in bytes */
    107 	.set		at
    108 #endif
    109 
    110 	R10KCBARRIER(0(ra))
    111 #ifdef __MIPSEB__
    112 	EX(LONG_S_L, a1, (a0), .Lfirst_fixup)	/* make word/dword aligned */
    113 #endif
    114 #ifdef __MIPSEL__
    115 	EX(LONG_S_R, a1, (a0), .Lfirst_fixup)	/* make word/dword aligned */
    116 #endif
    117 	PTR_SUBU	a0, t0			/* long align ptr */
    118 	PTR_ADDU	a2, t0			/* correct size */
    119 
    120 1:	ori		t1, a2, 0x3f		/* # of full blocks */
    121 	xori		t1, 0x3f
    122 	beqz		t1, .Lmemset_partial	/* no block to fill */
    123 	 andi		t0, a2, 0x40-STORSIZE
    124 
    125 	PTR_ADDU	t1, a0			/* end address */
    126 	.set		reorder
    127 1:	PTR_ADDIU	a0, 64
    128 	R10KCBARRIER(0(ra))
    129 	f_fill64 a0, -64, FILL64RG, .Lfwd_fixup
    130 	bne		t1, a0, 1b
    131 	.set		noreorder
    132 
    133 .Lmemset_partial:
    134 	R10KCBARRIER(0(ra))
    135 	PTR_LA		t1, 2f			/* where to start */
    136 #ifdef CONFIG_CPU_MICROMIPS
    137 	LONG_SRL	t7, t0, 1
    138 #endif
    139 #if LONGSIZE == 4
    140 	PTR_SUBU	t1, FILLPTRG
    141 #else
    142 	.set		noat
    143 	LONG_SRL	AT, FILLPTRG, 1
    144 	PTR_SUBU	t1, AT
    145 	.set		at
    146 #endif
    147 	jr		t1
    148 	 PTR_ADDU	a0, t0			/* dest ptr */
    149 
    150 	.set		push
    151 	.set		noreorder
    152 	.set		nomacro
    153 	f_fill64 a0, -64, FILL64RG, .Lpartial_fixup	/* ... but first do longs ... */
    154 2:	.set		pop
    155 	andi		a2, STORMASK		/* At most one long to go */
    156 
    157 	beqz		a2, 1f
    158 	 PTR_ADDU	a0, a2			/* What's left */
    159 	R10KCBARRIER(0(ra))
    160 #ifdef __MIPSEB__
    161 	EX(LONG_S_R, a1, -1(a0), .Llast_fixup)
    162 #endif
    163 #ifdef __MIPSEL__
    164 	EX(LONG_S_L, a1, -1(a0), .Llast_fixup)
    165 #endif
    166 1:	jr		ra
    167 	 move		a2, zero
    168 
    169 .Lsmall_memset:
    170 	beqz		a2, 2f
    171 	 PTR_ADDU	t1, a0, a2
    172 
    173 1:	PTR_ADDIU	a0, 1			/* fill bytewise */
    174 	R10KCBARRIER(0(ra))
    175 	bne		t1, a0, 1b
    176 	 sb		a1, -1(a0)
    177 
    178 2:	jr		ra			/* done */
    179 	 move		a2, zero
    180 	END(memset)
    181 
    182 .Lfirst_fixup:
    183 	jr	ra
    184 	 nop
    185 
    186 .Lfwd_fixup:
    187 	PTR_L		t0, TI_TASK($28)
    188 	andi		a2, 0x3f
    189 	LONG_L		t0, THREAD_BUADDR(t0)
    190 	LONG_ADDU	a2, t1
    191 	jr		ra
    192 	 LONG_SUBU	a2, t0
    193 
    194 .Lpartial_fixup:
    195 	PTR_L		t0, TI_TASK($28)
    196 	andi		a2, STORMASK
    197 	LONG_L		t0, THREAD_BUADDR(t0)
    198 	LONG_ADDU	a2, t1
    199 	jr		ra
    200 	 LONG_SUBU	a2, t0
    201 
    202 .Llast_fixup:
    203 	jr		ra
    204 	 andi		v1, a2, STORMASK
    205