blob: 32e91994b6b259440e64c97886219e0a04258557 [file] [log] [blame]
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001/*
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 */