aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/math-emu
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2015-02-12 07:08:27 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2015-03-25 06:49:33 -0400
commit5a79859ae0f35d25c67a03e82bf0c80592f16a39 (patch)
tree37264d49f069812f19ced94e6ae171814fb7e498 /arch/s390/math-emu
parent1833c9f647e9bda1cd24653ff8f9c207b5f5b911 (diff)
s390: remove 31 bit support
Remove the 31 bit support in order to reduce maintenance cost and effectively remove dead code. Since a couple of years there is no distribution left that comes with a 31 bit kernel. The 31 bit kernel also has been broken since more than a year before anybody noticed. In addition I added a removal warning to the kernel shown at ipl for 5 minutes: a960062e5826 ("s390: add 31 bit warning message") which let everybody know about the plan to remove 31 bit code. We didn't get any response. Given that the last 31 bit only machine was introduced in 1999 let's remove the code. Anybody with 31 bit user space code can still use the compat mode. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/math-emu')
-rw-r--r--arch/s390/math-emu/Makefile7
-rw-r--r--arch/s390/math-emu/math.c2255
2 files changed, 0 insertions, 2262 deletions
diff --git a/arch/s390/math-emu/Makefile b/arch/s390/math-emu/Makefile
deleted file mode 100644
index 51d399549f60..000000000000
--- a/arch/s390/math-emu/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
1#
2# Makefile for the FPU instruction emulation.
3#
4
5obj-$(CONFIG_MATHEMU) := math.o
6
7ccflags-y := -I$(src) -Iinclude/math-emu -w
diff --git a/arch/s390/math-emu/math.c b/arch/s390/math-emu/math.c
deleted file mode 100644
index a6ba0d724335..000000000000
--- a/arch/s390/math-emu/math.c
+++ /dev/null
@@ -1,2255 +0,0 @@
1/*
2 * S390 version
3 * Copyright IBM Corp. 1999, 2001
4 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
5 *
6 * 'math.c' emulates IEEE instructions on a S390 processor
7 * that does not have the IEEE fpu (all processors before G5).
8 */
9
10#include <linux/types.h>
11#include <linux/sched.h>
12#include <linux/mm.h>
13#include <asm/uaccess.h>
14#include <asm/lowcore.h>
15
16#include <asm/sfp-util.h>
17#include <math-emu/soft-fp.h>
18#include <math-emu/single.h>
19#include <math-emu/double.h>
20#include <math-emu/quad.h>
21
22#define FPC_VALID_MASK 0xF8F8FF03
23
24/*
25 * I miss a macro to round a floating point number to the
26 * nearest integer in the same floating point format.
27 */
28#define _FP_TO_FPINT_ROUND(fs, wc, X) \
29 do { \
30 switch (X##_c) \
31 { \
32 case FP_CLS_NORMAL: \
33 if (X##_e > _FP_FRACBITS_##fs + _FP_EXPBIAS_##fs) \
34 { /* floating point number has no bits after the dot. */ \
35 } \
36 else if (X##_e <= _FP_FRACBITS_##fs + _FP_EXPBIAS_##fs && \
37 X##_e > _FP_EXPBIAS_##fs) \
38 { /* some bits before the dot, some after it. */ \
39 _FP_FRAC_SRS_##wc(X, _FP_WFRACBITS_##fs, \
40 X##_e - _FP_EXPBIAS_##fs \
41 + _FP_FRACBITS_##fs); \
42 _FP_ROUND(wc, X); \
43 _FP_FRAC_SLL_##wc(X, X##_e - _FP_EXPBIAS_##fs \
44 + _FP_FRACBITS_##fs); \
45 } \
46 else \
47 { /* all bits after the dot. */ \
48 FP_SET_EXCEPTION(FP_EX_INEXACT); \
49 X##_c = FP_CLS_ZERO; \
50 } \
51 break; \
52 case FP_CLS_NAN: \
53 case FP_CLS_INF: \
54 case FP_CLS_ZERO: \
55 break; \
56 } \
57 } while (0)
58
59#define FP_TO_FPINT_ROUND_S(X) _FP_TO_FPINT_ROUND(S,1,X)
60#define FP_TO_FPINT_ROUND_D(X) _FP_TO_FPINT_ROUND(D,2,X)
61#define FP_TO_FPINT_ROUND_Q(X) _FP_TO_FPINT_ROUND(Q,4,X)
62
63typedef union {
64 long double ld;
65 struct {
66 __u64 high;
67 __u64 low;
68 } w;
69} mathemu_ldcv;
70
71#ifdef CONFIG_SYSCTL
72int sysctl_ieee_emulation_warnings=1;
73#endif
74
75#define mathemu_put_user(x, p) \
76 do { \
77 if (put_user((x),(p))) \
78 return SIGSEGV; \
79 } while (0)
80
81#define mathemu_get_user(x, p) \
82 do { \
83 if (get_user((x),(p))) \
84 return SIGSEGV; \
85 } while (0)
86
87#define mathemu_copy_from_user(d, s, n)\
88 do { \
89 if (copy_from_user((d),(s),(n)) != 0) \
90 return SIGSEGV; \
91 } while (0)
92
93#define mathemu_copy_to_user(d, s, n) \
94 do { \
95 if (copy_to_user((d),(s),(n)) != 0) \
96 return SIGSEGV; \
97 } while (0)
98
99static void display_emulation_not_implemented(struct pt_regs *regs, char *instr)
100{
101 __u16 *location;
102
103#ifdef CONFIG_SYSCTL
104 if(sysctl_ieee_emulation_warnings)
105#endif
106 {
107 location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc);
108 printk("%s ieee fpu instruction not emulated "
109 "process name: %s pid: %d \n",
110 instr, current->comm, current->pid);
111 printk("%s's PSW: %08lx %08lx\n", instr,
112 (unsigned long) regs->psw.mask,
113 (unsigned long) location);
114 }
115}
116
117static inline void emu_set_CC (struct pt_regs *regs, int cc)
118{
119 regs->psw.mask = (regs->psw.mask & 0xFFFFCFFF) | ((cc&3) << 12);
120}
121
122/*
123 * Set the condition code in the user psw.
124 * 0 : Result is zero
125 * 1 : Result is less than zero
126 * 2 : Result is greater than zero
127 * 3 : Result is NaN or INF
128 */
129static inline void emu_set_CC_cs(struct pt_regs *regs, int class, int sign)
130{
131 switch (class) {
132 case FP_CLS_NORMAL:
133 case FP_CLS_INF:
134 emu_set_CC(regs, sign ? 1 : 2);
135 break;
136 case FP_CLS_ZERO:
137 emu_set_CC(regs, 0);
138 break;
139 case FP_CLS_NAN:
140 emu_set_CC(regs, 3);
141 break;
142 }
143}
144
145/* Add long double */
146static int emu_axbr (struct pt_regs *regs, int rx, int ry) {
147 FP_DECL_Q(QA); FP_DECL_Q(QB); FP_DECL_Q(QR);
148 FP_DECL_EX;
149 mathemu_ldcv cvt;
150 int mode;
151
152 mode = current->thread.fp_regs.fpc & 3;
153 cvt.w.high = current->thread.fp_regs.fprs[rx].ui;
154 cvt.w.low = current->thread.fp_regs.fprs[rx+2].ui;
155 FP_UNPACK_QP(QA, &cvt.ld);
156 cvt.w.high = current->thread.fp_regs.fprs[ry].ui;
157 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui;
158 FP_UNPACK_QP(QB, &cvt.ld);
159 FP_ADD_Q(QR, QA, QB);
160 FP_PACK_QP(&cvt.ld, QR);
161 current->thread.fp_regs.fprs[rx].ui = cvt.w.high;
162 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low;
163 emu_set_CC_cs(regs, QR_c, QR_s);
164 return _fex;
165}
166
167/* Add double */
168static int emu_adbr (struct pt_regs *regs, int rx, int ry) {
169 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR);
170 FP_DECL_EX;
171 int mode;
172
173 mode = current->thread.fp_regs.fpc & 3;
174 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d);
175 FP_UNPACK_DP(DB, &current->thread.fp_regs.fprs[ry].d);
176 FP_ADD_D(DR, DA, DB);
177 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR);
178 emu_set_CC_cs(regs, DR_c, DR_s);
179 return _fex;
180}
181
182/* Add double */
183static int emu_adb (struct pt_regs *regs, int rx, double *val) {
184 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR);
185 FP_DECL_EX;
186 int mode;
187
188 mode = current->thread.fp_regs.fpc & 3;
189 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d);
190 FP_UNPACK_DP(DB, val);
191 FP_ADD_D(DR, DA, DB);
192 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR);
193 emu_set_CC_cs(regs, DR_c, DR_s);
194 return _fex;
195}
196
197/* Add float */
198static int emu_aebr (struct pt_regs *regs, int rx, int ry) {
199 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);
200 FP_DECL_EX;
201 int mode;
202
203 mode = current->thread.fp_regs.fpc & 3;
204 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f);
205 FP_UNPACK_SP(SB, &current->thread.fp_regs.fprs[ry].f);
206 FP_ADD_S(SR, SA, SB);
207 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR);
208 emu_set_CC_cs(regs, SR_c, SR_s);
209 return _fex;
210}
211
212/* Add float */
213static int emu_aeb (struct pt_regs *regs, int rx, float *val) {
214 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);
215 FP_DECL_EX;
216 int mode;
217
218 mode = current->thread.fp_regs.fpc & 3;
219 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f);
220 FP_UNPACK_SP(SB, val);
221 FP_ADD_S(SR, SA, SB);
222 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR);
223 emu_set_CC_cs(regs, SR_c, SR_s);
224 return _fex;
225}
226
227/* Compare long double */
228static int emu_cxbr (struct pt_regs *regs, int rx, int ry) {
229 FP_DECL_Q(QA); FP_DECL_Q(QB);
230 mathemu_ldcv cvt;
231 int IR;
232
233 cvt.w.high = current->thread.fp_regs.fprs[rx].ui;
234 cvt.w.low = current->thread.fp_regs.fprs[rx+2].ui;
235 FP_UNPACK_RAW_QP(QA, &cvt.ld);
236 cvt.w.high = current->thread.fp_regs.fprs[ry].ui;
237 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui;
238 FP_UNPACK_RAW_QP(QB, &cvt.ld);
239 FP_CMP_Q(IR, QA, QB, 3);
240 /*
241 * IR == -1 if DA < DB, IR == 0 if DA == DB,
242 * IR == 1 if DA > DB and IR == 3 if unorderded
243 */
244 emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR);
245 return 0;
246}
247
248/* Compare double */
249static int emu_cdbr (struct pt_regs *regs, int rx, int ry) {
250 FP_DECL_D(DA); FP_DECL_D(DB);
251 int IR;
252
253 FP_UNPACK_RAW_DP(DA, &current->thread.fp_regs.fprs[rx].d);
254 FP_UNPACK_RAW_DP(DB, &current->thread.fp_regs.fprs[ry].d);
255 FP_CMP_D(IR, DA, DB, 3);
256 /*
257 * IR == -1 if DA < DB, IR == 0 if DA == DB,
258 * IR == 1 if DA > DB and IR == 3 if unorderded
259 */
260 emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR);
261 return 0;
262}
263
264/* Compare double */
265static int emu_cdb (struct pt_regs *regs, int rx, double *val) {
266 FP_DECL_D(DA); FP_DECL_D(DB);
267 int IR;
268
269 FP_UNPACK_RAW_DP(DA, &current->thread.fp_regs.fprs[rx].d);
270 FP_UNPACK_RAW_DP(DB, val);
271 FP_CMP_D(IR, DA, DB, 3);
272 /*
273 * IR == -1 if DA < DB, IR == 0 if DA == DB,
274 * IR == 1 if DA > DB and IR == 3 if unorderded
275 */
276 emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR);
277 return 0;
278}
279
280/* Compare float */
281static int emu_cebr (struct pt_regs *regs, int rx, int ry) {
282 FP_DECL_S(SA); FP_DECL_S(SB);
283 int IR;
284
285 FP_UNPACK_RAW_SP(SA, &current->thread.fp_regs.fprs[rx].f);
286 FP_UNPACK_RAW_SP(SB, &current->thread.fp_regs.fprs[ry].f);
287 FP_CMP_S(IR, SA, SB, 3);
288 /*
289 * IR == -1 if DA < DB, IR == 0 if DA == DB,
290 * IR == 1 if DA > DB and IR == 3 if unorderded
291 */
292 emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR);
293 return 0;
294}
295
296/* Compare float */
297static int emu_ceb (struct pt_regs *regs, int rx, float *val) {
298 FP_DECL_S(SA); FP_DECL_S(SB);
299 int IR;
300
301 FP_UNPACK_RAW_SP(SA, &current->thread.fp_regs.fprs[rx].f);
302 FP_UNPACK_RAW_SP(SB, val);
303 FP_CMP_S(IR, SA, SB, 3);
304 /*
305 * IR == -1 if DA < DB, IR == 0 if DA == DB,
306 * IR == 1 if DA > DB and IR == 3 if unorderded
307 */
308 emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR);
309 return 0;
310}
311
312/* Compare and signal long double */
313static int emu_kxbr (struct pt_regs *regs, int rx, int ry) {
314 FP_DECL_Q(QA); FP_DECL_Q(QB);
315 FP_DECL_EX;
316 mathemu_ldcv cvt;
317 int IR;
318
319 cvt.w.high = current->thread.fp_regs.fprs[rx].ui;
320 cvt.w.low = current->thread.fp_regs.fprs[rx+2].ui;
321 FP_UNPACK_RAW_QP(QA, &cvt.ld);
322 cvt.w.high = current->thread.fp_regs.fprs[ry].ui;
323 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui;
324 FP_UNPACK_QP(QB, &cvt.ld);
325 FP_CMP_Q(IR, QA, QB, 3);
326 /*
327 * IR == -1 if DA < DB, IR == 0 if DA == DB,
328 * IR == 1 if DA > DB and IR == 3 if unorderded
329 */
330 emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR);
331 if (IR == 3)
332 FP_SET_EXCEPTION (FP_EX_INVALID);
333 return _fex;
334}
335
336/* Compare and signal double */
337static int emu_kdbr (struct pt_regs *regs, int rx, int ry) {
338 FP_DECL_D(DA); FP_DECL_D(DB);
339 FP_DECL_EX;
340 int IR;
341
342 FP_UNPACK_RAW_DP(DA, &current->thread.fp_regs.fprs[rx].d);
343 FP_UNPACK_RAW_DP(DB, &current->thread.fp_regs.fprs[ry].d);
344 FP_CMP_D(IR, DA, DB, 3);
345 /*
346 * IR == -1 if DA < DB, IR == 0 if DA == DB,
347 * IR == 1 if DA > DB and IR == 3 if unorderded
348 */
349 emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR);
350 if (IR == 3)
351 FP_SET_EXCEPTION (FP_EX_INVALID);
352 return _fex;
353}
354
355/* Compare and signal double */
356static int emu_kdb (struct pt_regs *regs, int rx, double *val) {
357 FP_DECL_D(DA); FP_DECL_D(DB);
358 FP_DECL_EX;
359 int IR;
360
361 FP_UNPACK_RAW_DP(DA, &current->thread.fp_regs.fprs[rx].d);
362 FP_UNPACK_RAW_DP(DB, val);
363 FP_CMP_D(IR, DA, DB, 3);
364 /*
365 * IR == -1 if DA < DB, IR == 0 if DA == DB,
366 * IR == 1 if DA > DB and IR == 3 if unorderded
367 */
368 emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR);
369 if (IR == 3)
370 FP_SET_EXCEPTION (FP_EX_INVALID);
371 return _fex;
372}
373
374/* Compare and signal float */
375static int emu_kebr (struct pt_regs *regs, int rx, int ry) {
376 FP_DECL_S(SA); FP_DECL_S(SB);
377 FP_DECL_EX;
378 int IR;
379
380 FP_UNPACK_RAW_SP(SA, &current->thread.fp_regs.fprs[rx].f);
381 FP_UNPACK_RAW_SP(SB, &current->thread.fp_regs.fprs[ry].f);
382 FP_CMP_S(IR, SA, SB, 3);
383 /*
384 * IR == -1 if DA < DB, IR == 0 if DA == DB,
385 * IR == 1 if DA > DB and IR == 3 if unorderded
386 */
387 emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR);
388 if (IR == 3)
389 FP_SET_EXCEPTION (FP_EX_INVALID);
390 return _fex;
391}
392
393/* Compare and signal float */
394static int emu_keb (struct pt_regs *regs, int rx, float *val) {
395 FP_DECL_S(SA); FP_DECL_S(SB);
396 FP_DECL_EX;
397 int IR;
398
399 FP_UNPACK_RAW_SP(SA, &current->thread.fp_regs.fprs[rx].f);
400 FP_UNPACK_RAW_SP(SB, val);
401 FP_CMP_S(IR, SA, SB, 3);
402 /*
403 * IR == -1 if DA < DB, IR == 0 if DA == DB,
404 * IR == 1 if DA > DB and IR == 3 if unorderded
405 */
406 emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR);
407 if (IR == 3)
408 FP_SET_EXCEPTION (FP_EX_INVALID);
409 return _fex;
410}
411
412/* Convert from fixed long double */
413static int emu_cxfbr (struct pt_regs *regs, int rx, int ry) {
414 FP_DECL_Q(QR);
415 FP_DECL_EX;
416 mathemu_ldcv cvt;
417 __s32 si;
418 int mode;
419
420 mode = current->thread.fp_regs.fpc & 3;
421 si = regs->gprs[ry];
422 FP_FROM_INT_Q(QR, si, 32, int);
423 FP_PACK_QP(&cvt.ld, QR);
424 current->thread.fp_regs.fprs[rx].ui = cvt.w.high;
425 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low;
426 return _fex;
427}
428
429/* Convert from fixed double */
430static int emu_cdfbr (struct pt_regs *regs, int rx, int ry) {
431 FP_DECL_D(DR);
432 FP_DECL_EX;
433 __s32 si;
434 int mode;
435
436 mode = current->thread.fp_regs.fpc & 3;
437 si = regs->gprs[ry];
438 FP_FROM_INT_D(DR, si, 32, int);
439 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR);
440 return _fex;
441}
442
443/* Convert from fixed float */
444static int emu_cefbr (struct pt_regs *regs, int rx, int ry) {
445 FP_DECL_S(SR);
446 FP_DECL_EX;
447 __s32 si;
448 int mode;
449
450 mode = current->thread.fp_regs.fpc & 3;
451 si = regs->gprs[ry];
452 FP_FROM_INT_S(SR, si, 32, int);
453 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR);
454 return _fex;
455}
456
457/* Convert to fixed long double */
458static int emu_cfxbr (struct pt_regs *regs, int rx, int ry, int mask) {
459 FP_DECL_Q(QA);
460 FP_DECL_EX;
461 mathemu_ldcv cvt;
462 __s32 si;
463 int mode;
464
465 if (mask == 0)
466 mode = current->thread.fp_regs.fpc & 3;
467 else if (mask == 1)
468 mode = FP_RND_NEAREST;
469 else
470 mode = mask - 4;
471 cvt.w.high = current->thread.fp_regs.fprs[ry].ui;
472 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui;
473 FP_UNPACK_QP(QA, &cvt.ld);
474 FP_TO_INT_ROUND_Q(si, QA, 32, 1);
475 regs->gprs[rx] = si;
476 emu_set_CC_cs(regs, QA_c, QA_s);
477 return _fex;
478}
479
480/* Convert to fixed double */
481static int emu_cfdbr (struct pt_regs *regs, int rx, int ry, int mask) {
482 FP_DECL_D(DA);
483 FP_DECL_EX;
484 __s32 si;
485 int mode;
486
487 if (mask == 0)
488 mode = current->thread.fp_regs.fpc & 3;
489 else if (mask == 1)
490 mode = FP_RND_NEAREST;
491 else
492 mode = mask - 4;
493 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[ry].d);
494 FP_TO_INT_ROUND_D(si, DA, 32, 1);
495 regs->gprs[rx] = si;
496 emu_set_CC_cs(regs, DA_c, DA_s);
497 return _fex;
498}
499
500/* Convert to fixed float */
501static int emu_cfebr (struct pt_regs *regs, int rx, int ry, int mask) {
502 FP_DECL_S(SA);
503 FP_DECL_EX;
504 __s32 si;
505 int mode;
506
507 if (mask == 0)
508 mode = current->thread.fp_regs.fpc & 3;
509 else if (mask == 1)
510 mode = FP_RND_NEAREST;
511 else
512 mode = mask - 4;
513 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[ry].f);
514 FP_TO_INT_ROUND_S(si, SA, 32, 1);
515 regs->gprs[rx] = si;
516 emu_set_CC_cs(regs, SA_c, SA_s);
517 return _fex;
518}
519
520/* Divide long double */
521static int emu_dxbr (struct pt_regs *regs, int rx, int ry) {
522 FP_DECL_Q(QA); FP_DECL_Q(QB); FP_DECL_Q(QR);
523 FP_DECL_EX;
524 mathemu_ldcv cvt;
525 int mode;
526
527 mode = current->thread.fp_regs.fpc & 3;
528 cvt.w.high = current->thread.fp_regs.fprs[rx].ui;
529 cvt.w.low = current->thread.fp_regs.fprs[rx+2].ui;
530 FP_UNPACK_QP(QA, &cvt.ld);
531 cvt.w.high = current->thread.fp_regs.fprs[ry].ui;
532 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui;
533 FP_UNPACK_QP(QB, &cvt.ld);
534 FP_DIV_Q(QR, QA, QB);
535 FP_PACK_QP(&cvt.ld, QR);
536 current->thread.fp_regs.fprs[rx].ui = cvt.w.high;
537 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low;
538 return _fex;
539}
540
541/* Divide double */
542static int emu_ddbr (struct pt_regs *regs, int rx, int ry) {
543 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR);
544 FP_DECL_EX;
545 int mode;
546
547 mode = current->thread.fp_regs.fpc & 3;
548 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d);
549 FP_UNPACK_DP(DB, &current->thread.fp_regs.fprs[ry].d);
550 FP_DIV_D(DR, DA, DB);
551 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR);
552 return _fex;
553}
554
555/* Divide double */
556static int emu_ddb (struct pt_regs *regs, int rx, double *val) {
557 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR);
558 FP_DECL_EX;
559 int mode;
560
561 mode = current->thread.fp_regs.fpc & 3;
562 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d);
563 FP_UNPACK_DP(DB, val);
564 FP_DIV_D(DR, DA, DB);
565 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR);
566 return _fex;
567}
568
569/* Divide float */
570static int emu_debr (struct pt_regs *regs, int rx, int ry) {
571 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);
572 FP_DECL_EX;
573 int mode;
574
575 mode = current->thread.fp_regs.fpc & 3;
576 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f);
577 FP_UNPACK_SP(SB, &current->thread.fp_regs.fprs[ry].f);
578 FP_DIV_S(SR, SA, SB);
579 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR);
580 return _fex;
581}
582
583/* Divide float */
584static int emu_deb (struct pt_regs *regs, int rx, float *val) {
585 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);
586 FP_DECL_EX;
587 int mode;
588
589 mode = current->thread.fp_regs.fpc & 3;
590 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f);
591 FP_UNPACK_SP(SB, val);
592 FP_DIV_S(SR, SA, SB);
593 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR);
594 return _fex;
595}
596
597/* Divide to integer double */
598static int emu_didbr (struct pt_regs *regs, int rx, int ry, int mask) {
599 display_emulation_not_implemented(regs, "didbr");
600 return 0;
601}
602
603/* Divide to integer float */
604static int emu_diebr (struct pt_regs *regs, int rx, int ry, int mask) {
605 display_emulation_not_implemented(regs, "diebr");
606 return 0;
607}
608
609/* Extract fpc */
610static int emu_efpc (struct pt_regs *regs, int rx, int ry) {
611 regs->gprs[rx] = current->thread.fp_regs.fpc;
612 return 0;
613}
614
615/* Load and test long double */
616static int emu_ltxbr (struct pt_regs *regs, int rx, int ry) {
617 s390_fp_regs *fp_regs = &current->thread.fp_regs;
618 mathemu_ldcv cvt;
619 FP_DECL_Q(QA);
620 FP_DECL_EX;
621
622 cvt.w.high = current->thread.fp_regs.fprs[ry].ui;
623 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui;
624 FP_UNPACK_QP(QA, &cvt.ld);
625 fp_regs->fprs[rx].ui = fp_regs->fprs[ry].ui;
626 fp_regs->fprs[rx+2].ui = fp_regs->fprs[ry+2].ui;
627 emu_set_CC_cs(regs, QA_c, QA_s);
628 return _fex;
629}
630
631/* Load and test double */
632static int emu_ltdbr (struct pt_regs *regs, int rx, int ry) {
633 s390_fp_regs *fp_regs = &current->thread.fp_regs;
634 FP_DECL_D(DA);
635 FP_DECL_EX;
636
637 FP_UNPACK_DP(DA, &fp_regs->fprs[ry].d);
638 fp_regs->fprs[rx].ui = fp_regs->fprs[ry].ui;
639 emu_set_CC_cs(regs, DA_c, DA_s);
640 return _fex;
641}
642
643/* Load and test double */
644static int emu_ltebr (struct pt_regs *regs, int rx, int ry) {
645 s390_fp_regs *fp_regs = &current->thread.fp_regs;
646 FP_DECL_S(SA);
647 FP_DECL_EX;
648
649 FP_UNPACK_SP(SA, &fp_regs->fprs[ry].f);
650 fp_regs->fprs[rx].ui = fp_regs->fprs[ry].ui;
651 emu_set_CC_cs(regs, SA_c, SA_s);
652 return _fex;
653}
654
655/* Load complement long double */
656static int emu_lcxbr (struct pt_regs *regs, int rx, int ry) {
657 FP_DECL_Q(QA); FP_DECL_Q(QR);
658 FP_DECL_EX;
659 mathemu_ldcv cvt;
660 int mode;
661
662 mode = current->thread.fp_regs.fpc & 3;
663 cvt.w.high = current->thread.fp_regs.fprs[ry].ui;
664 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui;
665 FP_UNPACK_QP(QA, &cvt.ld);
666 FP_NEG_Q(QR, QA);
667 FP_PACK_QP(&cvt.ld, QR);
668 current->thread.fp_regs.fprs[rx].ui = cvt.w.high;
669 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low;
670 emu_set_CC_cs(regs, QR_c, QR_s);
671 return _fex;
672}
673
674/* Load complement double */
675static int emu_lcdbr (struct pt_regs *regs, int rx, int ry) {
676 FP_DECL_D(DA); FP_DECL_D(DR);
677 FP_DECL_EX;
678 int mode;
679
680 mode = current->thread.fp_regs.fpc & 3;
681 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[ry].d);
682 FP_NEG_D(DR, DA);
683 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR);
684 emu_set_CC_cs(regs, DR_c, DR_s);
685 return _fex;
686}
687
688/* Load complement float */
689static int emu_lcebr (struct pt_regs *regs, int rx, int ry) {
690 FP_DECL_S(SA); FP_DECL_S(SR);
691 FP_DECL_EX;
692 int mode;
693
694 mode = current->thread.fp_regs.fpc & 3;
695 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[ry].f);
696 FP_NEG_S(SR, SA);
697 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR);
698 emu_set_CC_cs(regs, SR_c, SR_s);
699 return _fex;
700}
701
702/* Load floating point integer long double */
703static int emu_fixbr (struct pt_regs *regs, int rx, int ry, int mask) {
704 s390_fp_regs *fp_regs = &current->thread.fp_regs;
705 FP_DECL_Q(QA);
706 FP_DECL_EX;
707 mathemu_ldcv cvt;
708 __s32 si;
709 int mode;
710
711 if (mask == 0)
712 mode = fp_regs->fpc & 3;
713 else if (mask == 1)
714 mode = FP_RND_NEAREST;
715 else
716 mode = mask - 4;
717 cvt.w.high = fp_regs->fprs[ry].ui;
718 cvt.w.low = fp_regs->fprs[ry+2].ui;
719 FP_UNPACK_QP(QA, &cvt.ld);
720 FP_TO_FPINT_ROUND_Q(QA);
721 FP_PACK_QP(&cvt.ld, QA);
722 fp_regs->fprs[rx].ui = cvt.w.high;
723 fp_regs->fprs[rx+2].ui = cvt.w.low;
724 return _fex;
725}
726
727/* Load floating point integer double */
728static int emu_fidbr (struct pt_regs *regs, int rx, int ry, int mask) {
729 /* FIXME: rounding mode !! */
730 s390_fp_regs *fp_regs = &current->thread.fp_regs;
731 FP_DECL_D(DA);
732 FP_DECL_EX;
733 __s32 si;
734 int mode;
735
736 if (mask == 0)
737 mode = fp_regs->fpc & 3;
738 else if (mask == 1)
739 mode = FP_RND_NEAREST;
740 else
741 mode = mask - 4;
742 FP_UNPACK_DP(DA, &fp_regs->fprs[ry].d);
743 FP_TO_FPINT_ROUND_D(DA);
744 FP_PACK_DP(&fp_regs->fprs[rx].d, DA);
745 return _fex;
746}
747
748/* Load floating point integer float */
749static int emu_fiebr (struct pt_regs *regs, int rx, int ry, int mask) {
750 s390_fp_regs *fp_regs = &current->thread.fp_regs;
751 FP_DECL_S(SA);
752 FP_DECL_EX;
753 __s32 si;
754 int mode;
755
756 if (mask == 0)
757 mode = fp_regs->fpc & 3;
758 else if (mask == 1)
759 mode = FP_RND_NEAREST;
760 else
761 mode = mask - 4;
762 FP_UNPACK_SP(SA, &fp_regs->fprs[ry].f);
763 FP_TO_FPINT_ROUND_S(SA);
764 FP_PACK_SP(&fp_regs->fprs[rx].f, SA);
765 return _fex;
766}
767
768/* Load lengthened double to long double */
769static int emu_lxdbr (struct pt_regs *regs, int rx, int ry) {
770 FP_DECL_D(DA); FP_DECL_Q(QR);
771 FP_DECL_EX;
772 mathemu_ldcv cvt;
773 int mode;
774
775 mode = current->thread.fp_regs.fpc & 3;
776 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[ry].d);
777 FP_CONV (Q, D, 4, 2, QR, DA);
778 FP_PACK_QP(&cvt.ld, QR);
779 current->thread.fp_regs.fprs[rx].ui = cvt.w.high;
780 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low;
781 return _fex;
782}
783
784/* Load lengthened double to long double */
785static int emu_lxdb (struct pt_regs *regs, int rx, double *val) {
786 FP_DECL_D(DA); FP_DECL_Q(QR);
787 FP_DECL_EX;
788 mathemu_ldcv cvt;
789 int mode;
790
791 mode = current->thread.fp_regs.fpc & 3;
792 FP_UNPACK_DP(DA, val);
793 FP_CONV (Q, D, 4, 2, QR, DA);
794 FP_PACK_QP(&cvt.ld, QR);
795 current->thread.fp_regs.fprs[rx].ui = cvt.w.high;
796 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low;
797 return _fex;
798}
799
800/* Load lengthened float to long double */
801static int emu_lxebr (struct pt_regs *regs, int rx, int ry) {
802 FP_DECL_S(SA); FP_DECL_Q(QR);
803 FP_DECL_EX;
804 mathemu_ldcv cvt;
805 int mode;
806
807 mode = current->thread.fp_regs.fpc & 3;
808 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[ry].f);
809 FP_CONV (Q, S, 4, 1, QR, SA);
810 FP_PACK_QP(&cvt.ld, QR);
811 current->thread.fp_regs.fprs[rx].ui = cvt.w.high;
812 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low;
813 return _fex;
814}
815
816/* Load lengthened float to long double */
817static int emu_lxeb (struct pt_regs *regs, int rx, float *val) {
818 FP_DECL_S(SA); FP_DECL_Q(QR);
819 FP_DECL_EX;
820 mathemu_ldcv cvt;
821 int mode;
822
823 mode = current->thread.fp_regs.fpc & 3;
824 FP_UNPACK_SP(SA, val);
825 FP_CONV (Q, S, 4, 1, QR, SA);
826 FP_PACK_QP(&cvt.ld, QR);
827 current->thread.fp_regs.fprs[rx].ui = cvt.w.high;
828 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low;
829 return _fex;
830}
831
832/* Load lengthened float to double */
833static int emu_ldebr (struct pt_regs *regs, int rx, int ry) {
834 FP_DECL_S(SA); FP_DECL_D(DR);
835 FP_DECL_EX;
836 int mode;
837
838 mode = current->thread.fp_regs.fpc & 3;
839 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[ry].f);
840 FP_CONV (D, S, 2, 1, DR, SA);
841 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR);
842 return _fex;
843}
844
845/* Load lengthened float to double */
846static int emu_ldeb (struct pt_regs *regs, int rx, float *val) {
847 FP_DECL_S(SA); FP_DECL_D(DR);
848 FP_DECL_EX;
849 int mode;
850
851 mode = current->thread.fp_regs.fpc & 3;
852 FP_UNPACK_SP(SA, val);
853 FP_CONV (D, S, 2, 1, DR, SA);
854 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR);
855 return _fex;
856}
857
858/* Load negative long double */
859static int emu_lnxbr (struct pt_regs *regs, int rx, int ry) {
860 FP_DECL_Q(QA); FP_DECL_Q(QR);
861 FP_DECL_EX;
862 mathemu_ldcv cvt;
863 int mode;
864
865 mode = current->thread.fp_regs.fpc & 3;
866 cvt.w.high = current->thread.fp_regs.fprs[ry].ui;
867 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui;
868 FP_UNPACK_QP(QA, &cvt.ld);
869 if (QA_s == 0) {
870 FP_NEG_Q(QR, QA);
871 FP_PACK_QP(&cvt.ld, QR);
872 current->thread.fp_regs.fprs[rx].ui = cvt.w.high;
873 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low;
874 } else {
875 current->thread.fp_regs.fprs[rx].ui =
876 current->thread.fp_regs.fprs[ry].ui;
877 current->thread.fp_regs.fprs[rx+2].ui =
878 current->thread.fp_regs.fprs[ry+2].ui;
879 }
880 emu_set_CC_cs(regs, QR_c, QR_s);
881 return _fex;
882}
883
884/* Load negative double */
885static int emu_lndbr (struct pt_regs *regs, int rx, int ry) {
886 FP_DECL_D(DA); FP_DECL_D(DR);
887 FP_DECL_EX;
888 int mode;
889
890 mode = current->thread.fp_regs.fpc & 3;
891 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[ry].d);
892 if (DA_s == 0) {
893 FP_NEG_D(DR, DA);
894 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR);
895 } else
896 current->thread.fp_regs.fprs[rx].ui =
897 current->thread.fp_regs.fprs[ry].ui;
898 emu_set_CC_cs(regs, DR_c, DR_s);
899 return _fex;
900}
901
902/* Load negative float */
903static int emu_lnebr (struct pt_regs *regs, int rx, int ry) {
904 FP_DECL_S(SA); FP_DECL_S(SR);
905 FP_DECL_EX;
906 int mode;
907
908 mode = current->thread.fp_regs.fpc & 3;
909 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[ry].f);
910 if (SA_s == 0) {
911 FP_NEG_S(SR, SA);
912 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR);
913 } else
914 current->thread.fp_regs.fprs[rx].ui =
915 current->thread.fp_regs.fprs[ry].ui;
916 emu_set_CC_cs(regs, SR_c, SR_s);
917 return _fex;
918}
919
920/* Load positive long double */
921static int emu_lpxbr (struct pt_regs *regs, int rx, int ry) {
922 FP_DECL_Q(QA); FP_DECL_Q(QR);
923 FP_DECL_EX;
924 mathemu_ldcv cvt;
925 int mode;
926
927 mode = current->thread.fp_regs.fpc & 3;
928 cvt.w.high = current->thread.fp_regs.fprs[ry].ui;
929 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui;
930 FP_UNPACK_QP(QA, &cvt.ld);
931 if (QA_s != 0) {
932 FP_NEG_Q(QR, QA);
933 FP_PACK_QP(&cvt.ld, QR);
934 current->thread.fp_regs.fprs[rx].ui = cvt.w.high;
935 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low;
936 } else{
937 current->thread.fp_regs.fprs[rx].ui =
938 current->thread.fp_regs.fprs[ry].ui;
939 current->thread.fp_regs.fprs[rx+2].ui =
940 current->thread.fp_regs.fprs[ry+2].ui;
941 }
942 emu_set_CC_cs(regs, QR_c, QR_s);
943 return _fex;
944}
945
946/* Load positive double */
947static int emu_lpdbr (struct pt_regs *regs, int rx, int ry) {
948 FP_DECL_D(DA); FP_DECL_D(DR);
949 FP_DECL_EX;
950 int mode;
951
952 mode = current->thread.fp_regs.fpc & 3;
953 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[ry].d);
954 if (DA_s != 0) {
955 FP_NEG_D(DR, DA);
956 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR);
957 } else
958 current->thread.fp_regs.fprs[rx].ui =
959 current->thread.fp_regs.fprs[ry].ui;
960 emu_set_CC_cs(regs, DR_c, DR_s);
961 return _fex;
962}
963
964/* Load positive float */
965static int emu_lpebr (struct pt_regs *regs, int rx, int ry) {
966 FP_DECL_S(SA); FP_DECL_S(SR);
967 FP_DECL_EX;
968 int mode;
969
970 mode = current->thread.fp_regs.fpc & 3;
971 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[ry].f);
972 if (SA_s != 0) {
973 FP_NEG_S(SR, SA);
974 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR);
975 } else
976 current->thread.fp_regs.fprs[rx].ui =
977 current->thread.fp_regs.fprs[ry].ui;
978 emu_set_CC_cs(regs, SR_c, SR_s);
979 return _fex;
980}
981
982/* Load rounded long double to double */
983static int emu_ldxbr (struct pt_regs *regs, int rx, int ry) {
984 FP_DECL_Q(QA); FP_DECL_D(DR);
985 FP_DECL_EX;
986 mathemu_ldcv cvt;
987 int mode;
988
989 mode = current->thread.fp_regs.fpc & 3;
990 cvt.w.high = current->thread.fp_regs.fprs[ry].ui;
991 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui;
992 FP_UNPACK_QP(QA, &cvt.ld);
993 FP_CONV (D, Q, 2, 4, DR, QA);
994 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].f, DR);
995 return _fex;
996}
997
998/* Load rounded long double to float */
999static int emu_lexbr (struct pt_regs *regs, int rx, int ry) {
1000 FP_DECL_Q(QA); FP_DECL_S(SR);
1001 FP_DECL_EX;
1002 mathemu_ldcv cvt;
1003 int mode;
1004
1005 mode = current->thread.fp_regs.fpc & 3;
1006 cvt.w.high = current->thread.fp_regs.fprs[ry].ui;
1007 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui;
1008 FP_UNPACK_QP(QA, &cvt.ld);
1009 FP_CONV (S, Q, 1, 4, SR, QA);
1010 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR);
1011 return _fex;
1012}
1013
1014/* Load rounded double to float */
1015static int emu_ledbr (struct pt_regs *regs, int rx, int ry) {
1016 FP_DECL_D(DA); FP_DECL_S(SR);
1017 FP_DECL_EX;
1018 int mode;
1019
1020 mode = current->thread.fp_regs.fpc & 3;
1021 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[ry].d);
1022 FP_CONV (S, D, 1, 2, SR, DA);
1023 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR);
1024 return _fex;
1025}
1026
1027/* Multiply long double */
1028static int emu_mxbr (struct pt_regs *regs, int rx, int ry) {
1029 FP_DECL_Q(QA); FP_DECL_Q(QB); FP_DECL_Q(QR);
1030 FP_DECL_EX;
1031 mathemu_ldcv cvt;
1032 int mode;
1033
1034 mode = current->thread.fp_regs.fpc & 3;
1035 cvt.w.high = current->thread.fp_regs.fprs[rx].ui;
1036 cvt.w.low = current->thread.fp_regs.fprs[rx+2].ui;
1037 FP_UNPACK_QP(QA, &cvt.ld);
1038 cvt.w.high = current->thread.fp_regs.fprs[ry].ui;
1039 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui;
1040 FP_UNPACK_QP(QB, &cvt.ld);
1041 FP_MUL_Q(QR, QA, QB);
1042 FP_PACK_QP(&cvt.ld, QR);
1043 current->thread.fp_regs.fprs[rx].ui = cvt.w.high;
1044 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low;
1045 return _fex;
1046}
1047
1048/* Multiply double */
1049static int emu_mdbr (struct pt_regs *regs, int rx, int ry) {
1050 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR);
1051 FP_DECL_EX;
1052 int mode;
1053
1054 mode = current->thread.fp_regs.fpc & 3;
1055 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d);
1056 FP_UNPACK_DP(DB, &current->thread.fp_regs.fprs[ry].d);
1057 FP_MUL_D(DR, DA, DB);
1058 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR);
1059 return _fex;
1060}
1061
1062/* Multiply double */
1063static int emu_mdb (struct pt_regs *regs, int rx, double *val) {
1064 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR);
1065 FP_DECL_EX;
1066 int mode;
1067
1068 mode = current->thread.fp_regs.fpc & 3;
1069 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d);
1070 FP_UNPACK_DP(DB, val);
1071 FP_MUL_D(DR, DA, DB);
1072 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR);
1073 return _fex;
1074}
1075
1076/* Multiply double to long double */
1077static int emu_mxdbr (struct pt_regs *regs, int rx, int ry) {
1078 FP_DECL_D(DA); FP_DECL_Q(QA); FP_DECL_Q(QB); FP_DECL_Q(QR);
1079 FP_DECL_EX;
1080 mathemu_ldcv cvt;
1081 int mode;
1082
1083 mode = current->thread.fp_regs.fpc & 3;
1084 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d);
1085 FP_CONV (Q, D, 4, 2, QA, DA);
1086 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[ry].d);
1087 FP_CONV (Q, D, 4, 2, QB, DA);
1088 FP_MUL_Q(QR, QA, QB);
1089 FP_PACK_QP(&cvt.ld, QR);
1090 current->thread.fp_regs.fprs[rx].ui = cvt.w.high;
1091 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low;
1092 return _fex;
1093}
1094
1095/* Multiply double to long double */
1096static int emu_mxdb (struct pt_regs *regs, int rx, long double *val) {
1097 FP_DECL_Q(QA); FP_DECL_Q(QB); FP_DECL_Q(QR);
1098 FP_DECL_EX;
1099 mathemu_ldcv cvt;
1100 int mode;
1101
1102 mode = current->thread.fp_regs.fpc & 3;
1103 cvt.w.high = current->thread.fp_regs.fprs[rx].ui;
1104 cvt.w.low = current->thread.fp_regs.fprs[rx+2].ui;
1105 FP_UNPACK_QP(QA, &cvt.ld);
1106 FP_UNPACK_QP(QB, val);
1107 FP_MUL_Q(QR, QA, QB);
1108 FP_PACK_QP(&cvt.ld, QR);
1109 current->thread.fp_regs.fprs[rx].ui = cvt.w.high;
1110 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low;
1111 return _fex;
1112}
1113
1114/* Multiply float */
1115static int emu_meebr (struct pt_regs *regs, int rx, int ry) {
1116 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);
1117 FP_DECL_EX;
1118 int mode;
1119
1120 mode = current->thread.fp_regs.fpc & 3;
1121 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f);
1122 FP_UNPACK_SP(SB, &current->thread.fp_regs.fprs[ry].f);
1123 FP_MUL_S(SR, SA, SB);
1124 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR);
1125 return _fex;
1126}
1127
1128/* Multiply float */
1129static int emu_meeb (struct pt_regs *regs, int rx, float *val) {
1130 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);
1131 FP_DECL_EX;
1132 int mode;
1133
1134 mode = current->thread.fp_regs.fpc & 3;
1135 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f);
1136 FP_UNPACK_SP(SB, val);
1137 FP_MUL_S(SR, SA, SB);
1138 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR);
1139 return _fex;
1140}
1141
1142/* Multiply float to double */
1143static int emu_mdebr (struct pt_regs *regs, int rx, int ry) {
1144 FP_DECL_S(SA); FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR);
1145 FP_DECL_EX;
1146 int mode;
1147
1148 mode = current->thread.fp_regs.fpc & 3;
1149 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f);
1150 FP_CONV (D, S, 2, 1, DA, SA);
1151 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[ry].f);
1152 FP_CONV (D, S, 2, 1, DB, SA);
1153 FP_MUL_D(DR, DA, DB);
1154 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR);
1155 return _fex;
1156}
1157
1158/* Multiply float to double */
1159static int emu_mdeb (struct pt_regs *regs, int rx, float *val) {
1160 FP_DECL_S(SA); FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR);
1161 FP_DECL_EX;
1162 int mode;
1163
1164 mode = current->thread.fp_regs.fpc & 3;
1165 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f);
1166 FP_CONV (D, S, 2, 1, DA, SA);
1167 FP_UNPACK_SP(SA, val);
1168 FP_CONV (D, S, 2, 1, DB, SA);
1169 FP_MUL_D(DR, DA, DB);
1170 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR);
1171 return _fex;
1172}
1173
1174/* Multiply and add double */
1175static int emu_madbr (struct pt_regs *regs, int rx, int ry, int rz) {
1176 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DC); FP_DECL_D(DR);
1177 FP_DECL_EX;
1178 int mode;
1179
1180 mode = current->thread.fp_regs.fpc & 3;
1181 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d);
1182 FP_UNPACK_DP(DB, &current->thread.fp_regs.fprs[ry].d);
1183 FP_UNPACK_DP(DC, &current->thread.fp_regs.fprs[rz].d);
1184 FP_MUL_D(DR, DA, DB);
1185 FP_ADD_D(DR, DR, DC);
1186 FP_PACK_DP(&current->thread.fp_regs.fprs[rz].d, DR);
1187 return _fex;
1188}
1189
1190/* Multiply and add double */
1191static int emu_madb (struct pt_regs *regs, int rx, double *val, int rz) {
1192 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DC); FP_DECL_D(DR);
1193 FP_DECL_EX;
1194 int mode;
1195
1196 mode = current->thread.fp_regs.fpc & 3;
1197 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d);
1198 FP_UNPACK_DP(DB, val);
1199 FP_UNPACK_DP(DC, &current->thread.fp_regs.fprs[rz].d);
1200 FP_MUL_D(DR, DA, DB);
1201 FP_ADD_D(DR, DR, DC);
1202 FP_PACK_DP(&current->thread.fp_regs.fprs[rz].d, DR);
1203 return _fex;
1204}
1205
1206/* Multiply and add float */
1207static int emu_maebr (struct pt_regs *regs, int rx, int ry, int rz) {
1208 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SC); FP_DECL_S(SR);
1209 FP_DECL_EX;
1210 int mode;
1211
1212 mode = current->thread.fp_regs.fpc & 3;
1213 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f);
1214 FP_UNPACK_SP(SB, &current->thread.fp_regs.fprs[ry].f);
1215 FP_UNPACK_SP(SC, &current->thread.fp_regs.fprs[rz].f);
1216 FP_MUL_S(SR, SA, SB);
1217 FP_ADD_S(SR, SR, SC);
1218 FP_PACK_SP(&current->thread.fp_regs.fprs[rz].f, SR);
1219 return _fex;
1220}
1221
1222/* Multiply and add float */
1223static int emu_maeb (struct pt_regs *regs, int rx, float *val, int rz) {
1224 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SC); FP_DECL_S(SR);
1225 FP_DECL_EX;
1226 int mode;
1227
1228 mode = current->thread.fp_regs.fpc & 3;
1229 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f);
1230 FP_UNPACK_SP(SB, val);
1231 FP_UNPACK_SP(SC, &current->thread.fp_regs.fprs[rz].f);
1232 FP_MUL_S(SR, SA, SB);
1233 FP_ADD_S(SR, SR, SC);
1234 FP_PACK_SP(&current->thread.fp_regs.fprs[rz].f, SR);
1235 return _fex;
1236}
1237
1238/* Multiply and subtract double */
1239static int emu_msdbr (struct pt_regs *regs, int rx, int ry, int rz) {
1240 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DC); FP_DECL_D(DR);
1241 FP_DECL_EX;
1242 int mode;
1243
1244 mode = current->thread.fp_regs.fpc & 3;
1245 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d);
1246 FP_UNPACK_DP(DB, &current->thread.fp_regs.fprs[ry].d);
1247 FP_UNPACK_DP(DC, &current->thread.fp_regs.fprs[rz].d);
1248 FP_MUL_D(DR, DA, DB);
1249 FP_SUB_D(DR, DR, DC);
1250 FP_PACK_DP(&current->thread.fp_regs.fprs[rz].d, DR);
1251 return _fex;
1252}
1253
1254/* Multiply and subtract double */
1255static int emu_msdb (struct pt_regs *regs, int rx, double *val, int rz) {
1256 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DC); FP_DECL_D(DR);
1257 FP_DECL_EX;
1258 int mode;
1259
1260 mode = current->thread.fp_regs.fpc & 3;
1261 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d);
1262 FP_UNPACK_DP(DB, val);
1263 FP_UNPACK_DP(DC, &current->thread.fp_regs.fprs[rz].d);
1264 FP_MUL_D(DR, DA, DB);
1265 FP_SUB_D(DR, DR, DC);
1266 FP_PACK_DP(&current->thread.fp_regs.fprs[rz].d, DR);
1267 return _fex;
1268}
1269
1270/* Multiply and subtract float */
1271static int emu_msebr (struct pt_regs *regs, int rx, int ry, int rz) {
1272 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SC); FP_DECL_S(SR);
1273 FP_DECL_EX;
1274 int mode;
1275
1276 mode = current->thread.fp_regs.fpc & 3;
1277 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f);
1278 FP_UNPACK_SP(SB, &current->thread.fp_regs.fprs[ry].f);
1279 FP_UNPACK_SP(SC, &current->thread.fp_regs.fprs[rz].f);
1280 FP_MUL_S(SR, SA, SB);
1281 FP_SUB_S(SR, SR, SC);
1282 FP_PACK_SP(&current->thread.fp_regs.fprs[rz].f, SR);
1283 return _fex;
1284}
1285
1286/* Multiply and subtract float */
1287static int emu_mseb (struct pt_regs *regs, int rx, float *val, int rz) {
1288 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SC); FP_DECL_S(SR);
1289 FP_DECL_EX;
1290 int mode;
1291
1292 mode = current->thread.fp_regs.fpc & 3;
1293 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f);
1294 FP_UNPACK_SP(SB, val);
1295 FP_UNPACK_SP(SC, &current->thread.fp_regs.fprs[rz].f);
1296 FP_MUL_S(SR, SA, SB);
1297 FP_SUB_S(SR, SR, SC);
1298 FP_PACK_SP(&current->thread.fp_regs.fprs[rz].f, SR);
1299 return _fex;
1300}
1301
1302/* Set floating point control word */
1303static int emu_sfpc (struct pt_regs *regs, int rx, int ry) {
1304 __u32 temp;
1305
1306 temp = regs->gprs[rx];
1307 if ((temp & ~FPC_VALID_MASK) != 0)
1308 return SIGILL;
1309 current->thread.fp_regs.fpc = temp;
1310 return 0;
1311}
1312
1313/* Square root long double */
1314static int emu_sqxbr (struct pt_regs *regs, int rx, int ry) {
1315 FP_DECL_Q(QA); FP_DECL_Q(QR);
1316 FP_DECL_EX;
1317 mathemu_ldcv cvt;
1318 int mode;
1319
1320 mode = current->thread.fp_regs.fpc & 3;
1321 cvt.w.high = current->thread.fp_regs.fprs[ry].ui;
1322 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui;
1323 FP_UNPACK_QP(QA, &cvt.ld);
1324 FP_SQRT_Q(QR, QA);
1325 FP_PACK_QP(&cvt.ld, QR);
1326 current->thread.fp_regs.fprs[rx].ui = cvt.w.high;
1327 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low;
1328 emu_set_CC_cs(regs, QR_c, QR_s);
1329 return _fex;
1330}
1331
1332/* Square root double */
1333static int emu_sqdbr (struct pt_regs *regs, int rx, int ry) {
1334 FP_DECL_D(DA); FP_DECL_D(DR);
1335 FP_DECL_EX;
1336 int mode;
1337
1338 mode = current->thread.fp_regs.fpc & 3;
1339 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[ry].d);
1340 FP_SQRT_D(DR, DA);
1341 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR);
1342 emu_set_CC_cs(regs, DR_c, DR_s);
1343 return _fex;
1344}
1345
1346/* Square root double */
1347static int emu_sqdb (struct pt_regs *regs, int rx, double *val) {
1348 FP_DECL_D(DA); FP_DECL_D(DR);
1349 FP_DECL_EX;
1350 int mode;
1351
1352 mode = current->thread.fp_regs.fpc & 3;
1353 FP_UNPACK_DP(DA, val);
1354 FP_SQRT_D(DR, DA);
1355 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR);
1356 emu_set_CC_cs(regs, DR_c, DR_s);
1357 return _fex;
1358}
1359
1360/* Square root float */
1361static int emu_sqebr (struct pt_regs *regs, int rx, int ry) {
1362 FP_DECL_S(SA); FP_DECL_S(SR);
1363 FP_DECL_EX;
1364 int mode;
1365
1366 mode = current->thread.fp_regs.fpc & 3;
1367 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[ry].f);
1368 FP_SQRT_S(SR, SA);
1369 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR);
1370 emu_set_CC_cs(regs, SR_c, SR_s);
1371 return _fex;
1372}
1373
1374/* Square root float */
1375static int emu_sqeb (struct pt_regs *regs, int rx, float *val) {
1376 FP_DECL_S(SA); FP_DECL_S(SR);
1377 FP_DECL_EX;
1378 int mode;
1379
1380 mode = current->thread.fp_regs.fpc & 3;
1381 FP_UNPACK_SP(SA, val);
1382 FP_SQRT_S(SR, SA);
1383 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR);
1384 emu_set_CC_cs(regs, SR_c, SR_s);
1385 return _fex;
1386}
1387
1388/* Subtract long double */
1389static int emu_sxbr (struct pt_regs *regs, int rx, int ry) {
1390 FP_DECL_Q(QA); FP_DECL_Q(QB); FP_DECL_Q(QR);
1391 FP_DECL_EX;
1392 mathemu_ldcv cvt;
1393 int mode;
1394
1395 mode = current->thread.fp_regs.fpc & 3;
1396 cvt.w.high = current->thread.fp_regs.fprs[rx].ui;
1397 cvt.w.low = current->thread.fp_regs.fprs[rx+2].ui;
1398 FP_UNPACK_QP(QA, &cvt.ld);
1399 cvt.w.high = current->thread.fp_regs.fprs[ry].ui;
1400 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui;
1401 FP_UNPACK_QP(QB, &cvt.ld);
1402 FP_SUB_Q(QR, QA, QB);
1403 FP_PACK_QP(&cvt.ld, QR);
1404 current->thread.fp_regs.fprs[rx].ui = cvt.w.high;
1405 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low;
1406 emu_set_CC_cs(regs, QR_c, QR_s);
1407 return _fex;
1408}
1409
1410/* Subtract double */
1411static int emu_sdbr (struct pt_regs *regs, int rx, int ry) {
1412 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR);
1413 FP_DECL_EX;
1414 int mode;
1415
1416 mode = current->thread.fp_regs.fpc & 3;
1417 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d);
1418 FP_UNPACK_DP(DB, &current->thread.fp_regs.fprs[ry].d);
1419 FP_SUB_D(DR, DA, DB);
1420 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR);
1421 emu_set_CC_cs(regs, DR_c, DR_s);
1422 return _fex;
1423}
1424
1425/* Subtract double */
1426static int emu_sdb (struct pt_regs *regs, int rx, double *val) {
1427 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR);
1428 FP_DECL_EX;
1429 int mode;
1430
1431 mode = current->thread.fp_regs.fpc & 3;
1432 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d);
1433 FP_UNPACK_DP(DB, val);
1434 FP_SUB_D(DR, DA, DB);
1435 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR);
1436 emu_set_CC_cs(regs, DR_c, DR_s);
1437 return _fex;
1438}
1439
1440/* Subtract float */
1441static int emu_sebr (struct pt_regs *regs, int rx, int ry) {
1442 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);
1443 FP_DECL_EX;
1444 int mode;
1445
1446 mode = current->thread.fp_regs.fpc & 3;
1447 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f);
1448 FP_UNPACK_SP(SB, &current->thread.fp_regs.fprs[ry].f);
1449 FP_SUB_S(SR, SA, SB);
1450 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR);
1451 emu_set_CC_cs(regs, SR_c, SR_s);
1452 return _fex;
1453}
1454
1455/* Subtract float */
1456static int emu_seb (struct pt_regs *regs, int rx, float *val) {
1457 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);
1458 FP_DECL_EX;
1459 int mode;
1460
1461 mode = current->thread.fp_regs.fpc & 3;
1462 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f);
1463 FP_UNPACK_SP(SB, val);
1464 FP_SUB_S(SR, SA, SB);
1465 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR);
1466 emu_set_CC_cs(regs, SR_c, SR_s);
1467 return _fex;
1468}
1469
1470/* Test data class long double */
1471static int emu_tcxb (struct pt_regs *regs, int rx, long val) {
1472 FP_DECL_Q(QA);
1473 mathemu_ldcv cvt;
1474 int bit;
1475
1476 cvt.w.high = current->thread.fp_regs.fprs[rx].ui;
1477 cvt.w.low = current->thread.fp_regs.fprs[rx+2].ui;
1478 FP_UNPACK_RAW_QP(QA, &cvt.ld);
1479 switch (QA_e) {
1480 default:
1481 bit = 8; /* normalized number */
1482 break;
1483 case 0:
1484 if (_FP_FRAC_ZEROP_4(QA))
1485 bit = 10; /* zero */
1486 else
1487 bit = 6; /* denormalized number */
1488 break;
1489 case _FP_EXPMAX_Q:
1490 if (_FP_FRAC_ZEROP_4(QA))
1491 bit = 4; /* infinity */
1492 else if (_FP_FRAC_HIGH_RAW_Q(QA) & _FP_QNANBIT_Q)
1493 bit = 2; /* quiet NAN */
1494 else
1495 bit = 0; /* signaling NAN */
1496 break;
1497 }
1498 if (!QA_s)
1499 bit++;
1500 emu_set_CC(regs, ((__u32) val >> bit) & 1);
1501 return 0;
1502}
1503
1504/* Test data class double */
1505static int emu_tcdb (struct pt_regs *regs, int rx, long val) {
1506 FP_DECL_D(DA);
1507 int bit;
1508
1509 FP_UNPACK_RAW_DP(DA, &current->thread.fp_regs.fprs[rx].d);
1510 switch (DA_e) {
1511 default:
1512 bit = 8; /* normalized number */
1513 break;
1514 case 0:
1515 if (_FP_FRAC_ZEROP_2(DA))
1516 bit = 10; /* zero */
1517 else
1518 bit = 6; /* denormalized number */
1519 break;
1520 case _FP_EXPMAX_D:
1521 if (_FP_FRAC_ZEROP_2(DA))
1522 bit = 4; /* infinity */
1523 else if (_FP_FRAC_HIGH_RAW_D(DA) & _FP_QNANBIT_D)
1524 bit = 2; /* quiet NAN */
1525 else
1526 bit = 0; /* signaling NAN */
1527 break;
1528 }
1529 if (!DA_s)
1530 bit++;
1531 emu_set_CC(regs, ((__u32) val >> bit) & 1);
1532 return 0;
1533}
1534
1535/* Test data class float */
1536static int emu_tceb (struct pt_regs *regs, int rx, long val) {
1537 FP_DECL_S(SA);
1538 int bit;
1539
1540 FP_UNPACK_RAW_SP(SA, &current->thread.fp_regs.fprs[rx].f);
1541 switch (SA_e) {
1542 default:
1543 bit = 8; /* normalized number */
1544 break;
1545 case 0:
1546 if (_FP_FRAC_ZEROP_1(SA))
1547 bit = 10; /* zero */
1548 else
1549 bit = 6; /* denormalized number */
1550 break;
1551 case _FP_EXPMAX_S:
1552 if (_FP_FRAC_ZEROP_1(SA))
1553 bit = 4; /* infinity */
1554 else if (_FP_FRAC_HIGH_RAW_S(SA) & _FP_QNANBIT_S)
1555 bit = 2; /* quiet NAN */
1556 else
1557 bit = 0; /* signaling NAN */
1558 break;
1559 }
1560 if (!SA_s)
1561 bit++;
1562 emu_set_CC(regs, ((__u32) val >> bit) & 1);
1563 return 0;
1564}
1565
1566static inline void emu_load_regd(int reg) {
1567 if ((reg&9) != 0) /* test if reg in {0,2,4,6} */
1568 return;
1569 asm volatile( /* load reg from fp_regs.fprs[reg] */
1570 " bras 1,0f\n"
1571 " ld 0,0(%1)\n"
1572 "0: ex %0,0(1)"
1573 : /* no output */
1574 : "a" (reg<<4),"a" (&current->thread.fp_regs.fprs[reg].d)
1575 : "1");
1576}
1577
1578static inline void emu_load_rege(int reg) {
1579 if ((reg&9) != 0) /* test if reg in {0,2,4,6} */
1580 return;
1581 asm volatile( /* load reg from fp_regs.fprs[reg] */
1582 " bras 1,0f\n"
1583 " le 0,0(%1)\n"
1584 "0: ex %0,0(1)"
1585 : /* no output */
1586 : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].f)
1587 : "1");
1588}
1589
1590static inline void emu_store_regd(int reg) {
1591 if ((reg&9) != 0) /* test if reg in {0,2,4,6} */
1592 return;
1593 asm volatile( /* store reg to fp_regs.fprs[reg] */
1594 " bras 1,0f\n"
1595 " std 0,0(%1)\n"
1596 "0: ex %0,0(1)"
1597 : /* no output */
1598 : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].d)
1599 : "1");
1600}
1601
1602
1603static inline void emu_store_rege(int reg) {
1604 if ((reg&9) != 0) /* test if reg in {0,2,4,6} */
1605 return;
1606 asm volatile( /* store reg to fp_regs.fprs[reg] */
1607 " bras 1,0f\n"
1608 " ste 0,0(%1)\n"
1609 "0: ex %0,0(1)"
1610 : /* no output */
1611 : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].f)
1612 : "1");
1613}
1614
1615int math_emu_b3(__u8 *opcode, struct pt_regs * regs) {
1616 int _fex = 0;
1617 static const __u8 format_table[256] = {
1618 [0x00] = 0x03,[0x01] = 0x03,[0x02] = 0x03,[0x03] = 0x03,
1619 [0x04] = 0x0f,[0x05] = 0x0d,[0x06] = 0x0e,[0x07] = 0x0d,
1620 [0x08] = 0x03,[0x09] = 0x03,[0x0a] = 0x03,[0x0b] = 0x03,
1621 [0x0c] = 0x0f,[0x0d] = 0x03,[0x0e] = 0x06,[0x0f] = 0x06,
1622 [0x10] = 0x02,[0x11] = 0x02,[0x12] = 0x02,[0x13] = 0x02,
1623 [0x14] = 0x03,[0x15] = 0x02,[0x16] = 0x01,[0x17] = 0x03,
1624 [0x18] = 0x02,[0x19] = 0x02,[0x1a] = 0x02,[0x1b] = 0x02,
1625 [0x1c] = 0x02,[0x1d] = 0x02,[0x1e] = 0x05,[0x1f] = 0x05,
1626 [0x40] = 0x01,[0x41] = 0x01,[0x42] = 0x01,[0x43] = 0x01,
1627 [0x44] = 0x12,[0x45] = 0x0d,[0x46] = 0x11,[0x47] = 0x04,
1628 [0x48] = 0x01,[0x49] = 0x01,[0x4a] = 0x01,[0x4b] = 0x01,
1629 [0x4c] = 0x01,[0x4d] = 0x01,[0x53] = 0x06,[0x57] = 0x06,
1630 [0x5b] = 0x05,[0x5f] = 0x05,[0x84] = 0x13,[0x8c] = 0x13,
1631 [0x94] = 0x09,[0x95] = 0x08,[0x96] = 0x07,[0x98] = 0x0c,
1632 [0x99] = 0x0b,[0x9a] = 0x0a
1633 };
1634 static const void *jump_table[256]= {
1635 [0x00] = emu_lpebr,[0x01] = emu_lnebr,[0x02] = emu_ltebr,
1636 [0x03] = emu_lcebr,[0x04] = emu_ldebr,[0x05] = emu_lxdbr,
1637 [0x06] = emu_lxebr,[0x07] = emu_mxdbr,[0x08] = emu_kebr,
1638 [0x09] = emu_cebr, [0x0a] = emu_aebr, [0x0b] = emu_sebr,
1639 [0x0c] = emu_mdebr,[0x0d] = emu_debr, [0x0e] = emu_maebr,
1640 [0x0f] = emu_msebr,[0x10] = emu_lpdbr,[0x11] = emu_lndbr,
1641 [0x12] = emu_ltdbr,[0x13] = emu_lcdbr,[0x14] = emu_sqebr,
1642 [0x15] = emu_sqdbr,[0x16] = emu_sqxbr,[0x17] = emu_meebr,
1643 [0x18] = emu_kdbr, [0x19] = emu_cdbr, [0x1a] = emu_adbr,
1644 [0x1b] = emu_sdbr, [0x1c] = emu_mdbr, [0x1d] = emu_ddbr,
1645 [0x1e] = emu_madbr,[0x1f] = emu_msdbr,[0x40] = emu_lpxbr,
1646 [0x41] = emu_lnxbr,[0x42] = emu_ltxbr,[0x43] = emu_lcxbr,
1647 [0x44] = emu_ledbr,[0x45] = emu_ldxbr,[0x46] = emu_lexbr,
1648 [0x47] = emu_fixbr,[0x48] = emu_kxbr, [0x49] = emu_cxbr,
1649 [0x4a] = emu_axbr, [0x4b] = emu_sxbr, [0x4c] = emu_mxbr,
1650 [0x4d] = emu_dxbr, [0x53] = emu_diebr,[0x57] = emu_fiebr,
1651 [0x5b] = emu_didbr,[0x5f] = emu_fidbr,[0x84] = emu_sfpc,
1652 [0x8c] = emu_efpc, [0x94] = emu_cefbr,[0x95] = emu_cdfbr,
1653 [0x96] = emu_cxfbr,[0x98] = emu_cfebr,[0x99] = emu_cfdbr,
1654 [0x9a] = emu_cfxbr
1655 };
1656
1657 switch (format_table[opcode[1]]) {
1658 case 1: /* RRE format, long double operation */
1659 if (opcode[3] & 0x22)
1660 return SIGILL;
1661 emu_store_regd((opcode[3] >> 4) & 15);
1662 emu_store_regd(((opcode[3] >> 4) & 15) + 2);
1663 emu_store_regd(opcode[3] & 15);
1664 emu_store_regd((opcode[3] & 15) + 2);
1665 /* call the emulation function */
1666 _fex = ((int (*)(struct pt_regs *,int, int))
1667 jump_table[opcode[1]])
1668 (regs, opcode[3] >> 4, opcode[3] & 15);
1669 emu_load_regd((opcode[3] >> 4) & 15);
1670 emu_load_regd(((opcode[3] >> 4) & 15) + 2);
1671 emu_load_regd(opcode[3] & 15);
1672 emu_load_regd((opcode[3] & 15) + 2);
1673 break;
1674 case 2: /* RRE format, double operation */
1675 emu_store_regd((opcode[3] >> 4) & 15);
1676 emu_store_regd(opcode[3] & 15);
1677 /* call the emulation function */
1678 _fex = ((int (*)(struct pt_regs *, int, int))
1679 jump_table[opcode[1]])
1680 (regs, opcode[3] >> 4, opcode[3] & 15);
1681 emu_load_regd((opcode[3] >> 4) & 15);
1682 emu_load_regd(opcode[3] & 15);
1683 break;
1684 case 3: /* RRE format, float operation */
1685 emu_store_rege((opcode[3] >> 4) & 15);
1686 emu_store_rege(opcode[3] & 15);
1687 /* call the emulation function */
1688 _fex = ((int (*)(struct pt_regs *, int, int))
1689 jump_table[opcode[1]])
1690 (regs, opcode[3] >> 4, opcode[3] & 15);
1691 emu_load_rege((opcode[3] >> 4) & 15);
1692 emu_load_rege(opcode[3] & 15);
1693 break;
1694 case 4: /* RRF format, long double operation */
1695 if (opcode[3] & 0x22)
1696 return SIGILL;
1697 emu_store_regd((opcode[3] >> 4) & 15);
1698 emu_store_regd(((opcode[3] >> 4) & 15) + 2);
1699 emu_store_regd(opcode[3] & 15);
1700 emu_store_regd((opcode[3] & 15) + 2);
1701 /* call the emulation function */
1702 _fex = ((int (*)(struct pt_regs *, int, int, int))
1703 jump_table[opcode[1]])
1704 (regs, opcode[3] >> 4, opcode[3] & 15, opcode[2] >> 4);
1705 emu_load_regd((opcode[3] >> 4) & 15);
1706 emu_load_regd(((opcode[3] >> 4) & 15) + 2);
1707 emu_load_regd(opcode[3] & 15);
1708 emu_load_regd((opcode[3] & 15) + 2);
1709 break;
1710 case 5: /* RRF format, double operation */
1711 emu_store_regd((opcode[2] >> 4) & 15);
1712 emu_store_regd((opcode[3] >> 4) & 15);
1713 emu_store_regd(opcode[3] & 15);
1714 /* call the emulation function */
1715 _fex = ((int (*)(struct pt_regs *, int, int, int))
1716 jump_table[opcode[1]])
1717 (regs, opcode[3] >> 4, opcode[3] & 15, opcode[2] >> 4);
1718 emu_load_regd((opcode[2] >> 4) & 15);
1719 emu_load_regd((opcode[3] >> 4) & 15);
1720 emu_load_regd(opcode[3] & 15);
1721 break;
1722 case 6: /* RRF format, float operation */
1723 emu_store_rege((opcode[2] >> 4) & 15);
1724 emu_store_rege((opcode[3] >> 4) & 15);
1725 emu_store_rege(opcode[3] & 15);
1726 /* call the emulation function */
1727 _fex = ((int (*)(struct pt_regs *, int, int, int))
1728 jump_table[opcode[1]])
1729 (regs, opcode[3] >> 4, opcode[3] & 15, opcode[2] >> 4);
1730 emu_load_rege((opcode[2] >> 4) & 15);
1731 emu_load_rege((opcode[3] >> 4) & 15);
1732 emu_load_rege(opcode[3] & 15);
1733 break;
1734 case 7: /* RRE format, cxfbr instruction */
1735 /* call the emulation function */
1736 if (opcode[3] & 0x20)
1737 return SIGILL;
1738 _fex = ((int (*)(struct pt_regs *, int, int))
1739 jump_table[opcode[1]])
1740 (regs, opcode[3] >> 4, opcode[3] & 15);
1741 emu_load_regd((opcode[3] >> 4) & 15);
1742 emu_load_regd(((opcode[3] >> 4) & 15) + 2);
1743 break;
1744 case 8: /* RRE format, cdfbr instruction */
1745 /* call the emulation function */
1746 _fex = ((int (*)(struct pt_regs *, int, int))
1747 jump_table[opcode[1]])
1748 (regs, opcode[3] >> 4, opcode[3] & 15);
1749 emu_load_regd((opcode[3] >> 4) & 15);
1750 break;
1751 case 9: /* RRE format, cefbr instruction */
1752 /* call the emulation function */
1753 _fex = ((int (*)(struct pt_regs *, int, int))
1754 jump_table[opcode[1]])
1755 (regs, opcode[3] >> 4, opcode[3] & 15);
1756 emu_load_rege((opcode[3] >> 4) & 15);
1757 break;
1758 case 10: /* RRF format, cfxbr instruction */
1759 if ((opcode[2] & 128) == 128 || (opcode[2] & 96) == 32)
1760 /* mask of { 2,3,8-15 } is invalid */
1761 return SIGILL;
1762 if (opcode[3] & 2)
1763 return SIGILL;
1764 emu_store_regd(opcode[3] & 15);
1765 emu_store_regd((opcode[3] & 15) + 2);
1766 /* call the emulation function */
1767 _fex = ((int (*)(struct pt_regs *, int, int, int))
1768 jump_table[opcode[1]])
1769 (regs, opcode[3] >> 4, opcode[3] & 15, opcode[2] >> 4);
1770 break;
1771 case 11: /* RRF format, cfdbr instruction */
1772 if ((opcode[2] & 128) == 128 || (opcode[2] & 96) == 32)
1773 /* mask of { 2,3,8-15 } is invalid */
1774 return SIGILL;
1775 emu_store_regd(opcode[3] & 15);
1776 /* call the emulation function */
1777 _fex = ((int (*)(struct pt_regs *, int, int, int))
1778 jump_table[opcode[1]])
1779 (regs, opcode[3] >> 4, opcode[3] & 15, opcode[2] >> 4);
1780 break;
1781 case 12: /* RRF format, cfebr instruction */
1782 if ((opcode[2] & 128) == 128 || (opcode[2] & 96) == 32)
1783 /* mask of { 2,3,8-15 } is invalid */
1784 return SIGILL;
1785 emu_store_rege(opcode[3] & 15);
1786 /* call the emulation function */
1787 _fex = ((int (*)(struct pt_regs *, int, int, int))
1788 jump_table[opcode[1]])
1789 (regs, opcode[3] >> 4, opcode[3] & 15, opcode[2] >> 4);
1790 break;
1791 case 13: /* RRE format, ldxbr & mdxbr instruction */
1792 /* double store but long double load */
1793 if (opcode[3] & 0x20)
1794 return SIGILL;
1795 emu_store_regd((opcode[3] >> 4) & 15);
1796 emu_store_regd(opcode[3] & 15);
1797 /* call the emulation function */
1798 _fex = ((int (*)(struct pt_regs *, int, int))
1799 jump_table[opcode[1]])
1800 (regs, opcode[3] >> 4, opcode[3] & 15);
1801 emu_load_regd((opcode[3] >> 4) & 15);
1802 emu_load_regd(((opcode[3] >> 4) & 15) + 2);
1803 break;
1804 case 14: /* RRE format, ldxbr & mdxbr instruction */
1805 /* float store but long double load */
1806 if (opcode[3] & 0x20)
1807 return SIGILL;
1808 emu_store_rege((opcode[3] >> 4) & 15);
1809 emu_store_rege(opcode[3] & 15);
1810 /* call the emulation function */
1811 _fex = ((int (*)(struct pt_regs *, int, int))
1812 jump_table[opcode[1]])
1813 (regs, opcode[3] >> 4, opcode[3] & 15);
1814 emu_load_regd((opcode[3] >> 4) & 15);
1815 emu_load_regd(((opcode[3] >> 4) & 15) + 2);
1816 break;
1817 case 15: /* RRE format, ldebr & mdebr instruction */
1818 /* float store but double load */
1819 emu_store_rege((opcode[3] >> 4) & 15);
1820 emu_store_rege(opcode[3] & 15);
1821 /* call the emulation function */
1822 _fex = ((int (*)(struct pt_regs *, int, int))
1823 jump_table[opcode[1]])
1824 (regs, opcode[3] >> 4, opcode[3] & 15);
1825 emu_load_regd((opcode[3] >> 4) & 15);
1826 break;
1827 case 16: /* RRE format, ldxbr instruction */
1828 /* long double store but double load */
1829 if (opcode[3] & 2)
1830 return SIGILL;
1831 emu_store_regd(opcode[3] & 15);
1832 emu_store_regd((opcode[3] & 15) + 2);
1833 /* call the emulation function */
1834 _fex = ((int (*)(struct pt_regs *, int, int))
1835 jump_table[opcode[1]])
1836 (regs, opcode[3] >> 4, opcode[3] & 15);
1837 emu_load_regd((opcode[3] >> 4) & 15);
1838 break;
1839 case 17: /* RRE format, ldxbr instruction */
1840 /* long double store but float load */
1841 if (opcode[3] & 2)
1842 return SIGILL;
1843 emu_store_regd(opcode[3] & 15);
1844 emu_store_regd((opcode[3] & 15) + 2);
1845 /* call the emulation function */
1846 _fex = ((int (*)(struct pt_regs *, int, int))
1847 jump_table[opcode[1]])
1848 (regs, opcode[3] >> 4, opcode[3] & 15);
1849 emu_load_rege((opcode[3] >> 4) & 15);
1850 break;
1851 case 18: /* RRE format, ledbr instruction */
1852 /* double store but float load */
1853 emu_store_regd(opcode[3] & 15);
1854 /* call the emulation function */
1855 _fex = ((int (*)(struct pt_regs *, int, int))
1856 jump_table[opcode[1]])
1857 (regs, opcode[3] >> 4, opcode[3] & 15);
1858 emu_load_rege((opcode[3] >> 4) & 15);
1859 break;
1860 case 19: /* RRE format, efpc & sfpc instruction */
1861 /* call the emulation function */
1862 _fex = ((int (*)(struct pt_regs *, int, int))
1863 jump_table[opcode[1]])
1864 (regs, opcode[3] >> 4, opcode[3] & 15);
1865 break;
1866 default: /* invalid operation */
1867 return SIGILL;
1868 }
1869 if (_fex != 0) {
1870 current->thread.fp_regs.fpc |= _fex;
1871 if (current->thread.fp_regs.fpc & (_fex << 8))
1872 return SIGFPE;
1873 }
1874 return 0;
1875}
1876
1877static void* calc_addr(struct pt_regs *regs, int rx, int rb, int disp)
1878{
1879 addr_t addr;
1880
1881 rx &= 15;
1882 rb &= 15;
1883 addr = disp & 0xfff;
1884 addr += (rx != 0) ? regs->gprs[rx] : 0; /* + index */
1885 addr += (rb != 0) ? regs->gprs[rb] : 0; /* + base */
1886 return (void*) addr;
1887}
1888
1889int math_emu_ed(__u8 *opcode, struct pt_regs * regs) {
1890 int _fex = 0;
1891
1892 static const __u8 format_table[256] = {
1893 [0x04] = 0x06,[0x05] = 0x05,[0x06] = 0x07,[0x07] = 0x05,
1894 [0x08] = 0x02,[0x09] = 0x02,[0x0a] = 0x02,[0x0b] = 0x02,
1895 [0x0c] = 0x06,[0x0d] = 0x02,[0x0e] = 0x04,[0x0f] = 0x04,
1896 [0x10] = 0x08,[0x11] = 0x09,[0x12] = 0x0a,[0x14] = 0x02,
1897 [0x15] = 0x01,[0x17] = 0x02,[0x18] = 0x01,[0x19] = 0x01,
1898 [0x1a] = 0x01,[0x1b] = 0x01,[0x1c] = 0x01,[0x1d] = 0x01,
1899 [0x1e] = 0x03,[0x1f] = 0x03,
1900 };
1901 static const void *jump_table[]= {
1902 [0x04] = emu_ldeb,[0x05] = emu_lxdb,[0x06] = emu_lxeb,
1903 [0x07] = emu_mxdb,[0x08] = emu_keb, [0x09] = emu_ceb,
1904 [0x0a] = emu_aeb, [0x0b] = emu_seb, [0x0c] = emu_mdeb,
1905 [0x0d] = emu_deb, [0x0e] = emu_maeb,[0x0f] = emu_mseb,
1906 [0x10] = emu_tceb,[0x11] = emu_tcdb,[0x12] = emu_tcxb,
1907 [0x14] = emu_sqeb,[0x15] = emu_sqdb,[0x17] = emu_meeb,
1908 [0x18] = emu_kdb, [0x19] = emu_cdb, [0x1a] = emu_adb,
1909 [0x1b] = emu_sdb, [0x1c] = emu_mdb, [0x1d] = emu_ddb,
1910 [0x1e] = emu_madb,[0x1f] = emu_msdb
1911 };
1912
1913 switch (format_table[opcode[5]]) {
1914 case 1: /* RXE format, double constant */ {
1915 __u64 *dxb, temp;
1916 __u32 opc;
1917
1918 emu_store_regd((opcode[1] >> 4) & 15);
1919 opc = *((__u32 *) opcode);
1920 dxb = (__u64 *) calc_addr(regs, opc >> 16, opc >> 12, opc);
1921 mathemu_copy_from_user(&temp, dxb, 8);
1922 /* call the emulation function */
1923 _fex = ((int (*)(struct pt_regs *, int, double *))
1924 jump_table[opcode[5]])
1925 (regs, opcode[1] >> 4, (double *) &temp);
1926 emu_load_regd((opcode[1] >> 4) & 15);
1927 break;
1928 }
1929 case 2: /* RXE format, float constant */ {
1930 __u32 *dxb, temp;
1931 __u32 opc;
1932
1933 emu_store_rege((opcode[1] >> 4) & 15);
1934 opc = *((__u32 *) opcode);
1935 dxb = (__u32 *) calc_addr(regs, opc >> 16, opc >> 12, opc);
1936 mathemu_get_user(temp, dxb);
1937 /* call the emulation function */
1938 _fex = ((int (*)(struct pt_regs *, int, float *))
1939 jump_table[opcode[5]])
1940 (regs, opcode[1] >> 4, (float *) &temp);
1941 emu_load_rege((opcode[1] >> 4) & 15);
1942 break;
1943 }
1944 case 3: /* RXF format, double constant */ {
1945 __u64 *dxb, temp;
1946 __u32 opc;
1947
1948 emu_store_regd((opcode[1] >> 4) & 15);
1949 emu_store_regd((opcode[4] >> 4) & 15);
1950 opc = *((__u32 *) opcode);
1951 dxb = (__u64 *) calc_addr(regs, opc >> 16, opc >> 12, opc);
1952 mathemu_copy_from_user(&temp, dxb, 8);
1953 /* call the emulation function */
1954 _fex = ((int (*)(struct pt_regs *, int, double *, int))
1955 jump_table[opcode[5]])
1956 (regs, opcode[1] >> 4, (double *) &temp, opcode[4] >> 4);
1957 emu_load_regd((opcode[1] >> 4) & 15);
1958 break;
1959 }
1960 case 4: /* RXF format, float constant */ {
1961 __u32 *dxb, temp;
1962 __u32 opc;
1963
1964 emu_store_rege((opcode[1] >> 4) & 15);
1965 emu_store_rege((opcode[4] >> 4) & 15);
1966 opc = *((__u32 *) opcode);
1967 dxb = (__u32 *) calc_addr(regs, opc >> 16, opc >> 12, opc);
1968 mathemu_get_user(temp, dxb);
1969 /* call the emulation function */
1970 _fex = ((int (*)(struct pt_regs *, int, float *, int))
1971 jump_table[opcode[5]])
1972 (regs, opcode[1] >> 4, (float *) &temp, opcode[4] >> 4);
1973 emu_load_rege((opcode[4] >> 4) & 15);
1974 break;
1975 }
1976 case 5: /* RXE format, double constant */
1977 /* store double and load long double */
1978 {
1979 __u64 *dxb, temp;
1980 __u32 opc;
1981 if ((opcode[1] >> 4) & 0x20)
1982 return SIGILL;
1983 emu_store_regd((opcode[1] >> 4) & 15);
1984 opc = *((__u32 *) opcode);
1985 dxb = (__u64 *) calc_addr(regs, opc >> 16, opc >> 12, opc);
1986 mathemu_copy_from_user(&temp, dxb, 8);
1987 /* call the emulation function */
1988 _fex = ((int (*)(struct pt_regs *, int, double *))
1989 jump_table[opcode[5]])
1990 (regs, opcode[1] >> 4, (double *) &temp);
1991 emu_load_regd((opcode[1] >> 4) & 15);
1992 emu_load_regd(((opcode[1] >> 4) & 15) + 2);
1993 break;
1994 }
1995 case 6: /* RXE format, float constant */
1996 /* store float and load double */
1997 {
1998 __u32 *dxb, temp;
1999 __u32 opc;
2000 emu_store_rege((opcode[1] >> 4) & 15);
2001 opc = *((__u32 *) opcode);
2002 dxb = (__u32 *) calc_addr(regs, opc >> 16, opc >> 12, opc);
2003 mathemu_get_user(temp, dxb);
2004 /* call the emulation function */
2005 _fex = ((int (*)(struct pt_regs *, int, float *))
2006 jump_table[opcode[5]])
2007 (regs, opcode[1] >> 4, (float *) &temp);
2008 emu_load_regd((opcode[1] >> 4) & 15);
2009 break;
2010 }
2011 case 7: /* RXE format, float constant */
2012 /* store float and load long double */
2013 {
2014 __u32 *dxb, temp;
2015 __u32 opc;
2016 if ((opcode[1] >> 4) & 0x20)
2017 return SIGILL;
2018 emu_store_rege((opcode[1] >> 4) & 15);
2019 opc = *((__u32 *) opcode);
2020 dxb = (__u32 *) calc_addr(regs, opc >> 16, opc >> 12, opc);
2021 mathemu_get_user(temp, dxb);
2022 /* call the emulation function */
2023 _fex = ((int (*)(struct pt_regs *, int, float *))
2024 jump_table[opcode[5]])
2025 (regs, opcode[1] >> 4, (float *) &temp);
2026 emu_load_regd((opcode[1] >> 4) & 15);
2027 emu_load_regd(((opcode[1] >> 4) & 15) + 2);
2028 break;
2029 }
2030 case 8: /* RXE format, RX address used as int value */ {
2031 __u64 dxb;
2032 __u32 opc;
2033
2034 emu_store_rege((opcode[1] >> 4) & 15);
2035 opc = *((__u32 *) opcode);
2036 dxb = (__u64) calc_addr(regs, opc >> 16, opc >> 12, opc);
2037 /* call the emulation function */
2038 _fex = ((int (*)(struct pt_regs *, int, long))
2039 jump_table[opcode[5]])
2040 (regs, opcode[1] >> 4, dxb);
2041 break;
2042 }
2043 case 9: /* RXE format, RX address used as int value */ {
2044 __u64 dxb;
2045 __u32 opc;
2046
2047 emu_store_regd((opcode[1] >> 4) & 15);
2048 opc = *((__u32 *) opcode);
2049 dxb = (__u64) calc_addr(regs, opc >> 16, opc >> 12, opc);
2050 /* call the emulation function */
2051 _fex = ((int (*)(struct pt_regs *, int, long))
2052 jump_table[opcode[5]])
2053 (regs, opcode[1] >> 4, dxb);
2054 break;
2055 }
2056 case 10: /* RXE format, RX address used as int value */ {
2057 __u64 dxb;
2058 __u32 opc;
2059
2060 if ((opcode[1] >> 4) & 2)
2061 return SIGILL;
2062 emu_store_regd((opcode[1] >> 4) & 15);
2063 emu_store_regd(((opcode[1] >> 4) & 15) + 2);
2064 opc = *((__u32 *) opcode);
2065 dxb = (__u64) calc_addr(regs, opc >> 16, opc >> 12, opc);
2066 /* call the emulation function */
2067 _fex = ((int (*)(struct pt_regs *, int, long))
2068 jump_table[opcode[5]])
2069 (regs, opcode[1] >> 4, dxb);
2070 break;
2071 }
2072 default: /* invalid operation */
2073 return SIGILL;
2074 }
2075 if (_fex != 0) {
2076 current->thread.fp_regs.fpc |= _fex;
2077 if (current->thread.fp_regs.fpc & (_fex << 8))
2078 return SIGFPE;
2079 }
2080 return 0;
2081}
2082
2083/*
2084 * Emulate LDR Rx,Ry with Rx or Ry not in {0, 2, 4, 6}
2085 */
2086int math_emu_ldr(__u8 *opcode) {
2087 s390_fp_regs *fp_regs = &current->thread.fp_regs;
2088 __u16 opc = *((__u16 *) opcode);
2089
2090 if ((opc & 0x90) == 0) { /* test if rx in {0,2,4,6} */
2091 /* we got an exception therefore ry can't be in {0,2,4,6} */
2092 asm volatile( /* load rx from fp_regs.fprs[ry] */
2093 " bras 1,0f\n"
2094 " ld 0,0(%1)\n"
2095 "0: ex %0,0(1)"
2096 : /* no output */
2097 : "a" (opc & 0xf0), "a" (&fp_regs->fprs[opc & 0xf].d)
2098 : "1");
2099 } else if ((opc & 0x9) == 0) { /* test if ry in {0,2,4,6} */
2100 asm volatile ( /* store ry to fp_regs.fprs[rx] */
2101 " bras 1,0f\n"
2102 " std 0,0(%1)\n"
2103 "0: ex %0,0(1)"
2104 : /* no output */
2105 : "a" ((opc & 0xf) << 4),
2106 "a" (&fp_regs->fprs[(opc & 0xf0)>>4].d)
2107 : "1");
2108 } else /* move fp_regs.fprs[ry] to fp_regs.fprs[rx] */
2109 fp_regs->fprs[(opc & 0xf0) >> 4] = fp_regs->fprs[opc & 0xf];
2110 return 0;
2111}
2112
2113/*
2114 * Emulate LER Rx,Ry with Rx or Ry not in {0, 2, 4, 6}
2115 */
2116int math_emu_ler(__u8 *opcode) {
2117 s390_fp_regs *fp_regs = &current->thread.fp_regs;
2118 __u16 opc = *((__u16 *) opcode);
2119
2120 if ((opc & 0x90) == 0) { /* test if rx in {0,2,4,6} */
2121 /* we got an exception therefore ry can't be in {0,2,4,6} */
2122 asm volatile( /* load rx from fp_regs.fprs[ry] */
2123 " bras 1,0f\n"
2124 " le 0,0(%1)\n"
2125 "0: ex %0,0(1)"
2126 : /* no output */
2127 : "a" (opc & 0xf0), "a" (&fp_regs->fprs[opc & 0xf].f)
2128 : "1");
2129 } else if ((opc & 0x9) == 0) { /* test if ry in {0,2,4,6} */
2130 asm volatile( /* store ry to fp_regs.fprs[rx] */
2131 " bras 1,0f\n"
2132 " ste 0,0(%1)\n"
2133 "0: ex %0,0(1)"
2134 : /* no output */
2135 : "a" ((opc & 0xf) << 4),
2136 "a" (&fp_regs->fprs[(opc & 0xf0) >> 4].f)
2137 : "1");
2138 } else /* move fp_regs.fprs[ry] to fp_regs.fprs[rx] */
2139 fp_regs->fprs[(opc & 0xf0) >> 4] = fp_regs->fprs[opc & 0xf];
2140 return 0;
2141}
2142
2143/*
2144 * Emulate LD R,D(X,B) with R not in {0, 2, 4, 6}
2145 */
2146int math_emu_ld(__u8 *opcode, struct pt_regs * regs) {
2147 s390_fp_regs *fp_regs = &current->thread.fp_regs;
2148 __u32 opc = *((__u32 *) opcode);
2149 __u64 *dxb;
2150
2151 dxb = (__u64 *) calc_addr(regs, opc >> 16, opc >> 12, opc);
2152 mathemu_copy_from_user(&fp_regs->fprs[(opc >> 20) & 0xf].d, dxb, 8);
2153 return 0;
2154}
2155
2156/*
2157 * Emulate LE R,D(X,B) with R not in {0, 2, 4, 6}
2158 */
2159int math_emu_le(__u8 *opcode, struct pt_regs * regs) {
2160 s390_fp_regs *fp_regs = &current->thread.fp_regs;
2161 __u32 opc = *((__u32 *) opcode);
2162 __u32 *mem, *dxb;
2163
2164 dxb = (__u32 *) calc_addr(regs, opc >> 16, opc >> 12, opc);
2165 mem = (__u32 *) (&fp_regs->fprs[(opc >> 20) & 0xf].f);
2166 mathemu_get_user(mem[0], dxb);
2167 return 0;
2168}
2169
2170/*
2171 * Emulate STD R,D(X,B) with R not in {0, 2, 4, 6}
2172 */
2173int math_emu_std(__u8 *opcode, struct pt_regs * regs) {
2174 s390_fp_regs *fp_regs = &current->thread.fp_regs;
2175 __u32 opc = *((__u32 *) opcode);
2176 __u64 *dxb;
2177
2178 dxb = (__u64 *) calc_addr(regs, opc >> 16, opc >> 12, opc);
2179 mathemu_copy_to_user(dxb, &fp_regs->fprs[(opc >> 20) & 0xf].d, 8);
2180 return 0;
2181}
2182
2183/*
2184 * Emulate STE R,D(X,B) with R not in {0, 2, 4, 6}
2185 */
2186int math_emu_ste(__u8 *opcode, struct pt_regs * regs) {
2187 s390_fp_regs *fp_regs = &current->thread.fp_regs;
2188 __u32 opc = *((__u32 *) opcode);
2189 __u32 *mem, *dxb;
2190
2191 dxb = (__u32 *) calc_addr(regs, opc >> 16, opc >> 12, opc);
2192 mem = (__u32 *) (&fp_regs->fprs[(opc >> 20) & 0xf].f);
2193 mathemu_put_user(mem[0], dxb);
2194 return 0;
2195}
2196
2197/*
2198 * Emulate LFPC D(B)
2199 */
2200int math_emu_lfpc(__u8 *opcode, struct pt_regs *regs) {
2201 __u32 opc = *((__u32 *) opcode);
2202 __u32 *dxb, temp;
2203
2204 dxb= (__u32 *) calc_addr(regs, 0, opc>>12, opc);
2205 mathemu_get_user(temp, dxb);
2206 if ((temp & ~FPC_VALID_MASK) != 0)
2207 return SIGILL;
2208 current->thread.fp_regs.fpc = temp;
2209 return 0;
2210}
2211
2212/*
2213 * Emulate STFPC D(B)
2214 */
2215int math_emu_stfpc(__u8 *opcode, struct pt_regs *regs) {
2216 __u32 opc = *((__u32 *) opcode);
2217 __u32 *dxb;
2218
2219 dxb= (__u32 *) calc_addr(regs, 0, opc>>12, opc);
2220 mathemu_put_user(current->thread.fp_regs.fpc, dxb);
2221 return 0;
2222}
2223
2224/*
2225 * Emulate SRNM D(B)
2226 */
2227int math_emu_srnm(__u8 *opcode, struct pt_regs *regs) {
2228 __u32 opc = *((__u32 *) opcode);
2229 __u32 temp;
2230
2231 temp = calc_addr(regs, 0, opc>>12, opc);
2232 current->thread.fp_regs.fpc &= ~3;
2233 current->thread.fp_regs.fpc |= (temp & 3);
2234 return 0;
2235}
2236
2237/* broken compiler ... */
2238long long
2239__negdi2 (long long u)
2240{
2241
2242 union lll {
2243 long long ll;
2244 long s[2];
2245 };
2246
2247 union lll w,uu;
2248
2249 uu.ll = u;
2250
2251 w.s[1] = -uu.s[1];
2252 w.s[0] = -uu.s[0] - ((int) w.s[1] != 0);
2253
2254 return w.ll;
2255}