blob: 32e91994b6b259440e64c97886219e0a04258557 [file] [log] [blame]
Paul Mackerras0016a4c2010-06-15 14:48:58 +10001/*
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>
Christophe Leroyec0c4642018-07-05 16:24:57 +000018#include <asm/asm-compat.h>
Paul Mackerras0016a4c2010-06-15 14:48:58 +100019#include <linux/errno.h>
20
Sean MacLennancd64d162010-09-01 07:21:21 +000021#ifdef CONFIG_PPC_FPU
22
Paul Mackerras0016a4c2010-06-15 14:48:58 +100023#define STKFRM (PPC_MIN_STKFRM + 16)
24
Paul Mackerrasc22435a52017-08-30 14:12:33 +100025/* Get the contents of frN into *p; N is in r3 and p is in r4. */
Paul Mackerras0016a4c2010-06-15 14:48:58 +100026_GLOBAL(get_fpr)
27 mflr r0
Paul Mackerrasc22435a52017-08-30 14:12:33 +100028 mfmsr r6
29 ori r7, r6, MSR_FP
30 MTMSRD(r7)
31 isync
Paul Mackerras0016a4c2010-06-15 14:48:58 +100032 rlwinm r3,r3,3,0xf8
33 bcl 20,31,1f
Paul Mackerrasc22435a52017-08-30 14:12:33 +100034reg = 0
35 .rept 32
36 stfd reg, 0(r4)
37 b 2f
Paul Mackerras0016a4c2010-06-15 14:48:58 +100038reg = reg + 1
39 .endr
401: mflr r5
41 add r5,r3,r5
42 mtctr r5
43 mtlr r0
44 bctr
Paul Mackerrasc22435a52017-08-30 14:12:33 +1000452: MTMSRD(r6)
46 isync
47 blr
Paul Mackerras0016a4c2010-06-15 14:48:58 +100048
Paul Mackerrasc22435a52017-08-30 14:12:33 +100049/* Put the contents of *p into frN; N is in r3 and p is in r4. */
Paul Mackerras0016a4c2010-06-15 14:48:58 +100050_GLOBAL(put_fpr)
51 mflr r0
Paul Mackerrasc22435a52017-08-30 14:12:33 +100052 mfmsr r6
53 ori r7, r6, MSR_FP
54 MTMSRD(r7)
55 isync
Paul Mackerras0016a4c2010-06-15 14:48:58 +100056 rlwinm r3,r3,3,0xf8
57 bcl 20,31,1f
Paul Mackerrasc22435a52017-08-30 14:12:33 +100058reg = 0
59 .rept 32
60 lfd reg, 0(r4)
61 b 2f
Paul Mackerras0016a4c2010-06-15 14:48:58 +100062reg = reg + 1
63 .endr
641: mflr r5
65 add r5,r3,r5
66 mtctr r5
67 mtlr r0
68 bctr
Paul Mackerrasc22435a52017-08-30 14:12:33 +1000692: MTMSRD(r6)
Paul Mackerras0016a4c2010-06-15 14:48:58 +100070 isync
Paul Mackerras0016a4c2010-06-15 14:48:58 +100071 blr
Paul Mackerras0016a4c2010-06-15 14:48:58 +100072
73#ifdef CONFIG_ALTIVEC
Paul Mackerrasc22435a52017-08-30 14:12:33 +100074/* Get the contents of vrN into *p; N is in r3 and p is in r4. */
Paul Mackerras0016a4c2010-06-15 14:48:58 +100075_GLOBAL(get_vr)
76 mflr r0
Paul Mackerrasc22435a52017-08-30 14:12:33 +100077 mfmsr r6
78 oris r7, r6, MSR_VEC@h
79 MTMSRD(r7)
80 isync
Paul Mackerras4716e482017-09-04 13:59:00 +100081 rlwinm r3,r3,3,0xf8
Paul Mackerras0016a4c2010-06-15 14:48:58 +100082 bcl 20,31,1f
Paul Mackerrasc22435a52017-08-30 14:12:33 +100083reg = 0
84 .rept 32
85 stvx reg, 0, r4
86 b 2f
Paul Mackerras0016a4c2010-06-15 14:48:58 +100087reg = reg + 1
88 .endr
891: mflr r5
Paul Mackerras4716e482017-09-04 13:59:00 +100090 add r5,r3,r5
Paul Mackerras0016a4c2010-06-15 14:48:58 +100091 mtctr r5
92 mtlr r0
93 bctr
Paul Mackerrasc22435a52017-08-30 14:12:33 +1000942: MTMSRD(r6)
95 isync
96 blr
Paul Mackerras0016a4c2010-06-15 14:48:58 +100097
Paul Mackerrasc22435a52017-08-30 14:12:33 +100098/* Put the contents of *p into vrN; N is in r3 and p is in r4. */
Paul Mackerras0016a4c2010-06-15 14:48:58 +100099_GLOBAL(put_vr)
100 mflr r0
Paul Mackerrasc22435a52017-08-30 14:12:33 +1000101 mfmsr r6
102 oris r7, r6, MSR_VEC@h
103 MTMSRD(r7)
104 isync
Paul Mackerras4716e482017-09-04 13:59:00 +1000105 rlwinm r3,r3,3,0xf8
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000106 bcl 20,31,1f
Paul Mackerrasc22435a52017-08-30 14:12:33 +1000107reg = 0
108 .rept 32
109 lvx reg, 0, r4
110 b 2f
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000111reg = reg + 1
112 .endr
1131: mflr r5
Paul Mackerras4716e482017-09-04 13:59:00 +1000114 add r5,r3,r5
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000115 mtctr r5
116 mtlr r0
117 bctr
Paul Mackerrasc22435a52017-08-30 14:12:33 +10001182: MTMSRD(r6)
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000119 isync
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000120 blr
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000121#endif /* CONFIG_ALTIVEC */
122
123#ifdef CONFIG_VSX
Anton Blancharddf99e6e2015-02-10 09:51:23 +1100124/* Get the contents of vsN into vs0; N is in r3. */
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000125_GLOBAL(get_vsr)
126 mflr r0
127 rlwinm r3,r3,3,0x1f8
128 bcl 20,31,1f
Anton Blancharddf99e6e2015-02-10 09:51:23 +1100129 blr /* vs0 is already in vs0 */
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000130 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
Anton Blancharddf99e6e2015-02-10 09:51:23 +1100143/* Put the contents of vs0 into vsN; N is in r3. */
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000144_GLOBAL(put_vsr)
145 mflr r0
146 rlwinm r3,r3,3,0x1f8
147 bcl 20,31,1f
Anton Blanchardc2ce6f92015-02-10 09:51:22 +1100148 blr /* v0 is already in v0 */
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000149 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. */
Paul Mackerras350779a2017-08-30 14:12:27 +1000163_GLOBAL(load_vsrn)
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000164 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
Sean MacLennancd64d162010-09-01 07:21:21 +0000171 MTMSRD(r7)
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000172 isync
173 beq cr7,1f
Michael Neulingc75df6f2012-06-25 13:33:10 +0000174 STXVD2X(0,R1,R8)
Paul Mackerras350779a2017-08-30 14:12:27 +10001751: LXVD2X(0,R0,R4)
176#ifdef __LITTLE_ENDIAN__
177 XXSWAPD(0,0)
178#endif
179 beq cr7,4f
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000180 bl put_vsr
Michael Neulingc75df6f2012-06-25 13:33:10 +0000181 LXVD2X(0,R1,R8)
Paul Mackerras0016a4c2010-06-15 14:48:58 +10001824: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
183 mtlr r0
Sean MacLennancd64d162010-09-01 07:21:21 +0000184 MTMSRD(r6)
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000185 isync
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000186 addi r1,r1,STKFRM
187 blr
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000188
189/* Store VSX reg N to vector doubleword *p. N is in r3, p in r4. */
Paul Mackerras350779a2017-08-30 14:12:27 +1000190_GLOBAL(store_vsrn)
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000191 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
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000196 li r8,STKFRM-16
Sean MacLennancd64d162010-09-01 07:21:21 +0000197 MTMSRD(r7)
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000198 isync
Michael Neulingc75df6f2012-06-25 13:33:10 +0000199 STXVD2X(0,R1,R8)
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000200 bl get_vsr
Paul Mackerras350779a2017-08-30 14:12:27 +1000201#ifdef __LITTLE_ENDIAN__
202 XXSWAPD(0,0)
203#endif
204 STXVD2X(0,R0,R4)
Michael Neulingc75df6f2012-06-25 13:33:10 +0000205 LXVD2X(0,R1,R8)
Paul Mackerras350779a2017-08-30 14:12:27 +1000206 PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000207 mtlr r0
Sean MacLennancd64d162010-09-01 07:21:21 +0000208 MTMSRD(r6)
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000209 isync
210 mr r3,r9
211 addi r1,r1,STKFRM
212 blr
Paul Mackerras0016a4c2010-06-15 14:48:58 +1000213#endif /* CONFIG_VSX */
Sean MacLennancd64d162010-09-01 07:21:21 +0000214
Paul Mackerras350779a2017-08-30 14:12:27 +1000215/* 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
Sean MacLennancd64d162010-09-01 07:21:21 +0000245#endif /* CONFIG_PPC_FPU */