1/* MN10300 Low level FPU management operations
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/linkage.h>
12#include <asm/cpu-regs.h>
13#include <asm/smp.h>
14#include <asm/thread_info.h>
15#include <asm/asm-offsets.h>
16#include <asm/frame.inc>
17
18.macro FPU_INIT_STATE_ALL
19	fmov	0,fs0
20	fmov	fs0,fs1
21	fmov	fs0,fs2
22	fmov	fs0,fs3
23	fmov	fs0,fs4
24	fmov	fs0,fs5
25	fmov	fs0,fs6
26	fmov	fs0,fs7
27	fmov	fs0,fs8
28	fmov	fs0,fs9
29	fmov	fs0,fs10
30	fmov	fs0,fs11
31	fmov	fs0,fs12
32	fmov	fs0,fs13
33	fmov	fs0,fs14
34	fmov	fs0,fs15
35	fmov	fs0,fs16
36	fmov	fs0,fs17
37	fmov	fs0,fs18
38	fmov	fs0,fs19
39	fmov	fs0,fs20
40	fmov	fs0,fs21
41	fmov	fs0,fs22
42	fmov	fs0,fs23
43	fmov	fs0,fs24
44	fmov	fs0,fs25
45	fmov	fs0,fs26
46	fmov	fs0,fs27
47	fmov	fs0,fs28
48	fmov	fs0,fs29
49	fmov	fs0,fs30
50	fmov	fs0,fs31
51	fmov	FPCR_INIT,fpcr
52.endm
53
54.macro FPU_SAVE_ALL areg,dreg
55	fmov	fs0,(\areg+)
56	fmov	fs1,(\areg+)
57	fmov	fs2,(\areg+)
58	fmov	fs3,(\areg+)
59	fmov	fs4,(\areg+)
60	fmov	fs5,(\areg+)
61	fmov	fs6,(\areg+)
62	fmov	fs7,(\areg+)
63	fmov	fs8,(\areg+)
64	fmov	fs9,(\areg+)
65	fmov	fs10,(\areg+)
66	fmov	fs11,(\areg+)
67	fmov	fs12,(\areg+)
68	fmov	fs13,(\areg+)
69	fmov	fs14,(\areg+)
70	fmov	fs15,(\areg+)
71	fmov	fs16,(\areg+)
72	fmov	fs17,(\areg+)
73	fmov	fs18,(\areg+)
74	fmov	fs19,(\areg+)
75	fmov	fs20,(\areg+)
76	fmov	fs21,(\areg+)
77	fmov	fs22,(\areg+)
78	fmov	fs23,(\areg+)
79	fmov	fs24,(\areg+)
80	fmov	fs25,(\areg+)
81	fmov	fs26,(\areg+)
82	fmov	fs27,(\areg+)
83	fmov	fs28,(\areg+)
84	fmov	fs29,(\areg+)
85	fmov	fs30,(\areg+)
86	fmov	fs31,(\areg+)
87	fmov	fpcr,\dreg
88	mov	\dreg,(\areg)
89.endm
90
91.macro FPU_RESTORE_ALL areg,dreg
92	fmov	(\areg+),fs0
93	fmov	(\areg+),fs1
94	fmov	(\areg+),fs2
95	fmov	(\areg+),fs3
96	fmov	(\areg+),fs4
97	fmov	(\areg+),fs5
98	fmov	(\areg+),fs6
99	fmov	(\areg+),fs7
100	fmov	(\areg+),fs8
101	fmov	(\areg+),fs9
102	fmov	(\areg+),fs10
103	fmov	(\areg+),fs11
104	fmov	(\areg+),fs12
105	fmov	(\areg+),fs13
106	fmov	(\areg+),fs14
107	fmov	(\areg+),fs15
108	fmov	(\areg+),fs16
109	fmov	(\areg+),fs17
110	fmov	(\areg+),fs18
111	fmov	(\areg+),fs19
112	fmov	(\areg+),fs20
113	fmov	(\areg+),fs21
114	fmov	(\areg+),fs22
115	fmov	(\areg+),fs23
116	fmov	(\areg+),fs24
117	fmov	(\areg+),fs25
118	fmov	(\areg+),fs26
119	fmov	(\areg+),fs27
120	fmov	(\areg+),fs28
121	fmov	(\areg+),fs29
122	fmov	(\areg+),fs30
123	fmov	(\areg+),fs31
124	mov	(\areg),\dreg
125	fmov	\dreg,fpcr
126.endm
127
128###############################################################################
129#
130# void fpu_init_state(void)
131# - initialise the FPU
132#
133###############################################################################
134	.globl	fpu_init_state
135	.type	fpu_init_state,@function
136fpu_init_state:
137	mov	epsw,d0
138	or	EPSW_FE,epsw
139
140#ifdef CONFIG_MN10300_PROC_MN103E010
141	nop
142	nop
143	nop
144#endif
145	FPU_INIT_STATE_ALL
146#ifdef CONFIG_MN10300_PROC_MN103E010
147	nop
148	nop
149	nop
150#endif
151	mov	d0,epsw
152	ret	[],0
153
154	.size	fpu_init_state,.-fpu_init_state
155
156###############################################################################
157#
158# void fpu_save(struct fpu_state_struct *)
159# - save the fpu state
160# - note that an FPU Operational exception might occur during this process
161#
162###############################################################################
163	.globl	fpu_save
164	.type	fpu_save,@function
165fpu_save:
166	mov	epsw,d1
167	or	EPSW_FE,epsw		/* enable the FPU so we can access it */
168
169#ifdef CONFIG_MN10300_PROC_MN103E010
170	nop
171	nop
172#endif
173	mov	d0,a0
174	FPU_SAVE_ALL	a0,d0
175#ifdef CONFIG_MN10300_PROC_MN103E010
176	nop
177	nop
178#endif
179
180	mov	d1,epsw
181	ret	[],0
182
183	.size	fpu_save,.-fpu_save
184
185###############################################################################
186#
187# void fpu_disabled(void)
188# - handle an exception due to the FPU being disabled
189#   when CONFIG_FPU is enabled
190#
191###############################################################################
192	.type	fpu_disabled,@function
193	.globl	fpu_disabled
194fpu_disabled:
195	or	EPSW_nAR|EPSW_FE,epsw
196	nop
197	nop
198	nop
199
200	mov	sp,a1
201	mov	(a1),d1			/* get epsw of user context */
202	and	~(THREAD_SIZE-1),a1	/* a1: (thread_info *ti) */
203	mov	(TI_task,a1),a2		/* a2: (task_struct *tsk) */
204	btst	EPSW_nSL,d1
205	beq	fpu_used_in_kernel
206
207	or	EPSW_FE,d1
208	mov	d1,(sp)
209	mov	(TASK_THREAD+THREAD_FPU_FLAGS,a2),d1
210#ifndef CONFIG_LAZY_SAVE_FPU
211	or	__THREAD_HAS_FPU,d1
212	mov	d1,(TASK_THREAD+THREAD_FPU_FLAGS,a2)
213#else  /* !CONFIG_LAZY_SAVE_FPU */
214	mov	(fpu_state_owner),a0
215	cmp	0,a0
216	beq	fpu_regs_save_end
217
218	mov	(TASK_THREAD+THREAD_UREGS,a0),a1
219	add	TASK_THREAD+THREAD_FPU_STATE,a0
220	FPU_SAVE_ALL a0,d0
221
222	mov	(REG_EPSW,a1),d0
223	and	~EPSW_FE,d0
224	mov	d0,(REG_EPSW,a1)
225
226fpu_regs_save_end:
227	mov	a2,(fpu_state_owner)
228#endif /* !CONFIG_LAZY_SAVE_FPU */
229
230	btst	__THREAD_USING_FPU,d1
231	beq	fpu_regs_init
232	add	TASK_THREAD+THREAD_FPU_STATE,a2
233	FPU_RESTORE_ALL a2,d0
234	rti
235
236fpu_regs_init:
237	FPU_INIT_STATE_ALL
238	add	TASK_THREAD+THREAD_FPU_FLAGS,a2
239	bset	__THREAD_USING_FPU,(0,a2)
240	rti
241
242fpu_used_in_kernel:
243	and	~(EPSW_nAR|EPSW_FE),epsw
244	nop
245	nop
246
247	add	-4,sp
248	SAVE_ALL
249	mov	-1,d0
250	mov	d0,(REG_ORIG_D0,fp)
251
252	and	~EPSW_NMID,epsw
253
254	mov	fp,d0
255	call	fpu_disabled_in_kernel[],0
256	jmp	ret_from_exception
257
258	.size	fpu_disabled,.-fpu_disabled
259