xref: /openbmc/linux/arch/m68k/include/asm/math-emu.h (revision 498495dba268b20e8eadd7fe93c140c68b6cc9d2)
1  /* SPDX-License-Identifier: GPL-2.0 */
2  #ifndef _ASM_M68K_SETUP_H
3  #define _ASM_M68K_SETUP_H
4  
5  #include <asm/setup.h>
6  #include <linux/linkage.h>
7  
8  /* Status Register bits */
9  
10  /* accrued exception bits */
11  #define FPSR_AEXC_INEX	3
12  #define FPSR_AEXC_DZ	4
13  #define FPSR_AEXC_UNFL	5
14  #define FPSR_AEXC_OVFL	6
15  #define FPSR_AEXC_IOP	7
16  
17  /* exception status bits */
18  #define FPSR_EXC_INEX1	8
19  #define FPSR_EXC_INEX2	9
20  #define FPSR_EXC_DZ	10
21  #define FPSR_EXC_UNFL	11
22  #define FPSR_EXC_OVFL	12
23  #define FPSR_EXC_OPERR	13
24  #define FPSR_EXC_SNAN	14
25  #define FPSR_EXC_BSUN	15
26  
27  /* quotient byte, assumes big-endian, of course */
28  #define FPSR_QUOTIENT(fpsr) (*((signed char *) &(fpsr) + 1))
29  
30  /* condition code bits */
31  #define FPSR_CC_NAN	24
32  #define FPSR_CC_INF	25
33  #define FPSR_CC_Z	26
34  #define FPSR_CC_NEG	27
35  
36  
37  /* Control register bits */
38  
39  /* rounding mode */
40  #define	FPCR_ROUND_RN	0		/* round to nearest/even */
41  #define FPCR_ROUND_RZ	1		/* round to zero */
42  #define FPCR_ROUND_RM	2		/* minus infinity */
43  #define FPCR_ROUND_RP	3		/* plus infinity */
44  
45  /* rounding precision */
46  #define FPCR_PRECISION_X	0	/* long double */
47  #define FPCR_PRECISION_S	1	/* double */
48  #define FPCR_PRECISION_D	2	/* float */
49  
50  
51  /* Flags to select the debugging output */
52  #define PDECODE		0
53  #define PEXECUTE	1
54  #define PCONV		2
55  #define PNORM		3
56  #define PREGISTER	4
57  #define PINSTR		5
58  #define PUNIMPL		6
59  #define PMOVEM		7
60  
61  #define PMDECODE	(1<<PDECODE)
62  #define PMEXECUTE	(1<<PEXECUTE)
63  #define PMCONV		(1<<PCONV)
64  #define PMNORM		(1<<PNORM)
65  #define PMREGISTER	(1<<PREGISTER)
66  #define PMINSTR		(1<<PINSTR)
67  #define PMUNIMPL	(1<<PUNIMPL)
68  #define PMMOVEM		(1<<PMOVEM)
69  
70  #ifndef __ASSEMBLY__
71  
72  #include <linux/kernel.h>
73  #include <linux/sched.h>
74  
75  union fp_mant64 {
76  	unsigned long long m64;
77  	unsigned long m32[2];
78  };
79  
80  union fp_mant128 {
81  	unsigned long long m64[2];
82  	unsigned long m32[4];
83  };
84  
85  /* internal representation of extended fp numbers */
86  struct fp_ext {
87  	unsigned char lowmant;
88  	unsigned char sign;
89  	unsigned short exp;
90  	union fp_mant64 mant;
91  };
92  
93  /* C representation of FPU registers */
94  /* NOTE: if you change this, you have to change the assembler offsets
95     below and the size in <asm/fpu.h>, too */
96  struct fp_data {
97  	struct fp_ext fpreg[8];
98  	unsigned int fpcr;
99  	unsigned int fpsr;
100  	unsigned int fpiar;
101  	unsigned short prec;
102  	unsigned short rnd;
103  	struct fp_ext temp[2];
104  };
105  
106  #ifdef FPU_EMU_DEBUG
107  extern unsigned int fp_debugprint;
108  
109  #define dprint(bit, fmt, ...) ({			\
110  	if (fp_debugprint & (1 << (bit)))		\
111  		pr_info(fmt, ##__VA_ARGS__);		\
112  })
113  #else
114  #define dprint(bit, fmt, ...)	no_printk(fmt, ##__VA_ARGS__)
115  #endif
116  
117  #define uprint(str) ({					\
118  	static int __count = 3;				\
119  							\
120  	if (__count > 0) {				\
121  		pr_err("You just hit an unimplemented "	\
122  		       "fpu instruction (%s)\n", str);	\
123  		pr_err("Please report this to ....\n");	\
124  		__count--;				\
125  	}						\
126  })
127  
128  #define FPDATA		((struct fp_data *)current->thread.fp)
129  
130  #else	/* __ASSEMBLY__ */
131  
132  #define FPDATA		%a2
133  
134  /* offsets from the base register to the floating point data in the task struct */
135  #define FPD_FPREG	(TASK_THREAD+THREAD_FPREG+0)
136  #define FPD_FPCR	(TASK_THREAD+THREAD_FPREG+96)
137  #define FPD_FPSR	(TASK_THREAD+THREAD_FPREG+100)
138  #define FPD_FPIAR	(TASK_THREAD+THREAD_FPREG+104)
139  #define FPD_PREC	(TASK_THREAD+THREAD_FPREG+108)
140  #define FPD_RND		(TASK_THREAD+THREAD_FPREG+110)
141  #define FPD_TEMPFP1	(TASK_THREAD+THREAD_FPREG+112)
142  #define FPD_TEMPFP2	(TASK_THREAD+THREAD_FPREG+124)
143  #define FPD_SIZEOF	(TASK_THREAD+THREAD_FPREG+136)
144  
145  /* offsets on the stack to access saved registers,
146   * these are only used during instruction decoding
147   * where we always know how deep we're on the stack.
148   */
149  #define FPS_DO		(PT_OFF_D0)
150  #define FPS_D1		(PT_OFF_D1)
151  #define FPS_D2		(PT_OFF_D2)
152  #define FPS_A0		(PT_OFF_A0)
153  #define FPS_A1		(PT_OFF_A1)
154  #define FPS_A2		(PT_OFF_A2)
155  #define FPS_SR		(PT_OFF_SR)
156  #define FPS_PC		(PT_OFF_PC)
157  #define FPS_EA		(PT_OFF_PC+6)
158  #define FPS_PC2		(PT_OFF_PC+10)
159  
160  .macro	fp_get_fp_reg
161  	lea	(FPD_FPREG,FPDATA,%d0.w*4),%a0
162  	lea	(%a0,%d0.w*8),%a0
163  .endm
164  
165  /* Macros used to get/put the current program counter.
166   * 020/030 use a different stack frame then 040/060, for the
167   * 040/060 the return pc points already to the next location,
168   * so this only needs to be modified for jump instructions.
169   */
170  .macro	fp_get_pc dest
171  	move.l	(FPS_PC+4,%sp),\dest
172  .endm
173  
174  .macro	fp_put_pc src,jump=0
175  	move.l	\src,(FPS_PC+4,%sp)
176  .endm
177  
178  .macro	fp_get_instr_data	f,s,dest,label
179  	getuser	\f,%sp@(FPS_PC+4)@(0),\dest,\label,%sp@(FPS_PC+4)
180  	addq.l	#\s,%sp@(FPS_PC+4)
181  .endm
182  
183  .macro	fp_get_instr_word	dest,label,addr
184  	fp_get_instr_data	w,2,\dest,\label,\addr
185  .endm
186  
187  .macro	fp_get_instr_long	dest,label,addr
188  	fp_get_instr_data	l,4,\dest,\label,\addr
189  .endm
190  
191  /* These macros are used to read from/write to user space
192   * on error we jump to the fixup section, load the fault
193   * address into %a0 and jump to the exit.
194   * (derived from <asm/uaccess.h>)
195   */
196  .macro	getuser	size,src,dest,label,addr
197  |	printf	,"[\size<%08x]",1,\addr
198  .Lu1\@:	moves\size	\src,\dest
199  
200  	.section .fixup,"ax"
201  	.even
202  .Lu2\@:	move.l	\addr,%a0
203  	jra	\label
204  	.previous
205  
206  	.section __ex_table,"a"
207  	.align	4
208  	.long	.Lu1\@,.Lu2\@
209  	.previous
210  .endm
211  
212  .macro	putuser	size,src,dest,label,addr
213  |	printf	,"[\size>%08x]",1,\addr
214  .Lu1\@:	moves\size	\src,\dest
215  .Lu2\@:
216  
217  	.section .fixup,"ax"
218  	.even
219  .Lu3\@:	move.l	\addr,%a0
220  	jra	\label
221  	.previous
222  
223  	.section __ex_table,"a"
224  	.align	4
225  	.long	.Lu1\@,.Lu3\@
226  	.long	.Lu2\@,.Lu3\@
227  	.previous
228  .endm
229  
230  /* work around binutils idiocy */
231  old_gas=-1
232  .irp    gas_ident.x .x
233  old_gas=old_gas+1
234  .endr
235  .if !old_gas
236  .irp	m b,w,l
237  .macro	getuser.\m src,dest,label,addr
238  	getuser .\m,\src,\dest,\label,\addr
239  .endm
240  .macro	putuser.\m src,dest,label,addr
241  	putuser .\m,\src,\dest,\label,\addr
242  .endm
243  .endr
244  .endif
245  
246  .macro	movestack	nr,arg1,arg2,arg3,arg4,arg5
247  	.if	\nr
248  	movestack	(\nr-1),\arg2,\arg3,\arg4,\arg5
249  	move.l	\arg1,-(%sp)
250  	.endif
251  .endm
252  
253  .macro	printf	bit=-1,string,nr=0,arg1,arg2,arg3,arg4,arg5
254  #ifdef FPU_EMU_DEBUG
255  	.data
256  .Lpdata\@:
257  	.string	"\string"
258  	.previous
259  
260  	movem.l	%d0/%d1/%a0/%a1,-(%sp)
261  	.if	\bit+1
262  #if 0
263  	moveq	#\bit,%d0
264  	andw	#7,%d0
265  	btst	%d0,fp_debugprint+((31-\bit)/8)
266  #else
267  	btst	#\bit,fp_debugprint+((31-\bit)/8)
268  #endif
269  	jeq	.Lpskip\@
270  	.endif
271  	movestack	\nr,\arg1,\arg2,\arg3,\arg4,\arg5
272  	pea	.Lpdata\@
273  	jsr	printk
274  	lea	((\nr+1)*4,%sp),%sp
275  .Lpskip\@:
276  	movem.l	(%sp)+,%d0/%d1/%a0/%a1
277  #endif
278  .endm
279  
280  .macro	printx	bit,fp
281  #ifdef FPU_EMU_DEBUG
282  	movem.l	%d0/%a0,-(%sp)
283  	lea	\fp,%a0
284  #if 0
285  	moveq	#'+',%d0
286  	tst.w	(%a0)
287  	jeq	.Lx1\@
288  	moveq	#'-',%d0
289  .Lx1\@:	printf	\bit," %c",1,%d0
290  	move.l	(4,%a0),%d0
291  	bclr	#31,%d0
292  	jne	.Lx2\@
293  	printf	\bit,"0."
294  	jra	.Lx3\@
295  .Lx2\@:	printf	\bit,"1."
296  .Lx3\@:	printf	\bit,"%08x%08x",2,%d0,%a0@(8)
297  	move.w	(2,%a0),%d0
298  	ext.l	%d0
299  	printf	\bit,"E%04x",1,%d0
300  #else
301  	printf	\bit," %08x%08x%08x",3,%a0@,%a0@(4),%a0@(8)
302  #endif
303  	movem.l	(%sp)+,%d0/%a0
304  #endif
305  .endm
306  
307  .macro	debug	instr,args
308  #ifdef FPU_EMU_DEBUG
309  	\instr	\args
310  #endif
311  .endm
312  
313  
314  #endif	/* __ASSEMBLY__ */
315  
316  #endif	/* _ASM_M68K_SETUP_H */
317