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