 05d77ac90c
			
		
	
	
	05d77ac90c
	
	
	
		
			
			Neither lfs nor stfs touch the fpscr, so remove the restore/save of it around them. Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
		
			
				
	
	
		
			283 lines
		
	
	
	
		
			5.7 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			283 lines
		
	
	
	
		
			5.7 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /*
 | |
|  *  FPU helper code to use FPU operations from inside the kernel
 | |
|  *
 | |
|  *    Copyright (C) 2010 Alexander Graf (agraf@suse.de)
 | |
|  *
 | |
|  *  This program is free software; you can redistribute it and/or
 | |
|  *  modify it under the terms of the GNU General Public License
 | |
|  *  as published by the Free Software Foundation; either version
 | |
|  *  2 of the License, or (at your option) any later version.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include <asm/reg.h>
 | |
| #include <asm/page.h>
 | |
| #include <asm/mmu.h>
 | |
| #include <asm/pgtable.h>
 | |
| #include <asm/cputable.h>
 | |
| #include <asm/cache.h>
 | |
| #include <asm/thread_info.h>
 | |
| #include <asm/ppc_asm.h>
 | |
| #include <asm/asm-offsets.h>
 | |
| 
 | |
| /* Instructions operating on single parameters */
 | |
| 
 | |
| /*
 | |
|  * Single operation with one input operand
 | |
|  *
 | |
|  * R3 = (double*)&fpscr
 | |
|  * R4 = (short*)&result
 | |
|  * R5 = (short*)¶m1
 | |
|  */
 | |
| #define FPS_ONE_IN(name) 					\
 | |
| _GLOBAL(fps_ ## name);							\
 | |
| 	lfd	0,0(r3);		/* load up fpscr value */	\
 | |
| 	MTFSF_L(0);							\
 | |
| 	lfs	0,0(r5);						\
 | |
| 									\
 | |
| 	name	0,0;							\
 | |
| 									\
 | |
| 	stfs	0,0(r4);						\
 | |
| 	mffs	0;							\
 | |
| 	stfd	0,0(r3);	/* save new fpscr value */	\
 | |
| 	blr
 | |
| 
 | |
| /*
 | |
|  * Single operation with two input operands
 | |
|  *
 | |
|  * R3 = (double*)&fpscr
 | |
|  * R4 = (short*)&result
 | |
|  * R5 = (short*)¶m1
 | |
|  * R6 = (short*)¶m2
 | |
|  */
 | |
| #define FPS_TWO_IN(name) 					\
 | |
| _GLOBAL(fps_ ## name);							\
 | |
| 	lfd	0,0(r3);		/* load up fpscr value */	\
 | |
| 	MTFSF_L(0);							\
 | |
| 	lfs	0,0(r5);						\
 | |
| 	lfs	1,0(r6);						\
 | |
| 									\
 | |
| 	name	0,0,1;							\
 | |
| 									\
 | |
| 	stfs	0,0(r4);						\
 | |
| 	mffs	0;							\
 | |
| 	stfd	0,0(r3);		/* save new fpscr value */	\
 | |
| 	blr
 | |
| 
 | |
| /*
 | |
|  * Single operation with three input operands
 | |
|  *
 | |
|  * R3 = (double*)&fpscr
 | |
|  * R4 = (short*)&result
 | |
|  * R5 = (short*)¶m1
 | |
|  * R6 = (short*)¶m2
 | |
|  * R7 = (short*)¶m3
 | |
|  */
 | |
| #define FPS_THREE_IN(name) 					\
 | |
| _GLOBAL(fps_ ## name);							\
 | |
| 	lfd	0,0(r3);		/* load up fpscr value */	\
 | |
| 	MTFSF_L(0);							\
 | |
| 	lfs	0,0(r5);						\
 | |
| 	lfs	1,0(r6);						\
 | |
| 	lfs	2,0(r7);						\
 | |
| 									\
 | |
| 	name	0,0,1,2;						\
 | |
| 									\
 | |
| 	stfs	0,0(r4);						\
 | |
| 	mffs	0;							\
 | |
| 	stfd	0,0(r3);		/* save new fpscr value */	\
 | |
| 	blr
 | |
| 
 | |
| FPS_ONE_IN(fres)
 | |
| FPS_ONE_IN(frsqrte)
 | |
| FPS_ONE_IN(fsqrts)
 | |
| FPS_TWO_IN(fadds)
 | |
| FPS_TWO_IN(fdivs)
 | |
| FPS_TWO_IN(fmuls)
 | |
| FPS_TWO_IN(fsubs)
 | |
| FPS_THREE_IN(fmadds)
 | |
| FPS_THREE_IN(fmsubs)
 | |
| FPS_THREE_IN(fnmadds)
 | |
| FPS_THREE_IN(fnmsubs)
 | |
| FPS_THREE_IN(fsel)
 | |
| 
 | |
| 
 | |
| /* Instructions operating on double parameters */
 | |
| 
 | |
| /*
 | |
|  * Beginning of double instruction processing
 | |
|  *
 | |
|  * R3 = (double*)&fpscr
 | |
|  * R4 = (u32*)&cr
 | |
|  * R5 = (double*)&result
 | |
|  * R6 = (double*)¶m1
 | |
|  * R7 = (double*)¶m2 [load_two]
 | |
|  * R8 = (double*)¶m3 [load_three]
 | |
|  * LR = instruction call function
 | |
|  */
 | |
| fpd_load_three:
 | |
| 	lfd	2,0(r8)			/* load param3 */
 | |
| fpd_load_two:
 | |
| 	lfd	1,0(r7)			/* load param2 */
 | |
| fpd_load_one:
 | |
| 	lfd	0,0(r6)			/* load param1 */
 | |
| fpd_load_none:
 | |
| 	lfd	3,0(r3)			/* load up fpscr value */
 | |
| 	MTFSF_L(3)
 | |
| 	lwz	r6, 0(r4)		/* load cr */
 | |
| 	mtcr	r6
 | |
| 	blr
 | |
| 
 | |
| /*
 | |
|  * End of double instruction processing
 | |
|  *
 | |
|  * R3 = (double*)&fpscr
 | |
|  * R4 = (u32*)&cr
 | |
|  * R5 = (double*)&result
 | |
|  * LR = caller of instruction call function
 | |
|  */
 | |
| fpd_return:
 | |
| 	mfcr	r6
 | |
| 	stfd	0,0(r5)			/* save result */
 | |
| 	mffs	0
 | |
| 	stfd	0,0(r3)			/* save new fpscr value */
 | |
| 	stw	r6,0(r4)		/* save new cr value */
 | |
| 	blr
 | |
| 
 | |
| /*
 | |
|  * Double operation with no input operand
 | |
|  *
 | |
|  * R3 = (double*)&fpscr
 | |
|  * R4 = (u32*)&cr
 | |
|  * R5 = (double*)&result
 | |
|  */
 | |
| #define FPD_NONE_IN(name) 						\
 | |
| _GLOBAL(fpd_ ## name);							\
 | |
| 	mflr	r12;							\
 | |
| 	bl	fpd_load_none;						\
 | |
| 	mtlr	r12;							\
 | |
| 									\
 | |
| 	name.	0;			/* call instruction */		\
 | |
| 	b	fpd_return
 | |
| 
 | |
| /*
 | |
|  * Double operation with one input operand
 | |
|  *
 | |
|  * R3 = (double*)&fpscr
 | |
|  * R4 = (u32*)&cr
 | |
|  * R5 = (double*)&result
 | |
|  * R6 = (double*)¶m1
 | |
|  */
 | |
| #define FPD_ONE_IN(name) 						\
 | |
| _GLOBAL(fpd_ ## name);							\
 | |
| 	mflr	r12;							\
 | |
| 	bl	fpd_load_one;						\
 | |
| 	mtlr	r12;							\
 | |
| 									\
 | |
| 	name.	0,0;			/* call instruction */		\
 | |
| 	b	fpd_return
 | |
| 
 | |
| /*
 | |
|  * Double operation with two input operands
 | |
|  *
 | |
|  * R3 = (double*)&fpscr
 | |
|  * R4 = (u32*)&cr
 | |
|  * R5 = (double*)&result
 | |
|  * R6 = (double*)¶m1
 | |
|  * R7 = (double*)¶m2
 | |
|  * R8 = (double*)¶m3
 | |
|  */
 | |
| #define FPD_TWO_IN(name) 						\
 | |
| _GLOBAL(fpd_ ## name);							\
 | |
| 	mflr	r12;							\
 | |
| 	bl	fpd_load_two;						\
 | |
| 	mtlr	r12;							\
 | |
| 									\
 | |
| 	name.	0,0,1;			/* call instruction */		\
 | |
| 	b	fpd_return
 | |
| 
 | |
| /*
 | |
|  * CR Double operation with two input operands
 | |
|  *
 | |
|  * R3 = (double*)&fpscr
 | |
|  * R4 = (u32*)&cr
 | |
|  * R5 = (double*)¶m1
 | |
|  * R6 = (double*)¶m2
 | |
|  * R7 = (double*)¶m3
 | |
|  */
 | |
| #define FPD_TWO_IN_CR(name)						\
 | |
| _GLOBAL(fpd_ ## name);							\
 | |
| 	lfd	1,0(r6);		/* load param2 */		\
 | |
| 	lfd	0,0(r5);		/* load param1 */		\
 | |
| 	lfd	3,0(r3);		/* load up fpscr value */	\
 | |
| 	MTFSF_L(3);							\
 | |
| 	lwz	r6, 0(r4);		/* load cr */			\
 | |
| 	mtcr	r6;							\
 | |
| 									\
 | |
| 	name	0,0,1;			/* call instruction */		\
 | |
| 	mfcr	r6;							\
 | |
| 	mffs	0;							\
 | |
| 	stfd	0,0(r3);		/* save new fpscr value */	\
 | |
| 	stw	r6,0(r4);		/* save new cr value */		\
 | |
| 	blr
 | |
| 
 | |
| /*
 | |
|  * Double operation with three input operands
 | |
|  *
 | |
|  * R3 = (double*)&fpscr
 | |
|  * R4 = (u32*)&cr
 | |
|  * R5 = (double*)&result
 | |
|  * R6 = (double*)¶m1
 | |
|  * R7 = (double*)¶m2
 | |
|  * R8 = (double*)¶m3
 | |
|  */
 | |
| #define FPD_THREE_IN(name) 						\
 | |
| _GLOBAL(fpd_ ## name);							\
 | |
| 	mflr	r12;							\
 | |
| 	bl	fpd_load_three;						\
 | |
| 	mtlr	r12;							\
 | |
| 									\
 | |
| 	name.	0,0,1,2;		/* call instruction */		\
 | |
| 	b	fpd_return
 | |
| 
 | |
| FPD_ONE_IN(fsqrts)
 | |
| FPD_ONE_IN(frsqrtes)
 | |
| FPD_ONE_IN(fres)
 | |
| FPD_ONE_IN(frsp)
 | |
| FPD_ONE_IN(fctiw)
 | |
| FPD_ONE_IN(fctiwz)
 | |
| FPD_ONE_IN(fsqrt)
 | |
| FPD_ONE_IN(fre)
 | |
| FPD_ONE_IN(frsqrte)
 | |
| FPD_ONE_IN(fneg)
 | |
| FPD_ONE_IN(fabs)
 | |
| FPD_TWO_IN(fadds)
 | |
| FPD_TWO_IN(fsubs)
 | |
| FPD_TWO_IN(fdivs)
 | |
| FPD_TWO_IN(fmuls)
 | |
| FPD_TWO_IN_CR(fcmpu)
 | |
| FPD_TWO_IN(fcpsgn)
 | |
| FPD_TWO_IN(fdiv)
 | |
| FPD_TWO_IN(fadd)
 | |
| FPD_TWO_IN(fmul)
 | |
| FPD_TWO_IN_CR(fcmpo)
 | |
| FPD_TWO_IN(fsub)
 | |
| FPD_THREE_IN(fmsubs)
 | |
| FPD_THREE_IN(fmadds)
 | |
| FPD_THREE_IN(fnmsubs)
 | |
| FPD_THREE_IN(fnmadds)
 | |
| FPD_THREE_IN(fsel)
 | |
| FPD_THREE_IN(fmsub)
 | |
| FPD_THREE_IN(fmadd)
 | |
| FPD_THREE_IN(fnmsub)
 | |
| FPD_THREE_IN(fnmadd)
 | |
| 
 | |
| _GLOBAL(kvm_cvt_fd)
 | |
| 	lfs	0,0(r3)
 | |
| 	stfd	0,0(r4)
 | |
| 	blr
 | |
| 
 | |
| _GLOBAL(kvm_cvt_df)
 | |
| 	lfd	0,0(r3)
 | |
| 	stfs	0,0(r4)
 | |
| 	blr
 |