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 .macro inst32 op 25reg = 0 26 .rept 32 2720: \op reg,0,r4 28 b 3f 29 EX_TABLE(20b,99f) 30reg = reg + 1 31 .endr 32 .endm 33 34/* Get the contents of frN into fr0; N is in r3. */ 35_GLOBAL(get_fpr) 36 mflr r0 37 rlwinm r3,r3,3,0xf8 38 bcl 20,31,1f 39 blr /* fr0 is already in fr0 */ 40 nop 41reg = 1 42 .rept 31 43 fmr fr0,reg 44 blr 45reg = reg + 1 46 .endr 471: mflr r5 48 add r5,r3,r5 49 mtctr r5 50 mtlr r0 51 bctr 52 53/* Put the contents of fr0 into frN; N is in r3. */ 54_GLOBAL(put_fpr) 55 mflr r0 56 rlwinm r3,r3,3,0xf8 57 bcl 20,31,1f 58 blr /* fr0 is already in fr0 */ 59 nop 60reg = 1 61 .rept 31 62 fmr reg,fr0 63 blr 64reg = reg + 1 65 .endr 661: mflr r5 67 add r5,r3,r5 68 mtctr r5 69 mtlr r0 70 bctr 71 72/* Load FP reg N from float at *p. N is in r3, p in r4. */ 73_GLOBAL(do_lfs) 74 PPC_STLU r1,-STKFRM(r1) 75 mflr r0 76 PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) 77 mfmsr r6 78 ori r7,r6,MSR_FP 79 cmpwi cr7,r3,0 80 MTMSRD(r7) 81 isync 82 beq cr7,1f 83 stfd fr0,STKFRM-16(r1) 841: li r9,-EFAULT 852: lfs fr0,0(r4) 86 li r9,0 873: bl put_fpr 88 beq cr7,4f 89 lfd fr0,STKFRM-16(r1) 904: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) 91 mtlr r0 92 MTMSRD(r6) 93 isync 94 mr r3,r9 95 addi r1,r1,STKFRM 96 blr 97 EX_TABLE(2b,3b) 98 99/* Load FP reg N from double at *p. N is in r3, p in r4. */ 100_GLOBAL(do_lfd) 101 PPC_STLU r1,-STKFRM(r1) 102 mflr r0 103 PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) 104 mfmsr r6 105 ori r7,r6,MSR_FP 106 cmpwi cr7,r3,0 107 MTMSRD(r7) 108 isync 109 beq cr7,1f 110 stfd fr0,STKFRM-16(r1) 1111: li r9,-EFAULT 1122: lfd fr0,0(r4) 113 li r9,0 1143: beq cr7,4f 115 bl put_fpr 116 lfd fr0,STKFRM-16(r1) 1174: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) 118 mtlr r0 119 MTMSRD(r6) 120 isync 121 mr r3,r9 122 addi r1,r1,STKFRM 123 blr 124 EX_TABLE(2b,3b) 125 126/* Store FP reg N to float at *p. N is in r3, p in r4. */ 127_GLOBAL(do_stfs) 128 PPC_STLU r1,-STKFRM(r1) 129 mflr r0 130 PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) 131 mfmsr r6 132 ori r7,r6,MSR_FP 133 cmpwi cr7,r3,0 134 MTMSRD(r7) 135 isync 136 beq cr7,1f 137 stfd fr0,STKFRM-16(r1) 138 bl get_fpr 1391: li r9,-EFAULT 1402: stfs fr0,0(r4) 141 li r9,0 1423: beq cr7,4f 143 lfd fr0,STKFRM-16(r1) 1444: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) 145 mtlr r0 146 MTMSRD(r6) 147 isync 148 mr r3,r9 149 addi r1,r1,STKFRM 150 blr 151 EX_TABLE(2b,3b) 152 153/* Store FP reg N to double at *p. N is in r3, p in r4. */ 154_GLOBAL(do_stfd) 155 PPC_STLU r1,-STKFRM(r1) 156 mflr r0 157 PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) 158 mfmsr r6 159 ori r7,r6,MSR_FP 160 cmpwi cr7,r3,0 161 MTMSRD(r7) 162 isync 163 beq cr7,1f 164 stfd fr0,STKFRM-16(r1) 165 bl get_fpr 1661: li r9,-EFAULT 1672: stfd fr0,0(r4) 168 li r9,0 1693: beq cr7,4f 170 lfd fr0,STKFRM-16(r1) 1714: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) 172 mtlr r0 173 MTMSRD(r6) 174 isync 175 mr r3,r9 176 addi r1,r1,STKFRM 177 blr 178 EX_TABLE(2b,3b) 179 180#ifdef CONFIG_ALTIVEC 181/* Get the contents of vrN into v0; N is in r3. */ 182_GLOBAL(get_vr) 183 mflr r0 184 rlwinm r3,r3,3,0xf8 185 bcl 20,31,1f 186 blr /* v0 is already in v0 */ 187 nop 188reg = 1 189 .rept 31 190 vor v0,reg,reg /* assembler doesn't know vmr? */ 191 blr 192reg = reg + 1 193 .endr 1941: mflr r5 195 add r5,r3,r5 196 mtctr r5 197 mtlr r0 198 bctr 199 200/* Put the contents of v0 into vrN; N is in r3. */ 201_GLOBAL(put_vr) 202 mflr r0 203 rlwinm r3,r3,3,0xf8 204 bcl 20,31,1f 205 blr /* v0 is already in v0 */ 206 nop 207reg = 1 208 .rept 31 209 vor reg,v0,v0 210 blr 211reg = reg + 1 212 .endr 2131: mflr r5 214 add r5,r3,r5 215 mtctr r5 216 mtlr r0 217 bctr 218 219/* Load vector reg N from *p. N is in r3, p in r4. */ 220_GLOBAL(do_lvx) 221 PPC_STLU r1,-STKFRM(r1) 222 mflr r0 223 PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) 224 mfmsr r6 225 oris r7,r6,MSR_VEC@h 226 cmpwi cr7,r3,0 227 li r8,STKFRM-16 228 MTMSRD(r7) 229 isync 230 beq cr7,1f 231 stvx v0,r1,r8 2321: li r9,-EFAULT 2332: lvx v0,0,r4 234 li r9,0 2353: beq cr7,4f 236 bl put_vr 237 lvx v0,r1,r8 2384: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) 239 mtlr r0 240 MTMSRD(r6) 241 isync 242 mr r3,r9 243 addi r1,r1,STKFRM 244 blr 245 EX_TABLE(2b,3b) 246 247/* Store vector reg N to *p. N is in r3, p in r4. */ 248_GLOBAL(do_stvx) 249 PPC_STLU r1,-STKFRM(r1) 250 mflr r0 251 PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) 252 mfmsr r6 253 oris r7,r6,MSR_VEC@h 254 cmpwi cr7,r3,0 255 li r8,STKFRM-16 256 MTMSRD(r7) 257 isync 258 beq cr7,1f 259 stvx v0,r1,r8 260 bl get_vr 2611: li r9,-EFAULT 2622: stvx v0,0,r4 263 li r9,0 2643: beq cr7,4f 265 lvx v0,r1,r8 2664: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) 267 mtlr r0 268 MTMSRD(r6) 269 isync 270 mr r3,r9 271 addi r1,r1,STKFRM 272 blr 273 EX_TABLE(2b,3b) 274#endif /* CONFIG_ALTIVEC */ 275 276#ifdef CONFIG_VSX 277/* Get the contents of vsN into vs0; N is in r3. */ 278_GLOBAL(get_vsr) 279 mflr r0 280 rlwinm r3,r3,3,0x1f8 281 bcl 20,31,1f 282 blr /* vs0 is already in vs0 */ 283 nop 284reg = 1 285 .rept 63 286 XXLOR(0,reg,reg) 287 blr 288reg = reg + 1 289 .endr 2901: mflr r5 291 add r5,r3,r5 292 mtctr r5 293 mtlr r0 294 bctr 295 296/* Put the contents of vs0 into vsN; N is in r3. */ 297_GLOBAL(put_vsr) 298 mflr r0 299 rlwinm r3,r3,3,0x1f8 300 bcl 20,31,1f 301 blr /* v0 is already in v0 */ 302 nop 303reg = 1 304 .rept 63 305 XXLOR(reg,0,0) 306 blr 307reg = reg + 1 308 .endr 3091: mflr r5 310 add r5,r3,r5 311 mtctr r5 312 mtlr r0 313 bctr 314 315/* Load VSX reg N from vector doubleword *p. N is in r3, p in r4. */ 316_GLOBAL(do_lxvd2x) 317 PPC_STLU r1,-STKFRM(r1) 318 mflr r0 319 PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) 320 mfmsr r6 321 oris r7,r6,MSR_VSX@h 322 cmpwi cr7,r3,0 323 li r8,STKFRM-16 324 MTMSRD(r7) 325 isync 326 beq cr7,1f 327 STXVD2X(0,R1,R8) 3281: li r9,-EFAULT 3292: LXVD2X(0,R0,R4) 330 li r9,0 3313: beq cr7,4f 332 bl put_vsr 333 LXVD2X(0,R1,R8) 3344: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) 335 mtlr r0 336 MTMSRD(r6) 337 isync 338 mr r3,r9 339 addi r1,r1,STKFRM 340 blr 341 EX_TABLE(2b,3b) 342 343/* Store VSX reg N to vector doubleword *p. N is in r3, p in r4. */ 344_GLOBAL(do_stxvd2x) 345 PPC_STLU r1,-STKFRM(r1) 346 mflr r0 347 PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) 348 mfmsr r6 349 oris r7,r6,MSR_VSX@h 350 cmpwi cr7,r3,0 351 li r8,STKFRM-16 352 MTMSRD(r7) 353 isync 354 beq cr7,1f 355 STXVD2X(0,R1,R8) 356 bl get_vsr 3571: li r9,-EFAULT 3582: STXVD2X(0,R0,R4) 359 li r9,0 3603: beq cr7,4f 361 LXVD2X(0,R1,R8) 3624: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) 363 mtlr r0 364 MTMSRD(r6) 365 isync 366 mr r3,r9 367 addi r1,r1,STKFRM 368 blr 369 EX_TABLE(2b,3b) 370 371#endif /* CONFIG_VSX */ 372 373#endif /* CONFIG_PPC_FPU */ 374