Merge master.kernel.org:/home/rmk/linux-2.6-arm
[linux-2.6] / arch / m68k / math-emu / fp_movem.S
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