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
|