xref: /linux/arch/powerpc/kernel/vecemu.c (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2564ee7a5SStephen Rothwell /*
3564ee7a5SStephen Rothwell  * Routines to emulate some Altivec/VMX instructions, specifically
4564ee7a5SStephen Rothwell  * those that can trap when given denormalized operands in Java mode.
5564ee7a5SStephen Rothwell  */
6564ee7a5SStephen Rothwell #include <linux/kernel.h>
7564ee7a5SStephen Rothwell #include <linux/errno.h>
8564ee7a5SStephen Rothwell #include <linux/sched.h>
9564ee7a5SStephen Rothwell #include <asm/ptrace.h>
10564ee7a5SStephen Rothwell #include <asm/processor.h>
11d647b210SMathieu Malaterre #include <asm/switch_to.h>
127c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
138094892dSJordan Niethe #include <asm/inst.h>
14564ee7a5SStephen Rothwell 
15564ee7a5SStephen Rothwell /* Functions in vector.S */
16564ee7a5SStephen Rothwell extern void vaddfp(vector128 *dst, vector128 *a, vector128 *b);
17564ee7a5SStephen Rothwell extern void vsubfp(vector128 *dst, vector128 *a, vector128 *b);
18564ee7a5SStephen Rothwell extern void vmaddfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c);
19564ee7a5SStephen Rothwell extern void vnmsubfp(vector128 *dst, vector128 *a, vector128 *b, vector128 *c);
20564ee7a5SStephen Rothwell extern void vrefp(vector128 *dst, vector128 *src);
21564ee7a5SStephen Rothwell extern void vrsqrtefp(vector128 *dst, vector128 *src);
22564ee7a5SStephen Rothwell extern void vexptep(vector128 *dst, vector128 *src);
23564ee7a5SStephen Rothwell 
24564ee7a5SStephen Rothwell static unsigned int exp2s[8] = {
25564ee7a5SStephen Rothwell 	0x800000,
26564ee7a5SStephen Rothwell 	0x8b95c2,
27564ee7a5SStephen Rothwell 	0x9837f0,
28564ee7a5SStephen Rothwell 	0xa5fed7,
29564ee7a5SStephen Rothwell 	0xb504f3,
30564ee7a5SStephen Rothwell 	0xc5672a,
31564ee7a5SStephen Rothwell 	0xd744fd,
32564ee7a5SStephen Rothwell 	0xeac0c7
33564ee7a5SStephen Rothwell };
34564ee7a5SStephen Rothwell 
35564ee7a5SStephen Rothwell /*
36564ee7a5SStephen Rothwell  * Computes an estimate of 2^x.  The `s' argument is the 32-bit
37564ee7a5SStephen Rothwell  * single-precision floating-point representation of x.
38564ee7a5SStephen Rothwell  */
eexp2(unsigned int s)39564ee7a5SStephen Rothwell static unsigned int eexp2(unsigned int s)
40564ee7a5SStephen Rothwell {
41564ee7a5SStephen Rothwell 	int exp, pwr;
42564ee7a5SStephen Rothwell 	unsigned int mant, frac;
43564ee7a5SStephen Rothwell 
44564ee7a5SStephen Rothwell 	/* extract exponent field from input */
45564ee7a5SStephen Rothwell 	exp = ((s >> 23) & 0xff) - 127;
46564ee7a5SStephen Rothwell 	if (exp > 7) {
47564ee7a5SStephen Rothwell 		/* check for NaN input */
48564ee7a5SStephen Rothwell 		if (exp == 128 && (s & 0x7fffff) != 0)
49564ee7a5SStephen Rothwell 			return s | 0x400000;	/* return QNaN */
50564ee7a5SStephen Rothwell 		/* 2^-big = 0, 2^+big = +Inf */
51564ee7a5SStephen Rothwell 		return (s & 0x80000000)? 0: 0x7f800000;	/* 0 or +Inf */
52564ee7a5SStephen Rothwell 	}
53564ee7a5SStephen Rothwell 	if (exp < -23)
54564ee7a5SStephen Rothwell 		return 0x3f800000;	/* 1.0 */
55564ee7a5SStephen Rothwell 
56564ee7a5SStephen Rothwell 	/* convert to fixed point integer in 9.23 representation */
57564ee7a5SStephen Rothwell 	pwr = (s & 0x7fffff) | 0x800000;
58564ee7a5SStephen Rothwell 	if (exp > 0)
59564ee7a5SStephen Rothwell 		pwr <<= exp;
60564ee7a5SStephen Rothwell 	else
61564ee7a5SStephen Rothwell 		pwr >>= -exp;
62564ee7a5SStephen Rothwell 	if (s & 0x80000000)
63564ee7a5SStephen Rothwell 		pwr = -pwr;
64564ee7a5SStephen Rothwell 
65564ee7a5SStephen Rothwell 	/* extract integer part, which becomes exponent part of result */
66564ee7a5SStephen Rothwell 	exp = (pwr >> 23) + 126;
67564ee7a5SStephen Rothwell 	if (exp >= 254)
68564ee7a5SStephen Rothwell 		return 0x7f800000;
69564ee7a5SStephen Rothwell 	if (exp < -23)
70564ee7a5SStephen Rothwell 		return 0;
71564ee7a5SStephen Rothwell 
72564ee7a5SStephen Rothwell 	/* table lookup on top 3 bits of fraction to get mantissa */
73564ee7a5SStephen Rothwell 	mant = exp2s[(pwr >> 20) & 7];
74564ee7a5SStephen Rothwell 
75564ee7a5SStephen Rothwell 	/* linear interpolation using remaining 20 bits of fraction */
76564ee7a5SStephen Rothwell 	asm("mulhwu %0,%1,%2" : "=r" (frac)
77564ee7a5SStephen Rothwell 	    : "r" (pwr << 12), "r" (0x172b83ff));
78564ee7a5SStephen Rothwell 	asm("mulhwu %0,%1,%2" : "=r" (frac) : "r" (frac), "r" (mant));
79564ee7a5SStephen Rothwell 	mant += frac;
80564ee7a5SStephen Rothwell 
81564ee7a5SStephen Rothwell 	if (exp >= 0)
82564ee7a5SStephen Rothwell 		return mant + (exp << 23);
83564ee7a5SStephen Rothwell 
84564ee7a5SStephen Rothwell 	/* denormalized result */
85564ee7a5SStephen Rothwell 	exp = -exp;
86564ee7a5SStephen Rothwell 	mant += 1 << (exp - 1);
87564ee7a5SStephen Rothwell 	return mant >> exp;
88564ee7a5SStephen Rothwell }
89564ee7a5SStephen Rothwell 
90564ee7a5SStephen Rothwell /*
91564ee7a5SStephen Rothwell  * Computes an estimate of log_2(x).  The `s' argument is the 32-bit
92564ee7a5SStephen Rothwell  * single-precision floating-point representation of x.
93564ee7a5SStephen Rothwell  */
elog2(unsigned int s)94564ee7a5SStephen Rothwell static unsigned int elog2(unsigned int s)
95564ee7a5SStephen Rothwell {
96564ee7a5SStephen Rothwell 	int exp, mant, lz, frac;
97564ee7a5SStephen Rothwell 
98564ee7a5SStephen Rothwell 	exp = s & 0x7f800000;
99564ee7a5SStephen Rothwell 	mant = s & 0x7fffff;
100564ee7a5SStephen Rothwell 	if (exp == 0x7f800000) {	/* Inf or NaN */
101564ee7a5SStephen Rothwell 		if (mant != 0)
102564ee7a5SStephen Rothwell 			s |= 0x400000;	/* turn NaN into QNaN */
103564ee7a5SStephen Rothwell 		return s;
104564ee7a5SStephen Rothwell 	}
105564ee7a5SStephen Rothwell 	if ((exp | mant) == 0)		/* +0 or -0 */
106564ee7a5SStephen Rothwell 		return 0xff800000;	/* return -Inf */
107564ee7a5SStephen Rothwell 
108564ee7a5SStephen Rothwell 	if (exp == 0) {
109564ee7a5SStephen Rothwell 		/* denormalized */
110564ee7a5SStephen Rothwell 		asm("cntlzw %0,%1" : "=r" (lz) : "r" (mant));
111564ee7a5SStephen Rothwell 		mant <<= lz - 8;
112564ee7a5SStephen Rothwell 		exp = (-118 - lz) << 23;
113564ee7a5SStephen Rothwell 	} else {
114564ee7a5SStephen Rothwell 		mant |= 0x800000;
115564ee7a5SStephen Rothwell 		exp -= 127 << 23;
116564ee7a5SStephen Rothwell 	}
117564ee7a5SStephen Rothwell 
118564ee7a5SStephen Rothwell 	if (mant >= 0xb504f3) {				/* 2^0.5 * 2^23 */
119564ee7a5SStephen Rothwell 		exp |= 0x400000;			/* 0.5 * 2^23 */
120564ee7a5SStephen Rothwell 		asm("mulhwu %0,%1,%2" : "=r" (mant)
121564ee7a5SStephen Rothwell 		    : "r" (mant), "r" (0xb504f334));	/* 2^-0.5 * 2^32 */
122564ee7a5SStephen Rothwell 	}
123564ee7a5SStephen Rothwell 	if (mant >= 0x9837f0) {				/* 2^0.25 * 2^23 */
124564ee7a5SStephen Rothwell 		exp |= 0x200000;			/* 0.25 * 2^23 */
125564ee7a5SStephen Rothwell 		asm("mulhwu %0,%1,%2" : "=r" (mant)
126564ee7a5SStephen Rothwell 		    : "r" (mant), "r" (0xd744fccb));	/* 2^-0.25 * 2^32 */
127564ee7a5SStephen Rothwell 	}
128564ee7a5SStephen Rothwell 	if (mant >= 0x8b95c2) {				/* 2^0.125 * 2^23 */
129564ee7a5SStephen Rothwell 		exp |= 0x100000;			/* 0.125 * 2^23 */
130564ee7a5SStephen Rothwell 		asm("mulhwu %0,%1,%2" : "=r" (mant)
131564ee7a5SStephen Rothwell 		    : "r" (mant), "r" (0xeac0c6e8));	/* 2^-0.125 * 2^32 */
132564ee7a5SStephen Rothwell 	}
133564ee7a5SStephen Rothwell 	if (mant > 0x800000) {				/* 1.0 * 2^23 */
134564ee7a5SStephen Rothwell 		/* calculate (mant - 1) * 1.381097463 */
135564ee7a5SStephen Rothwell 		/* 1.381097463 == 0.125 / (2^0.125 - 1) */
136564ee7a5SStephen Rothwell 		asm("mulhwu %0,%1,%2" : "=r" (frac)
137564ee7a5SStephen Rothwell 		    : "r" ((mant - 0x800000) << 1), "r" (0xb0c7cd3a));
138564ee7a5SStephen Rothwell 		exp += frac;
139564ee7a5SStephen Rothwell 	}
140564ee7a5SStephen Rothwell 	s = exp & 0x80000000;
141564ee7a5SStephen Rothwell 	if (exp != 0) {
142564ee7a5SStephen Rothwell 		if (s)
143564ee7a5SStephen Rothwell 			exp = -exp;
144564ee7a5SStephen Rothwell 		asm("cntlzw %0,%1" : "=r" (lz) : "r" (exp));
145564ee7a5SStephen Rothwell 		lz = 8 - lz;
146564ee7a5SStephen Rothwell 		if (lz > 0)
147564ee7a5SStephen Rothwell 			exp >>= lz;
148564ee7a5SStephen Rothwell 		else if (lz < 0)
149564ee7a5SStephen Rothwell 			exp <<= -lz;
150564ee7a5SStephen Rothwell 		s += ((lz + 126) << 23) + exp;
151564ee7a5SStephen Rothwell 	}
152564ee7a5SStephen Rothwell 	return s;
153564ee7a5SStephen Rothwell }
154564ee7a5SStephen Rothwell 
155564ee7a5SStephen Rothwell #define VSCR_SAT	1
156564ee7a5SStephen Rothwell 
ctsxs(unsigned int x,int scale,unsigned int * vscrp)157564ee7a5SStephen Rothwell static int ctsxs(unsigned int x, int scale, unsigned int *vscrp)
158564ee7a5SStephen Rothwell {
159564ee7a5SStephen Rothwell 	int exp, mant;
160564ee7a5SStephen Rothwell 
161564ee7a5SStephen Rothwell 	exp = (x >> 23) & 0xff;
162564ee7a5SStephen Rothwell 	mant = x & 0x7fffff;
163564ee7a5SStephen Rothwell 	if (exp == 255 && mant != 0)
164564ee7a5SStephen Rothwell 		return 0;		/* NaN -> 0 */
165564ee7a5SStephen Rothwell 	exp = exp - 127 + scale;
166564ee7a5SStephen Rothwell 	if (exp < 0)
167564ee7a5SStephen Rothwell 		return 0;		/* round towards zero */
168564ee7a5SStephen Rothwell 	if (exp >= 31) {
169564ee7a5SStephen Rothwell 		/* saturate, unless the result would be -2^31 */
170564ee7a5SStephen Rothwell 		if (x + (scale << 23) != 0xcf000000)
171564ee7a5SStephen Rothwell 			*vscrp |= VSCR_SAT;
172564ee7a5SStephen Rothwell 		return (x & 0x80000000)? 0x80000000: 0x7fffffff;
173564ee7a5SStephen Rothwell 	}
174564ee7a5SStephen Rothwell 	mant |= 0x800000;
175564ee7a5SStephen Rothwell 	mant = (mant << 7) >> (30 - exp);
176564ee7a5SStephen Rothwell 	return (x & 0x80000000)? -mant: mant;
177564ee7a5SStephen Rothwell }
178564ee7a5SStephen Rothwell 
ctuxs(unsigned int x,int scale,unsigned int * vscrp)179564ee7a5SStephen Rothwell static unsigned int ctuxs(unsigned int x, int scale, unsigned int *vscrp)
180564ee7a5SStephen Rothwell {
181564ee7a5SStephen Rothwell 	int exp;
182564ee7a5SStephen Rothwell 	unsigned int mant;
183564ee7a5SStephen Rothwell 
184564ee7a5SStephen Rothwell 	exp = (x >> 23) & 0xff;
185564ee7a5SStephen Rothwell 	mant = x & 0x7fffff;
186564ee7a5SStephen Rothwell 	if (exp == 255 && mant != 0)
187564ee7a5SStephen Rothwell 		return 0;		/* NaN -> 0 */
188564ee7a5SStephen Rothwell 	exp = exp - 127 + scale;
189564ee7a5SStephen Rothwell 	if (exp < 0)
190564ee7a5SStephen Rothwell 		return 0;		/* round towards zero */
191564ee7a5SStephen Rothwell 	if (x & 0x80000000) {
192564ee7a5SStephen Rothwell 		/* negative => saturate to 0 */
193564ee7a5SStephen Rothwell 		*vscrp |= VSCR_SAT;
194564ee7a5SStephen Rothwell 		return 0;
195564ee7a5SStephen Rothwell 	}
196564ee7a5SStephen Rothwell 	if (exp >= 32) {
197564ee7a5SStephen Rothwell 		/* saturate */
198564ee7a5SStephen Rothwell 		*vscrp |= VSCR_SAT;
199564ee7a5SStephen Rothwell 		return 0xffffffff;
200564ee7a5SStephen Rothwell 	}
201564ee7a5SStephen Rothwell 	mant |= 0x800000;
202564ee7a5SStephen Rothwell 	mant = (mant << 8) >> (31 - exp);
203564ee7a5SStephen Rothwell 	return mant;
204564ee7a5SStephen Rothwell }
205564ee7a5SStephen Rothwell 
206564ee7a5SStephen Rothwell /* Round to floating integer, towards 0 */
rfiz(unsigned int x)207564ee7a5SStephen Rothwell static unsigned int rfiz(unsigned int x)
208564ee7a5SStephen Rothwell {
209564ee7a5SStephen Rothwell 	int exp;
210564ee7a5SStephen Rothwell 
211564ee7a5SStephen Rothwell 	exp = ((x >> 23) & 0xff) - 127;
212564ee7a5SStephen Rothwell 	if (exp == 128 && (x & 0x7fffff) != 0)
213564ee7a5SStephen Rothwell 		return x | 0x400000;	/* NaN -> make it a QNaN */
214564ee7a5SStephen Rothwell 	if (exp >= 23)
215564ee7a5SStephen Rothwell 		return x;		/* it's an integer already (or Inf) */
216564ee7a5SStephen Rothwell 	if (exp < 0)
217564ee7a5SStephen Rothwell 		return x & 0x80000000;	/* |x| < 1.0 rounds to 0 */
218564ee7a5SStephen Rothwell 	return x & ~(0x7fffff >> exp);
219564ee7a5SStephen Rothwell }
220564ee7a5SStephen Rothwell 
221564ee7a5SStephen Rothwell /* Round to floating integer, towards +/- Inf */
rfii(unsigned int x)222564ee7a5SStephen Rothwell static unsigned int rfii(unsigned int x)
223564ee7a5SStephen Rothwell {
224564ee7a5SStephen Rothwell 	int exp, mask;
225564ee7a5SStephen Rothwell 
226564ee7a5SStephen Rothwell 	exp = ((x >> 23) & 0xff) - 127;
227564ee7a5SStephen Rothwell 	if (exp == 128 && (x & 0x7fffff) != 0)
228564ee7a5SStephen Rothwell 		return x | 0x400000;	/* NaN -> make it a QNaN */
229564ee7a5SStephen Rothwell 	if (exp >= 23)
230564ee7a5SStephen Rothwell 		return x;		/* it's an integer already (or Inf) */
231564ee7a5SStephen Rothwell 	if ((x & 0x7fffffff) == 0)
232564ee7a5SStephen Rothwell 		return x;		/* +/-0 -> +/-0 */
233564ee7a5SStephen Rothwell 	if (exp < 0)
234564ee7a5SStephen Rothwell 		/* 0 < |x| < 1.0 rounds to +/- 1.0 */
235564ee7a5SStephen Rothwell 		return (x & 0x80000000) | 0x3f800000;
236564ee7a5SStephen Rothwell 	mask = 0x7fffff >> exp;
237564ee7a5SStephen Rothwell 	/* mantissa overflows into exponent - that's OK,
238564ee7a5SStephen Rothwell 	   it can't overflow into the sign bit */
239564ee7a5SStephen Rothwell 	return (x + mask) & ~mask;
240564ee7a5SStephen Rothwell }
241564ee7a5SStephen Rothwell 
242564ee7a5SStephen Rothwell /* Round to floating integer, to nearest */
rfin(unsigned int x)243564ee7a5SStephen Rothwell static unsigned int rfin(unsigned int x)
244564ee7a5SStephen Rothwell {
245564ee7a5SStephen Rothwell 	int exp, half;
246564ee7a5SStephen Rothwell 
247564ee7a5SStephen Rothwell 	exp = ((x >> 23) & 0xff) - 127;
248564ee7a5SStephen Rothwell 	if (exp == 128 && (x & 0x7fffff) != 0)
249564ee7a5SStephen Rothwell 		return x | 0x400000;	/* NaN -> make it a QNaN */
250564ee7a5SStephen Rothwell 	if (exp >= 23)
251564ee7a5SStephen Rothwell 		return x;		/* it's an integer already (or Inf) */
252564ee7a5SStephen Rothwell 	if (exp < -1)
253564ee7a5SStephen Rothwell 		return x & 0x80000000;	/* |x| < 0.5 -> +/-0 */
254564ee7a5SStephen Rothwell 	if (exp == -1)
255564ee7a5SStephen Rothwell 		/* 0.5 <= |x| < 1.0 rounds to +/- 1.0 */
256564ee7a5SStephen Rothwell 		return (x & 0x80000000) | 0x3f800000;
257564ee7a5SStephen Rothwell 	half = 0x400000 >> exp;
258564ee7a5SStephen Rothwell 	/* add 0.5 to the magnitude and chop off the fraction bits */
259564ee7a5SStephen Rothwell 	return (x + half) & ~(0x7fffff >> exp);
260564ee7a5SStephen Rothwell }
261564ee7a5SStephen Rothwell 
emulate_altivec(struct pt_regs * regs)262564ee7a5SStephen Rothwell int emulate_altivec(struct pt_regs *regs)
263564ee7a5SStephen Rothwell {
264*c545b9f0SChristophe Leroy 	ppc_inst_t instr;
26594afd069SJordan Niethe 	unsigned int i, word;
266564ee7a5SStephen Rothwell 	unsigned int va, vb, vc, vd;
267564ee7a5SStephen Rothwell 	vector128 *vrs;
268564ee7a5SStephen Rothwell 
2695249385aSJordan Niethe 	if (get_user_instr(instr, (void __user *)regs->nip))
270564ee7a5SStephen Rothwell 		return -EFAULT;
271777e26f0SJordan Niethe 
272777e26f0SJordan Niethe 	word = ppc_inst_val(instr);
2738094892dSJordan Niethe 	if (ppc_inst_primary_opcode(instr) != 4)
274564ee7a5SStephen Rothwell 		return -EINVAL;		/* not an altivec instruction */
275777e26f0SJordan Niethe 	vd = (word >> 21) & 0x1f;
276777e26f0SJordan Niethe 	va = (word >> 16) & 0x1f;
277777e26f0SJordan Niethe 	vb = (word >> 11) & 0x1f;
278777e26f0SJordan Niethe 	vc = (word >> 6) & 0x1f;
279564ee7a5SStephen Rothwell 
280de79f7b9SPaul Mackerras 	vrs = current->thread.vr_state.vr;
281777e26f0SJordan Niethe 	switch (word & 0x3f) {
282564ee7a5SStephen Rothwell 	case 10:
283564ee7a5SStephen Rothwell 		switch (vc) {
284564ee7a5SStephen Rothwell 		case 0:	/* vaddfp */
285564ee7a5SStephen Rothwell 			vaddfp(&vrs[vd], &vrs[va], &vrs[vb]);
286564ee7a5SStephen Rothwell 			break;
287564ee7a5SStephen Rothwell 		case 1:	/* vsubfp */
288564ee7a5SStephen Rothwell 			vsubfp(&vrs[vd], &vrs[va], &vrs[vb]);
289564ee7a5SStephen Rothwell 			break;
290564ee7a5SStephen Rothwell 		case 4:	/* vrefp */
291564ee7a5SStephen Rothwell 			vrefp(&vrs[vd], &vrs[vb]);
292564ee7a5SStephen Rothwell 			break;
293564ee7a5SStephen Rothwell 		case 5:	/* vrsqrtefp */
294564ee7a5SStephen Rothwell 			vrsqrtefp(&vrs[vd], &vrs[vb]);
295564ee7a5SStephen Rothwell 			break;
296564ee7a5SStephen Rothwell 		case 6:	/* vexptefp */
297564ee7a5SStephen Rothwell 			for (i = 0; i < 4; ++i)
298564ee7a5SStephen Rothwell 				vrs[vd].u[i] = eexp2(vrs[vb].u[i]);
299564ee7a5SStephen Rothwell 			break;
300564ee7a5SStephen Rothwell 		case 7:	/* vlogefp */
301564ee7a5SStephen Rothwell 			for (i = 0; i < 4; ++i)
302564ee7a5SStephen Rothwell 				vrs[vd].u[i] = elog2(vrs[vb].u[i]);
303564ee7a5SStephen Rothwell 			break;
304564ee7a5SStephen Rothwell 		case 8:		/* vrfin */
305564ee7a5SStephen Rothwell 			for (i = 0; i < 4; ++i)
306564ee7a5SStephen Rothwell 				vrs[vd].u[i] = rfin(vrs[vb].u[i]);
307564ee7a5SStephen Rothwell 			break;
308564ee7a5SStephen Rothwell 		case 9:		/* vrfiz */
309564ee7a5SStephen Rothwell 			for (i = 0; i < 4; ++i)
310564ee7a5SStephen Rothwell 				vrs[vd].u[i] = rfiz(vrs[vb].u[i]);
311564ee7a5SStephen Rothwell 			break;
312564ee7a5SStephen Rothwell 		case 10:	/* vrfip */
313564ee7a5SStephen Rothwell 			for (i = 0; i < 4; ++i) {
314564ee7a5SStephen Rothwell 				u32 x = vrs[vb].u[i];
315564ee7a5SStephen Rothwell 				x = (x & 0x80000000)? rfiz(x): rfii(x);
316564ee7a5SStephen Rothwell 				vrs[vd].u[i] = x;
317564ee7a5SStephen Rothwell 			}
318564ee7a5SStephen Rothwell 			break;
319564ee7a5SStephen Rothwell 		case 11:	/* vrfim */
320564ee7a5SStephen Rothwell 			for (i = 0; i < 4; ++i) {
321564ee7a5SStephen Rothwell 				u32 x = vrs[vb].u[i];
322564ee7a5SStephen Rothwell 				x = (x & 0x80000000)? rfii(x): rfiz(x);
323564ee7a5SStephen Rothwell 				vrs[vd].u[i] = x;
324564ee7a5SStephen Rothwell 			}
325564ee7a5SStephen Rothwell 			break;
326564ee7a5SStephen Rothwell 		case 14:	/* vctuxs */
327564ee7a5SStephen Rothwell 			for (i = 0; i < 4; ++i)
328564ee7a5SStephen Rothwell 				vrs[vd].u[i] = ctuxs(vrs[vb].u[i], va,
329de79f7b9SPaul Mackerras 					&current->thread.vr_state.vscr.u[3]);
330564ee7a5SStephen Rothwell 			break;
331564ee7a5SStephen Rothwell 		case 15:	/* vctsxs */
332564ee7a5SStephen Rothwell 			for (i = 0; i < 4; ++i)
333564ee7a5SStephen Rothwell 				vrs[vd].u[i] = ctsxs(vrs[vb].u[i], va,
334de79f7b9SPaul Mackerras 					&current->thread.vr_state.vscr.u[3]);
335564ee7a5SStephen Rothwell 			break;
336564ee7a5SStephen Rothwell 		default:
337564ee7a5SStephen Rothwell 			return -EINVAL;
338564ee7a5SStephen Rothwell 		}
339564ee7a5SStephen Rothwell 		break;
340564ee7a5SStephen Rothwell 	case 46:	/* vmaddfp */
341564ee7a5SStephen Rothwell 		vmaddfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]);
342564ee7a5SStephen Rothwell 		break;
343564ee7a5SStephen Rothwell 	case 47:	/* vnmsubfp */
344564ee7a5SStephen Rothwell 		vnmsubfp(&vrs[vd], &vrs[va], &vrs[vb], &vrs[vc]);
345564ee7a5SStephen Rothwell 		break;
346564ee7a5SStephen Rothwell 	default:
347564ee7a5SStephen Rothwell 		return -EINVAL;
348564ee7a5SStephen Rothwell 	}
349564ee7a5SStephen Rothwell 
350564ee7a5SStephen Rothwell 	return 0;
351564ee7a5SStephen Rothwell }
352