linux/arch/powerpc/lib/ldstfp.S
<<
>>
Prefs
   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