1 /*
2  * fp_movem.S
3  *
4  * Copyright Roman Zippel, 1997.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, and the entire permission notice in its entirety,
11  *    including the disclaimer of warranties.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote
16  *    products derived from this software without specific prior
17  *    written permission.
18  *
19  * ALTERNATIVELY, this product may be distributed under the terms of
20  * the GNU General Public License, in which case the provisions of the GPL are
21  * required INSTEAD OF the above restrictions.  (This clause is
22  * necessary due to a potential bad interaction between the GPL and
23  * the restrictions contained in a BSD-style copyright.)
24  *
25  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
26  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
29  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
35  * OF THE POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 #include "fp_emu.h"
39 #include "fp_decode.h"
40 
41 | set flags for decode macros for fmovem
42 do_fmovem=1
43 
44 	.globl	fp_fmovem_fp, fp_fmovem_cr
45 
46 | %d1 contains the mask and count of the register list
47 | for other register usage see fp_decode.h
48 
49 fp_fmovem_fp:
50 	printf	PDECODE,"fmovem.x "
51 	| get register list and count them
52 	btst	#11,%d2
53 	jne	1f
54 	bfextu	%d2{#24,#8},%d0		| static register list
55 	jra	2f
56 1:	bfextu	%d2{#25,#3},%d0		| dynamic register list
57 	jsr	fp_get_data_reg
58 2:	move.l	%d0,%d1
59 	swap	%d1
60 	jra	2f
61 1:	addq.w	#1,%d1			| count the # of registers in
62 2:	lsr.b	#1,%d0			| register list and keep it in %d1
63 	jcs	1b
64 	jne	2b
65 	printf	PDECODE,"#%08x",1,%d1
66 #ifdef FPU_EMU_DEBUG
67 	btst	#12,%d2
68 	jne	1f
69 	printf	PDECODE,"-"		| decremental move
70 	jra	2f
71 1:	printf	PDECODE,"+"		| incremental move
72 2:	btst	#13,%d2
73 	jeq	1f
74 	printf	PDECODE,"->"		| fpu -> cpu
75 	jra	2f
76 1:	printf	PDECODE,"<-"		| fpu <- cpu
77 2:
78 #endif
79 
80 	| decode address mode
81 	fp_decode_addr_mode
82 
83 	.long	fp_ill, fp_ill
84 	.long	fpr_indirect, fpr_postinc
85 	.long	fpr_predecr, fpr_disp16
86 	.long	fpr_extmode0, fpr_extmode1
87 
88 	| addressing mode: address register indirect
89 fpr_indirect:
90 	fp_mode_addr_indirect
91 	jra	fpr_do_movem
92 
93 	| addressing mode: address register indirect with postincrement
94 fpr_postinc:
95 	fp_mode_addr_indirect_postinc
96 	jra	fpr_do_movem
97 
98 fpr_predecr:
99 	fp_mode_addr_indirect_predec
100 	jra	fpr_do_movem
101 
102 	| addressing mode: address register/programm counter indirect
103 	|		   with 16bit displacement
104 fpr_disp16:
105 	fp_mode_addr_indirect_disp16
106 	jra	fpr_do_movem
107 
108 fpr_extmode0:
109 	fp_mode_addr_indirect_extmode0
110 	jra	fpr_do_movem
111 
112 fpr_extmode1:
113 	fp_decode_addr_reg
114 	jmp	([0f:w,%pc,%d0*4])
115 
116 	.align	4
117 0:
118 	.long	fpr_absolute_short, fpr_absolute_long
119 	.long	fpr_disp16, fpr_extmode0
120 	.long	fp_ill, fp_ill
121 	.long	fp_ill, fp_ill
122 
123 fpr_absolute_short:
124 	fp_mode_abs_short
125 	jra	fpr_do_movem
126 
127 fpr_absolute_long:
128 	fp_mode_abs_long
129 |	jra	fpr_do_movem
130 
131 fpr_do_movem:
132 	swap	%d1			| get fpu register list
133 	lea	(FPD_FPREG,FPDATA),%a1
134 	moveq	#12,%d0
135 	btst	#12,%d2
136 	jne	1f
137 	lea	(-12,%a1,%d0*8),%a1
138 	neg.l	%d0
139 1:	btst	#13,%d2
140 	jne	4f
141 	| move register from memory into fpu
142 	jra	3f
143 1:	printf	PMOVEM,"(%p>%p)",2,%a0,%a1
144 	getuser.l (%a0)+,%d2,fp_err_ua1,%a0
145 	lsr.l	#8,%d2
146 	lsr.l	#7,%d2
147 	lsr.w	#1,%d2
148 	move.l	%d2,(%a1)+
149 	getuser.l (%a0)+,%d2,fp_err_ua1,%a0
150 	move.l	%d2,(%a1)+
151 	getuser.l (%a0),%d2,fp_err_ua1,%a0
152 	move.l	%d2,(%a1)
153 	subq.l	#8,%a0
154 	subq.l	#8,%a1
155 	add.l	%d0,%a0
156 2:	add.l	%d0,%a1
157 3:	lsl.b	#1,%d1
158 	jcs	1b
159 	jne	2b
160 	jra	5f
161 	| move register from fpu into memory
162 1:	printf	PMOVEM,"(%p>%p)",2,%a1,%a0
163 	move.l	(%a1)+,%d2
164 	lsl.w	#1,%d2
165 	lsl.l	#7,%d2
166 	lsl.l	#8,%d2
167 	putuser.l %d2,(%a0)+,fp_err_ua1,%a0
168 	move.l	(%a1)+,%d2
169 	putuser.l %d2,(%a0)+,fp_err_ua1,%a0
170 	move.l	(%a1),%d2
171 	putuser.l %d2,(%a0),fp_err_ua1,%a0
172 	subq.l	#8,%a1
173 	subq.l	#8,%a0
174 	add.l	%d0,%a0
175 2:	add.l	%d0,%a1
176 4:	lsl.b	#1,%d1
177 	jcs	1b
178 	jne	2b
179 5:
180 	printf	PDECODE,"\n"
181 #if 0
182 	lea	(FPD_FPREG,FPDATA),%a0
183 	printf	PMOVEM,"fp:"
184 	printx	PMOVEM,%a0@(0)
185 	printx	PMOVEM,%a0@(12)
186 	printf	PMOVEM,"\n   "
187 	printx	PMOVEM,%a0@(24)
188 	printx	PMOVEM,%a0@(36)
189 	printf	PMOVEM,"\n   "
190 	printx	PMOVEM,%a0@(48)
191 	printx	PMOVEM,%a0@(60)
192 	printf	PMOVEM,"\n   "
193 	printx	PMOVEM,%a0@(72)
194 	printx	PMOVEM,%a0@(84)
195 	printf	PMOVEM,"\n"
196 #endif
197 	jra	fp_end
198 
199 | set flags for decode macros for fmovem control register
200 do_fmovem=1
201 do_fmovem_cr=1
202 
203 fp_fmovem_cr:
204 	printf	PDECODE,"fmovem.cr "
205 	| get register list and count them
206 	bfextu	%d2{#19,#3},%d0
207 	move.l	%d0,%d1
208 	swap	%d1
209 	jra	2f
210 1:	addq.w	#1,%d1
211 2:	lsr.l	#1,%d0
212 	jcs	1b
213 	jne	2b
214 	printf	PDECODE,"#%08x",1,%d1
215 #ifdef FPU_EMU_DEBUG
216 	btst	#13,%d2
217 	jeq	1f
218 	printf	PDECODE,"->"		| fpu -> cpu
219 	jra	2f
220 1:	printf	PDECODE,"<-"		| fpu <- cpu
221 2:
222 #endif
223 
224 	| decode address mode
225 	fp_decode_addr_mode
226 
227 	.long	fpc_data, fpc_addr
228 	.long	fpc_indirect, fpc_postinc
229 	.long	fpc_predecr, fpc_disp16
230 	.long	fpc_extmode0, fpc_extmode1
231 
232 fpc_data:
233 	fp_mode_data_direct
234 	move.w	%d0,%d1
235 	bfffo	%d2{#19,#3},%d0
236 	sub.w	#19,%d0
237 	lea	(FPD_FPCR,FPDATA,%d0.w*4),%a1
238 	btst	#13,%d2
239 	jne	1f
240 	move.w	%d1,%d0
241 	jsr	fp_get_data_reg
242 	move.l	%d0,(%a1)
243 	jra	fpc_movem_fin
244 1:	move.l	(%a1),%d0
245 	jsr	fp_put_data_reg
246 	jra	fpc_movem_fin
247 
248 fpc_addr:
249 	fp_decode_addr_reg
250 	printf	PDECODE,"a%d",1,%d0
251 	btst	#13,%d2
252 	jne	1f
253 	jsr	fp_get_addr_reg
254 	move.l	%a0,(FPD_FPIAR,FPDATA)
255 	jra	fpc_movem_fin
256 1:	move.l	(FPD_FPIAR,FPDATA),%a0
257 	jsr	fp_put_addr_reg
258 	jra	fpc_movem_fin
259 
260 fpc_indirect:
261 	fp_mode_addr_indirect
262 	jra	fpc_do_movem
263 
264 fpc_postinc:
265 	fp_mode_addr_indirect_postinc
266 	jra	fpc_do_movem
267 
268 fpc_predecr:
269 	fp_mode_addr_indirect_predec
270 	jra	fpc_do_movem
271 
272 fpc_disp16:
273 	fp_mode_addr_indirect_disp16
274 	jra	fpc_do_movem
275 
276 fpc_extmode0:
277 	fp_mode_addr_indirect_extmode0
278 	jra	fpc_do_movem
279 
280 fpc_extmode1:
281 	fp_decode_addr_reg
282 	jmp	([0f:w,%pc,%d0*4])
283 
284 	.align	4
285 0:
286 	.long	fpc_absolute_short, fpc_absolute_long
287 	.long	fpc_disp16, fpc_extmode0
288 	.long	fpc_immediate, fp_ill
289 	.long	fp_ill, fp_ill
290 
291 fpc_absolute_short:
292 	fp_mode_abs_short
293 	jra	fpc_do_movem
294 
295 fpc_absolute_long:
296 	fp_mode_abs_long
297 	jra	fpc_do_movem
298 
299 fpc_immediate:
300 	fp_get_pc %a0
301 	lea	(%a0,%d1.w*4),%a1
302 	fp_put_pc %a1
303 	printf	PDECODE,"#imm"
304 |	jra	fpc_do_movem
305 #if 0
306 	swap	%d1
307 	lsl.l	#5,%d1
308 	lea	(FPD_FPCR,FPDATA),%a0
309 	jra	3f
310 1:	move.l	%d0,(%a0)
311 2:	addq.l	#4,%a0
312 3:	lsl.b	#1,%d1
313 	jcs	1b
314 	jne	2b
315 	jra	fpc_movem_fin
316 #endif
317 
318 fpc_do_movem:
319 	swap	%d1			| get fpu register list
320 	lsl.l	#5,%d1
321 	lea	(FPD_FPCR,FPDATA),%a1
322 1:	btst	#13,%d2
323 	jne	4f
324 
325 	| move register from memory into fpu
326 	jra	3f
327 1:	printf	PMOVEM,"(%p>%p)",2,%a0,%a1
328 	getuser.l (%a0)+,%d0,fp_err_ua1,%a0
329 	move.l	%d0,(%a1)
330 2:	addq.l	#4,%a1
331 3:	lsl.b	#1,%d1
332 	jcs	1b
333 	jne	2b
334 	jra	fpc_movem_fin
335 
336 	| move register from fpu into memory
337 1:	printf	PMOVEM,"(%p>%p)",2,%a1,%a0
338 	move.l	(%a1),%d0
339 	putuser.l %d0,(%a0)+,fp_err_ua1,%a0
340 2:	addq.l	#4,%a1
341 4:	lsl.b	#1,%d1
342 	jcs	1b
343 	jne	2b
344 
345 fpc_movem_fin:
346 	and.l	#0x0000fff0,(FPD_FPCR,FPDATA)
347 	and.l	#0x0ffffff8,(FPD_FPSR,FPDATA)
348 	move.l	(FPD_FPCR,FPDATA),%d0
349 	lsr.l	#4,%d0
350 	moveq	#3,%d1
351 	and.l	%d0,%d1
352 	move.w	%d1,(FPD_RND,FPDATA)
353 	lsr.l	#2,%d0
354 	moveq	#3,%d1
355 	and.l	%d0,%d1
356 	move.w	%d1,(FPD_PREC,FPDATA)
357 	printf	PDECODE,"\n"
358 #if 0
359 	printf	PMOVEM,"fpcr : %08x\n",1,FPDATA@(FPD_FPCR)
360 	printf	PMOVEM,"fpsr : %08x\n",1,FPDATA@(FPD_FPSR)
361 	printf	PMOVEM,"fpiar: %08x\n",1,FPDATA@(FPD_FPIAR)
362 	clr.l	%d0
363 	move.w	(FPD_PREC,FPDATA),%d0
364 	printf	PMOVEM,"prec : %04x\n",1,%d0
365 	move.w	(FPD_RND,FPDATA),%d0
366 	printf	PMOVEM,"rnd  : %04x\n",1,%d0
367 #endif
368 	jra	fp_end
369