xref: /netbsd-src/sys/arch/mips/mips/cache_r4k_subr.S (revision 3373dde8839e003ab15767f3e2a17e08ffe7c929)
1/*-
2 * Copyright (c) 2011 The NetBSD Foundation, Inc.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Matt Thomas of 3am Software Foundry.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#ifdef __mips_n32
31/*
32 * Treat N32 as N64
33 */
34#undef _MIPS_SZPTR
35#define _MIPS_SZPTR 64
36#endif
37
38#include <mips/asm.h>
39
40RCSID("$NetBSD: cache_r4k_subr.S,v 1.3 2017/04/27 19:40:55 skrll Exp $")
41
42#include <mips/cache_r4k.h>
43
44#ifndef LINE_SHIFT
45#error LINE_SHIFT undefined
46#endif
47
48#ifdef __mips_o32
49	.set	mips32
50#else
51	.set	mips3
52#endif
53
54#define	LINE_SIZE		(1 << LINE_SHIFT)
55
56#ifdef __STDC__
57#define	_CONCAT3(a,b,c)		a ## _ ## b ## _ ## c
58#define	_CONCAT4(a,b,c,d)	a ## _ ## b ## _ ## c ## _ ## d
59#else
60#define	_CONCAT3(a,b,c)		a/**/_/**/b/**/_/**/c
61#define	_CONCAT4(a,b,c,d)	a/**/_/**/b/**/_/**/c/**/_/**/d
62#endif
63
64#define	_OPNAME(a,b,c)		_CONCAT3(a,b,c)
65#define	_OPNAME32(a,b,c)	_CONCAT4(a,b,32lines,c)
66
67#ifndef OPNAME
68#define OPNAME is not defined!
69#endif
70#ifndef OPNAME32
71#define OPNAME32 is not defined!
72#endif
73
74STATIC_LEAF_NOPROFILE(OPNAME(doop))
75	.set	push
76	.set	noreorder
77	/*
78	 * Jump in the table to do from 0 to 32 cache ops
79	 * t9 = first op @ 31*LINE_SIZE(a0)
80	 * a0 = starting va (may be unaligned)
81	 * a1 = size in bytes (may be unaligned)
82	 */
83	and	v1, a0, LINE_SIZE - 1		# get offset in cache line
84	xor	a0, v1				# align start to cache line
85	PTR_ADDU a1, v1				# add offset to size
86	PTR_ADDU a1, LINE_SIZE - 1		# size is now rounded
87	PTR_SRL	t0, a1, LINE_SHIFT		# get # of cache lines
88
89	beqz	t0, 3f				# bail if t0 is 0 (no lines)
90	 PTR_SRL v0, t0, 5			# v0 = # of (32x lines)
91	beqz	v0, 2f				# must have < 32 sets
92	 nop					# delay slot
93	/*
94	 * We have 1 more sets of 32 cache lines to deal with.  The number of
95	 * sets is in v0.  Keep calling the 32op routines until we run out of
96	 * sets.  We have to save ra since the jalr will overwrite it.
97	 */
98	move	ta0, ra				# save return address
991:
100	jalr	t9				# do 32 cache ops (31..0)
101	 PTR_ADDU v0, -1			# decrement 32x set count
102	bnez	v0, 1b				# do next 32x set if > 0
103	 PTR_ADDU a0, 32*LINE_SIZE		# adjust address by 32 lines
104	/*
105	 * Now we have < 32 sets so need to remove the number of 32x line sets
106	 * from the of lines we have left to do.
107	 */
108	andi	t0, 31				# t0 = # of lines left
109	beqz	t0, 3f				# no more to do?
110	 move	ra, ta0				# restore return address
1112:
112	PTR_SLL	t0, INT_SCALESHIFT		# shift to instruction index
113	PTR_ADDU t9, 32 << INT_SCALESHIFT	# point to end of table
114	PTR_SUBU t9, t0				# backup N cacheops
115	jr	t9				# and do them.
116	 nop
1173:
118	jr	ra
119	 nop
120	.set	pop
121END(OPNAME(doop))
122
123#ifdef WANT_ICACHE_OPS
124LEAF_NOPROFILE(OPNAME(icache_index_inv))
125	PTR_LA	t9, OPNAME32(icache_index_inv)	# get address of first op
126	b	OPNAME(doop)
127END(OPNAME(icache_index_inv))
128
129LEAF_NOPROFILE(OPNAME(icache_hit_inv))
130	PTR_LA	t9, OPNAME32(icache_hit_inv)	# get address of first op
131	b	OPNAME(doop)
132END(OPNAME(icache_hit_inv))
133#endif /* WANT_ICACHE_OPS */
134
135#ifdef WANT_PDCACHE_OPS
136LEAF_NOPROFILE(OPNAME(pdcache_index_wb_inv))
137	PTR_LA	t9, OPNAME32(pdcache_index_wb_inv) # get address of first op
138	b	OPNAME(doop)
139END(OPNAME(pdcache_index_wb_inv))
140
141LEAF_NOPROFILE(OPNAME(pdcache_hit_inv))
142	PTR_LA	t9, OPNAME32(pdcache_hit_inv)	# get address of first op
143	b	OPNAME(doop)
144END(OPNAME(pdcache_hit_inv))
145
146LEAF_NOPROFILE(OPNAME(pdcache_hit_wb_inv))
147	PTR_LA	t9, OPNAME32(pdcache_hit_wb_inv) # get address of first op
148	b	OPNAME(doop)
149END(OPNAME(pdcache_hit_wb_inv))
150
151LEAF_NOPROFILE(OPNAME(pdcache_hit_wb))
152	PTR_LA	t9, OPNAME32(pdcache_hit_wb)	# get address of first op
153	b	OPNAME(doop)
154END(OPNAME(pdcache_hit_wb))
155#endif /* WANT_PDCACHE_OPS */
156
157#ifdef WANT_SDCACHE_OPS
158LEAF_NOPROFILE(OPNAME(sdcache_index_wb_inv))
159	PTR_LA	t9, OPNAME32(sdcache_index_wb_inv) # get address of first op
160	b	OPNAME(doop)
161END(OPNAME(sdcache_index_wb_inv))
162
163LEAF_NOPROFILE(OPNAME(sdcache_hit_inv))
164	PTR_LA	t9, OPNAME32(sdcache_hit_inv)	# get address of first op
165	b	OPNAME(doop)
166END(OPNAME(sdcache_hit_inv))
167
168LEAF_NOPROFILE(OPNAME(sdcache_hit_wb_inv))
169	PTR_LA	t9, OPNAME32(sdcache_hit_wb_inv) # get address of first op
170	b	OPNAME(doop)
171END(OPNAME(sdcache_hit_wb_inv))
172
173LEAF_NOPROFILE(OPNAME(sdcache_hit_wb))
174	PTR_LA	t9, OPNAME32(sdcache_hit_wb)	# get address of first op
175	b	OPNAME(doop)
176END(OPNAME(sdcache_hit_wb))
177#endif /* WANT_SDCACHE_OPS */
178
179/*
180 * Macro to emit 32 cache instruction with the right op and offset in the
181 * proper order.
182 */
183	.macro	emitops	name, op, start=31
184	.ifeq	\start - 31
185	.p2align 4
186STATIC_LEAF_NOPROFILE(\name)
187	.endif
188	cache	\op, (\start*LINE_SIZE)(a0)
189	.ifgt	\start
190	emitops	\name, \op, "(\start-1)"
191	.else
192	j	ra
193	 sync
194END(\name)
195	.endif
196	.endm
197
198	.set	noreorder
199#ifdef WANT_ICACHE_OPS
200	emitops	OPNAME32(icache_index_inv), CACHE_R4K_I|CACHEOP_R4K_INDEX_INV
201	emitops	OPNAME32(icache_hit_inv), CACHE_R4K_I|CACHEOP_R4K_HIT_INV
202#endif
203
204#ifdef WANT_PDCACHE_OPS
205	emitops	OPNAME32(pdcache_index_wb_inv), CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV
206	emitops	OPNAME32(pdcache_hit_inv), CACHE_R4K_D|CACHEOP_R4K_HIT_INV
207	emitops	OPNAME32(pdcache_hit_wb_inv), CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV
208	emitops	OPNAME32(pdcache_hit_wb), CACHE_R4K_D|CACHEOP_R4K_HIT_WB
209#endif
210
211#ifdef WANT_SDCACHE_OPS
212	emitops	OPNAME32(sdcache_index_wb_inv), CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV
213	emitops	OPNAME32(sdcache_hit_inv), CACHE_R4K_SD|CACHEOP_R4K_HIT_INV
214	emitops	OPNAME32(sdcache_hit_wb_inv), CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV
215	emitops	OPNAME32(sdcache_hit_wb), CACHE_R4K_SD|CACHEOP_R4K_HIT_WB
216#endif
217