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) 2003, 2004 Ralf Baechle <ralf@linux-mips.org>
7 * Copyright (C) MIPS Technologies, Inc.
8 *   written by Ralf Baechle <ralf@linux-mips.org>
9 */
10#ifndef _ASM_HAZARDS_H
11#define _ASM_HAZARDS_H
12
13
14#ifdef __ASSEMBLY__
15#define ASMMACRO(name, code...) .macro name; code; .endm
16#else
17
18#define ASMMACRO(name, code...)						\
19__asm__(".macro " #name "; " #code "; .endm");				\
20									\
21static inline void name(void)						\
22{									\
23	__asm__ __volatile__ (#name);					\
24}
25
26#endif
27
28ASMMACRO(_ssnop,
29	 sll	$0, $0, 1
30	)
31
32ASMMACRO(_ehb,
33	 sll	$0, $0, 3
34	)
35
36/*
37 * TLB hazards
38 */
39#if defined(CONFIG_CPU_MIPSR2)
40
41/*
42 * MIPSR2 defines ehb for hazard avoidance
43 */
44
45ASMMACRO(mtc0_tlbw_hazard,
46	 _ehb
47	)
48ASMMACRO(tlbw_use_hazard,
49	 _ehb
50	)
51ASMMACRO(tlb_probe_hazard,
52	 _ehb
53	)
54ASMMACRO(irq_enable_hazard,
55	 _ehb
56	)
57ASMMACRO(irq_disable_hazard,
58	_ehb
59	)
60ASMMACRO(back_to_back_c0_hazard,
61	 _ehb
62	)
63/*
64 * gcc has a tradition of misscompiling the previous construct using the
65 * address of a label as argument to inline assembler.  Gas otoh has the
66 * annoying difference between la and dla which are only usable for 32-bit
67 * rsp. 64-bit code, so can't be used without conditional compilation.
68 * The alterantive is switching the assembler to 64-bit code which happens
69 * to work right even for 32-bit code ...
70 */
71#define instruction_hazard()						\
72do {									\
73	unsigned long tmp;						\
74									\
75	__asm__ __volatile__(						\
76	"	.set	mips64r2				\n"	\
77	"	dla	%0, 1f					\n"	\
78	"	jr.hb	%0					\n"	\
79	"	.set	mips0					\n"	\
80	"1:							\n"	\
81	: "=r" (tmp));							\
82} while (0)
83
84#elif defined(CONFIG_CPU_R10000)
85
86/*
87 * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
88 */
89
90ASMMACRO(mtc0_tlbw_hazard,
91	)
92ASMMACRO(tlbw_use_hazard,
93	)
94ASMMACRO(tlb_probe_hazard,
95	)
96ASMMACRO(irq_enable_hazard,
97	)
98ASMMACRO(irq_disable_hazard,
99	)
100ASMMACRO(back_to_back_c0_hazard,
101	)
102#define instruction_hazard() do { } while (0)
103
104#elif defined(CONFIG_CPU_RM9000)
105
106/*
107 * RM9000 hazards.  When the JTLB is updated by tlbwi or tlbwr, a subsequent
108 * use of the JTLB for instructions should not occur for 4 cpu cycles and use
109 * for data translations should not occur for 3 cpu cycles.
110 */
111
112ASMMACRO(mtc0_tlbw_hazard,
113	 _ssnop; _ssnop; _ssnop; _ssnop
114	)
115ASMMACRO(tlbw_use_hazard,
116	 _ssnop; _ssnop; _ssnop; _ssnop
117	)
118ASMMACRO(tlb_probe_hazard,
119	 _ssnop; _ssnop; _ssnop; _ssnop
120	)
121ASMMACRO(irq_enable_hazard,
122	)
123ASMMACRO(irq_disable_hazard,
124	)
125ASMMACRO(back_to_back_c0_hazard,
126	)
127#define instruction_hazard() do { } while (0)
128
129#elif defined(CONFIG_CPU_SB1)
130
131/*
132 * Mostly like R4000 for historic reasons
133 */
134ASMMACRO(mtc0_tlbw_hazard,
135	)
136ASMMACRO(tlbw_use_hazard,
137	)
138ASMMACRO(tlb_probe_hazard,
139	)
140ASMMACRO(irq_enable_hazard,
141	)
142ASMMACRO(irq_disable_hazard,
143	 _ssnop; _ssnop; _ssnop
144	)
145ASMMACRO(back_to_back_c0_hazard,
146	)
147#define instruction_hazard() do { } while (0)
148
149#else
150
151/*
152 * Finally the catchall case for all other processors including R4000, R4400,
153 * R4600, R4700, R5000, RM7000, NEC VR41xx etc.
154 *
155 * The taken branch will result in a two cycle penalty for the two killed
156 * instructions on R4000 / R4400.  Other processors only have a single cycle
157 * hazard so this is nice trick to have an optimal code for a range of
158 * processors.
159 * Make it compatible with Mips32r2 processors
160 */
161ASMMACRO(mtc0_tlbw_hazard,
162	nop; nop; _ehb
163	)
164ASMMACRO(tlbw_use_hazard,
165	nop; nop; nop; _ehb
166	)
167ASMMACRO(tlb_probe_hazard,
168	nop; nop; nop; _ehb
169	)
170ASMMACRO(irq_enable_hazard,
171	_ehb
172	)
173ASMMACRO(irq_disable_hazard,
174	nop; nop; nop; _ehb
175	)
176ASMMACRO(back_to_back_c0_hazard,
177	_ssnop; _ssnop; _ssnop; _ehb
178	)
179#define instruction_hazard() do { } while (0)
180
181#endif
182
183
184/* FPU hazards */
185
186#if defined(CONFIG_CPU_SB1)
187ASMMACRO(enable_fpu_hazard,
188	 .set	push;
189	 .set	mips64;
190	 .set	noreorder;
191	 _ssnop;
192	 bnezl	$0,.+4;
193	 _ssnop;
194	 .set	pop
195)
196ASMMACRO(disable_fpu_hazard,
197)
198
199#elif defined(CONFIG_CPU_MIPSR2)
200ASMMACRO(enable_fpu_hazard,
201	 _ehb
202)
203ASMMACRO(disable_fpu_hazard,
204	 _ehb
205)
206#else
207ASMMACRO(enable_fpu_hazard,
208	 nop; nop; nop; nop; _ehb
209)
210ASMMACRO(disable_fpu_hazard,
211	 _ehb
212)
213#endif
214
215#endif /* _ASM_HAZARDS_H */
216