File: /usr/src/linux/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 seperates 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 seperates 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 */
418