xref: /linux/arch/m68k/include/asm/math-emu.h (revision 498495dba268b20e8eadd7fe93c140c68b6cc9d2)
1*b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
249148020SSam Ravnborg #ifndef _ASM_M68K_SETUP_H
349148020SSam Ravnborg #define _ASM_M68K_SETUP_H
449148020SSam Ravnborg 
549148020SSam Ravnborg #include <asm/setup.h>
649148020SSam Ravnborg #include <linux/linkage.h>
749148020SSam Ravnborg 
849148020SSam Ravnborg /* Status Register bits */
949148020SSam Ravnborg 
1049148020SSam Ravnborg /* accrued exception bits */
1149148020SSam Ravnborg #define FPSR_AEXC_INEX	3
1249148020SSam Ravnborg #define FPSR_AEXC_DZ	4
1349148020SSam Ravnborg #define FPSR_AEXC_UNFL	5
1449148020SSam Ravnborg #define FPSR_AEXC_OVFL	6
1549148020SSam Ravnborg #define FPSR_AEXC_IOP	7
1649148020SSam Ravnborg 
1749148020SSam Ravnborg /* exception status bits */
1849148020SSam Ravnborg #define FPSR_EXC_INEX1	8
1949148020SSam Ravnborg #define FPSR_EXC_INEX2	9
2049148020SSam Ravnborg #define FPSR_EXC_DZ	10
2149148020SSam Ravnborg #define FPSR_EXC_UNFL	11
2249148020SSam Ravnborg #define FPSR_EXC_OVFL	12
2349148020SSam Ravnborg #define FPSR_EXC_OPERR	13
2449148020SSam Ravnborg #define FPSR_EXC_SNAN	14
2549148020SSam Ravnborg #define FPSR_EXC_BSUN	15
2649148020SSam Ravnborg 
2749148020SSam Ravnborg /* quotient byte, assumes big-endian, of course */
2849148020SSam Ravnborg #define FPSR_QUOTIENT(fpsr) (*((signed char *) &(fpsr) + 1))
2949148020SSam Ravnborg 
3049148020SSam Ravnborg /* condition code bits */
3149148020SSam Ravnborg #define FPSR_CC_NAN	24
3249148020SSam Ravnborg #define FPSR_CC_INF	25
3349148020SSam Ravnborg #define FPSR_CC_Z	26
3449148020SSam Ravnborg #define FPSR_CC_NEG	27
3549148020SSam Ravnborg 
3649148020SSam Ravnborg 
3749148020SSam Ravnborg /* Control register bits */
3849148020SSam Ravnborg 
3949148020SSam Ravnborg /* rounding mode */
4049148020SSam Ravnborg #define	FPCR_ROUND_RN	0		/* round to nearest/even */
4149148020SSam Ravnborg #define FPCR_ROUND_RZ	1		/* round to zero */
4249148020SSam Ravnborg #define FPCR_ROUND_RM	2		/* minus infinity */
4349148020SSam Ravnborg #define FPCR_ROUND_RP	3		/* plus infinity */
4449148020SSam Ravnborg 
4549148020SSam Ravnborg /* rounding precision */
4649148020SSam Ravnborg #define FPCR_PRECISION_X	0	/* long double */
4749148020SSam Ravnborg #define FPCR_PRECISION_S	1	/* double */
4849148020SSam Ravnborg #define FPCR_PRECISION_D	2	/* float */
4949148020SSam Ravnborg 
5049148020SSam Ravnborg 
5149148020SSam Ravnborg /* Flags to select the debugging output */
5249148020SSam Ravnborg #define PDECODE		0
5349148020SSam Ravnborg #define PEXECUTE	1
5449148020SSam Ravnborg #define PCONV		2
5549148020SSam Ravnborg #define PNORM		3
5649148020SSam Ravnborg #define PREGISTER	4
5749148020SSam Ravnborg #define PINSTR		5
5849148020SSam Ravnborg #define PUNIMPL		6
5949148020SSam Ravnborg #define PMOVEM		7
6049148020SSam Ravnborg 
6149148020SSam Ravnborg #define PMDECODE	(1<<PDECODE)
6249148020SSam Ravnborg #define PMEXECUTE	(1<<PEXECUTE)
6349148020SSam Ravnborg #define PMCONV		(1<<PCONV)
6449148020SSam Ravnborg #define PMNORM		(1<<PNORM)
6549148020SSam Ravnborg #define PMREGISTER	(1<<PREGISTER)
6649148020SSam Ravnborg #define PMINSTR		(1<<PINSTR)
6749148020SSam Ravnborg #define PMUNIMPL	(1<<PUNIMPL)
6849148020SSam Ravnborg #define PMMOVEM		(1<<PMOVEM)
6949148020SSam Ravnborg 
7049148020SSam Ravnborg #ifndef __ASSEMBLY__
7149148020SSam Ravnborg 
7249148020SSam Ravnborg #include <linux/kernel.h>
7349148020SSam Ravnborg #include <linux/sched.h>
7449148020SSam Ravnborg 
7549148020SSam Ravnborg union fp_mant64 {
7649148020SSam Ravnborg 	unsigned long long m64;
7749148020SSam Ravnborg 	unsigned long m32[2];
7849148020SSam Ravnborg };
7949148020SSam Ravnborg 
8049148020SSam Ravnborg union fp_mant128 {
8149148020SSam Ravnborg 	unsigned long long m64[2];
8249148020SSam Ravnborg 	unsigned long m32[4];
8349148020SSam Ravnborg };
8449148020SSam Ravnborg 
8549148020SSam Ravnborg /* internal representation of extended fp numbers */
8649148020SSam Ravnborg struct fp_ext {
8749148020SSam Ravnborg 	unsigned char lowmant;
8849148020SSam Ravnborg 	unsigned char sign;
8949148020SSam Ravnborg 	unsigned short exp;
9049148020SSam Ravnborg 	union fp_mant64 mant;
9149148020SSam Ravnborg };
9249148020SSam Ravnborg 
9349148020SSam Ravnborg /* C representation of FPU registers */
9449148020SSam Ravnborg /* NOTE: if you change this, you have to change the assembler offsets
9549148020SSam Ravnborg    below and the size in <asm/fpu.h>, too */
9649148020SSam Ravnborg struct fp_data {
9749148020SSam Ravnborg 	struct fp_ext fpreg[8];
9849148020SSam Ravnborg 	unsigned int fpcr;
9949148020SSam Ravnborg 	unsigned int fpsr;
10049148020SSam Ravnborg 	unsigned int fpiar;
10149148020SSam Ravnborg 	unsigned short prec;
10249148020SSam Ravnborg 	unsigned short rnd;
10349148020SSam Ravnborg 	struct fp_ext temp[2];
10449148020SSam Ravnborg };
10549148020SSam Ravnborg 
10649148020SSam Ravnborg #ifdef FPU_EMU_DEBUG
10749148020SSam Ravnborg extern unsigned int fp_debugprint;
10849148020SSam Ravnborg 
109f0b914aeSGeert Uytterhoeven #define dprint(bit, fmt, ...) ({			\
11049148020SSam Ravnborg 	if (fp_debugprint & (1 << (bit)))		\
111f0b914aeSGeert Uytterhoeven 		pr_info(fmt, ##__VA_ARGS__);		\
11249148020SSam Ravnborg })
11349148020SSam Ravnborg #else
114f0b914aeSGeert Uytterhoeven #define dprint(bit, fmt, ...)	no_printk(fmt, ##__VA_ARGS__)
11549148020SSam Ravnborg #endif
11649148020SSam Ravnborg 
11749148020SSam Ravnborg #define uprint(str) ({					\
11849148020SSam Ravnborg 	static int __count = 3;				\
11949148020SSam Ravnborg 							\
12049148020SSam Ravnborg 	if (__count > 0) {				\
121f0b914aeSGeert Uytterhoeven 		pr_err("You just hit an unimplemented "	\
12249148020SSam Ravnborg 		       "fpu instruction (%s)\n", str);	\
123f0b914aeSGeert Uytterhoeven 		pr_err("Please report this to ....\n");	\
12449148020SSam Ravnborg 		__count--;				\
12549148020SSam Ravnborg 	}						\
12649148020SSam Ravnborg })
12749148020SSam Ravnborg 
12849148020SSam Ravnborg #define FPDATA		((struct fp_data *)current->thread.fp)
12949148020SSam Ravnborg 
13049148020SSam Ravnborg #else	/* __ASSEMBLY__ */
13149148020SSam Ravnborg 
13249148020SSam Ravnborg #define FPDATA		%a2
13349148020SSam Ravnborg 
13449148020SSam Ravnborg /* offsets from the base register to the floating point data in the task struct */
13549148020SSam Ravnborg #define FPD_FPREG	(TASK_THREAD+THREAD_FPREG+0)
13649148020SSam Ravnborg #define FPD_FPCR	(TASK_THREAD+THREAD_FPREG+96)
13749148020SSam Ravnborg #define FPD_FPSR	(TASK_THREAD+THREAD_FPREG+100)
13849148020SSam Ravnborg #define FPD_FPIAR	(TASK_THREAD+THREAD_FPREG+104)
13949148020SSam Ravnborg #define FPD_PREC	(TASK_THREAD+THREAD_FPREG+108)
14049148020SSam Ravnborg #define FPD_RND		(TASK_THREAD+THREAD_FPREG+110)
14149148020SSam Ravnborg #define FPD_TEMPFP1	(TASK_THREAD+THREAD_FPREG+112)
14249148020SSam Ravnborg #define FPD_TEMPFP2	(TASK_THREAD+THREAD_FPREG+124)
14349148020SSam Ravnborg #define FPD_SIZEOF	(TASK_THREAD+THREAD_FPREG+136)
14449148020SSam Ravnborg 
14549148020SSam Ravnborg /* offsets on the stack to access saved registers,
14649148020SSam Ravnborg  * these are only used during instruction decoding
14749148020SSam Ravnborg  * where we always know how deep we're on the stack.
14849148020SSam Ravnborg  */
149f159ee78SHeiko Carstens #define FPS_DO		(PT_OFF_D0)
150f159ee78SHeiko Carstens #define FPS_D1		(PT_OFF_D1)
151f159ee78SHeiko Carstens #define FPS_D2		(PT_OFF_D2)
152f159ee78SHeiko Carstens #define FPS_A0		(PT_OFF_A0)
153f159ee78SHeiko Carstens #define FPS_A1		(PT_OFF_A1)
154f159ee78SHeiko Carstens #define FPS_A2		(PT_OFF_A2)
155f159ee78SHeiko Carstens #define FPS_SR		(PT_OFF_SR)
156f159ee78SHeiko Carstens #define FPS_PC		(PT_OFF_PC)
157f159ee78SHeiko Carstens #define FPS_EA		(PT_OFF_PC+6)
158f159ee78SHeiko Carstens #define FPS_PC2		(PT_OFF_PC+10)
15949148020SSam Ravnborg 
16049148020SSam Ravnborg .macro	fp_get_fp_reg
16149148020SSam Ravnborg 	lea	(FPD_FPREG,FPDATA,%d0.w*4),%a0
16249148020SSam Ravnborg 	lea	(%a0,%d0.w*8),%a0
16349148020SSam Ravnborg .endm
16449148020SSam Ravnborg 
16549148020SSam Ravnborg /* Macros used to get/put the current program counter.
16649148020SSam Ravnborg  * 020/030 use a different stack frame then 040/060, for the
16749148020SSam Ravnborg  * 040/060 the return pc points already to the next location,
16849148020SSam Ravnborg  * so this only needs to be modified for jump instructions.
16949148020SSam Ravnborg  */
17049148020SSam Ravnborg .macro	fp_get_pc dest
17149148020SSam Ravnborg 	move.l	(FPS_PC+4,%sp),\dest
17249148020SSam Ravnborg .endm
17349148020SSam Ravnborg 
17449148020SSam Ravnborg .macro	fp_put_pc src,jump=0
17549148020SSam Ravnborg 	move.l	\src,(FPS_PC+4,%sp)
17649148020SSam Ravnborg .endm
17749148020SSam Ravnborg 
17849148020SSam Ravnborg .macro	fp_get_instr_data	f,s,dest,label
17949148020SSam Ravnborg 	getuser	\f,%sp@(FPS_PC+4)@(0),\dest,\label,%sp@(FPS_PC+4)
18049148020SSam Ravnborg 	addq.l	#\s,%sp@(FPS_PC+4)
18149148020SSam Ravnborg .endm
18249148020SSam Ravnborg 
18349148020SSam Ravnborg .macro	fp_get_instr_word	dest,label,addr
18449148020SSam Ravnborg 	fp_get_instr_data	w,2,\dest,\label,\addr
18549148020SSam Ravnborg .endm
18649148020SSam Ravnborg 
18749148020SSam Ravnborg .macro	fp_get_instr_long	dest,label,addr
18849148020SSam Ravnborg 	fp_get_instr_data	l,4,\dest,\label,\addr
18949148020SSam Ravnborg .endm
19049148020SSam Ravnborg 
19149148020SSam Ravnborg /* These macros are used to read from/write to user space
19249148020SSam Ravnborg  * on error we jump to the fixup section, load the fault
19349148020SSam Ravnborg  * address into %a0 and jump to the exit.
19449148020SSam Ravnborg  * (derived from <asm/uaccess.h>)
19549148020SSam Ravnborg  */
19649148020SSam Ravnborg .macro	getuser	size,src,dest,label,addr
19749148020SSam Ravnborg |	printf	,"[\size<%08x]",1,\addr
19849148020SSam Ravnborg .Lu1\@:	moves\size	\src,\dest
19949148020SSam Ravnborg 
20049148020SSam Ravnborg 	.section .fixup,"ax"
20149148020SSam Ravnborg 	.even
20249148020SSam Ravnborg .Lu2\@:	move.l	\addr,%a0
20349148020SSam Ravnborg 	jra	\label
20449148020SSam Ravnborg 	.previous
20549148020SSam Ravnborg 
20649148020SSam Ravnborg 	.section __ex_table,"a"
20749148020SSam Ravnborg 	.align	4
20849148020SSam Ravnborg 	.long	.Lu1\@,.Lu2\@
20949148020SSam Ravnborg 	.previous
21049148020SSam Ravnborg .endm
21149148020SSam Ravnborg 
21249148020SSam Ravnborg .macro	putuser	size,src,dest,label,addr
21349148020SSam Ravnborg |	printf	,"[\size>%08x]",1,\addr
21449148020SSam Ravnborg .Lu1\@:	moves\size	\src,\dest
21549148020SSam Ravnborg .Lu2\@:
21649148020SSam Ravnborg 
21749148020SSam Ravnborg 	.section .fixup,"ax"
21849148020SSam Ravnborg 	.even
21949148020SSam Ravnborg .Lu3\@:	move.l	\addr,%a0
22049148020SSam Ravnborg 	jra	\label
22149148020SSam Ravnborg 	.previous
22249148020SSam Ravnborg 
22349148020SSam Ravnborg 	.section __ex_table,"a"
22449148020SSam Ravnborg 	.align	4
22549148020SSam Ravnborg 	.long	.Lu1\@,.Lu3\@
22649148020SSam Ravnborg 	.long	.Lu2\@,.Lu3\@
22749148020SSam Ravnborg 	.previous
22849148020SSam Ravnborg .endm
22949148020SSam Ravnborg 
23049148020SSam Ravnborg /* work around binutils idiocy */
23149148020SSam Ravnborg old_gas=-1
23249148020SSam Ravnborg .irp    gas_ident.x .x
23349148020SSam Ravnborg old_gas=old_gas+1
23449148020SSam Ravnborg .endr
23549148020SSam Ravnborg .if !old_gas
23649148020SSam Ravnborg .irp	m b,w,l
23749148020SSam Ravnborg .macro	getuser.\m src,dest,label,addr
23849148020SSam Ravnborg 	getuser .\m,\src,\dest,\label,\addr
23949148020SSam Ravnborg .endm
24049148020SSam Ravnborg .macro	putuser.\m src,dest,label,addr
24149148020SSam Ravnborg 	putuser .\m,\src,\dest,\label,\addr
24249148020SSam Ravnborg .endm
24349148020SSam Ravnborg .endr
24449148020SSam Ravnborg .endif
24549148020SSam Ravnborg 
24649148020SSam Ravnborg .macro	movestack	nr,arg1,arg2,arg3,arg4,arg5
24749148020SSam Ravnborg 	.if	\nr
24849148020SSam Ravnborg 	movestack	(\nr-1),\arg2,\arg3,\arg4,\arg5
24949148020SSam Ravnborg 	move.l	\arg1,-(%sp)
25049148020SSam Ravnborg 	.endif
25149148020SSam Ravnborg .endm
25249148020SSam Ravnborg 
25349148020SSam Ravnborg .macro	printf	bit=-1,string,nr=0,arg1,arg2,arg3,arg4,arg5
25449148020SSam Ravnborg #ifdef FPU_EMU_DEBUG
25549148020SSam Ravnborg 	.data
25649148020SSam Ravnborg .Lpdata\@:
25749148020SSam Ravnborg 	.string	"\string"
25849148020SSam Ravnborg 	.previous
25949148020SSam Ravnborg 
26049148020SSam Ravnborg 	movem.l	%d0/%d1/%a0/%a1,-(%sp)
26149148020SSam Ravnborg 	.if	\bit+1
26249148020SSam Ravnborg #if 0
26349148020SSam Ravnborg 	moveq	#\bit,%d0
26449148020SSam Ravnborg 	andw	#7,%d0
26549148020SSam Ravnborg 	btst	%d0,fp_debugprint+((31-\bit)/8)
26649148020SSam Ravnborg #else
26749148020SSam Ravnborg 	btst	#\bit,fp_debugprint+((31-\bit)/8)
26849148020SSam Ravnborg #endif
26949148020SSam Ravnborg 	jeq	.Lpskip\@
27049148020SSam Ravnborg 	.endif
27149148020SSam Ravnborg 	movestack	\nr,\arg1,\arg2,\arg3,\arg4,\arg5
27249148020SSam Ravnborg 	pea	.Lpdata\@
27349148020SSam Ravnborg 	jsr	printk
27449148020SSam Ravnborg 	lea	((\nr+1)*4,%sp),%sp
27549148020SSam Ravnborg .Lpskip\@:
27649148020SSam Ravnborg 	movem.l	(%sp)+,%d0/%d1/%a0/%a1
27749148020SSam Ravnborg #endif
27849148020SSam Ravnborg .endm
27949148020SSam Ravnborg 
28049148020SSam Ravnborg .macro	printx	bit,fp
28149148020SSam Ravnborg #ifdef FPU_EMU_DEBUG
28249148020SSam Ravnborg 	movem.l	%d0/%a0,-(%sp)
28349148020SSam Ravnborg 	lea	\fp,%a0
28449148020SSam Ravnborg #if 0
28549148020SSam Ravnborg 	moveq	#'+',%d0
28649148020SSam Ravnborg 	tst.w	(%a0)
28749148020SSam Ravnborg 	jeq	.Lx1\@
28849148020SSam Ravnborg 	moveq	#'-',%d0
28949148020SSam Ravnborg .Lx1\@:	printf	\bit," %c",1,%d0
29049148020SSam Ravnborg 	move.l	(4,%a0),%d0
29149148020SSam Ravnborg 	bclr	#31,%d0
29249148020SSam Ravnborg 	jne	.Lx2\@
29349148020SSam Ravnborg 	printf	\bit,"0."
29449148020SSam Ravnborg 	jra	.Lx3\@
29549148020SSam Ravnborg .Lx2\@:	printf	\bit,"1."
29649148020SSam Ravnborg .Lx3\@:	printf	\bit,"%08x%08x",2,%d0,%a0@(8)
29749148020SSam Ravnborg 	move.w	(2,%a0),%d0
29849148020SSam Ravnborg 	ext.l	%d0
29949148020SSam Ravnborg 	printf	\bit,"E%04x",1,%d0
30049148020SSam Ravnborg #else
30149148020SSam Ravnborg 	printf	\bit," %08x%08x%08x",3,%a0@,%a0@(4),%a0@(8)
30249148020SSam Ravnborg #endif
30349148020SSam Ravnborg 	movem.l	(%sp)+,%d0/%a0
30449148020SSam Ravnborg #endif
30549148020SSam Ravnborg .endm
30649148020SSam Ravnborg 
30749148020SSam Ravnborg .macro	debug	instr,args
30849148020SSam Ravnborg #ifdef FPU_EMU_DEBUG
30949148020SSam Ravnborg 	\instr	\args
31049148020SSam Ravnborg #endif
31149148020SSam Ravnborg .endm
31249148020SSam Ravnborg 
31349148020SSam Ravnborg 
31449148020SSam Ravnborg #endif	/* __ASSEMBLY__ */
31549148020SSam Ravnborg 
31649148020SSam Ravnborg #endif	/* _ASM_M68K_SETUP_H */
317