Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  * Floating-point, VMX/Altivec and VSX loads and stores
0004  * for use in instruction emulation.
0005  *
0006  * Copyright 2010 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
0007  */
0008 
0009 #include <asm/processor.h>
0010 #include <asm/ppc_asm.h>
0011 #include <asm/ppc-opcode.h>
0012 #include <asm/reg.h>
0013 #include <asm/asm-offsets.h>
0014 #include <asm/asm-compat.h>
0015 #include <linux/errno.h>
0016 
0017 #define STKFRM  (PPC_MIN_STKFRM + 16)
0018 
0019 /* Get the contents of frN into *p; N is in r3 and p is in r4. */
0020 _GLOBAL(get_fpr)
0021     mflr    r0
0022     mfmsr   r6
0023     ori r7, r6, MSR_FP
0024     MTMSRD(r7)
0025     isync
0026     rlwinm  r3,r3,3,0xf8
0027     bcl 20,31,1f
0028 reg = 0
0029     .rept   32
0030     stfd    reg, 0(r4)
0031     b   2f
0032 reg = reg + 1
0033     .endr
0034 1:  mflr    r5
0035     add r5,r3,r5
0036     mtctr   r5
0037     mtlr    r0
0038     bctr
0039 2:  MTMSRD(r6)
0040     isync
0041     blr
0042 
0043 /* Put the contents of *p into frN; N is in r3 and p is in r4. */
0044 _GLOBAL(put_fpr)
0045     mflr    r0
0046     mfmsr   r6
0047     ori r7, r6, MSR_FP
0048     MTMSRD(r7)
0049     isync
0050     rlwinm  r3,r3,3,0xf8
0051     bcl 20,31,1f
0052 reg = 0
0053     .rept   32
0054     lfd reg, 0(r4)
0055     b   2f
0056 reg = reg + 1
0057     .endr
0058 1:  mflr    r5
0059     add r5,r3,r5
0060     mtctr   r5
0061     mtlr    r0
0062     bctr
0063 2:  MTMSRD(r6)
0064     isync
0065     blr
0066 
0067 #ifdef CONFIG_ALTIVEC
0068 /* Get the contents of vrN into *p; N is in r3 and p is in r4. */
0069 _GLOBAL(get_vr)
0070     mflr    r0
0071     mfmsr   r6
0072     oris    r7, r6, MSR_VEC@h
0073     MTMSRD(r7)
0074     isync
0075     rlwinm  r3,r3,3,0xf8
0076     bcl 20,31,1f
0077 reg = 0
0078     .rept   32
0079     stvx    reg, 0, r4
0080     b   2f
0081 reg = reg + 1
0082     .endr
0083 1:  mflr    r5
0084     add r5,r3,r5
0085     mtctr   r5
0086     mtlr    r0
0087     bctr
0088 2:  MTMSRD(r6)
0089     isync
0090     blr
0091 
0092 /* Put the contents of *p into vrN; N is in r3 and p is in r4. */
0093 _GLOBAL(put_vr)
0094     mflr    r0
0095     mfmsr   r6
0096     oris    r7, r6, MSR_VEC@h
0097     MTMSRD(r7)
0098     isync
0099     rlwinm  r3,r3,3,0xf8
0100     bcl 20,31,1f
0101 reg = 0
0102     .rept   32
0103     lvx reg, 0, r4
0104     b   2f
0105 reg = reg + 1
0106     .endr
0107 1:  mflr    r5
0108     add r5,r3,r5
0109     mtctr   r5
0110     mtlr    r0
0111     bctr
0112 2:  MTMSRD(r6)
0113     isync
0114     blr
0115 #endif /* CONFIG_ALTIVEC */
0116 
0117 #ifdef CONFIG_VSX
0118 /* Get the contents of vsN into vs0; N is in r3. */
0119 _GLOBAL(get_vsr)
0120     mflr    r0
0121     rlwinm  r3,r3,3,0x1f8
0122     bcl 20,31,1f
0123     blr         /* vs0 is already in vs0 */
0124     nop
0125 reg = 1
0126     .rept   63
0127     XXLOR(0,reg,reg)
0128     blr
0129 reg = reg + 1
0130     .endr
0131 1:  mflr    r5
0132     add r5,r3,r5
0133     mtctr   r5
0134     mtlr    r0
0135     bctr
0136 
0137 /* Put the contents of vs0 into vsN; N is in r3. */
0138 _GLOBAL(put_vsr)
0139     mflr    r0
0140     rlwinm  r3,r3,3,0x1f8
0141     bcl 20,31,1f
0142     blr         /* v0 is already in v0 */
0143     nop
0144 reg = 1
0145     .rept   63
0146     XXLOR(reg,0,0)
0147     blr
0148 reg = reg + 1
0149     .endr
0150 1:  mflr    r5
0151     add r5,r3,r5
0152     mtctr   r5
0153     mtlr    r0
0154     bctr
0155 
0156 /* Load VSX reg N from vector doubleword *p.  N is in r3, p in r4. */
0157 _GLOBAL(load_vsrn)
0158     PPC_STLU r1,-STKFRM(r1)
0159     mflr    r0
0160     PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
0161     mfmsr   r6
0162     oris    r7,r6,MSR_VSX@h
0163     cmpwi   cr7,r3,0
0164     li  r8,STKFRM-16
0165     MTMSRD(r7)
0166     isync
0167     beq cr7,1f
0168     STXVD2X(0,R1,R8)
0169 1:  LXVD2X(0,R0,R4)
0170 #ifdef __LITTLE_ENDIAN__
0171     XXSWAPD(0,0)
0172 #endif
0173     beq cr7,4f
0174     bl  put_vsr
0175     LXVD2X(0,R1,R8)
0176 4:  PPC_LL  r0,STKFRM+PPC_LR_STKOFF(r1)
0177     mtlr    r0
0178     MTMSRD(r6)
0179     isync
0180     addi    r1,r1,STKFRM
0181     blr
0182 
0183 /* Store VSX reg N to vector doubleword *p.  N is in r3, p in r4. */
0184 _GLOBAL(store_vsrn)
0185     PPC_STLU r1,-STKFRM(r1)
0186     mflr    r0
0187     PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
0188     mfmsr   r6
0189     oris    r7,r6,MSR_VSX@h
0190     li  r8,STKFRM-16
0191     MTMSRD(r7)
0192     isync
0193     STXVD2X(0,R1,R8)
0194     bl  get_vsr
0195 #ifdef __LITTLE_ENDIAN__
0196     XXSWAPD(0,0)
0197 #endif
0198     STXVD2X(0,R0,R4)
0199     LXVD2X(0,R1,R8)
0200     PPC_LL  r0,STKFRM+PPC_LR_STKOFF(r1)
0201     mtlr    r0
0202     MTMSRD(r6)
0203     isync
0204     mr  r3,r9
0205     addi    r1,r1,STKFRM
0206     blr
0207 #endif /* CONFIG_VSX */
0208 
0209 /* Convert single-precision to double, without disturbing FPRs. */
0210 /* conv_sp_to_dp(float *sp, double *dp) */
0211 _GLOBAL(conv_sp_to_dp)
0212     mfmsr   r6
0213     ori r7, r6, MSR_FP
0214     MTMSRD(r7)
0215     isync
0216     stfd    fr0, -16(r1)
0217     lfs fr0, 0(r3)
0218     stfd    fr0, 0(r4)
0219     lfd fr0, -16(r1)
0220     MTMSRD(r6)
0221     isync
0222     blr
0223 
0224 /* Convert single-precision to double, without disturbing FPRs. */
0225 /* conv_sp_to_dp(double *dp, float *sp) */
0226 _GLOBAL(conv_dp_to_sp)
0227     mfmsr   r6
0228     ori r7, r6, MSR_FP
0229     MTMSRD(r7)
0230     isync
0231     stfd    fr0, -16(r1)
0232     lfd fr0, 0(r3)
0233     stfs    fr0, 0(r4)
0234     lfd fr0, -16(r1)
0235     MTMSRD(r6)
0236     isync
0237     blr