File: /usr/src/linux/arch/s390/math-emu/math.c

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