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 <asm/asm-compat.h> 19#include <linux/errno.h> 20 21#ifdef CONFIG_PPC_FPU 22 23#define STKFRM (PPC_MIN_STKFRM + 16) 24 25/* Get the contents of frN into *p; N is in r3 and p is in r4. */ 26_GLOBAL(get_fpr) 27 mflr r0 28 mfmsr r6 29 ori r7, r6, MSR_FP 30 MTMSRD(r7) 31 isync 32 rlwinm r3,r3,3,0xf8 33 bcl 20,31,1f 34reg = 0 35 .rept 32 36 stfd reg, 0(r4) 37 b 2f 38reg = reg + 1 39 .endr 401: mflr r5 41 add r5,r3,r5 42 mtctr r5 43 mtlr r0 44 bctr 452: MTMSRD(r6) 46 isync 47 blr 48 49/* Put the contents of *p into frN; N is in r3 and p is in r4. */ 50_GLOBAL(put_fpr) 51 mflr r0 52 mfmsr r6 53 ori r7, r6, MSR_FP 54 MTMSRD(r7) 55 isync 56 rlwinm r3,r3,3,0xf8 57 bcl 20,31,1f 58reg = 0 59 .rept 32 60 lfd reg, 0(r4) 61 b 2f 62reg = reg + 1 63 .endr 641: mflr r5 65 add r5,r3,r5 66 mtctr r5 67 mtlr r0 68 bctr 692: MTMSRD(r6) 70 isync 71 blr 72 73#ifdef CONFIG_ALTIVEC 74/* Get the contents of vrN into *p; N is in r3 and p is in r4. */ 75_GLOBAL(get_vr) 76 mflr r0 77 mfmsr r6 78 oris r7, r6, MSR_VEC@h 79 MTMSRD(r7) 80 isync 81 rlwinm r3,r3,3,0xf8 82 bcl 20,31,1f 83reg = 0 84 .rept 32 85 stvx reg, 0, r4 86 b 2f 87reg = reg + 1 88 .endr 891: mflr r5 90 add r5,r3,r5 91 mtctr r5 92 mtlr r0 93 bctr 942: MTMSRD(r6) 95 isync 96 blr 97 98/* Put the contents of *p into vrN; N is in r3 and p is in r4. */ 99_GLOBAL(put_vr) 100 mflr r0 101 mfmsr r6 102 oris r7, r6, MSR_VEC@h 103 MTMSRD(r7) 104 isync 105 rlwinm r3,r3,3,0xf8 106 bcl 20,31,1f 107reg = 0 108 .rept 32 109 lvx reg, 0, r4 110 b 2f 111reg = reg + 1 112 .endr 1131: mflr r5 114 add r5,r3,r5 115 mtctr r5 116 mtlr r0 117 bctr 1182: MTMSRD(r6) 119 isync 120 blr 121#endif /* CONFIG_ALTIVEC */ 122 123#ifdef CONFIG_VSX 124/* Get the contents of vsN into vs0; N is in r3. */ 125_GLOBAL(get_vsr) 126 mflr r0 127 rlwinm r3,r3,3,0x1f8 128 bcl 20,31,1f 129 blr /* vs0 is already in vs0 */ 130 nop 131reg = 1 132 .rept 63 133 XXLOR(0,reg,reg) 134 blr 135reg = reg + 1 136 .endr 1371: mflr r5 138 add r5,r3,r5 139 mtctr r5 140 mtlr r0 141 bctr 142 143/* Put the contents of vs0 into vsN; N is in r3. */ 144_GLOBAL(put_vsr) 145 mflr r0 146 rlwinm r3,r3,3,0x1f8 147 bcl 20,31,1f 148 blr /* v0 is already in v0 */ 149 nop 150reg = 1 151 .rept 63 152 XXLOR(reg,0,0) 153 blr 154reg = reg + 1 155 .endr 1561: mflr r5 157 add r5,r3,r5 158 mtctr r5 159 mtlr r0 160 bctr 161 162/* Load VSX reg N from vector doubleword *p. N is in r3, p in r4. */ 163_GLOBAL(load_vsrn) 164 PPC_STLU r1,-STKFRM(r1) 165 mflr r0 166 PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) 167 mfmsr r6 168 oris r7,r6,MSR_VSX@h 169 cmpwi cr7,r3,0 170 li r8,STKFRM-16 171 MTMSRD(r7) 172 isync 173 beq cr7,1f 174 STXVD2X(0,R1,R8) 1751: LXVD2X(0,R0,R4) 176#ifdef __LITTLE_ENDIAN__ 177 XXSWAPD(0,0) 178#endif 179 beq cr7,4f 180 bl put_vsr 181 LXVD2X(0,R1,R8) 1824: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) 183 mtlr r0 184 MTMSRD(r6) 185 isync 186 addi r1,r1,STKFRM 187 blr 188 189/* Store VSX reg N to vector doubleword *p. N is in r3, p in r4. */ 190_GLOBAL(store_vsrn) 191 PPC_STLU r1,-STKFRM(r1) 192 mflr r0 193 PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) 194 mfmsr r6 195 oris r7,r6,MSR_VSX@h 196 li r8,STKFRM-16 197 MTMSRD(r7) 198 isync 199 STXVD2X(0,R1,R8) 200 bl get_vsr 201#ifdef __LITTLE_ENDIAN__ 202 XXSWAPD(0,0) 203#endif 204 STXVD2X(0,R0,R4) 205 LXVD2X(0,R1,R8) 206 PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) 207 mtlr r0 208 MTMSRD(r6) 209 isync 210 mr r3,r9 211 addi r1,r1,STKFRM 212 blr 213#endif /* CONFIG_VSX */ 214 215/* Convert single-precision to double, without disturbing FPRs. */ 216/* conv_sp_to_dp(float *sp, double *dp) */ 217_GLOBAL(conv_sp_to_dp) 218 mfmsr r6 219 ori r7, r6, MSR_FP 220 MTMSRD(r7) 221 isync 222 stfd fr0, -16(r1) 223 lfs fr0, 0(r3) 224 stfd fr0, 0(r4) 225 lfd fr0, -16(r1) 226 MTMSRD(r6) 227 isync 228 blr 229 230/* Convert single-precision to double, without disturbing FPRs. */ 231/* conv_sp_to_dp(double *dp, float *sp) */ 232_GLOBAL(conv_dp_to_sp) 233 mfmsr r6 234 ori r7, r6, MSR_FP 235 MTMSRD(r7) 236 isync 237 stfd fr0, -16(r1) 238 lfd fr0, 0(r3) 239 stfs fr0, 0(r4) 240 lfd fr0, -16(r1) 241 MTMSRD(r6) 242 isync 243 blr 244 245#endif /* CONFIG_PPC_FPU */ 246