Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / m68k / math-emu / fp_decode.h
1 /*
2  * fp_decode.h
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 #ifndef _FP_DECODE_H
39 #define _FP_DECODE_H
40
41 /* These macros do the dirty work of the instr decoding, several variables
42  * can be defined in the source file to modify the work of these macros,
43  * currently the following variables are used:
44  * ...
45  * The register usage:
46  * d0 - will contain source operand for data direct mode,
47  *      otherwise scratch register
48  * d1 - upper 16bit are reserved for caller
49  *      lower 16bit may contain further arguments,
50  *      is destroyed during decoding
51  * d2 - contains first two instruction words,
52  *      first word will be used for extension word
53  * a0 - will point to source/dest operand for any indirect mode
54  *      otherwise scratch register
55  * a1 - scratch register
56  * a2 - base addr to the task structure
57  *
58  * the current implementation doesn't check for every disallowed
59  * addressing mode (e.g. pc relative modes as destination), as long
60  * as it only means a new addressing mode, which should not appear
61  * in a program and that doesn't crash the emulation, I think it's
62  * not a problem to allow these modes.
63  */
64
65 do_fmovem=0
66 do_fmovem_cr=0
67 do_no_pc_mode=0
68 do_fscc=0
69
70 | first decoding of the instr type
71 | this separates the conditional instr
72 .macro  fp_decode_cond_instr_type
73         bfextu  %d2{#8,#2},%d0
74         jmp     ([0f:w,%pc,%d0*4])
75
76         .align  4
77 0:
78 |       .long   "f<op>","fscc/fdbcc"
79 |       .long   "fbccw","fbccl"
80 .endm
81
82 | second decoding of the instr type
83 | this separates most move instr
84 .macro  fp_decode_move_instr_type
85         bfextu  %d2{#16,#3},%d0
86         jmp     ([0f:w,%pc,%d0*4])
87
88         .align  4
89 0:
90 |       .long   "f<op> fpx,fpx","invalid instr"
91 |       .long   "f<op> <ea>,fpx","fmove fpx,<ea>"
92 |       .long   "fmovem <ea>,fpcr","fmovem <ea>,fpx"
93 |       .long   "fmovem fpcr,<ea>","fmovem fpx,<ea>"
94 .endm
95
96 | extract the source specifier, specifies
97 | either source fp register or data format
98 .macro  fp_decode_sourcespec
99         bfextu  %d2{#19,#3},%d0
100 .endm
101
102 | decode destination format for fmove reg,ea
103 .macro  fp_decode_dest_format
104         bfextu  %d2{#19,#3},%d0
105 .endm
106
107 | decode source register for fmove reg,ea
108 .macro  fp_decode_src_reg
109         bfextu  %d2{#22,#3},%d0
110 .endm
111
112 | extract the addressing mode
113 | it depends on the instr which of the modes is valid
114 .macro  fp_decode_addr_mode
115         bfextu  %d2{#10,#3},%d0
116         jmp     ([0f:w,%pc,%d0*4])
117
118         .align  4
119 0:
120 |       .long   "data register direct","addr register direct"
121 |       .long   "addr register indirect"
122 |       .long   "addr register indirect postincrement"
123 |       .long   "addr register indirect predecrement"
124 |       .long   "addr register + index16"
125 |       .long   "extension mode1","extension mode2"
126 .endm
127
128 | extract the register for the addressing mode
129 .macro  fp_decode_addr_reg
130         bfextu  %d2{#13,#3},%d0
131 .endm
132
133 | decode the 8bit diplacement from the brief extension word
134 .macro  fp_decode_disp8
135         move.b  %d2,%d0
136         ext.w   %d0
137 .endm
138
139 | decode the index of the brief/full extension word
140 .macro  fp_decode_index
141         bfextu  %d2{#17,#3},%d0         | get the register nr
142         btst    #15,%d2                 | test for data/addr register
143         jne     1\@f
144         printf  PDECODE,"d%d",1,%d0
145         jsr     fp_get_data_reg
146         jra     2\@f
147 1\@:    printf  PDECODE,"a%d",1,%d0
148         jsr     fp_get_addr_reg
149         move.l  %a0,%d0
150 2\@:
151 debug   lea     "'l'.w,%a0"
152         btst    #11,%d2                 | 16/32 bit size?
153         jne     3\@f
154 debug   lea     "'w'.w,%a0"
155         ext.l   %d0
156 3\@:    printf  PDECODE,":%c",1,%a0
157         move.w  %d2,%d1                 | scale factor
158         rol.w   #7,%d1
159         and.w   #3,%d1
160 debug   move.l  "%d1,-(%sp)"
161 debug   ext.l   "%d1"
162         printf  PDECODE,":%d",1,%d1
163 debug   move.l  "(%sp)+,%d1"
164         lsl.l   %d1,%d0
165 .endm
166
167 | decode the base displacement size
168 .macro  fp_decode_basedisp
169         bfextu  %d2{#26,#2},%d0
170         jmp     ([0f:w,%pc,%d0*4])
171
172         .align  4
173 0:
174 |       .long   "reserved","null displacement"
175 |       .long   "word displacement","long displacement"
176 .endm
177
178 .macro  fp_decode_outerdisp
179         bfextu  %d2{#30,#2},%d0
180         jmp     ([0f:w,%pc,%d0*4])
181
182         .align  4
183 0:
184 |       .long   "no memory indirect action/reserved","null outer displacement"
185 |       .long   "word outer displacement","long outer displacement"
186 .endm
187
188 | get the extension word and test for brief or full extension type
189 .macro  fp_get_test_extword label
190         fp_get_instr_word %d2,fp_err_ua1
191         btst    #8,%d2
192         jne     \label
193 .endm
194
195
196 | test if %pc is the base register for the indirect addr mode
197 .macro  fp_test_basereg_d16     label
198         btst    #20,%d2
199         jeq     \label
200 .endm
201
202 | test if %pc is the base register for one of the extended modes
203 .macro  fp_test_basereg_ext     label
204         btst    #19,%d2
205         jeq     \label
206 .endm
207
208 .macro  fp_test_suppr_index label
209         btst    #6,%d2
210         jne     \label
211 .endm
212
213
214 | addressing mode: data register direct
215 .macro  fp_mode_data_direct
216         fp_decode_addr_reg
217         printf  PDECODE,"d%d",1,%d0
218 .endm
219
220 | addressing mode: address register indirect
221 .macro  fp_mode_addr_indirect
222         fp_decode_addr_reg
223         printf  PDECODE,"(a%d)",1,%d0
224         jsr     fp_get_addr_reg
225 .endm
226
227 | adjust stack for byte moves from/to stack
228 .macro  fp_test_sp_byte_move
229         .if     !do_fmovem
230         .if     do_fscc
231         move.w  #6,%d1
232         .endif
233         cmp.w   #7,%d0
234         jne     1\@f
235         .if     !do_fscc
236         cmp.w   #6,%d1
237         jne     1\@f
238         .endif
239         move.w  #4,%d1
240 1\@:
241         .endif
242 .endm
243
244 | addressing mode: address register indirect with postincrement
245 .macro  fp_mode_addr_indirect_postinc
246         fp_decode_addr_reg
247         printf  PDECODE,"(a%d)+",1,%d0
248         fp_test_sp_byte_move
249         jsr     fp_get_addr_reg
250         move.l  %a0,%a1                 | save addr
251         .if     do_fmovem
252         lea     (%a0,%d1.w*4),%a0
253         .if     !do_fmovem_cr
254         lea     (%a0,%d1.w*8),%a0
255         .endif
256         .else
257         add.w   (fp_datasize,%d1.w*2),%a0
258         .endif
259         jsr     fp_put_addr_reg
260         move.l  %a1,%a0
261 .endm
262
263 | addressing mode: address register indirect with predecrement
264 .macro  fp_mode_addr_indirect_predec
265         fp_decode_addr_reg
266         printf  PDECODE,"-(a%d)",1,%d0
267         fp_test_sp_byte_move
268         jsr     fp_get_addr_reg
269         .if     do_fmovem
270         .if     !do_fmovem_cr
271         lea     (-12,%a0),%a1           | setup to addr of 1st reg to move
272         neg.w   %d1
273         lea     (%a0,%d1.w*4),%a0
274         add.w   %d1,%d1
275         lea     (%a0,%d1.w*4),%a0
276         jsr     fp_put_addr_reg
277         move.l  %a1,%a0
278         .else
279         neg.w   %d1
280         lea     (%a0,%d1.w*4),%a0
281         jsr     fp_put_addr_reg
282         .endif
283         .else
284         sub.w   (fp_datasize,%d1.w*2),%a0
285         jsr     fp_put_addr_reg
286         .endif
287 .endm
288
289 | addressing mode: address register/programm counter indirect
290 |                  with 16bit displacement
291 .macro  fp_mode_addr_indirect_disp16
292         .if     !do_no_pc_mode
293         fp_test_basereg_d16 1f
294         printf  PDECODE,"pc"
295         fp_get_pc %a0
296         jra     2f
297         .endif
298 1:      fp_decode_addr_reg
299         printf  PDECODE,"a%d",1,%d0
300         jsr     fp_get_addr_reg
301 2:      fp_get_instr_word %a1,fp_err_ua1
302         printf  PDECODE,"@(%x)",1,%a1
303         add.l   %a1,%a0
304 .endm
305
306 | perform preindex (if I/IS == 0xx and xx != 00)
307 .macro  fp_do_preindex
308         moveq   #3,%d0
309         and.w   %d2,%d0
310         jeq     1f
311         btst    #2,%d2
312         jne     1f
313         printf  PDECODE,")@("
314         getuser.l (%a1),%a1,fp_err_ua1,%a1
315 debug   jra     "2f"
316 1:      printf  PDECODE,","
317 2:
318 .endm
319
320 | perform postindex (if I/IS == 1xx)
321 .macro  fp_do_postindex
322         btst    #2,%d2
323         jeq     1f
324         printf  PDECODE,")@("
325         getuser.l (%a1),%a1,fp_err_ua1,%a1
326 debug   jra     "2f"
327 1:      printf  PDECODE,","
328 2:
329 .endm
330
331 | all other indirect addressing modes will finally end up here
332 .macro  fp_mode_addr_indirect_extmode0
333         .if     !do_no_pc_mode
334         fp_test_basereg_ext 1f
335         printf  PDECODE,"pc"
336         fp_get_pc %a0
337         jra     2f
338         .endif
339 1:      fp_decode_addr_reg
340         printf  PDECODE,"a%d",1,%d0
341         jsr     fp_get_addr_reg
342 2:      move.l  %a0,%a1
343         swap    %d2
344         fp_get_test_extword 3f
345         | addressing mode: address register/programm counter indirect
346         |                  with index and 8bit displacement
347         fp_decode_disp8
348 debug   ext.l   "%d0"
349         printf  PDECODE,"@(%x,",1,%d0
350         add.w   %d0,%a1
351         fp_decode_index
352         add.l   %d0,%a1
353         printf  PDECODE,")"
354         jra     9f
355 3:      | addressing mode: address register/programm counter memory indirect
356         |                  with base and/or outer displacement
357         btst    #7,%d2                  | base register suppressed?
358         jeq     1f
359         printf  PDECODE,"!"
360         sub.l   %a1,%a1
361 1:      printf  PDECODE,"@("
362         fp_decode_basedisp
363
364         .long   fp_ill,1f
365         .long   2f,3f
366
367 #ifdef FPU_EMU_DEBUG
368 1:      printf  PDECODE,"0"             | null base displacement
369         jra     1f
370 #endif
371 2:      fp_get_instr_word %a0,fp_err_ua1 | 16bit base displacement
372         printf  PDECODE,"%x:w",1,%a0
373         jra     4f
374 3:      fp_get_instr_long %a0,fp_err_ua1 | 32bit base displacement
375         printf  PDECODE,"%x:l",1,%a0
376 4:      add.l   %a0,%a1
377 1:
378         fp_do_postindex
379         fp_test_suppr_index 1f
380         fp_decode_index
381         add.l   %d0,%a1
382 1:      fp_do_preindex
383
384         fp_decode_outerdisp
385
386         .long   5f,1f
387         .long   2f,3f
388
389 #ifdef FPU_EMU_DEBUG
390 1:      printf  PDECODE,"0"             | null outer displacement
391         jra     1f
392 #endif
393 2:      fp_get_instr_word %a0,fp_err_ua1 | 16bit outer displacement
394         printf  PDECODE,"%x:w",1,%a0
395         jra     4f
396 3:      fp_get_instr_long %a0,fp_err_ua1 | 32bit outer displacement
397         printf  PDECODE,"%x:l",1,%a0
398 4:      add.l   %a0,%a1
399 1:
400 5:      printf  PDECODE,")"
401 9:      move.l  %a1,%a0
402         swap    %d2
403 .endm
404
405 | get the absolute short address from user space
406 .macro  fp_mode_abs_short
407         fp_get_instr_word %a0,fp_err_ua1
408         printf  PDECODE,"%x.w",1,%a0
409 .endm
410
411 | get the absolute long address from user space
412 .macro  fp_mode_abs_long
413         fp_get_instr_long %a0,fp_err_ua1
414         printf  PDECODE,"%x.l",1,%a0
415 .endm
416
417 #endif /* _FP_DECODE_H */