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) 1994, 1995, 1996, 1998, 1999, 2002, 2003 Ralf Baechle
7 * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
8 * Copyright (C) 1994, 1995, 1996, by Andreas Busse
9 * Copyright (C) 1999 Silicon Graphics, Inc.
10 * Copyright (C) 2000 MIPS Technologies, Inc.
11 *    written by Carsten Langgaard, carstenl@mips.com
12 */
13
14#define USE_ALTERNATE_RESUME_IMPL 1
15	.set push
16	.set arch=mips64r2
17#include "r4k_switch.S"
18	.set pop
19/*
20 * task_struct *resume(task_struct *prev, task_struct *next,
21 *		       struct thread_info *next_ti, int usedfpu)
22 */
23	.align	7
24	LEAF(resume)
25	.set arch=octeon
26	mfc0	t1, CP0_STATUS
27	LONG_S	t1, THREAD_STATUS(a0)
28	cpu_save_nonscratch a0
29	LONG_S	ra, THREAD_REG31(a0)
30
31	/*
32	 * check if we need to save FPU registers
33	 */
34	.set push
35	.set noreorder
36	beqz	a3, 1f
37	 PTR_L	t3, TASK_THREAD_INFO(a0)
38	.set pop
39
40	/*
41	 * clear saved user stack CU1 bit
42	 */
43	LONG_L	t0, ST_OFF(t3)
44	li	t1, ~ST0_CU1
45	and	t0, t0, t1
46	LONG_S	t0, ST_OFF(t3)
47
48	.set push
49	.set arch=mips64r2
50	fpu_save_double a0 t0 t1		# c0_status passed in t0
51						# clobbers t1
52	.set pop
531:
54
55#if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
56	/* Check if we need to store CVMSEG state */
57	dmfc0	t0, $11,7	/* CvmMemCtl */
58	bbit0	t0, 6, 3f	/* Is user access enabled? */
59
60	/* Store the CVMSEG state */
61	/* Extract the size of CVMSEG */
62	andi	t0, 0x3f
63	/* Multiply * (cache line size/sizeof(long)/2) */
64	sll	t0, 7-LONGLOG-1
65	li	t1, -32768	/* Base address of CVMSEG */
66	LONG_ADDI t2, a0, THREAD_CVMSEG /* Where to store CVMSEG to */
67	synciobdma
682:
69	.set noreorder
70	LONG_L	t8, 0(t1)	/* Load from CVMSEG */
71	subu	t0, 1		/* Decrement loop var */
72	LONG_L	t9, LONGSIZE(t1)/* Load from CVMSEG */
73	LONG_ADDU t1, LONGSIZE*2 /* Increment loc in CVMSEG */
74	LONG_S	t8, 0(t2)	/* Store CVMSEG to thread storage */
75	LONG_ADDU t2, LONGSIZE*2 /* Increment loc in thread storage */
76	bnez	t0, 2b		/* Loop until we've copied it all */
77	 LONG_S t9, -LONGSIZE(t2)/* Store CVMSEG to thread storage */
78	.set reorder
79
80	/* Disable access to CVMSEG */
81	dmfc0	t0, $11,7	/* CvmMemCtl */
82	xori	t0, t0, 0x40	/* Bit 6 is CVMSEG user enable */
83	dmtc0	t0, $11,7	/* CvmMemCtl */
84#endif
853:
86
87#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
88	PTR_LA	t8, __stack_chk_guard
89	LONG_L	t9, TASK_STACK_CANARY(a1)
90	LONG_S	t9, 0(t8)
91#endif
92
93	/*
94	 * The order of restoring the registers takes care of the race
95	 * updating $28, $29 and kernelsp without disabling ints.
96	 */
97	move	$28, a2
98	cpu_restore_nonscratch a1
99
100	PTR_ADDU	t0, $28, _THREAD_SIZE - 32
101	set_saved_sp	t0, t1, t2
102
103	mfc0	t1, CP0_STATUS		/* Do we really need this? */
104	li	a3, 0xff01
105	and	t1, a3
106	LONG_L	a2, THREAD_STATUS(a1)
107	nor	a3, $0, a3
108	and	a2, a3
109	or	a2, t1
110	mtc0	a2, CP0_STATUS
111	move	v0, a0
112	jr	ra
113	END(resume)
114
115/*
116 * void octeon_cop2_save(struct octeon_cop2_state *a0)
117 */
118	.align	7
119	.set push
120	.set noreorder
121	LEAF(octeon_cop2_save)
122
123	dmfc0	t9, $9,7	/* CvmCtl register. */
124
125	/* Save the COP2 CRC state */
126	dmfc2	t0, 0x0201
127	dmfc2	t1, 0x0202
128	dmfc2	t2, 0x0200
129	sd	t0, OCTEON_CP2_CRC_IV(a0)
130	sd	t1, OCTEON_CP2_CRC_LENGTH(a0)
131	/* Skip next instructions if CvmCtl[NODFA_CP2] set */
132	bbit1	t9, 28, 1f
133	 sd	t2, OCTEON_CP2_CRC_POLY(a0)
134
135	/* Save the LLM state */
136	dmfc2	t0, 0x0402
137	dmfc2	t1, 0x040A
138	sd	t0, OCTEON_CP2_LLM_DAT(a0)
139
1401:	bbit1	t9, 26, 3f	/* done if CvmCtl[NOCRYPTO] set */
141	 sd	t1, OCTEON_CP2_LLM_DAT+8(a0)
142
143	/* Save the COP2 crypto state */
144	/* this part is mostly common to both pass 1 and later revisions */
145	dmfc2	t0, 0x0084
146	dmfc2	t1, 0x0080
147	dmfc2	t2, 0x0081
148	dmfc2	t3, 0x0082
149	sd	t0, OCTEON_CP2_3DES_IV(a0)
150	dmfc2	t0, 0x0088
151	sd	t1, OCTEON_CP2_3DES_KEY(a0)
152	dmfc2	t1, 0x0111			/* only necessary for pass 1 */
153	sd	t2, OCTEON_CP2_3DES_KEY+8(a0)
154	dmfc2	t2, 0x0102
155	sd	t3, OCTEON_CP2_3DES_KEY+16(a0)
156	dmfc2	t3, 0x0103
157	sd	t0, OCTEON_CP2_3DES_RESULT(a0)
158	dmfc2	t0, 0x0104
159	sd	t1, OCTEON_CP2_AES_INP0(a0)	/* only necessary for pass 1 */
160	dmfc2	t1, 0x0105
161	sd	t2, OCTEON_CP2_AES_IV(a0)
162	dmfc2	t2, 0x0106
163	sd	t3, OCTEON_CP2_AES_IV+8(a0)
164	dmfc2	t3, 0x0107
165	sd	t0, OCTEON_CP2_AES_KEY(a0)
166	dmfc2	t0, 0x0110
167	sd	t1, OCTEON_CP2_AES_KEY+8(a0)
168	dmfc2	t1, 0x0100
169	sd	t2, OCTEON_CP2_AES_KEY+16(a0)
170	dmfc2	t2, 0x0101
171	sd	t3, OCTEON_CP2_AES_KEY+24(a0)
172	mfc0	v0, $15,0	/* Get the processor ID register */
173	sd	t0, OCTEON_CP2_AES_KEYLEN(a0)
174	li	v1, 0x000d0000	/* This is the processor ID of Octeon Pass1 */
175	sd	t1, OCTEON_CP2_AES_RESULT(a0)
176	/* Skip to the Pass1 version of the remainder of the COP2 state */
177	beq	v0, v1, 2f
178	 sd	t2, OCTEON_CP2_AES_RESULT+8(a0)
179
180	/* the non-pass1 state when !CvmCtl[NOCRYPTO] */
181	dmfc2	t1, 0x0240
182	dmfc2	t2, 0x0241
183	ori	v1, v1, 0x9500 /* lowest OCTEON III PrId*/
184	dmfc2	t3, 0x0242
185	subu	v1, v0, v1 /* prid - lowest OCTEON III PrId */
186	dmfc2	t0, 0x0243
187	sd	t1, OCTEON_CP2_HSH_DATW(a0)
188	dmfc2	t1, 0x0244
189	sd	t2, OCTEON_CP2_HSH_DATW+8(a0)
190	dmfc2	t2, 0x0245
191	sd	t3, OCTEON_CP2_HSH_DATW+16(a0)
192	dmfc2	t3, 0x0246
193	sd	t0, OCTEON_CP2_HSH_DATW+24(a0)
194	dmfc2	t0, 0x0247
195	sd	t1, OCTEON_CP2_HSH_DATW+32(a0)
196	dmfc2	t1, 0x0248
197	sd	t2, OCTEON_CP2_HSH_DATW+40(a0)
198	dmfc2	t2, 0x0249
199	sd	t3, OCTEON_CP2_HSH_DATW+48(a0)
200	dmfc2	t3, 0x024A
201	sd	t0, OCTEON_CP2_HSH_DATW+56(a0)
202	dmfc2	t0, 0x024B
203	sd	t1, OCTEON_CP2_HSH_DATW+64(a0)
204	dmfc2	t1, 0x024C
205	sd	t2, OCTEON_CP2_HSH_DATW+72(a0)
206	dmfc2	t2, 0x024D
207	sd	t3, OCTEON_CP2_HSH_DATW+80(a0)
208	dmfc2	t3, 0x024E
209	sd	t0, OCTEON_CP2_HSH_DATW+88(a0)
210	dmfc2	t0, 0x0250
211	sd	t1, OCTEON_CP2_HSH_DATW+96(a0)
212	dmfc2	t1, 0x0251
213	sd	t2, OCTEON_CP2_HSH_DATW+104(a0)
214	dmfc2	t2, 0x0252
215	sd	t3, OCTEON_CP2_HSH_DATW+112(a0)
216	dmfc2	t3, 0x0253
217	sd	t0, OCTEON_CP2_HSH_IVW(a0)
218	dmfc2	t0, 0x0254
219	sd	t1, OCTEON_CP2_HSH_IVW+8(a0)
220	dmfc2	t1, 0x0255
221	sd	t2, OCTEON_CP2_HSH_IVW+16(a0)
222	dmfc2	t2, 0x0256
223	sd	t3, OCTEON_CP2_HSH_IVW+24(a0)
224	dmfc2	t3, 0x0257
225	sd	t0, OCTEON_CP2_HSH_IVW+32(a0)
226	dmfc2	t0, 0x0258
227	sd	t1, OCTEON_CP2_HSH_IVW+40(a0)
228	dmfc2	t1, 0x0259
229	sd	t2, OCTEON_CP2_HSH_IVW+48(a0)
230	dmfc2	t2, 0x025E
231	sd	t3, OCTEON_CP2_HSH_IVW+56(a0)
232	dmfc2	t3, 0x025A
233	sd	t0, OCTEON_CP2_GFM_MULT(a0)
234	dmfc2	t0, 0x025B
235	sd	t1, OCTEON_CP2_GFM_MULT+8(a0)
236	sd	t2, OCTEON_CP2_GFM_POLY(a0)
237	sd	t3, OCTEON_CP2_GFM_RESULT(a0)
238	bltz	v1, 4f
239	 sd	t0, OCTEON_CP2_GFM_RESULT+8(a0)
240	/* OCTEON III things*/
241	dmfc2	t0, 0x024F
242	dmfc2	t1, 0x0050
243	sd	t0, OCTEON_CP2_SHA3(a0)
244	sd	t1, OCTEON_CP2_SHA3+8(a0)
2454:
246	jr	ra
247	 nop
248
2492:	/* pass 1 special stuff when !CvmCtl[NOCRYPTO] */
250	dmfc2	t3, 0x0040
251	dmfc2	t0, 0x0041
252	dmfc2	t1, 0x0042
253	dmfc2	t2, 0x0043
254	sd	t3, OCTEON_CP2_HSH_DATW(a0)
255	dmfc2	t3, 0x0044
256	sd	t0, OCTEON_CP2_HSH_DATW+8(a0)
257	dmfc2	t0, 0x0045
258	sd	t1, OCTEON_CP2_HSH_DATW+16(a0)
259	dmfc2	t1, 0x0046
260	sd	t2, OCTEON_CP2_HSH_DATW+24(a0)
261	dmfc2	t2, 0x0048
262	sd	t3, OCTEON_CP2_HSH_DATW+32(a0)
263	dmfc2	t3, 0x0049
264	sd	t0, OCTEON_CP2_HSH_DATW+40(a0)
265	dmfc2	t0, 0x004A
266	sd	t1, OCTEON_CP2_HSH_DATW+48(a0)
267	sd	t2, OCTEON_CP2_HSH_IVW(a0)
268	sd	t3, OCTEON_CP2_HSH_IVW+8(a0)
269	sd	t0, OCTEON_CP2_HSH_IVW+16(a0)
270
2713:	/* pass 1 or CvmCtl[NOCRYPTO] set */
272	jr	ra
273	 nop
274	END(octeon_cop2_save)
275	.set pop
276
277/*
278 * void octeon_cop2_restore(struct octeon_cop2_state *a0)
279 */
280	.align	7
281	.set push
282	.set noreorder
283	LEAF(octeon_cop2_restore)
284	/* First cache line was prefetched before the call */
285	pref	4,  128(a0)
286	dmfc0	t9, $9,7	/* CvmCtl register. */
287
288	pref	4,  256(a0)
289	ld	t0, OCTEON_CP2_CRC_IV(a0)
290	pref	4,  384(a0)
291	ld	t1, OCTEON_CP2_CRC_LENGTH(a0)
292	ld	t2, OCTEON_CP2_CRC_POLY(a0)
293
294	/* Restore the COP2 CRC state */
295	dmtc2	t0, 0x0201
296	dmtc2	t1, 0x1202
297	bbit1	t9, 28, 2f	/* Skip LLM if CvmCtl[NODFA_CP2] is set */
298	 dmtc2	t2, 0x4200
299
300	/* Restore the LLM state */
301	ld	t0, OCTEON_CP2_LLM_DAT(a0)
302	ld	t1, OCTEON_CP2_LLM_DAT+8(a0)
303	dmtc2	t0, 0x0402
304	dmtc2	t1, 0x040A
305
3062:
307	bbit1	t9, 26, done_restore	/* done if CvmCtl[NOCRYPTO] set */
308	 nop
309
310	/* Restore the COP2 crypto state common to pass 1 and pass 2 */
311	ld	t0, OCTEON_CP2_3DES_IV(a0)
312	ld	t1, OCTEON_CP2_3DES_KEY(a0)
313	ld	t2, OCTEON_CP2_3DES_KEY+8(a0)
314	dmtc2	t0, 0x0084
315	ld	t0, OCTEON_CP2_3DES_KEY+16(a0)
316	dmtc2	t1, 0x0080
317	ld	t1, OCTEON_CP2_3DES_RESULT(a0)
318	dmtc2	t2, 0x0081
319	ld	t2, OCTEON_CP2_AES_INP0(a0) /* only really needed for pass 1 */
320	dmtc2	t0, 0x0082
321	ld	t0, OCTEON_CP2_AES_IV(a0)
322	dmtc2	t1, 0x0098
323	ld	t1, OCTEON_CP2_AES_IV+8(a0)
324	dmtc2	t2, 0x010A		    /* only really needed for pass 1 */
325	ld	t2, OCTEON_CP2_AES_KEY(a0)
326	dmtc2	t0, 0x0102
327	ld	t0, OCTEON_CP2_AES_KEY+8(a0)
328	dmtc2	t1, 0x0103
329	ld	t1, OCTEON_CP2_AES_KEY+16(a0)
330	dmtc2	t2, 0x0104
331	ld	t2, OCTEON_CP2_AES_KEY+24(a0)
332	dmtc2	t0, 0x0105
333	ld	t0, OCTEON_CP2_AES_KEYLEN(a0)
334	dmtc2	t1, 0x0106
335	ld	t1, OCTEON_CP2_AES_RESULT(a0)
336	dmtc2	t2, 0x0107
337	ld	t2, OCTEON_CP2_AES_RESULT+8(a0)
338	mfc0	t3, $15,0	/* Get the processor ID register */
339	dmtc2	t0, 0x0110
340	li	v0, 0x000d0000	/* This is the processor ID of Octeon Pass1 */
341	dmtc2	t1, 0x0100
342	bne	v0, t3, 3f	/* Skip the next stuff for non-pass1 */
343	 dmtc2	t2, 0x0101
344
345	/* this code is specific for pass 1 */
346	ld	t0, OCTEON_CP2_HSH_DATW(a0)
347	ld	t1, OCTEON_CP2_HSH_DATW+8(a0)
348	ld	t2, OCTEON_CP2_HSH_DATW+16(a0)
349	dmtc2	t0, 0x0040
350	ld	t0, OCTEON_CP2_HSH_DATW+24(a0)
351	dmtc2	t1, 0x0041
352	ld	t1, OCTEON_CP2_HSH_DATW+32(a0)
353	dmtc2	t2, 0x0042
354	ld	t2, OCTEON_CP2_HSH_DATW+40(a0)
355	dmtc2	t0, 0x0043
356	ld	t0, OCTEON_CP2_HSH_DATW+48(a0)
357	dmtc2	t1, 0x0044
358	ld	t1, OCTEON_CP2_HSH_IVW(a0)
359	dmtc2	t2, 0x0045
360	ld	t2, OCTEON_CP2_HSH_IVW+8(a0)
361	dmtc2	t0, 0x0046
362	ld	t0, OCTEON_CP2_HSH_IVW+16(a0)
363	dmtc2	t1, 0x0048
364	dmtc2	t2, 0x0049
365	b done_restore	 /* unconditional branch */
366	 dmtc2	t0, 0x004A
367
3683:	/* this is post-pass1 code */
369	ld	t2, OCTEON_CP2_HSH_DATW(a0)
370	ori	v0, v0, 0x9500 /* lowest OCTEON III PrId*/
371	ld	t0, OCTEON_CP2_HSH_DATW+8(a0)
372	ld	t1, OCTEON_CP2_HSH_DATW+16(a0)
373	dmtc2	t2, 0x0240
374	ld	t2, OCTEON_CP2_HSH_DATW+24(a0)
375	dmtc2	t0, 0x0241
376	ld	t0, OCTEON_CP2_HSH_DATW+32(a0)
377	dmtc2	t1, 0x0242
378	ld	t1, OCTEON_CP2_HSH_DATW+40(a0)
379	dmtc2	t2, 0x0243
380	ld	t2, OCTEON_CP2_HSH_DATW+48(a0)
381	dmtc2	t0, 0x0244
382	ld	t0, OCTEON_CP2_HSH_DATW+56(a0)
383	dmtc2	t1, 0x0245
384	ld	t1, OCTEON_CP2_HSH_DATW+64(a0)
385	dmtc2	t2, 0x0246
386	ld	t2, OCTEON_CP2_HSH_DATW+72(a0)
387	dmtc2	t0, 0x0247
388	ld	t0, OCTEON_CP2_HSH_DATW+80(a0)
389	dmtc2	t1, 0x0248
390	ld	t1, OCTEON_CP2_HSH_DATW+88(a0)
391	dmtc2	t2, 0x0249
392	ld	t2, OCTEON_CP2_HSH_DATW+96(a0)
393	dmtc2	t0, 0x024A
394	ld	t0, OCTEON_CP2_HSH_DATW+104(a0)
395	dmtc2	t1, 0x024B
396	ld	t1, OCTEON_CP2_HSH_DATW+112(a0)
397	dmtc2	t2, 0x024C
398	ld	t2, OCTEON_CP2_HSH_IVW(a0)
399	dmtc2	t0, 0x024D
400	ld	t0, OCTEON_CP2_HSH_IVW+8(a0)
401	dmtc2	t1, 0x024E
402	ld	t1, OCTEON_CP2_HSH_IVW+16(a0)
403	dmtc2	t2, 0x0250
404	ld	t2, OCTEON_CP2_HSH_IVW+24(a0)
405	dmtc2	t0, 0x0251
406	ld	t0, OCTEON_CP2_HSH_IVW+32(a0)
407	dmtc2	t1, 0x0252
408	ld	t1, OCTEON_CP2_HSH_IVW+40(a0)
409	dmtc2	t2, 0x0253
410	ld	t2, OCTEON_CP2_HSH_IVW+48(a0)
411	dmtc2	t0, 0x0254
412	ld	t0, OCTEON_CP2_HSH_IVW+56(a0)
413	dmtc2	t1, 0x0255
414	ld	t1, OCTEON_CP2_GFM_MULT(a0)
415	dmtc2	t2, 0x0256
416	ld	t2, OCTEON_CP2_GFM_MULT+8(a0)
417	dmtc2	t0, 0x0257
418	ld	t0, OCTEON_CP2_GFM_POLY(a0)
419	dmtc2	t1, 0x0258
420	ld	t1, OCTEON_CP2_GFM_RESULT(a0)
421	dmtc2	t2, 0x0259
422	ld	t2, OCTEON_CP2_GFM_RESULT+8(a0)
423	dmtc2	t0, 0x025E
424	subu	v0, t3, v0 /* prid - lowest OCTEON III PrId */
425	dmtc2	t1, 0x025A
426	bltz	v0, done_restore
427	 dmtc2	t2, 0x025B
428	/* OCTEON III things*/
429	ld	t0, OCTEON_CP2_SHA3(a0)
430	ld	t1, OCTEON_CP2_SHA3+8(a0)
431	dmtc2	t0, 0x0051
432	dmtc2	t1, 0x0050
433done_restore:
434	jr	ra
435	 nop
436	END(octeon_cop2_restore)
437	.set pop
438
439/*
440 * void octeon_mult_save()
441 * sp is assumed to point to a struct pt_regs
442 *
443 * NOTE: This is called in SAVE_TEMP in stackframe.h. It can
444 *       safely modify v1,k0, k1,$10-$15, and $24.  It will
445 *	 be overwritten with a processor specific version of the code.
446 */
447	.p2align 7
448	.set push
449	.set noreorder
450	LEAF(octeon_mult_save)
451	jr	ra
452	 nop
453	.space 30 * 4, 0
454octeon_mult_save_end:
455	EXPORT(octeon_mult_save_end)
456	END(octeon_mult_save)
457
458	LEAF(octeon_mult_save2)
459	/* Save the multiplier state OCTEON II and earlier*/
460	v3mulu	k0, $0, $0
461	v3mulu	k1, $0, $0
462	sd	k0, PT_MTP(sp)	      /* PT_MTP	   has P0 */
463	v3mulu	k0, $0, $0
464	sd	k1, PT_MTP+8(sp)      /* PT_MTP+8  has P1 */
465	ori	k1, $0, 1
466	v3mulu	k1, k1, $0
467	sd	k0, PT_MTP+16(sp)     /* PT_MTP+16 has P2 */
468	v3mulu	k0, $0, $0
469	sd	k1, PT_MPL(sp)	      /* PT_MPL	   has MPL0 */
470	v3mulu	k1, $0, $0
471	sd	k0, PT_MPL+8(sp)      /* PT_MPL+8  has MPL1 */
472	jr	ra
473	 sd	k1, PT_MPL+16(sp)     /* PT_MPL+16 has MPL2 */
474octeon_mult_save2_end:
475	EXPORT(octeon_mult_save2_end)
476	END(octeon_mult_save2)
477
478	LEAF(octeon_mult_save3)
479	/* Save the multiplier state OCTEON III */
480	v3mulu	$10, $0, $0		/* read P0 */
481	v3mulu	$11, $0, $0		/* read P1 */
482	v3mulu	$12, $0, $0		/* read P2 */
483	sd	$10, PT_MTP+(0*8)(sp)	/* store P0 */
484	v3mulu	$10, $0, $0		/* read P3 */
485	sd	$11, PT_MTP+(1*8)(sp)	/*  store P1 */
486	v3mulu	$11, $0, $0		/* read P4 */
487	sd	$12, PT_MTP+(2*8)(sp)	/* store P2 */
488	ori	$13, $0, 1
489	v3mulu	$12, $0, $0		/* read P5 */
490	sd	$10, PT_MTP+(3*8)(sp)	/* store P3 */
491	v3mulu	$13, $13, $0		/* P4-P0 = MPL5-MPL1, $13 = MPL0 */
492	sd	$11, PT_MTP+(4*8)(sp)	/* store P4 */
493	v3mulu	$10, $0, $0		/* read MPL1 */
494	sd	$12, PT_MTP+(5*8)(sp)	/* store P5 */
495	v3mulu	$11, $0, $0		/* read MPL2 */
496	sd	$13, PT_MPL+(0*8)(sp)	/* store MPL0 */
497	v3mulu	$12, $0, $0		/* read MPL3 */
498	sd	$10, PT_MPL+(1*8)(sp)	/* store MPL1 */
499	v3mulu	$10, $0, $0		/* read MPL4 */
500	sd	$11, PT_MPL+(2*8)(sp)	/* store MPL2 */
501	v3mulu	$11, $0, $0		/* read MPL5 */
502	sd	$12, PT_MPL+(3*8)(sp)	/* store MPL3 */
503	sd	$10, PT_MPL+(4*8)(sp)	/* store MPL4 */
504	jr	ra
505	 sd	$11, PT_MPL+(5*8)(sp)	/* store MPL5 */
506octeon_mult_save3_end:
507	EXPORT(octeon_mult_save3_end)
508	END(octeon_mult_save3)
509	.set pop
510
511/*
512 * void octeon_mult_restore()
513 * sp is assumed to point to a struct pt_regs
514 *
515 * NOTE: This is called in RESTORE_TEMP in stackframe.h.
516 */
517	.p2align 7
518	.set push
519	.set noreorder
520	LEAF(octeon_mult_restore)
521	jr	ra
522	 nop
523	.space 30 * 4, 0
524octeon_mult_restore_end:
525	EXPORT(octeon_mult_restore_end)
526	END(octeon_mult_restore)
527
528	LEAF(octeon_mult_restore2)
529	ld	v0, PT_MPL(sp)        	/* MPL0 */
530	ld	v1, PT_MPL+8(sp)      	/* MPL1 */
531	ld	k0, PT_MPL+16(sp)     	/* MPL2 */
532	/* Restore the multiplier state */
533	ld	k1, PT_MTP+16(sp)     	/* P2 */
534	mtm0	v0			/* MPL0 */
535	ld	v0, PT_MTP+8(sp)	/* P1 */
536	mtm1	v1			/* MPL1 */
537	ld	v1, PT_MTP(sp)   	/* P0 */
538	mtm2	k0			/* MPL2 */
539	mtp2	k1			/* P2 */
540	mtp1	v0			/* P1 */
541	jr	ra
542	 mtp0	v1			/* P0 */
543octeon_mult_restore2_end:
544	EXPORT(octeon_mult_restore2_end)
545	END(octeon_mult_restore2)
546
547	LEAF(octeon_mult_restore3)
548	ld	$12, PT_MPL+(0*8)(sp)	/* read MPL0 */
549	ld	$13, PT_MPL+(3*8)(sp)	/* read MPL3 */
550	ld	$10, PT_MPL+(1*8)(sp)	/* read MPL1 */
551	ld	$11, PT_MPL+(4*8)(sp)	/* read MPL4 */
552	.word	0x718d0008
553	/* mtm0	$12, $13		   restore MPL0 and MPL3 */
554	ld	$12, PT_MPL+(2*8)(sp)	/* read MPL2 */
555	.word	0x714b000c
556	/* mtm1	$10, $11		   restore MPL1 and MPL4 */
557	ld	$13, PT_MPL+(5*8)(sp)	/* read MPL5 */
558	ld	$10, PT_MTP+(0*8)(sp)	/* read P0 */
559	ld	$11, PT_MTP+(3*8)(sp)	/* read P3 */
560	.word	0x718d000d
561	/* mtm2	$12, $13		   restore MPL2 and MPL5 */
562	ld	$12, PT_MTP+(1*8)(sp)	/* read P1 */
563	.word	0x714b0009
564	/* mtp0	$10, $11		   restore P0 and P3 */
565	ld	$13, PT_MTP+(4*8)(sp)	/* read P4 */
566	ld	$10, PT_MTP+(2*8)(sp)	/* read P2 */
567	ld	$11, PT_MTP+(5*8)(sp)	/* read P5 */
568	.word	0x718d000a
569	/* mtp1	$12, $13		   restore P1 and P4 */
570	jr	ra
571	.word	0x714b000b
572	/* mtp2	$10, $11		   restore P2 and P5 */
573
574octeon_mult_restore3_end:
575	EXPORT(octeon_mult_restore3_end)
576	END(octeon_mult_restore3)
577	.set pop
578