~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/s390/math-emu/math.c

Version: ~ [ linux-5.4 ] ~ [ linux-5.3.13 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.86 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.156 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.203 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.202 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.78 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp