mips-extns.h revision 224110
1/*-
2 * Copyright 2003-2011 Netlogic Microsystems (Netlogic). All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in
13 *    the documentation and/or other materials provided with the
14 *    distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY Netlogic Microsystems ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26 * THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $FreeBSD: head/sys/mips/nlm/hal/mips-extns.h 224110 2011-07-16 19:35:44Z jchandra $
29 * NETLOGIC_BSD */
30
31#ifndef __NLM_MIPS_EXTNS_H__
32#define __NLM_MIPS_EXTNS_H__
33
34#if !defined(LOCORE) && !defined(__ASSEMBLY__)
35static __inline__ int32_t nlm_swapw(int32_t *loc, int32_t val)
36{
37	int32_t oldval = 0;
38
39	__asm__ __volatile__ (
40		".set push\n"
41		".set noreorder\n"
42		"move $9, %2\n"
43		"move $8, %3\n"
44		".word 0x71280014\n"   /* "swapw $8, $9\n" */
45		"move %1, $8\n"
46		".set pop\n"
47		: "+m" (*loc), "=r" (oldval)
48		: "r" (loc), "r" (val)
49		: "$8", "$9" );
50
51	return oldval;
52}
53
54static __inline__ uint32_t nlm_swapwu(int32_t *loc, uint32_t val)
55{
56	uint32_t oldval;
57
58	__asm__ __volatile__ (
59		".set push\n"
60		".set noreorder\n"
61		"move $9, %2\n"
62		"move $8, %3\n"
63		".word 0x71280015\n"   /* "swapwu $8, $9\n" */
64		"move %1, $8\n"
65		".set pop\n"
66		: "+m" (*loc), "=r" (oldval)
67		: "r" (loc), "r" (val)
68		: "$8", "$9" );
69
70	return oldval;
71}
72
73#if (__mips == 64)
74static __inline__ uint64_t nlm_swapd(int32_t *loc, uint64_t val)
75{
76	uint64_t oldval;
77
78	__asm__ __volatile__ (
79		".set push\n"
80		".set noreorder\n"
81		"move $9, %2\n"
82		"move $8, %3\n"
83		".word 0x71280014\n"   /* "swapw $8, $9\n" */
84		"move %1, $8\n"
85		".set pop\n"
86		: "+m" (*loc), "=r" (oldval)
87		: "r" (loc), "r" (val)
88		: "$8", "$9" );
89
90	return oldval;
91}
92#endif
93
94#if defined(__mips_n64) || defined(__mips_n32)
95static __inline uint64_t
96nlm_mfcr(uint32_t reg)
97{
98	uint64_t res;
99
100	__asm__ __volatile__(
101	    ".set	push\n\t"
102	    ".set	noreorder\n\t"
103	    "move	$9, %1\n\t"
104	    ".word	0x71280018\n\t"  /* mfcr $8, $9 */
105	    "move	%0, $8\n\t"
106	    ".set	pop\n"
107	    : "=r" (res) : "r"(reg)
108	    : "$8", "$9"
109	);
110	return (res);
111}
112
113static __inline void
114nlm_mtcr(uint32_t reg, uint64_t value)
115{
116	__asm__ __volatile__(
117	    ".set	push\n\t"
118	    ".set	noreorder\n\t"
119	    "move	$8, %0\n"
120	    "move	$9, %1\n"
121	    ".word	0x71280019\n"    /* mtcr $8, $9  */
122	    ".set	pop\n"
123	    :
124	    : "r" (value), "r" (reg)
125	    : "$8", "$9"
126	);
127}
128
129#else /* !(defined(__mips_n64) || defined(__mips_n32)) */
130
131static __inline__  uint64_t
132nlm_mfcr(uint32_t reg)
133{
134        uint64_t hi;
135        uint64_t lo;
136
137        __asm__ __volatile__ (
138                ".set push\n"
139                ".set mips64\n"
140                "move   $8, %2\n"
141                ".word  0x71090018\n"
142		"nop	\n"
143                "dsra32 %0, $9, 0\n"
144                "sll    %1, $9, 0\n"
145                ".set pop\n"
146                : "=r"(hi), "=r"(lo)
147                : "r"(reg) : "$8", "$9");
148
149        return (((uint64_t)hi) << 32) | lo;
150}
151
152static __inline__  void
153nlm_mtcr(uint32_t reg, uint64_t val)
154{
155	uint32_t hi, lo;
156	hi = val >> 32;
157	lo = val & 0xffffffff;
158
159        __asm__ __volatile__ (
160                ".set push\n"
161                ".set mips64\n"
162                "move   $9, %0\n"
163                "dsll32 $9, %1, 0\n"
164                "dsll32 $8, %0, 0\n"
165                "dsrl32 $9, $9, 0\n"
166                "or     $9, $9, $8\n"
167                "move   $8, %2\n"
168                ".word  0x71090019\n"
169		"nop	\n"
170                ".set pop\n"
171                ::"r"(hi), "r"(lo), "r"(reg)
172                : "$8", "$9");
173}
174#endif /* (defined(__mips_n64) || defined(__mips_n32)) */
175
176/* dcrc2 */
177/* XLP additional instructions */
178
179/*
180 * Atomic increment a unsigned  int
181 */
182static __inline unsigned int
183nlm_ldaddwu(unsigned int value, unsigned int *addr)
184{
185	__asm__	 __volatile__(
186	    ".set	push\n"
187	    ".set	noreorder\n"
188	    "move	$8, %2\n"
189	    "move	$9, %3\n"
190	    ".word	0x71280011\n"  /* ldaddwu $8, $9 */
191	    "move	%0, $8\n"
192	    ".set	pop\n"
193	    : "=&r"(value), "+m"(*addr)
194	    : "0"(value), "r" ((unsigned long)addr)
195	    :  "$8", "$9");
196
197	return (value);
198}
199#endif
200#endif
201