blob: d8579857a81dc1eb61c72fc2f14279130d81286a [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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.
Steven J. Hill26c5e072013-03-25 13:40:49 -05008 * Copyright (C) 2007 by Maciej W. Rozycki
9 * Copyright (C) 2011, 2012 MIPS Technologies, Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 */
11#include <asm/asm.h>
Sam Ravnborg048eb582005-09-09 22:32:31 +020012#include <asm/asm-offsets.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <asm/regdef.h>
14
Atsushi Nemotoa5831582006-12-18 00:07:40 +090015#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
Steven J. Hill26c5e072013-03-25 13:40:49 -050023#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
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#define EX(insn,reg,addr,handler) \
389: insn reg, addr; \
Ralf Baechle70342282013-01-22 12:59:30 +010039 .section __ex_table,"a"; \
40 PTR 9b, handler; \
Linus Torvalds1da177e2005-04-16 15:20:36 -070041 .previous
42
43 .macro f_fill64 dst, offset, val, fixup
Steven J. Hill26c5e072013-03-25 13:40:49 -050044 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)
Atsushi Nemotoa5831582006-12-18 00:07:40 +090063#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 .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
75LEAF(memset)
76 beqz a1, 1f
Markos Chandras8483b142014-01-03 09:21:20 +000077 move v0, a0 /* result */
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
79 andi a1, 0xff /* spread fillword */
Atsushi Nemotoa5831582006-12-18 00:07:40 +090080 LONG_SLL t1, a1, 8
Linus Torvalds1da177e2005-04-16 15:20:36 -070081 or a1, t1
Atsushi Nemotoa5831582006-12-18 00:07:40 +090082 LONG_SLL t1, a1, 16
83#if LONGSIZE == 8
84 or a1, t1
85 LONG_SLL t1, a1, 32
86#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070087 or a1, t1
881:
89
90FEXPORT(__bzero)
Steven J. Hill26c5e072013-03-25 13:40:49 -050091 sltiu t0, a2, STORSIZE /* very small region? */
Ralf Baechlec5ec1982008-01-29 10:14:59 +000092 bnez t0, .Lsmall_memset
Markos Chandras8483b142014-01-03 09:21:20 +000093 andi t0, a0, STORMASK /* aligned? */
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
Steven J. Hill26c5e072013-03-25 13:40:49 -050095#ifdef CONFIG_CPU_MICROMIPS
96 move t8, a1 /* used by 'swp' instruction */
97 move t9, a1
98#endif
Maciej W. Rozycki619b6e12007-10-23 12:43:25 +010099#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100 beqz t0, 1f
Markos Chandras8483b142014-01-03 09:21:20 +0000101 PTR_SUBU t0, STORSIZE /* alignment in bytes */
Maciej W. Rozycki619b6e12007-10-23 12:43:25 +0100102#else
103 .set noat
Steven J. Hill26c5e072013-03-25 13:40:49 -0500104 li AT, STORSIZE
Maciej W. Rozycki619b6e12007-10-23 12:43:25 +0100105 beqz t0, 1f
Markos Chandras8483b142014-01-03 09:21:20 +0000106 PTR_SUBU t0, AT /* alignment in bytes */
Maciej W. Rozycki619b6e12007-10-23 12:43:25 +0100107 .set at
108#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109
Thomas Bogendoerfer930bff82007-11-25 11:47:56 +0100110 R10KCBARRIER(0(ra))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111#ifdef __MIPSEB__
Ralf Baechlec5ec1982008-01-29 10:14:59 +0000112 EX(LONG_S_L, a1, (a0), .Lfirst_fixup) /* make word/dword aligned */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113#endif
114#ifdef __MIPSEL__
Ralf Baechlec5ec1982008-01-29 10:14:59 +0000115 EX(LONG_S_R, a1, (a0), .Lfirst_fixup) /* make word/dword aligned */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116#endif
117 PTR_SUBU a0, t0 /* long align ptr */
118 PTR_ADDU a2, t0 /* correct size */
119
1201: ori t1, a2, 0x3f /* # of full blocks */
121 xori t1, 0x3f
Ralf Baechlec5ec1982008-01-29 10:14:59 +0000122 beqz t1, .Lmemset_partial /* no block to fill */
Markos Chandras8483b142014-01-03 09:21:20 +0000123 andi t0, a2, 0x40-STORSIZE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124
125 PTR_ADDU t1, a0 /* end address */
126 .set reorder
1271: PTR_ADDIU a0, 64
Thomas Bogendoerfer930bff82007-11-25 11:47:56 +0100128 R10KCBARRIER(0(ra))
Steven J. Hill26c5e072013-03-25 13:40:49 -0500129 f_fill64 a0, -64, FILL64RG, .Lfwd_fixup
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130 bne t1, a0, 1b
131 .set noreorder
132
Ralf Baechlec5ec1982008-01-29 10:14:59 +0000133.Lmemset_partial:
Thomas Bogendoerfer930bff82007-11-25 11:47:56 +0100134 R10KCBARRIER(0(ra))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 PTR_LA t1, 2f /* where to start */
Steven J. Hill26c5e072013-03-25 13:40:49 -0500136#ifdef CONFIG_CPU_MICROMIPS
137 LONG_SRL t7, t0, 1
138#endif
Atsushi Nemotoa5831582006-12-18 00:07:40 +0900139#if LONGSIZE == 4
Steven J. Hill26c5e072013-03-25 13:40:49 -0500140 PTR_SUBU t1, FILLPTRG
Atsushi Nemotoa5831582006-12-18 00:07:40 +0900141#else
142 .set noat
Steven J. Hill26c5e072013-03-25 13:40:49 -0500143 LONG_SRL AT, FILLPTRG, 1
Atsushi Nemotoa5831582006-12-18 00:07:40 +0900144 PTR_SUBU t1, AT
Maciej W. Rozycki619b6e12007-10-23 12:43:25 +0100145 .set at
Atsushi Nemotoa5831582006-12-18 00:07:40 +0900146#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 jr t1
Markos Chandras8483b142014-01-03 09:21:20 +0000148 PTR_ADDU a0, t0 /* dest ptr */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149
150 .set push
151 .set noreorder
152 .set nomacro
Steven J. Hill26c5e072013-03-25 13:40:49 -0500153 f_fill64 a0, -64, FILL64RG, .Lpartial_fixup /* ... but first do longs ... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542: .set pop
Steven J. Hill26c5e072013-03-25 13:40:49 -0500155 andi a2, STORMASK /* At most one long to go */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156
157 beqz a2, 1f
Markos Chandras8483b142014-01-03 09:21:20 +0000158 PTR_ADDU a0, a2 /* What's left */
Thomas Bogendoerfer930bff82007-11-25 11:47:56 +0100159 R10KCBARRIER(0(ra))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160#ifdef __MIPSEB__
Ralf Baechlec5ec1982008-01-29 10:14:59 +0000161 EX(LONG_S_R, a1, -1(a0), .Llast_fixup)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162#endif
163#ifdef __MIPSEL__
Ralf Baechlec5ec1982008-01-29 10:14:59 +0000164 EX(LONG_S_L, a1, -1(a0), .Llast_fixup)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165#endif
1661: jr ra
Markos Chandras8483b142014-01-03 09:21:20 +0000167 move a2, zero
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168
Ralf Baechlec5ec1982008-01-29 10:14:59 +0000169.Lsmall_memset:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 beqz a2, 2f
Markos Chandras8483b142014-01-03 09:21:20 +0000171 PTR_ADDU t1, a0, a2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172
1731: PTR_ADDIU a0, 1 /* fill bytewise */
Thomas Bogendoerfer930bff82007-11-25 11:47:56 +0100174 R10KCBARRIER(0(ra))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 bne t1, a0, 1b
Markos Chandras8483b142014-01-03 09:21:20 +0000176 sb a1, -1(a0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177
1782: jr ra /* done */
Markos Chandras8483b142014-01-03 09:21:20 +0000179 move a2, zero
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 END(memset)
181
Ralf Baechlec5ec1982008-01-29 10:14:59 +0000182.Lfirst_fixup:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 jr ra
Markos Chandras8483b142014-01-03 09:21:20 +0000184 nop
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185
Ralf Baechlec5ec1982008-01-29 10:14:59 +0000186.Lfwd_fixup:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 PTR_L t0, TI_TASK($28)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 andi a2, 0x3f
Tony Wue5674ad2010-11-10 21:48:15 +0800189 LONG_L t0, THREAD_BUADDR(t0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 LONG_ADDU a2, t1
191 jr ra
Markos Chandras8483b142014-01-03 09:21:20 +0000192 LONG_SUBU a2, t0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193
Ralf Baechlec5ec1982008-01-29 10:14:59 +0000194.Lpartial_fixup:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 PTR_L t0, TI_TASK($28)
Steven J. Hill26c5e072013-03-25 13:40:49 -0500196 andi a2, STORMASK
Tony Wue5674ad2010-11-10 21:48:15 +0800197 LONG_L t0, THREAD_BUADDR(t0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 LONG_ADDU a2, t1
199 jr ra
Markos Chandras8483b142014-01-03 09:21:20 +0000200 LONG_SUBU a2, t0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
Ralf Baechlec5ec1982008-01-29 10:14:59 +0000202.Llast_fixup:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 jr ra
Markos Chandras8483b142014-01-03 09:21:20 +0000204 andi v1, a2, STORMASK