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 extab instr,handler 25 .section __ex_table,"a" 26 PPC_LONG \instr,\handler 27 .previous 28 .endm 29 30 .macro inst32 op 31reg = 0 32 .rept 32 3320: \op reg,0,r4 34 b 3f 35 extab 20b,99f 36reg = reg + 1 37 .endr 38 .endm 39 40/* Get the contents of frN into fr0; N is in r3. */ 41_GLOBAL(get_fpr) 42 mflr r0 43 rlwinm r3,r3,3,0xf8 44 bcl 20,31,1f 45 blr /* fr0 is already in fr0 */ 46 nop 47reg = 1 48 .rept 31 49 fmr fr0,reg 50 blr 51reg = reg + 1 52 .endr 531: mflr r5 54 add r5,r3,r5 55 mtctr r5 56 mtlr r0 57 bctr 58 59/* Put the contents of fr0 into frN; N is in r3. */ 60_GLOBAL(put_fpr) 61 mflr r0 62 rlwinm r3,r3,3,0xf8 63 bcl 20,31,1f 64 blr /* fr0 is already in fr0 */ 65 nop 66reg = 1 67 .rept 31 68 fmr reg,fr0 69 blr 70reg = reg + 1 71 .endr 721: mflr r5 73 add r5,r3,r5 74 mtctr r5 75 mtlr r0 76 bctr 77 78/* Load FP reg N from float at *p. N is in r3, p in r4. */ 79_GLOBAL(do_lfs) 80 PPC_STLU r1,-STKFRM(r1) 81 mflr r0 82 PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) 83 mfmsr r6 84 ori r7,r6,MSR_FP 85 cmpwi cr7,r3,0 86 MTMSRD(r7) 87 isync 88 beq cr7,1f 89 stfd fr0,STKFRM-16(r1) 901: li r9,-EFAULT 912: lfs fr0,0(r4) 92 li r9,0 933: bl put_fpr 94 beq cr7,4f 95 lfd fr0,STKFRM-16(r1) 964: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) 97 mtlr r0 98 MTMSRD(r6) 99 isync 100 mr r3,r9 101 addi r1,r1,STKFRM 102 blr 103 extab 2b,3b 104 105/* Load FP reg N from double at *p. N is in r3, p in r4. */ 106_GLOBAL(do_lfd) 107 PPC_STLU r1,-STKFRM(r1) 108 mflr r0 109 PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) 110 mfmsr r6 111 ori r7,r6,MSR_FP 112 cmpwi cr7,r3,0 113 MTMSRD(r7) 114 isync 115 beq cr7,1f 116 stfd fr0,STKFRM-16(r1) 1171: li r9,-EFAULT 1182: lfd fr0,0(r4) 119 li r9,0 1203: beq cr7,4f 121 bl put_fpr 122 lfd fr0,STKFRM-16(r1) 1234: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) 124 mtlr r0 125 MTMSRD(r6) 126 isync 127 mr r3,r9 128 addi r1,r1,STKFRM 129 blr 130 extab 2b,3b 131 132/* Store FP reg N to float at *p. N is in r3, p in r4. */ 133_GLOBAL(do_stfs) 134 PPC_STLU r1,-STKFRM(r1) 135 mflr r0 136 PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) 137 mfmsr r6 138 ori r7,r6,MSR_FP 139 cmpwi cr7,r3,0 140 MTMSRD(r7) 141 isync 142 beq cr7,1f 143 stfd fr0,STKFRM-16(r1) 144 bl get_fpr 1451: li r9,-EFAULT 1462: stfs fr0,0(r4) 147 li r9,0 1483: beq cr7,4f 149 lfd fr0,STKFRM-16(r1) 1504: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) 151 mtlr r0 152 MTMSRD(r6) 153 isync 154 mr r3,r9 155 addi r1,r1,STKFRM 156 blr 157 extab 2b,3b 158 159/* Store FP reg N to double at *p. N is in r3, p in r4. */ 160_GLOBAL(do_stfd) 161 PPC_STLU r1,-STKFRM(r1) 162 mflr r0 163 PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) 164 mfmsr r6 165 ori r7,r6,MSR_FP 166 cmpwi cr7,r3,0 167 MTMSRD(r7) 168 isync 169 beq cr7,1f 170 stfd fr0,STKFRM-16(r1) 171 bl get_fpr 1721: li r9,-EFAULT 1732: stfd fr0,0(r4) 174 li r9,0 1753: beq cr7,4f 176 lfd fr0,STKFRM-16(r1) 1774: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) 178 mtlr r0 179 MTMSRD(r6) 180 isync 181 mr r3,r9 182 addi r1,r1,STKFRM 183 blr 184 extab 2b,3b 185 186#ifdef CONFIG_ALTIVEC 187/* Get the contents of vrN into v0; N is in r3. */ 188_GLOBAL(get_vr) 189 mflr r0 190 rlwinm r3,r3,3,0xf8 191 bcl 20,31,1f 192 blr /* v0 is already in v0 */ 193 nop 194reg = 1 195 .rept 31 196 vor v0,reg,reg /* assembler doesn't know vmr? */ 197 blr 198reg = reg + 1 199 .endr 2001: mflr r5 201 add r5,r3,r5 202 mtctr r5 203 mtlr r0 204 bctr 205 206/* Put the contents of v0 into vrN; N is in r3. */ 207_GLOBAL(put_vr) 208 mflr r0 209 rlwinm r3,r3,3,0xf8 210 bcl 20,31,1f 211 blr /* v0 is already in v0 */ 212 nop 213reg = 1 214 .rept 31 215 vor reg,v0,v0 216 blr 217reg = reg + 1 218 .endr 2191: mflr r5 220 add r5,r3,r5 221 mtctr r5 222 mtlr r0 223 bctr 224 225/* Load vector reg N from *p. N is in r3, p in r4. */ 226_GLOBAL(do_lvx) 227 PPC_STLU r1,-STKFRM(r1) 228 mflr r0 229 PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) 230 mfmsr r6 231 oris r7,r6,MSR_VEC@h 232 cmpwi cr7,r3,0 233 li r8,STKFRM-16 234 MTMSRD(r7) 235 isync 236 beq cr7,1f 237 stvx v0,r1,r8 2381: li r9,-EFAULT 2392: lvx v0,0,r4 240 li r9,0 2413: beq cr7,4f 242 bl put_vr 243 lvx v0,r1,r8 2444: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) 245 mtlr r0 246 MTMSRD(r6) 247 isync 248 mr r3,r9 249 addi r1,r1,STKFRM 250 blr 251 extab 2b,3b 252 253/* Store vector reg N to *p. N is in r3, p in r4. */ 254_GLOBAL(do_stvx) 255 PPC_STLU r1,-STKFRM(r1) 256 mflr r0 257 PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) 258 mfmsr r6 259 oris r7,r6,MSR_VEC@h 260 cmpwi cr7,r3,0 261 li r8,STKFRM-16 262 MTMSRD(r7) 263 isync 264 beq cr7,1f 265 stvx v0,r1,r8 266 bl get_vr 2671: li r9,-EFAULT 2682: stvx v0,0,r4 269 li r9,0 2703: beq cr7,4f 271 lvx v0,r1,r8 2724: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) 273 mtlr r0 274 MTMSRD(r6) 275 isync 276 mr r3,r9 277 addi r1,r1,STKFRM 278 blr 279 extab 2b,3b 280#endif /* CONFIG_ALTIVEC */ 281 282#ifdef CONFIG_VSX 283/* Get the contents of vsN into vs0; N is in r3. */ 284_GLOBAL(get_vsr) 285 mflr r0 286 rlwinm r3,r3,3,0x1f8 287 bcl 20,31,1f 288 blr /* vs0 is already in vs0 */ 289 nop 290reg = 1 291 .rept 63 292 XXLOR(0,reg,reg) 293 blr 294reg = reg + 1 295 .endr 2961: mflr r5 297 add r5,r3,r5 298 mtctr r5 299 mtlr r0 300 bctr 301 302/* Put the contents of vs0 into vsN; N is in r3. */ 303_GLOBAL(put_vsr) 304 mflr r0 305 rlwinm r3,r3,3,0x1f8 306 bcl 20,31,1f 307 blr /* v0 is already in v0 */ 308 nop 309reg = 1 310 .rept 63 311 XXLOR(reg,0,0) 312 blr 313reg = reg + 1 314 .endr 3151: mflr r5 316 add r5,r3,r5 317 mtctr r5 318 mtlr r0 319 bctr 320 321/* Load VSX reg N from vector doubleword *p. N is in r3, p in r4. */ 322_GLOBAL(do_lxvd2x) 323 PPC_STLU r1,-STKFRM(r1) 324 mflr r0 325 PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) 326 mfmsr r6 327 oris r7,r6,MSR_VSX@h 328 cmpwi cr7,r3,0 329 li r8,STKFRM-16 330 MTMSRD(r7) 331 isync 332 beq cr7,1f 333 STXVD2X(0,R1,R8) 3341: li r9,-EFAULT 3352: LXVD2X(0,R0,R4) 336 li r9,0 3373: beq cr7,4f 338 bl put_vsr 339 LXVD2X(0,R1,R8) 3404: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) 341 mtlr r0 342 MTMSRD(r6) 343 isync 344 mr r3,r9 345 addi r1,r1,STKFRM 346 blr 347 extab 2b,3b 348 349/* Store VSX reg N to vector doubleword *p. N is in r3, p in r4. */ 350_GLOBAL(do_stxvd2x) 351 PPC_STLU r1,-STKFRM(r1) 352 mflr r0 353 PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) 354 mfmsr r6 355 oris r7,r6,MSR_VSX@h 356 cmpwi cr7,r3,0 357 li r8,STKFRM-16 358 MTMSRD(r7) 359 isync 360 beq cr7,1f 361 STXVD2X(0,R1,R8) 362 bl get_vsr 3631: li r9,-EFAULT 3642: STXVD2X(0,R0,R4) 365 li r9,0 3663: beq cr7,4f 367 LXVD2X(0,R1,R8) 3684: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) 369 mtlr r0 370 MTMSRD(r6) 371 isync 372 mr r3,r9 373 addi r1,r1,STKFRM 374 blr 375 extab 2b,3b 376 377#endif /* CONFIG_VSX */ 378 379#endif /* CONFIG_PPC_FPU */ 380