1/* 2 * Floating-point, VMX/Altivec and VSX loads and stores 3 * for use in instruction emulation. 4 * 5 * Copyright 2010 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 10 * 2 of the License, or (at your option) any later version. 11 */ 12 13#include <asm/processor.h> 14#include <asm/ppc_asm.h> 15#include <asm/ppc-opcode.h> 16#include <asm/reg.h> 17#include <asm/asm-offsets.h> 18#include <linux/errno.h> 19 20#ifdef CONFIG_PPC_FPU 21 22#define STKFRM (PPC_MIN_STKFRM + 16) 23 24/* Get the contents of frN into *p; N is in r3 and p is in r4. */ 25_GLOBAL(get_fpr) 26 mflr r0 27 mfmsr r6 28 ori r7, r6, MSR_FP 29 MTMSRD(r7) 30 isync 31 rlwinm r3,r3,3,0xf8 32 bcl 20,31,1f 33reg = 0 34 .rept 32 35 stfd reg, 0(r4) 36 b 2f 37reg = reg + 1 38 .endr 391: mflr r5 40 add r5,r3,r5 41 mtctr r5 42 mtlr r0 43 bctr 442: MTMSRD(r6) 45 isync 46 blr 47 48/* Put the contents of *p into frN; N is in r3 and p is in r4. */ 49_GLOBAL(put_fpr) 50 mflr r0 51 mfmsr r6 52 ori r7, r6, MSR_FP 53 MTMSRD(r7) 54 isync 55 rlwinm r3,r3,3,0xf8 56 bcl 20,31,1f 57reg = 0 58 .rept 32 59 lfd reg, 0(r4) 60 b 2f 61reg = reg + 1 62 .endr 631: mflr r5 64 add r5,r3,r5 65 mtctr r5 66 mtlr r0 67 bctr 682: MTMSRD(r6) 69 isync 70 blr 71 72#ifdef CONFIG_ALTIVEC 73/* Get the contents of vrN into *p; N is in r3 and p is in r4. */ 74_GLOBAL(get_vr) 75 mflr r0 76 mfmsr r6 77 oris r7, r6, MSR_VEC@h 78 MTMSRD(r7) 79 isync 80 rlwinm r3,r3,3,0xf8 81 bcl 20,31,1f 82reg = 0 83 .rept 32 84 stvx reg, 0, r4 85 b 2f 86reg = reg + 1 87 .endr 881: mflr r5 89 add r5,r3,r5 90 mtctr r5 91 mtlr r0 92 bctr 932: MTMSRD(r6) 94 isync 95 blr 96 97/* Put the contents of *p into vrN; N is in r3 and p is in r4. */ 98_GLOBAL(put_vr) 99 mflr r0 100 mfmsr r6 101 oris r7, r6, MSR_VEC@h 102 MTMSRD(r7) 103 isync 104 rlwinm r3,r3,3,0xf8 105 bcl 20,31,1f 106reg = 0 107 .rept 32 108 lvx reg, 0, r4 109 b 2f 110reg = reg + 1 111 .endr 1121: mflr r5 113 add r5,r3,r5 114 mtctr r5 115 mtlr r0 116 bctr 1172: MTMSRD(r6) 118 isync 119 blr 120#endif /* CONFIG_ALTIVEC */ 121 122#ifdef CONFIG_VSX 123/* Get the contents of vsN into vs0; N is in r3. */ 124_GLOBAL(get_vsr) 125 mflr r0 126 rlwinm r3,r3,3,0x1f8 127 bcl 20,31,1f 128 blr /* vs0 is already in vs0 */ 129 nop 130reg = 1 131 .rept 63 132 XXLOR(0,reg,reg) 133 blr 134reg = reg + 1 135 .endr 1361: mflr r5 137 add r5,r3,r5 138 mtctr r5 139 mtlr r0 140 bctr 141 142/* Put the contents of vs0 into vsN; N is in r3. */ 143_GLOBAL(put_vsr) 144 mflr r0 145 rlwinm r3,r3,3,0x1f8 146 bcl 20,31,1f 147 blr /* v0 is already in v0 */ 148 nop 149reg = 1 150 .rept 63 151 XXLOR(reg,0,0) 152 blr 153reg = reg + 1 154 .endr 1551: mflr r5 156 add r5,r3,r5 157 mtctr r5 158 mtlr r0 159 bctr 160 161/* Load VSX reg N from vector doubleword *p. N is in r3, p in r4. */ 162_GLOBAL(load_vsrn) 163 PPC_STLU r1,-STKFRM(r1) 164 mflr r0 165 PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) 166 mfmsr r6 167 oris r7,r6,MSR_VSX@h 168 cmpwi cr7,r3,0 169 li r8,STKFRM-16 170 MTMSRD(r7) 171 isync 172 beq cr7,1f 173 STXVD2X(0,R1,R8) 1741: LXVD2X(0,R0,R4) 175#ifdef __LITTLE_ENDIAN__ 176 XXSWAPD(0,0) 177#endif 178 beq cr7,4f 179 bl put_vsr 180 LXVD2X(0,R1,R8) 1814: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) 182 mtlr r0 183 MTMSRD(r6) 184 isync 185 addi r1,r1,STKFRM 186 blr 187 188/* Store VSX reg N to vector doubleword *p. N is in r3, p in r4. */ 189_GLOBAL(store_vsrn) 190 PPC_STLU r1,-STKFRM(r1) 191 mflr r0 192 PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) 193 mfmsr r6 194 oris r7,r6,MSR_VSX@h 195 li r8,STKFRM-16 196 MTMSRD(r7) 197 isync 198 STXVD2X(0,R1,R8) 199 bl get_vsr 200#ifdef __LITTLE_ENDIAN__ 201 XXSWAPD(0,0) 202#endif 203 STXVD2X(0,R0,R4) 204 LXVD2X(0,R1,R8) 205 PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) 206 mtlr r0 207 MTMSRD(r6) 208 isync 209 mr r3,r9 210 addi r1,r1,STKFRM 211 blr 212#endif /* CONFIG_VSX */ 213 214/* Convert single-precision to double, without disturbing FPRs. */ 215/* conv_sp_to_dp(float *sp, double *dp) */ 216_GLOBAL(conv_sp_to_dp) 217 mfmsr r6 218 ori r7, r6, MSR_FP 219 MTMSRD(r7) 220 isync 221 stfd fr0, -16(r1) 222 lfs fr0, 0(r3) 223 stfd fr0, 0(r4) 224 lfd fr0, -16(r1) 225 MTMSRD(r6) 226 isync 227 blr 228 229/* Convert single-precision to double, without disturbing FPRs. */ 230/* conv_sp_to_dp(double *dp, float *sp) */ 231_GLOBAL(conv_dp_to_sp) 232 mfmsr r6 233 ori r7, r6, MSR_FP 234 MTMSRD(r7) 235 isync 236 stfd fr0, -16(r1) 237 lfd fr0, 0(r3) 238 stfs fr0, 0(r4) 239 lfd fr0, -16(r1) 240 MTMSRD(r6) 241 isync 242 blr 243 244#endif /* CONFIG_PPC_FPU */ 245