2 * arch/s390/math-emu/math.c
5 * Copyright (C) 1999-2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
6 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
8 * 'math.c' emulates IEEE instructions on a S390 processor
9 * that does not have the IEEE fpu (all processors before G5).
12 #include <linux/config.h>
13 #include <linux/types.h>
14 #include <linux/sched.h>
16 #include <asm/uaccess.h>
17 #include <asm/lowcore.h>
20 #include <math-emu/soft-fp.h>
21 #include <math-emu/single.h>
22 #include <math-emu/double.h>
23 #include <math-emu/quad.h>
26 * I miss a macro to round a floating point number to the
27 * nearest integer in the same floating point format.
29 #define _FP_TO_FPINT_ROUND(fs, wc, X) \
34 if (X##_e > _FP_FRACBITS_##fs + _FP_EXPBIAS_##fs) \
35 { /* floating point number has no bits after the dot. */ \
37 else if (X##_e <= _FP_FRACBITS_##fs + _FP_EXPBIAS_##fs && \
38 X##_e > _FP_EXPBIAS_##fs) \
39 { /* some bits before the dot, some after it. */ \
40 _FP_FRAC_SRS_##wc(X, _FP_WFRACBITS_##fs, \
41 X##_e - _FP_EXPBIAS_##fs \
42 + _FP_FRACBITS_##fs); \
44 _FP_FRAC_SLL_##wc(X, X##_e - _FP_EXPBIAS_##fs \
45 + _FP_FRACBITS_##fs); \
48 { /* all bits after the dot. */ \
49 FP_SET_EXCEPTION(FP_EX_INEXACT); \
50 X##_c = FP_CLS_ZERO; \
60 #define FP_TO_FPINT_ROUND_S(X) _FP_TO_FPINT_ROUND(S,1,X)
61 #define FP_TO_FPINT_ROUND_D(X) _FP_TO_FPINT_ROUND(D,2,X)
62 #define FP_TO_FPINT_ROUND_Q(X) _FP_TO_FPINT_ROUND(Q,4,X)
73 int sysctl_ieee_emulation_warnings
=1;
76 #define mathemu_put_user(x, p) \
78 if (put_user((x),(p))) \
82 #define mathemu_get_user(x, p) \
84 if (get_user((x),(p))) \
88 #define mathemu_copy_from_user(d, s, n)\
90 if (copy_from_user((d),(s),(n)) != 0) \
94 #define mathemu_copy_to_user(d, s, n) \
96 if (copy_to_user((d),(s),(n)) != 0) \
100 static void display_emulation_not_implemented(struct pt_regs
*regs
, char *instr
)
105 if(sysctl_ieee_emulation_warnings
)
108 location
= (__u16
*)(regs
->psw
.addr
-S390_lowcore
.pgm_ilc
);
109 printk("%s ieee fpu instruction not emulated "
110 "process name: %s pid: %d \n",
111 instr
, current
->comm
, current
->pid
);
112 printk("%s's PSW: %08lx %08lx\n", instr
,
113 (unsigned long) regs
->psw
.mask
,
114 (unsigned long) location
);
118 static inline void emu_set_CC (struct pt_regs
*regs
, int cc
)
120 regs
->psw
.mask
= (regs
->psw
.mask
& 0xFFFFCFFF) | ((cc
&3) << 12);
124 * Set the condition code in the user psw.
126 * 1 : Result is less than zero
127 * 2 : Result is greater than zero
128 * 3 : Result is NaN or INF
130 static inline void emu_set_CC_cs(struct pt_regs
*regs
, int class, int sign
)
135 emu_set_CC(regs
, sign
? 1 : 2);
146 /* Add long double */
147 static int emu_axbr (struct pt_regs
*regs
, int rx
, int ry
) {
148 FP_DECL_Q(QA
); FP_DECL_Q(QB
); FP_DECL_Q(QR
);
153 mode
= current
->thread
.fp_regs
.fpc
& 3;
154 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[rx
].ui
;
155 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[rx
+2].ui
;
156 FP_UNPACK_QP(QA
, &cvt
.ld
);
157 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[ry
].ui
;
158 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[ry
+2].ui
;
159 FP_UNPACK_QP(QB
, &cvt
.ld
);
160 FP_ADD_Q(QR
, QA
, QB
);
161 FP_PACK_QP(&cvt
.ld
, QR
);
162 current
->thread
.fp_regs
.fprs
[rx
].ui
= cvt
.w
.high
;
163 current
->thread
.fp_regs
.fprs
[rx
+2].ui
= cvt
.w
.low
;
164 emu_set_CC_cs(regs
, QR_c
, QR_s
);
169 static int emu_adbr (struct pt_regs
*regs
, int rx
, int ry
) {
170 FP_DECL_D(DA
); FP_DECL_D(DB
); FP_DECL_D(DR
);
174 mode
= current
->thread
.fp_regs
.fpc
& 3;
175 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[rx
].d
);
176 FP_UNPACK_DP(DB
, ¤t
->thread
.fp_regs
.fprs
[ry
].d
);
177 FP_ADD_D(DR
, DA
, DB
);
178 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rx
].d
, DR
);
179 emu_set_CC_cs(regs
, DR_c
, DR_s
);
184 static int emu_adb (struct pt_regs
*regs
, int rx
, double *val
) {
185 FP_DECL_D(DA
); FP_DECL_D(DB
); FP_DECL_D(DR
);
189 mode
= current
->thread
.fp_regs
.fpc
& 3;
190 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[rx
].d
);
191 FP_UNPACK_DP(DB
, val
);
192 FP_ADD_D(DR
, DA
, DB
);
193 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rx
].d
, DR
);
194 emu_set_CC_cs(regs
, DR_c
, DR_s
);
199 static int emu_aebr (struct pt_regs
*regs
, int rx
, int ry
) {
200 FP_DECL_S(SA
); FP_DECL_S(SB
); FP_DECL_S(SR
);
204 mode
= current
->thread
.fp_regs
.fpc
& 3;
205 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[rx
].f
);
206 FP_UNPACK_SP(SB
, ¤t
->thread
.fp_regs
.fprs
[ry
].f
);
207 FP_ADD_S(SR
, SA
, SB
);
208 FP_PACK_SP(¤t
->thread
.fp_regs
.fprs
[rx
].f
, SR
);
209 emu_set_CC_cs(regs
, SR_c
, SR_s
);
214 static int emu_aeb (struct pt_regs
*regs
, int rx
, float *val
) {
215 FP_DECL_S(SA
); FP_DECL_S(SB
); FP_DECL_S(SR
);
219 mode
= current
->thread
.fp_regs
.fpc
& 3;
220 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[rx
].f
);
221 FP_UNPACK_SP(SB
, val
);
222 FP_ADD_S(SR
, SA
, SB
);
223 FP_PACK_SP(¤t
->thread
.fp_regs
.fprs
[rx
].f
, SR
);
224 emu_set_CC_cs(regs
, SR_c
, SR_s
);
228 /* Compare long double */
229 static int emu_cxbr (struct pt_regs
*regs
, int rx
, int ry
) {
230 FP_DECL_Q(QA
); FP_DECL_Q(QB
);
234 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[rx
].ui
;
235 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[rx
+2].ui
;
236 FP_UNPACK_RAW_QP(QA
, &cvt
.ld
);
237 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[ry
].ui
;
238 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[ry
+2].ui
;
239 FP_UNPACK_RAW_QP(QB
, &cvt
.ld
);
240 FP_CMP_Q(IR
, QA
, QB
, 3);
242 * IR == -1 if DA < DB, IR == 0 if DA == DB,
243 * IR == 1 if DA > DB and IR == 3 if unorderded
245 emu_set_CC(regs
, (IR
== -1) ? 1 : (IR
== 1) ? 2 : IR
);
250 static int emu_cdbr (struct pt_regs
*regs
, int rx
, int ry
) {
251 FP_DECL_D(DA
); FP_DECL_D(DB
);
254 FP_UNPACK_RAW_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[rx
].d
);
255 FP_UNPACK_RAW_DP(DB
, ¤t
->thread
.fp_regs
.fprs
[ry
].d
);
256 FP_CMP_D(IR
, DA
, DB
, 3);
258 * IR == -1 if DA < DB, IR == 0 if DA == DB,
259 * IR == 1 if DA > DB and IR == 3 if unorderded
261 emu_set_CC(regs
, (IR
== -1) ? 1 : (IR
== 1) ? 2 : IR
);
266 static int emu_cdb (struct pt_regs
*regs
, int rx
, double *val
) {
267 FP_DECL_D(DA
); FP_DECL_D(DB
);
270 FP_UNPACK_RAW_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[rx
].d
);
271 FP_UNPACK_RAW_DP(DB
, val
);
272 FP_CMP_D(IR
, DA
, DB
, 3);
274 * IR == -1 if DA < DB, IR == 0 if DA == DB,
275 * IR == 1 if DA > DB and IR == 3 if unorderded
277 emu_set_CC(regs
, (IR
== -1) ? 1 : (IR
== 1) ? 2 : IR
);
282 static int emu_cebr (struct pt_regs
*regs
, int rx
, int ry
) {
283 FP_DECL_S(SA
); FP_DECL_S(SB
);
286 FP_UNPACK_RAW_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[rx
].f
);
287 FP_UNPACK_RAW_SP(SB
, ¤t
->thread
.fp_regs
.fprs
[ry
].f
);
288 FP_CMP_S(IR
, SA
, SB
, 3);
290 * IR == -1 if DA < DB, IR == 0 if DA == DB,
291 * IR == 1 if DA > DB and IR == 3 if unorderded
293 emu_set_CC(regs
, (IR
== -1) ? 1 : (IR
== 1) ? 2 : IR
);
298 static int emu_ceb (struct pt_regs
*regs
, int rx
, float *val
) {
299 FP_DECL_S(SA
); FP_DECL_S(SB
);
302 FP_UNPACK_RAW_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[rx
].f
);
303 FP_UNPACK_RAW_SP(SB
, val
);
304 FP_CMP_S(IR
, SA
, SB
, 3);
306 * IR == -1 if DA < DB, IR == 0 if DA == DB,
307 * IR == 1 if DA > DB and IR == 3 if unorderded
309 emu_set_CC(regs
, (IR
== -1) ? 1 : (IR
== 1) ? 2 : IR
);
313 /* Compare and signal long double */
314 static int emu_kxbr (struct pt_regs
*regs
, int rx
, int ry
) {
315 FP_DECL_Q(QA
); FP_DECL_Q(QB
);
320 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[rx
].ui
;
321 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[rx
+2].ui
;
322 FP_UNPACK_RAW_QP(QA
, &cvt
.ld
);
323 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[ry
].ui
;
324 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[ry
+2].ui
;
325 FP_UNPACK_QP(QB
, &cvt
.ld
);
326 FP_CMP_Q(IR
, QA
, QB
, 3);
328 * IR == -1 if DA < DB, IR == 0 if DA == DB,
329 * IR == 1 if DA > DB and IR == 3 if unorderded
331 emu_set_CC(regs
, (IR
== -1) ? 1 : (IR
== 1) ? 2 : IR
);
333 FP_SET_EXCEPTION (FP_EX_INVALID
);
337 /* Compare and signal double */
338 static int emu_kdbr (struct pt_regs
*regs
, int rx
, int ry
) {
339 FP_DECL_D(DA
); FP_DECL_D(DB
);
343 FP_UNPACK_RAW_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[rx
].d
);
344 FP_UNPACK_RAW_DP(DB
, ¤t
->thread
.fp_regs
.fprs
[ry
].d
);
345 FP_CMP_D(IR
, DA
, DB
, 3);
347 * IR == -1 if DA < DB, IR == 0 if DA == DB,
348 * IR == 1 if DA > DB and IR == 3 if unorderded
350 emu_set_CC(regs
, (IR
== -1) ? 1 : (IR
== 1) ? 2 : IR
);
352 FP_SET_EXCEPTION (FP_EX_INVALID
);
356 /* Compare and signal double */
357 static int emu_kdb (struct pt_regs
*regs
, int rx
, double *val
) {
358 FP_DECL_D(DA
); FP_DECL_D(DB
);
362 FP_UNPACK_RAW_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[rx
].d
);
363 FP_UNPACK_RAW_DP(DB
, val
);
364 FP_CMP_D(IR
, DA
, DB
, 3);
366 * IR == -1 if DA < DB, IR == 0 if DA == DB,
367 * IR == 1 if DA > DB and IR == 3 if unorderded
369 emu_set_CC(regs
, (IR
== -1) ? 1 : (IR
== 1) ? 2 : IR
);
371 FP_SET_EXCEPTION (FP_EX_INVALID
);
375 /* Compare and signal float */
376 static int emu_kebr (struct pt_regs
*regs
, int rx
, int ry
) {
377 FP_DECL_S(SA
); FP_DECL_S(SB
);
381 FP_UNPACK_RAW_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[rx
].f
);
382 FP_UNPACK_RAW_SP(SB
, ¤t
->thread
.fp_regs
.fprs
[ry
].f
);
383 FP_CMP_S(IR
, SA
, SB
, 3);
385 * IR == -1 if DA < DB, IR == 0 if DA == DB,
386 * IR == 1 if DA > DB and IR == 3 if unorderded
388 emu_set_CC(regs
, (IR
== -1) ? 1 : (IR
== 1) ? 2 : IR
);
390 FP_SET_EXCEPTION (FP_EX_INVALID
);
394 /* Compare and signal float */
395 static int emu_keb (struct pt_regs
*regs
, int rx
, float *val
) {
396 FP_DECL_S(SA
); FP_DECL_S(SB
);
400 FP_UNPACK_RAW_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[rx
].f
);
401 FP_UNPACK_RAW_SP(SB
, val
);
402 FP_CMP_S(IR
, SA
, SB
, 3);
404 * IR == -1 if DA < DB, IR == 0 if DA == DB,
405 * IR == 1 if DA > DB and IR == 3 if unorderded
407 emu_set_CC(regs
, (IR
== -1) ? 1 : (IR
== 1) ? 2 : IR
);
409 FP_SET_EXCEPTION (FP_EX_INVALID
);
413 /* Convert from fixed long double */
414 static int emu_cxfbr (struct pt_regs
*regs
, int rx
, int ry
) {
421 mode
= current
->thread
.fp_regs
.fpc
& 3;
423 FP_FROM_INT_Q(QR
, si
, 32, int);
424 FP_PACK_QP(&cvt
.ld
, QR
);
425 current
->thread
.fp_regs
.fprs
[rx
].ui
= cvt
.w
.high
;
426 current
->thread
.fp_regs
.fprs
[rx
+2].ui
= cvt
.w
.low
;
430 /* Convert from fixed double */
431 static int emu_cdfbr (struct pt_regs
*regs
, int rx
, int ry
) {
437 mode
= current
->thread
.fp_regs
.fpc
& 3;
439 FP_FROM_INT_D(DR
, si
, 32, int);
440 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rx
].d
, DR
);
444 /* Convert from fixed float */
445 static int emu_cefbr (struct pt_regs
*regs
, int rx
, int ry
) {
451 mode
= current
->thread
.fp_regs
.fpc
& 3;
453 FP_FROM_INT_S(SR
, si
, 32, int);
454 FP_PACK_SP(¤t
->thread
.fp_regs
.fprs
[rx
].f
, SR
);
458 /* Convert to fixed long double */
459 static int emu_cfxbr (struct pt_regs
*regs
, int rx
, int ry
, int mask
) {
467 mode
= current
->thread
.fp_regs
.fpc
& 3;
469 mode
= FP_RND_NEAREST
;
472 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[ry
].ui
;
473 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[ry
+2].ui
;
474 FP_UNPACK_QP(QA
, &cvt
.ld
);
475 FP_TO_INT_ROUND_Q(si
, QA
, 32, 1);
477 emu_set_CC_cs(regs
, QA_c
, QA_s
);
481 /* Convert to fixed double */
482 static int emu_cfdbr (struct pt_regs
*regs
, int rx
, int ry
, int mask
) {
489 mode
= current
->thread
.fp_regs
.fpc
& 3;
491 mode
= FP_RND_NEAREST
;
494 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[ry
].d
);
495 FP_TO_INT_ROUND_D(si
, DA
, 32, 1);
497 emu_set_CC_cs(regs
, DA_c
, DA_s
);
501 /* Convert to fixed float */
502 static int emu_cfebr (struct pt_regs
*regs
, int rx
, int ry
, int mask
) {
509 mode
= current
->thread
.fp_regs
.fpc
& 3;
511 mode
= FP_RND_NEAREST
;
514 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[ry
].f
);
515 FP_TO_INT_ROUND_S(si
, SA
, 32, 1);
517 emu_set_CC_cs(regs
, SA_c
, SA_s
);
521 /* Divide long double */
522 static int emu_dxbr (struct pt_regs
*regs
, int rx
, int ry
) {
523 FP_DECL_Q(QA
); FP_DECL_Q(QB
); FP_DECL_Q(QR
);
528 mode
= current
->thread
.fp_regs
.fpc
& 3;
529 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[rx
].ui
;
530 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[rx
+2].ui
;
531 FP_UNPACK_QP(QA
, &cvt
.ld
);
532 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[ry
].ui
;
533 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[ry
+2].ui
;
534 FP_UNPACK_QP(QB
, &cvt
.ld
);
535 FP_DIV_Q(QR
, QA
, QB
);
536 FP_PACK_QP(&cvt
.ld
, QR
);
537 current
->thread
.fp_regs
.fprs
[rx
].ui
= cvt
.w
.high
;
538 current
->thread
.fp_regs
.fprs
[rx
+2].ui
= cvt
.w
.low
;
543 static int emu_ddbr (struct pt_regs
*regs
, int rx
, int ry
) {
544 FP_DECL_D(DA
); FP_DECL_D(DB
); FP_DECL_D(DR
);
548 mode
= current
->thread
.fp_regs
.fpc
& 3;
549 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[rx
].d
);
550 FP_UNPACK_DP(DB
, ¤t
->thread
.fp_regs
.fprs
[ry
].d
);
551 FP_DIV_D(DR
, DA
, DB
);
552 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rx
].d
, DR
);
557 static int emu_ddb (struct pt_regs
*regs
, int rx
, double *val
) {
558 FP_DECL_D(DA
); FP_DECL_D(DB
); FP_DECL_D(DR
);
562 mode
= current
->thread
.fp_regs
.fpc
& 3;
563 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[rx
].d
);
564 FP_UNPACK_DP(DB
, val
);
565 FP_DIV_D(DR
, DA
, DB
);
566 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rx
].d
, DR
);
571 static int emu_debr (struct pt_regs
*regs
, int rx
, int ry
) {
572 FP_DECL_S(SA
); FP_DECL_S(SB
); FP_DECL_S(SR
);
576 mode
= current
->thread
.fp_regs
.fpc
& 3;
577 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[rx
].f
);
578 FP_UNPACK_SP(SB
, ¤t
->thread
.fp_regs
.fprs
[ry
].f
);
579 FP_DIV_S(SR
, SA
, SB
);
580 FP_PACK_SP(¤t
->thread
.fp_regs
.fprs
[rx
].f
, SR
);
585 static int emu_deb (struct pt_regs
*regs
, int rx
, float *val
) {
586 FP_DECL_S(SA
); FP_DECL_S(SB
); FP_DECL_S(SR
);
590 mode
= current
->thread
.fp_regs
.fpc
& 3;
591 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[rx
].f
);
592 FP_UNPACK_SP(SB
, val
);
593 FP_DIV_S(SR
, SA
, SB
);
594 FP_PACK_SP(¤t
->thread
.fp_regs
.fprs
[rx
].f
, SR
);
598 /* Divide to integer double */
599 static int emu_didbr (struct pt_regs
*regs
, int rx
, int ry
, int mask
) {
600 display_emulation_not_implemented(regs
, "didbr");
604 /* Divide to integer float */
605 static int emu_diebr (struct pt_regs
*regs
, int rx
, int ry
, int mask
) {
606 display_emulation_not_implemented(regs
, "diebr");
611 static int emu_efpc (struct pt_regs
*regs
, int rx
, int ry
) {
612 regs
->gprs
[rx
] = current
->thread
.fp_regs
.fpc
;
616 /* Load and test long double */
617 static int emu_ltxbr (struct pt_regs
*regs
, int rx
, int ry
) {
618 s390_fp_regs
*fp_regs
= ¤t
->thread
.fp_regs
;
623 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[ry
].ui
;
624 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[ry
+2].ui
;
625 FP_UNPACK_QP(QA
, &cvt
.ld
);
626 fp_regs
->fprs
[rx
].ui
= fp_regs
->fprs
[ry
].ui
;
627 fp_regs
->fprs
[rx
+2].ui
= fp_regs
->fprs
[ry
+2].ui
;
628 emu_set_CC_cs(regs
, QA_c
, QA_s
);
632 /* Load and test double */
633 static int emu_ltdbr (struct pt_regs
*regs
, int rx
, int ry
) {
634 s390_fp_regs
*fp_regs
= ¤t
->thread
.fp_regs
;
638 FP_UNPACK_DP(DA
, &fp_regs
->fprs
[ry
].d
);
639 fp_regs
->fprs
[rx
].ui
= fp_regs
->fprs
[ry
].ui
;
640 emu_set_CC_cs(regs
, DA_c
, DA_s
);
644 /* Load and test double */
645 static int emu_ltebr (struct pt_regs
*regs
, int rx
, int ry
) {
646 s390_fp_regs
*fp_regs
= ¤t
->thread
.fp_regs
;
650 FP_UNPACK_SP(SA
, &fp_regs
->fprs
[ry
].f
);
651 fp_regs
->fprs
[rx
].ui
= fp_regs
->fprs
[ry
].ui
;
652 emu_set_CC_cs(regs
, SA_c
, SA_s
);
656 /* Load complement long double */
657 static int emu_lcxbr (struct pt_regs
*regs
, int rx
, int ry
) {
658 FP_DECL_Q(QA
); FP_DECL_Q(QR
);
663 mode
= current
->thread
.fp_regs
.fpc
& 3;
664 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[ry
].ui
;
665 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[ry
+2].ui
;
666 FP_UNPACK_QP(QA
, &cvt
.ld
);
668 FP_PACK_QP(&cvt
.ld
, QR
);
669 current
->thread
.fp_regs
.fprs
[rx
].ui
= cvt
.w
.high
;
670 current
->thread
.fp_regs
.fprs
[rx
+2].ui
= cvt
.w
.low
;
671 emu_set_CC_cs(regs
, QR_c
, QR_s
);
675 /* Load complement double */
676 static int emu_lcdbr (struct pt_regs
*regs
, int rx
, int ry
) {
677 FP_DECL_D(DA
); FP_DECL_D(DR
);
681 mode
= current
->thread
.fp_regs
.fpc
& 3;
682 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[ry
].d
);
684 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rx
].d
, DR
);
685 emu_set_CC_cs(regs
, DR_c
, DR_s
);
689 /* Load complement float */
690 static int emu_lcebr (struct pt_regs
*regs
, int rx
, int ry
) {
691 FP_DECL_S(SA
); FP_DECL_S(SR
);
695 mode
= current
->thread
.fp_regs
.fpc
& 3;
696 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[ry
].f
);
698 FP_PACK_SP(¤t
->thread
.fp_regs
.fprs
[rx
].f
, SR
);
699 emu_set_CC_cs(regs
, SR_c
, SR_s
);
703 /* Load floating point integer long double */
704 static int emu_fixbr (struct pt_regs
*regs
, int rx
, int ry
, int mask
) {
705 s390_fp_regs
*fp_regs
= ¤t
->thread
.fp_regs
;
713 mode
= fp_regs
->fpc
& 3;
715 mode
= FP_RND_NEAREST
;
718 cvt
.w
.high
= fp_regs
->fprs
[ry
].ui
;
719 cvt
.w
.low
= fp_regs
->fprs
[ry
+2].ui
;
720 FP_UNPACK_QP(QA
, &cvt
.ld
);
721 FP_TO_FPINT_ROUND_Q(QA
);
722 FP_PACK_QP(&cvt
.ld
, QA
);
723 fp_regs
->fprs
[rx
].ui
= cvt
.w
.high
;
724 fp_regs
->fprs
[rx
+2].ui
= cvt
.w
.low
;
728 /* Load floating point integer double */
729 static int emu_fidbr (struct pt_regs
*regs
, int rx
, int ry
, int mask
) {
730 /* FIXME: rounding mode !! */
731 s390_fp_regs
*fp_regs
= ¤t
->thread
.fp_regs
;
738 mode
= fp_regs
->fpc
& 3;
740 mode
= FP_RND_NEAREST
;
743 FP_UNPACK_DP(DA
, &fp_regs
->fprs
[ry
].d
);
744 FP_TO_FPINT_ROUND_D(DA
);
745 FP_PACK_DP(&fp_regs
->fprs
[rx
].d
, DA
);
749 /* Load floating point integer float */
750 static int emu_fiebr (struct pt_regs
*regs
, int rx
, int ry
, int mask
) {
751 s390_fp_regs
*fp_regs
= ¤t
->thread
.fp_regs
;
758 mode
= fp_regs
->fpc
& 3;
760 mode
= FP_RND_NEAREST
;
763 FP_UNPACK_SP(SA
, &fp_regs
->fprs
[ry
].f
);
764 FP_TO_FPINT_ROUND_S(SA
);
765 FP_PACK_SP(&fp_regs
->fprs
[rx
].f
, SA
);
769 /* Load lengthened double to long double */
770 static int emu_lxdbr (struct pt_regs
*regs
, int rx
, int ry
) {
771 FP_DECL_D(DA
); FP_DECL_Q(QR
);
776 mode
= current
->thread
.fp_regs
.fpc
& 3;
777 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[ry
].d
);
778 FP_CONV (Q
, D
, 4, 2, QR
, DA
);
779 FP_PACK_QP(&cvt
.ld
, QR
);
780 current
->thread
.fp_regs
.fprs
[rx
].ui
= cvt
.w
.high
;
781 current
->thread
.fp_regs
.fprs
[rx
+2].ui
= cvt
.w
.low
;
785 /* Load lengthened double to long double */
786 static int emu_lxdb (struct pt_regs
*regs
, int rx
, double *val
) {
787 FP_DECL_D(DA
); FP_DECL_Q(QR
);
792 mode
= current
->thread
.fp_regs
.fpc
& 3;
793 FP_UNPACK_DP(DA
, val
);
794 FP_CONV (Q
, D
, 4, 2, QR
, DA
);
795 FP_PACK_QP(&cvt
.ld
, QR
);
796 current
->thread
.fp_regs
.fprs
[rx
].ui
= cvt
.w
.high
;
797 current
->thread
.fp_regs
.fprs
[rx
+2].ui
= cvt
.w
.low
;
801 /* Load lengthened float to long double */
802 static int emu_lxebr (struct pt_regs
*regs
, int rx
, int ry
) {
803 FP_DECL_S(SA
); FP_DECL_Q(QR
);
808 mode
= current
->thread
.fp_regs
.fpc
& 3;
809 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[ry
].f
);
810 FP_CONV (Q
, S
, 4, 1, QR
, SA
);
811 FP_PACK_QP(&cvt
.ld
, QR
);
812 current
->thread
.fp_regs
.fprs
[rx
].ui
= cvt
.w
.high
;
813 current
->thread
.fp_regs
.fprs
[rx
+2].ui
= cvt
.w
.low
;
817 /* Load lengthened float to long double */
818 static int emu_lxeb (struct pt_regs
*regs
, int rx
, float *val
) {
819 FP_DECL_S(SA
); FP_DECL_Q(QR
);
824 mode
= current
->thread
.fp_regs
.fpc
& 3;
825 FP_UNPACK_SP(SA
, val
);
826 FP_CONV (Q
, S
, 4, 1, QR
, SA
);
827 FP_PACK_QP(&cvt
.ld
, QR
);
828 current
->thread
.fp_regs
.fprs
[rx
].ui
= cvt
.w
.high
;
829 current
->thread
.fp_regs
.fprs
[rx
+2].ui
= cvt
.w
.low
;
833 /* Load lengthened float to double */
834 static int emu_ldebr (struct pt_regs
*regs
, int rx
, int ry
) {
835 FP_DECL_S(SA
); FP_DECL_D(DR
);
839 mode
= current
->thread
.fp_regs
.fpc
& 3;
840 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[ry
].f
);
841 FP_CONV (D
, S
, 2, 1, DR
, SA
);
842 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rx
].d
, DR
);
846 /* Load lengthened float to double */
847 static int emu_ldeb (struct pt_regs
*regs
, int rx
, float *val
) {
848 FP_DECL_S(SA
); FP_DECL_D(DR
);
852 mode
= current
->thread
.fp_regs
.fpc
& 3;
853 FP_UNPACK_SP(SA
, val
);
854 FP_CONV (D
, S
, 2, 1, DR
, SA
);
855 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rx
].d
, DR
);
859 /* Load negative long double */
860 static int emu_lnxbr (struct pt_regs
*regs
, int rx
, int ry
) {
861 FP_DECL_Q(QA
); FP_DECL_Q(QR
);
866 mode
= current
->thread
.fp_regs
.fpc
& 3;
867 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[ry
].ui
;
868 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[ry
+2].ui
;
869 FP_UNPACK_QP(QA
, &cvt
.ld
);
872 FP_PACK_QP(&cvt
.ld
, QR
);
873 current
->thread
.fp_regs
.fprs
[rx
].ui
= cvt
.w
.high
;
874 current
->thread
.fp_regs
.fprs
[rx
+2].ui
= cvt
.w
.low
;
876 current
->thread
.fp_regs
.fprs
[rx
].ui
=
877 current
->thread
.fp_regs
.fprs
[ry
].ui
;
878 current
->thread
.fp_regs
.fprs
[rx
+2].ui
=
879 current
->thread
.fp_regs
.fprs
[ry
+2].ui
;
881 emu_set_CC_cs(regs
, QR_c
, QR_s
);
885 /* Load negative double */
886 static int emu_lndbr (struct pt_regs
*regs
, int rx
, int ry
) {
887 FP_DECL_D(DA
); FP_DECL_D(DR
);
891 mode
= current
->thread
.fp_regs
.fpc
& 3;
892 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[ry
].d
);
895 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rx
].d
, DR
);
897 current
->thread
.fp_regs
.fprs
[rx
].ui
=
898 current
->thread
.fp_regs
.fprs
[ry
].ui
;
899 emu_set_CC_cs(regs
, DR_c
, DR_s
);
903 /* Load negative float */
904 static int emu_lnebr (struct pt_regs
*regs
, int rx
, int ry
) {
905 FP_DECL_S(SA
); FP_DECL_S(SR
);
909 mode
= current
->thread
.fp_regs
.fpc
& 3;
910 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[ry
].f
);
913 FP_PACK_SP(¤t
->thread
.fp_regs
.fprs
[rx
].f
, SR
);
915 current
->thread
.fp_regs
.fprs
[rx
].ui
=
916 current
->thread
.fp_regs
.fprs
[ry
].ui
;
917 emu_set_CC_cs(regs
, SR_c
, SR_s
);
921 /* Load positive long double */
922 static int emu_lpxbr (struct pt_regs
*regs
, int rx
, int ry
) {
923 FP_DECL_Q(QA
); FP_DECL_Q(QR
);
928 mode
= current
->thread
.fp_regs
.fpc
& 3;
929 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[ry
].ui
;
930 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[ry
+2].ui
;
931 FP_UNPACK_QP(QA
, &cvt
.ld
);
934 FP_PACK_QP(&cvt
.ld
, QR
);
935 current
->thread
.fp_regs
.fprs
[rx
].ui
= cvt
.w
.high
;
936 current
->thread
.fp_regs
.fprs
[rx
+2].ui
= cvt
.w
.low
;
938 current
->thread
.fp_regs
.fprs
[rx
].ui
=
939 current
->thread
.fp_regs
.fprs
[ry
].ui
;
940 current
->thread
.fp_regs
.fprs
[rx
+2].ui
=
941 current
->thread
.fp_regs
.fprs
[ry
+2].ui
;
943 emu_set_CC_cs(regs
, QR_c
, QR_s
);
947 /* Load positive double */
948 static int emu_lpdbr (struct pt_regs
*regs
, int rx
, int ry
) {
949 FP_DECL_D(DA
); FP_DECL_D(DR
);
953 mode
= current
->thread
.fp_regs
.fpc
& 3;
954 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[ry
].d
);
957 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rx
].d
, DR
);
959 current
->thread
.fp_regs
.fprs
[rx
].ui
=
960 current
->thread
.fp_regs
.fprs
[ry
].ui
;
961 emu_set_CC_cs(regs
, DR_c
, DR_s
);
965 /* Load positive float */
966 static int emu_lpebr (struct pt_regs
*regs
, int rx
, int ry
) {
967 FP_DECL_S(SA
); FP_DECL_S(SR
);
971 mode
= current
->thread
.fp_regs
.fpc
& 3;
972 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[ry
].f
);
975 FP_PACK_SP(¤t
->thread
.fp_regs
.fprs
[rx
].f
, SR
);
977 current
->thread
.fp_regs
.fprs
[rx
].ui
=
978 current
->thread
.fp_regs
.fprs
[ry
].ui
;
979 emu_set_CC_cs(regs
, SR_c
, SR_s
);
983 /* Load rounded long double to double */
984 static int emu_ldxbr (struct pt_regs
*regs
, int rx
, int ry
) {
985 FP_DECL_Q(QA
); FP_DECL_D(DR
);
990 mode
= current
->thread
.fp_regs
.fpc
& 3;
991 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[ry
].ui
;
992 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[ry
+2].ui
;
993 FP_UNPACK_QP(QA
, &cvt
.ld
);
994 FP_CONV (D
, Q
, 2, 4, DR
, QA
);
995 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rx
].f
, DR
);
999 /* Load rounded long double to float */
1000 static int emu_lexbr (struct pt_regs
*regs
, int rx
, int ry
) {
1001 FP_DECL_Q(QA
); FP_DECL_S(SR
);
1006 mode
= current
->thread
.fp_regs
.fpc
& 3;
1007 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[ry
].ui
;
1008 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[ry
+2].ui
;
1009 FP_UNPACK_QP(QA
, &cvt
.ld
);
1010 FP_CONV (S
, Q
, 1, 4, SR
, QA
);
1011 FP_PACK_SP(¤t
->thread
.fp_regs
.fprs
[rx
].f
, SR
);
1015 /* Load rounded double to float */
1016 static int emu_ledbr (struct pt_regs
*regs
, int rx
, int ry
) {
1017 FP_DECL_D(DA
); FP_DECL_S(SR
);
1021 mode
= current
->thread
.fp_regs
.fpc
& 3;
1022 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[ry
].d
);
1023 FP_CONV (S
, D
, 1, 2, SR
, DA
);
1024 FP_PACK_SP(¤t
->thread
.fp_regs
.fprs
[rx
].f
, SR
);
1028 /* Multiply long double */
1029 static int emu_mxbr (struct pt_regs
*regs
, int rx
, int ry
) {
1030 FP_DECL_Q(QA
); FP_DECL_Q(QB
); FP_DECL_Q(QR
);
1035 mode
= current
->thread
.fp_regs
.fpc
& 3;
1036 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[rx
].ui
;
1037 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[rx
+2].ui
;
1038 FP_UNPACK_QP(QA
, &cvt
.ld
);
1039 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[ry
].ui
;
1040 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[ry
+2].ui
;
1041 FP_UNPACK_QP(QB
, &cvt
.ld
);
1042 FP_MUL_Q(QR
, QA
, QB
);
1043 FP_PACK_QP(&cvt
.ld
, QR
);
1044 current
->thread
.fp_regs
.fprs
[rx
].ui
= cvt
.w
.high
;
1045 current
->thread
.fp_regs
.fprs
[rx
+2].ui
= cvt
.w
.low
;
1049 /* Multiply double */
1050 static int emu_mdbr (struct pt_regs
*regs
, int rx
, int ry
) {
1051 FP_DECL_D(DA
); FP_DECL_D(DB
); FP_DECL_D(DR
);
1055 mode
= current
->thread
.fp_regs
.fpc
& 3;
1056 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[rx
].d
);
1057 FP_UNPACK_DP(DB
, ¤t
->thread
.fp_regs
.fprs
[ry
].d
);
1058 FP_MUL_D(DR
, DA
, DB
);
1059 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rx
].d
, DR
);
1063 /* Multiply double */
1064 static int emu_mdb (struct pt_regs
*regs
, int rx
, double *val
) {
1065 FP_DECL_D(DA
); FP_DECL_D(DB
); FP_DECL_D(DR
);
1069 mode
= current
->thread
.fp_regs
.fpc
& 3;
1070 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[rx
].d
);
1071 FP_UNPACK_DP(DB
, val
);
1072 FP_MUL_D(DR
, DA
, DB
);
1073 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rx
].d
, DR
);
1077 /* Multiply double to long double */
1078 static int emu_mxdbr (struct pt_regs
*regs
, int rx
, int ry
) {
1079 FP_DECL_D(DA
); FP_DECL_Q(QA
); FP_DECL_Q(QB
); FP_DECL_Q(QR
);
1084 mode
= current
->thread
.fp_regs
.fpc
& 3;
1085 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[rx
].d
);
1086 FP_CONV (Q
, D
, 4, 2, QA
, DA
);
1087 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[ry
].d
);
1088 FP_CONV (Q
, D
, 4, 2, QB
, DA
);
1089 FP_MUL_Q(QR
, QA
, QB
);
1090 FP_PACK_QP(&cvt
.ld
, QR
);
1091 current
->thread
.fp_regs
.fprs
[rx
].ui
= cvt
.w
.high
;
1092 current
->thread
.fp_regs
.fprs
[rx
+2].ui
= cvt
.w
.low
;
1096 /* Multiply double to long double */
1097 static int emu_mxdb (struct pt_regs
*regs
, int rx
, long double *val
) {
1098 FP_DECL_Q(QA
); FP_DECL_Q(QB
); FP_DECL_Q(QR
);
1103 mode
= current
->thread
.fp_regs
.fpc
& 3;
1104 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[rx
].ui
;
1105 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[rx
+2].ui
;
1106 FP_UNPACK_QP(QA
, &cvt
.ld
);
1107 FP_UNPACK_QP(QB
, val
);
1108 FP_MUL_Q(QR
, QA
, QB
);
1109 FP_PACK_QP(&cvt
.ld
, QR
);
1110 current
->thread
.fp_regs
.fprs
[rx
].ui
= cvt
.w
.high
;
1111 current
->thread
.fp_regs
.fprs
[rx
+2].ui
= cvt
.w
.low
;
1115 /* Multiply float */
1116 static int emu_meebr (struct pt_regs
*regs
, int rx
, int ry
) {
1117 FP_DECL_S(SA
); FP_DECL_S(SB
); FP_DECL_S(SR
);
1121 mode
= current
->thread
.fp_regs
.fpc
& 3;
1122 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[rx
].f
);
1123 FP_UNPACK_SP(SB
, ¤t
->thread
.fp_regs
.fprs
[ry
].f
);
1124 FP_MUL_S(SR
, SA
, SB
);
1125 FP_PACK_SP(¤t
->thread
.fp_regs
.fprs
[rx
].f
, SR
);
1129 /* Multiply float */
1130 static int emu_meeb (struct pt_regs
*regs
, int rx
, float *val
) {
1131 FP_DECL_S(SA
); FP_DECL_S(SB
); FP_DECL_S(SR
);
1135 mode
= current
->thread
.fp_regs
.fpc
& 3;
1136 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[rx
].f
);
1137 FP_UNPACK_SP(SB
, val
);
1138 FP_MUL_S(SR
, SA
, SB
);
1139 FP_PACK_SP(¤t
->thread
.fp_regs
.fprs
[rx
].f
, SR
);
1143 /* Multiply float to double */
1144 static int emu_mdebr (struct pt_regs
*regs
, int rx
, int ry
) {
1145 FP_DECL_S(SA
); FP_DECL_D(DA
); FP_DECL_D(DB
); FP_DECL_D(DR
);
1149 mode
= current
->thread
.fp_regs
.fpc
& 3;
1150 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[rx
].f
);
1151 FP_CONV (D
, S
, 2, 1, DA
, SA
);
1152 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[ry
].f
);
1153 FP_CONV (D
, S
, 2, 1, DB
, SA
);
1154 FP_MUL_D(DR
, DA
, DB
);
1155 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rx
].d
, DR
);
1159 /* Multiply float to double */
1160 static int emu_mdeb (struct pt_regs
*regs
, int rx
, float *val
) {
1161 FP_DECL_S(SA
); FP_DECL_D(DA
); FP_DECL_D(DB
); FP_DECL_D(DR
);
1165 mode
= current
->thread
.fp_regs
.fpc
& 3;
1166 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[rx
].f
);
1167 FP_CONV (D
, S
, 2, 1, DA
, SA
);
1168 FP_UNPACK_SP(SA
, val
);
1169 FP_CONV (D
, S
, 2, 1, DB
, SA
);
1170 FP_MUL_D(DR
, DA
, DB
);
1171 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rx
].d
, DR
);
1175 /* Multiply and add double */
1176 static int emu_madbr (struct pt_regs
*regs
, int rx
, int ry
, int rz
) {
1177 FP_DECL_D(DA
); FP_DECL_D(DB
); FP_DECL_D(DC
); FP_DECL_D(DR
);
1181 mode
= current
->thread
.fp_regs
.fpc
& 3;
1182 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[rx
].d
);
1183 FP_UNPACK_DP(DB
, ¤t
->thread
.fp_regs
.fprs
[ry
].d
);
1184 FP_UNPACK_DP(DC
, ¤t
->thread
.fp_regs
.fprs
[rz
].d
);
1185 FP_MUL_D(DR
, DA
, DB
);
1186 FP_ADD_D(DR
, DR
, DC
);
1187 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rz
].d
, DR
);
1191 /* Multiply and add double */
1192 static int emu_madb (struct pt_regs
*regs
, int rx
, double *val
, int rz
) {
1193 FP_DECL_D(DA
); FP_DECL_D(DB
); FP_DECL_D(DC
); FP_DECL_D(DR
);
1197 mode
= current
->thread
.fp_regs
.fpc
& 3;
1198 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[rx
].d
);
1199 FP_UNPACK_DP(DB
, val
);
1200 FP_UNPACK_DP(DC
, ¤t
->thread
.fp_regs
.fprs
[rz
].d
);
1201 FP_MUL_D(DR
, DA
, DB
);
1202 FP_ADD_D(DR
, DR
, DC
);
1203 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rz
].d
, DR
);
1207 /* Multiply and add float */
1208 static int emu_maebr (struct pt_regs
*regs
, int rx
, int ry
, int rz
) {
1209 FP_DECL_S(SA
); FP_DECL_S(SB
); FP_DECL_S(SC
); FP_DECL_S(SR
);
1213 mode
= current
->thread
.fp_regs
.fpc
& 3;
1214 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[rx
].f
);
1215 FP_UNPACK_SP(SB
, ¤t
->thread
.fp_regs
.fprs
[ry
].f
);
1216 FP_UNPACK_SP(SC
, ¤t
->thread
.fp_regs
.fprs
[rz
].f
);
1217 FP_MUL_S(SR
, SA
, SB
);
1218 FP_ADD_S(SR
, SR
, SC
);
1219 FP_PACK_SP(¤t
->thread
.fp_regs
.fprs
[rz
].f
, SR
);
1223 /* Multiply and add float */
1224 static int emu_maeb (struct pt_regs
*regs
, int rx
, float *val
, int rz
) {
1225 FP_DECL_S(SA
); FP_DECL_S(SB
); FP_DECL_S(SC
); FP_DECL_S(SR
);
1229 mode
= current
->thread
.fp_regs
.fpc
& 3;
1230 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[rx
].f
);
1231 FP_UNPACK_SP(SB
, val
);
1232 FP_UNPACK_SP(SC
, ¤t
->thread
.fp_regs
.fprs
[rz
].f
);
1233 FP_MUL_S(SR
, SA
, SB
);
1234 FP_ADD_S(SR
, SR
, SC
);
1235 FP_PACK_SP(¤t
->thread
.fp_regs
.fprs
[rz
].f
, SR
);
1239 /* Multiply and subtract double */
1240 static int emu_msdbr (struct pt_regs
*regs
, int rx
, int ry
, int rz
) {
1241 FP_DECL_D(DA
); FP_DECL_D(DB
); FP_DECL_D(DC
); FP_DECL_D(DR
);
1245 mode
= current
->thread
.fp_regs
.fpc
& 3;
1246 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[rx
].d
);
1247 FP_UNPACK_DP(DB
, ¤t
->thread
.fp_regs
.fprs
[ry
].d
);
1248 FP_UNPACK_DP(DC
, ¤t
->thread
.fp_regs
.fprs
[rz
].d
);
1249 FP_MUL_D(DR
, DA
, DB
);
1250 FP_SUB_D(DR
, DR
, DC
);
1251 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rz
].d
, DR
);
1255 /* Multiply and subtract double */
1256 static int emu_msdb (struct pt_regs
*regs
, int rx
, double *val
, int rz
) {
1257 FP_DECL_D(DA
); FP_DECL_D(DB
); FP_DECL_D(DC
); FP_DECL_D(DR
);
1261 mode
= current
->thread
.fp_regs
.fpc
& 3;
1262 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[rx
].d
);
1263 FP_UNPACK_DP(DB
, val
);
1264 FP_UNPACK_DP(DC
, ¤t
->thread
.fp_regs
.fprs
[rz
].d
);
1265 FP_MUL_D(DR
, DA
, DB
);
1266 FP_SUB_D(DR
, DR
, DC
);
1267 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rz
].d
, DR
);
1271 /* Multiply and subtract float */
1272 static int emu_msebr (struct pt_regs
*regs
, int rx
, int ry
, int rz
) {
1273 FP_DECL_S(SA
); FP_DECL_S(SB
); FP_DECL_S(SC
); FP_DECL_S(SR
);
1277 mode
= current
->thread
.fp_regs
.fpc
& 3;
1278 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[rx
].f
);
1279 FP_UNPACK_SP(SB
, ¤t
->thread
.fp_regs
.fprs
[ry
].f
);
1280 FP_UNPACK_SP(SC
, ¤t
->thread
.fp_regs
.fprs
[rz
].f
);
1281 FP_MUL_S(SR
, SA
, SB
);
1282 FP_SUB_S(SR
, SR
, SC
);
1283 FP_PACK_SP(¤t
->thread
.fp_regs
.fprs
[rz
].f
, SR
);
1287 /* Multiply and subtract float */
1288 static int emu_mseb (struct pt_regs
*regs
, int rx
, float *val
, int rz
) {
1289 FP_DECL_S(SA
); FP_DECL_S(SB
); FP_DECL_S(SC
); FP_DECL_S(SR
);
1293 mode
= current
->thread
.fp_regs
.fpc
& 3;
1294 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[rx
].f
);
1295 FP_UNPACK_SP(SB
, val
);
1296 FP_UNPACK_SP(SC
, ¤t
->thread
.fp_regs
.fprs
[rz
].f
);
1297 FP_MUL_S(SR
, SA
, SB
);
1298 FP_SUB_S(SR
, SR
, SC
);
1299 FP_PACK_SP(¤t
->thread
.fp_regs
.fprs
[rz
].f
, SR
);
1303 /* Set floating point control word */
1304 static int emu_sfpc (struct pt_regs
*regs
, int rx
, int ry
) {
1307 temp
= regs
->gprs
[rx
];
1308 if ((temp
& ~FPC_VALID_MASK
) != 0)
1310 current
->thread
.fp_regs
.fpc
= temp
;
1314 /* Square root long double */
1315 static int emu_sqxbr (struct pt_regs
*regs
, int rx
, int ry
) {
1316 FP_DECL_Q(QA
); FP_DECL_Q(QR
);
1321 mode
= current
->thread
.fp_regs
.fpc
& 3;
1322 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[ry
].ui
;
1323 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[ry
+2].ui
;
1324 FP_UNPACK_QP(QA
, &cvt
.ld
);
1326 FP_PACK_QP(&cvt
.ld
, QR
);
1327 current
->thread
.fp_regs
.fprs
[rx
].ui
= cvt
.w
.high
;
1328 current
->thread
.fp_regs
.fprs
[rx
+2].ui
= cvt
.w
.low
;
1329 emu_set_CC_cs(regs
, QR_c
, QR_s
);
1333 /* Square root double */
1334 static int emu_sqdbr (struct pt_regs
*regs
, int rx
, int ry
) {
1335 FP_DECL_D(DA
); FP_DECL_D(DR
);
1339 mode
= current
->thread
.fp_regs
.fpc
& 3;
1340 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[ry
].d
);
1342 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rx
].d
, DR
);
1343 emu_set_CC_cs(regs
, DR_c
, DR_s
);
1347 /* Square root double */
1348 static int emu_sqdb (struct pt_regs
*regs
, int rx
, double *val
) {
1349 FP_DECL_D(DA
); FP_DECL_D(DR
);
1353 mode
= current
->thread
.fp_regs
.fpc
& 3;
1354 FP_UNPACK_DP(DA
, val
);
1356 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rx
].d
, DR
);
1357 emu_set_CC_cs(regs
, DR_c
, DR_s
);
1361 /* Square root float */
1362 static int emu_sqebr (struct pt_regs
*regs
, int rx
, int ry
) {
1363 FP_DECL_S(SA
); FP_DECL_S(SR
);
1367 mode
= current
->thread
.fp_regs
.fpc
& 3;
1368 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[ry
].f
);
1370 FP_PACK_SP(¤t
->thread
.fp_regs
.fprs
[rx
].f
, SR
);
1371 emu_set_CC_cs(regs
, SR_c
, SR_s
);
1375 /* Square root float */
1376 static int emu_sqeb (struct pt_regs
*regs
, int rx
, float *val
) {
1377 FP_DECL_S(SA
); FP_DECL_S(SR
);
1381 mode
= current
->thread
.fp_regs
.fpc
& 3;
1382 FP_UNPACK_SP(SA
, val
);
1384 FP_PACK_SP(¤t
->thread
.fp_regs
.fprs
[rx
].f
, SR
);
1385 emu_set_CC_cs(regs
, SR_c
, SR_s
);
1389 /* Subtract long double */
1390 static int emu_sxbr (struct pt_regs
*regs
, int rx
, int ry
) {
1391 FP_DECL_Q(QA
); FP_DECL_Q(QB
); FP_DECL_Q(QR
);
1396 mode
= current
->thread
.fp_regs
.fpc
& 3;
1397 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[rx
].ui
;
1398 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[rx
+2].ui
;
1399 FP_UNPACK_QP(QA
, &cvt
.ld
);
1400 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[ry
].ui
;
1401 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[ry
+2].ui
;
1402 FP_UNPACK_QP(QB
, &cvt
.ld
);
1403 FP_SUB_Q(QR
, QA
, QB
);
1404 FP_PACK_QP(&cvt
.ld
, QR
);
1405 current
->thread
.fp_regs
.fprs
[rx
].ui
= cvt
.w
.high
;
1406 current
->thread
.fp_regs
.fprs
[rx
+2].ui
= cvt
.w
.low
;
1407 emu_set_CC_cs(regs
, QR_c
, QR_s
);
1411 /* Subtract double */
1412 static int emu_sdbr (struct pt_regs
*regs
, int rx
, int ry
) {
1413 FP_DECL_D(DA
); FP_DECL_D(DB
); FP_DECL_D(DR
);
1417 mode
= current
->thread
.fp_regs
.fpc
& 3;
1418 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[rx
].d
);
1419 FP_UNPACK_DP(DB
, ¤t
->thread
.fp_regs
.fprs
[ry
].d
);
1420 FP_SUB_D(DR
, DA
, DB
);
1421 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rx
].d
, DR
);
1422 emu_set_CC_cs(regs
, DR_c
, DR_s
);
1426 /* Subtract double */
1427 static int emu_sdb (struct pt_regs
*regs
, int rx
, double *val
) {
1428 FP_DECL_D(DA
); FP_DECL_D(DB
); FP_DECL_D(DR
);
1432 mode
= current
->thread
.fp_regs
.fpc
& 3;
1433 FP_UNPACK_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[rx
].d
);
1434 FP_UNPACK_DP(DB
, val
);
1435 FP_SUB_D(DR
, DA
, DB
);
1436 FP_PACK_DP(¤t
->thread
.fp_regs
.fprs
[rx
].d
, DR
);
1437 emu_set_CC_cs(regs
, DR_c
, DR_s
);
1441 /* Subtract float */
1442 static int emu_sebr (struct pt_regs
*regs
, int rx
, int ry
) {
1443 FP_DECL_S(SA
); FP_DECL_S(SB
); FP_DECL_S(SR
);
1447 mode
= current
->thread
.fp_regs
.fpc
& 3;
1448 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[rx
].f
);
1449 FP_UNPACK_SP(SB
, ¤t
->thread
.fp_regs
.fprs
[ry
].f
);
1450 FP_SUB_S(SR
, SA
, SB
);
1451 FP_PACK_SP(¤t
->thread
.fp_regs
.fprs
[rx
].f
, SR
);
1452 emu_set_CC_cs(regs
, SR_c
, SR_s
);
1456 /* Subtract float */
1457 static int emu_seb (struct pt_regs
*regs
, int rx
, float *val
) {
1458 FP_DECL_S(SA
); FP_DECL_S(SB
); FP_DECL_S(SR
);
1462 mode
= current
->thread
.fp_regs
.fpc
& 3;
1463 FP_UNPACK_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[rx
].f
);
1464 FP_UNPACK_SP(SB
, val
);
1465 FP_SUB_S(SR
, SA
, SB
);
1466 FP_PACK_SP(¤t
->thread
.fp_regs
.fprs
[rx
].f
, SR
);
1467 emu_set_CC_cs(regs
, SR_c
, SR_s
);
1471 /* Test data class long double */
1472 static int emu_tcxb (struct pt_regs
*regs
, int rx
, long val
) {
1477 cvt
.w
.high
= current
->thread
.fp_regs
.fprs
[rx
].ui
;
1478 cvt
.w
.low
= current
->thread
.fp_regs
.fprs
[rx
+2].ui
;
1479 FP_UNPACK_RAW_QP(QA
, &cvt
.ld
);
1482 bit
= 8; /* normalized number */
1485 if (_FP_FRAC_ZEROP_4(QA
))
1486 bit
= 10; /* zero */
1488 bit
= 6; /* denormalized number */
1491 if (_FP_FRAC_ZEROP_4(QA
))
1492 bit
= 4; /* infinity */
1493 else if (_FP_FRAC_HIGH_RAW_Q(QA
) & _FP_QNANBIT_Q
)
1494 bit
= 2; /* quiet NAN */
1496 bit
= 0; /* signaling NAN */
1501 emu_set_CC(regs
, ((__u32
) val
>> bit
) & 1);
1505 /* Test data class double */
1506 static int emu_tcdb (struct pt_regs
*regs
, int rx
, long val
) {
1510 FP_UNPACK_RAW_DP(DA
, ¤t
->thread
.fp_regs
.fprs
[rx
].d
);
1513 bit
= 8; /* normalized number */
1516 if (_FP_FRAC_ZEROP_2(DA
))
1517 bit
= 10; /* zero */
1519 bit
= 6; /* denormalized number */
1522 if (_FP_FRAC_ZEROP_2(DA
))
1523 bit
= 4; /* infinity */
1524 else if (_FP_FRAC_HIGH_RAW_D(DA
) & _FP_QNANBIT_D
)
1525 bit
= 2; /* quiet NAN */
1527 bit
= 0; /* signaling NAN */
1532 emu_set_CC(regs
, ((__u32
) val
>> bit
) & 1);
1536 /* Test data class float */
1537 static int emu_tceb (struct pt_regs
*regs
, int rx
, long val
) {
1541 FP_UNPACK_RAW_SP(SA
, ¤t
->thread
.fp_regs
.fprs
[rx
].f
);
1544 bit
= 8; /* normalized number */
1547 if (_FP_FRAC_ZEROP_1(SA
))
1548 bit
= 10; /* zero */
1550 bit
= 6; /* denormalized number */
1553 if (_FP_FRAC_ZEROP_1(SA
))
1554 bit
= 4; /* infinity */
1555 else if (_FP_FRAC_HIGH_RAW_S(SA
) & _FP_QNANBIT_S
)
1556 bit
= 2; /* quiet NAN */
1558 bit
= 0; /* signaling NAN */
1563 emu_set_CC(regs
, ((__u32
) val
>> bit
) & 1);
1567 static inline void emu_load_regd(int reg
) {
1568 if ((reg
&9) != 0) /* test if reg in {0,2,4,6} */
1570 asm volatile ( /* load reg from fp_regs.fprs[reg] */
1575 : "a" (reg
<<4),"a" (¤t
->thread
.fp_regs
.fprs
[reg
].d
)
1579 static inline void emu_load_rege(int reg
) {
1580 if ((reg
&9) != 0) /* test if reg in {0,2,4,6} */
1582 asm volatile ( /* load reg from fp_regs.fprs[reg] */
1587 : "a" (reg
<<4), "a" (¤t
->thread
.fp_regs
.fprs
[reg
].f
)
1591 static inline void emu_store_regd(int reg
) {
1592 if ((reg
&9) != 0) /* test if reg in {0,2,4,6} */
1594 asm volatile ( /* store reg to fp_regs.fprs[reg] */
1599 : "a" (reg
<<4), "a" (¤t
->thread
.fp_regs
.fprs
[reg
].d
)
1604 static inline void emu_store_rege(int reg
) {
1605 if ((reg
&9) != 0) /* test if reg in {0,2,4,6} */
1607 asm volatile ( /* store reg to fp_regs.fprs[reg] */
1612 : "a" (reg
<<4), "a" (¤t
->thread
.fp_regs
.fprs
[reg
].f
)
1616 int math_emu_b3(__u8
*opcode
, struct pt_regs
* regs
) {
1618 static const __u8 format_table
[256] = {
1619 [0x00] = 0x03,[0x01] = 0x03,[0x02] = 0x03,[0x03] = 0x03,
1620 [0x04] = 0x0f,[0x05] = 0x0d,[0x06] = 0x0e,[0x07] = 0x0d,
1621 [0x08] = 0x03,[0x09] = 0x03,[0x0a] = 0x03,[0x0b] = 0x03,
1622 [0x0c] = 0x0f,[0x0d] = 0x03,[0x0e] = 0x06,[0x0f] = 0x06,
1623 [0x10] = 0x02,[0x11] = 0x02,[0x12] = 0x02,[0x13] = 0x02,
1624 [0x14] = 0x03,[0x15] = 0x02,[0x16] = 0x01,[0x17] = 0x03,
1625 [0x18] = 0x02,[0x19] = 0x02,[0x1a] = 0x02,[0x1b] = 0x02,
1626 [0x1c] = 0x02,[0x1d] = 0x02,[0x1e] = 0x05,[0x1f] = 0x05,
1627 [0x40] = 0x01,[0x41] = 0x01,[0x42] = 0x01,[0x43] = 0x01,
1628 [0x44] = 0x12,[0x45] = 0x0d,[0x46] = 0x11,[0x47] = 0x04,
1629 [0x48] = 0x01,[0x49] = 0x01,[0x4a] = 0x01,[0x4b] = 0x01,
1630 [0x4c] = 0x01,[0x4d] = 0x01,[0x53] = 0x06,[0x57] = 0x06,
1631 [0x5b] = 0x05,[0x5f] = 0x05,[0x84] = 0x13,[0x8c] = 0x13,
1632 [0x94] = 0x09,[0x95] = 0x08,[0x96] = 0x07,[0x98] = 0x0c,
1633 [0x99] = 0x0b,[0x9a] = 0x0a
1635 static const void *jump_table
[256]= {
1636 [0x00] = emu_lpebr
,[0x01] = emu_lnebr
,[0x02] = emu_ltebr
,
1637 [0x03] = emu_lcebr
,[0x04] = emu_ldebr
,[0x05] = emu_lxdbr
,
1638 [0x06] = emu_lxebr
,[0x07] = emu_mxdbr
,[0x08] = emu_kebr
,
1639 [0x09] = emu_cebr
, [0x0a] = emu_aebr
, [0x0b] = emu_sebr
,
1640 [0x0c] = emu_mdebr
,[0x0d] = emu_debr
, [0x0e] = emu_maebr
,
1641 [0x0f] = emu_msebr
,[0x10] = emu_lpdbr
,[0x11] = emu_lndbr
,
1642 [0x12] = emu_ltdbr
,[0x13] = emu_lcdbr
,[0x14] = emu_sqebr
,
1643 [0x15] = emu_sqdbr
,[0x16] = emu_sqxbr
,[0x17] = emu_meebr
,
1644 [0x18] = emu_kdbr
, [0x19] = emu_cdbr
, [0x1a] = emu_adbr
,
1645 [0x1b] = emu_sdbr
, [0x1c] = emu_mdbr
, [0x1d] = emu_ddbr
,
1646 [0x1e] = emu_madbr
,[0x1f] = emu_msdbr
,[0x40] = emu_lpxbr
,
1647 [0x41] = emu_lnxbr
,[0x42] = emu_ltxbr
,[0x43] = emu_lcxbr
,
1648 [0x44] = emu_ledbr
,[0x45] = emu_ldxbr
,[0x46] = emu_lexbr
,
1649 [0x47] = emu_fixbr
,[0x48] = emu_kxbr
, [0x49] = emu_cxbr
,
1650 [0x4a] = emu_axbr
, [0x4b] = emu_sxbr
, [0x4c] = emu_mxbr
,
1651 [0x4d] = emu_dxbr
, [0x53] = emu_diebr
,[0x57] = emu_fiebr
,
1652 [0x5b] = emu_didbr
,[0x5f] = emu_fidbr
,[0x84] = emu_sfpc
,
1653 [0x8c] = emu_efpc
, [0x94] = emu_cefbr
,[0x95] = emu_cdfbr
,
1654 [0x96] = emu_cxfbr
,[0x98] = emu_cfebr
,[0x99] = emu_cfdbr
,
1658 switch (format_table
[opcode
[1]]) {
1659 case 1: /* RRE format, long double operation */
1660 if (opcode
[3] & 0x22)
1662 emu_store_regd((opcode
[3] >> 4) & 15);
1663 emu_store_regd(((opcode
[3] >> 4) & 15) + 2);
1664 emu_store_regd(opcode
[3] & 15);
1665 emu_store_regd((opcode
[3] & 15) + 2);
1666 /* call the emulation function */
1667 _fex
= ((int (*)(struct pt_regs
*,int, int))
1668 jump_table
[opcode
[1]])
1669 (regs
, opcode
[3] >> 4, opcode
[3] & 15);
1670 emu_load_regd((opcode
[3] >> 4) & 15);
1671 emu_load_regd(((opcode
[3] >> 4) & 15) + 2);
1672 emu_load_regd(opcode
[3] & 15);
1673 emu_load_regd((opcode
[3] & 15) + 2);
1675 case 2: /* RRE format, double operation */
1676 emu_store_regd((opcode
[3] >> 4) & 15);
1677 emu_store_regd(opcode
[3] & 15);
1678 /* call the emulation function */
1679 _fex
= ((int (*)(struct pt_regs
*, int, int))
1680 jump_table
[opcode
[1]])
1681 (regs
, opcode
[3] >> 4, opcode
[3] & 15);
1682 emu_load_regd((opcode
[3] >> 4) & 15);
1683 emu_load_regd(opcode
[3] & 15);
1685 case 3: /* RRE format, float operation */
1686 emu_store_rege((opcode
[3] >> 4) & 15);
1687 emu_store_rege(opcode
[3] & 15);
1688 /* call the emulation function */
1689 _fex
= ((int (*)(struct pt_regs
*, int, int))
1690 jump_table
[opcode
[1]])
1691 (regs
, opcode
[3] >> 4, opcode
[3] & 15);
1692 emu_load_rege((opcode
[3] >> 4) & 15);
1693 emu_load_rege(opcode
[3] & 15);
1695 case 4: /* RRF format, long double operation */
1696 if (opcode
[3] & 0x22)
1698 emu_store_regd((opcode
[3] >> 4) & 15);
1699 emu_store_regd(((opcode
[3] >> 4) & 15) + 2);
1700 emu_store_regd(opcode
[3] & 15);
1701 emu_store_regd((opcode
[3] & 15) + 2);
1702 /* call the emulation function */
1703 _fex
= ((int (*)(struct pt_regs
*, int, int, int))
1704 jump_table
[opcode
[1]])
1705 (regs
, opcode
[3] >> 4, opcode
[3] & 15, opcode
[2] >> 4);
1706 emu_load_regd((opcode
[3] >> 4) & 15);
1707 emu_load_regd(((opcode
[3] >> 4) & 15) + 2);
1708 emu_load_regd(opcode
[3] & 15);
1709 emu_load_regd((opcode
[3] & 15) + 2);
1711 case 5: /* RRF format, double operation */
1712 emu_store_regd((opcode
[2] >> 4) & 15);
1713 emu_store_regd((opcode
[3] >> 4) & 15);
1714 emu_store_regd(opcode
[3] & 15);
1715 /* call the emulation function */
1716 _fex
= ((int (*)(struct pt_regs
*, int, int, int))
1717 jump_table
[opcode
[1]])
1718 (regs
, opcode
[3] >> 4, opcode
[3] & 15, opcode
[2] >> 4);
1719 emu_load_regd((opcode
[2] >> 4) & 15);
1720 emu_load_regd((opcode
[3] >> 4) & 15);
1721 emu_load_regd(opcode
[3] & 15);
1723 case 6: /* RRF format, float operation */
1724 emu_store_rege((opcode
[2] >> 4) & 15);
1725 emu_store_rege((opcode
[3] >> 4) & 15);
1726 emu_store_rege(opcode
[3] & 15);
1727 /* call the emulation function */
1728 _fex
= ((int (*)(struct pt_regs
*, int, int, int))
1729 jump_table
[opcode
[1]])
1730 (regs
, opcode
[3] >> 4, opcode
[3] & 15, opcode
[2] >> 4);
1731 emu_load_rege((opcode
[2] >> 4) & 15);
1732 emu_load_rege((opcode
[3] >> 4) & 15);
1733 emu_load_rege(opcode
[3] & 15);
1735 case 7: /* RRE format, cxfbr instruction */
1736 /* call the emulation function */
1737 if (opcode
[3] & 0x20)
1739 _fex
= ((int (*)(struct pt_regs
*, int, int))
1740 jump_table
[opcode
[1]])
1741 (regs
, opcode
[3] >> 4, opcode
[3] & 15);
1742 emu_load_regd((opcode
[3] >> 4) & 15);
1743 emu_load_regd(((opcode
[3] >> 4) & 15) + 2);
1745 case 8: /* RRE format, cdfbr instruction */
1746 /* call the emulation function */
1747 _fex
= ((int (*)(struct pt_regs
*, int, int))
1748 jump_table
[opcode
[1]])
1749 (regs
, opcode
[3] >> 4, opcode
[3] & 15);
1750 emu_load_regd((opcode
[3] >> 4) & 15);
1752 case 9: /* RRE format, cefbr instruction */
1753 /* call the emulation function */
1754 _fex
= ((int (*)(struct pt_regs
*, int, int))
1755 jump_table
[opcode
[1]])
1756 (regs
, opcode
[3] >> 4, opcode
[3] & 15);
1757 emu_load_rege((opcode
[3] >> 4) & 15);
1759 case 10: /* RRF format, cfxbr instruction */
1760 if ((opcode
[2] & 128) == 128 || (opcode
[2] & 96) == 32)
1761 /* mask of { 2,3,8-15 } is invalid */
1765 emu_store_regd(opcode
[3] & 15);
1766 emu_store_regd((opcode
[3] & 15) + 2);
1767 /* call the emulation function */
1768 _fex
= ((int (*)(struct pt_regs
*, int, int, int))
1769 jump_table
[opcode
[1]])
1770 (regs
, opcode
[3] >> 4, opcode
[3] & 15, opcode
[2] >> 4);
1772 case 11: /* RRF format, cfdbr instruction */
1773 if ((opcode
[2] & 128) == 128 || (opcode
[2] & 96) == 32)
1774 /* mask of { 2,3,8-15 } is invalid */
1776 emu_store_regd(opcode
[3] & 15);
1777 /* call the emulation function */
1778 _fex
= ((int (*)(struct pt_regs
*, int, int, int))
1779 jump_table
[opcode
[1]])
1780 (regs
, opcode
[3] >> 4, opcode
[3] & 15, opcode
[2] >> 4);
1782 case 12: /* RRF format, cfebr instruction */
1783 if ((opcode
[2] & 128) == 128 || (opcode
[2] & 96) == 32)
1784 /* mask of { 2,3,8-15 } is invalid */
1786 emu_store_rege(opcode
[3] & 15);
1787 /* call the emulation function */
1788 _fex
= ((int (*)(struct pt_regs
*, int, int, int))
1789 jump_table
[opcode
[1]])
1790 (regs
, opcode
[3] >> 4, opcode
[3] & 15, opcode
[2] >> 4);
1792 case 13: /* RRE format, ldxbr & mdxbr instruction */
1793 /* double store but long double load */
1794 if (opcode
[3] & 0x20)
1796 emu_store_regd((opcode
[3] >> 4) & 15);
1797 emu_store_regd(opcode
[3] & 15);
1798 /* call the emulation function */
1799 _fex
= ((int (*)(struct pt_regs
*, int, int))
1800 jump_table
[opcode
[1]])
1801 (regs
, opcode
[3] >> 4, opcode
[3] & 15);
1802 emu_load_regd((opcode
[3] >> 4) & 15);
1803 emu_load_regd(((opcode
[3] >> 4) & 15) + 2);
1805 case 14: /* RRE format, ldxbr & mdxbr instruction */
1806 /* float store but long double load */
1807 if (opcode
[3] & 0x20)
1809 emu_store_rege((opcode
[3] >> 4) & 15);
1810 emu_store_rege(opcode
[3] & 15);
1811 /* call the emulation function */
1812 _fex
= ((int (*)(struct pt_regs
*, int, int))
1813 jump_table
[opcode
[1]])
1814 (regs
, opcode
[3] >> 4, opcode
[3] & 15);
1815 emu_load_regd((opcode
[3] >> 4) & 15);
1816 emu_load_regd(((opcode
[3] >> 4) & 15) + 2);
1818 case 15: /* RRE format, ldebr & mdebr instruction */
1819 /* float store but double load */
1820 emu_store_rege((opcode
[3] >> 4) & 15);
1821 emu_store_rege(opcode
[3] & 15);
1822 /* call the emulation function */
1823 _fex
= ((int (*)(struct pt_regs
*, int, int))
1824 jump_table
[opcode
[1]])
1825 (regs
, opcode
[3] >> 4, opcode
[3] & 15);
1826 emu_load_regd((opcode
[3] >> 4) & 15);
1828 case 16: /* RRE format, ldxbr instruction */
1829 /* long double store but double load */
1832 emu_store_regd(opcode
[3] & 15);
1833 emu_store_regd((opcode
[3] & 15) + 2);
1834 /* call the emulation function */
1835 _fex
= ((int (*)(struct pt_regs
*, int, int))
1836 jump_table
[opcode
[1]])
1837 (regs
, opcode
[3] >> 4, opcode
[3] & 15);
1838 emu_load_regd((opcode
[3] >> 4) & 15);
1840 case 17: /* RRE format, ldxbr instruction */
1841 /* long double store but float load */
1844 emu_store_regd(opcode
[3] & 15);
1845 emu_store_regd((opcode
[3] & 15) + 2);
1846 /* call the emulation function */
1847 _fex
= ((int (*)(struct pt_regs
*, int, int))
1848 jump_table
[opcode
[1]])
1849 (regs
, opcode
[3] >> 4, opcode
[3] & 15);
1850 emu_load_rege((opcode
[3] >> 4) & 15);
1852 case 18: /* RRE format, ledbr instruction */
1853 /* double store but float load */
1854 emu_store_regd(opcode
[3] & 15);
1855 /* call the emulation function */
1856 _fex
= ((int (*)(struct pt_regs
*, int, int))
1857 jump_table
[opcode
[1]])
1858 (regs
, opcode
[3] >> 4, opcode
[3] & 15);
1859 emu_load_rege((opcode
[3] >> 4) & 15);
1861 case 19: /* RRE format, efpc & sfpc instruction */
1862 /* call the emulation function */
1863 _fex
= ((int (*)(struct pt_regs
*, int, int))
1864 jump_table
[opcode
[1]])
1865 (regs
, opcode
[3] >> 4, opcode
[3] & 15);
1867 default: /* invalid operation */
1871 current
->thread
.fp_regs
.fpc
|= _fex
;
1872 if (current
->thread
.fp_regs
.fpc
& (_fex
<< 8))
1878 static void* calc_addr(struct pt_regs
*regs
, int rx
, int rb
, int disp
)
1884 addr
= disp
& 0xfff;
1885 addr
+= (rx
!= 0) ? regs
->gprs
[rx
] : 0; /* + index */
1886 addr
+= (rb
!= 0) ? regs
->gprs
[rb
] : 0; /* + base */
1887 return (void*) addr
;
1890 int math_emu_ed(__u8
*opcode
, struct pt_regs
* regs
) {
1893 static const __u8 format_table
[256] = {
1894 [0x04] = 0x06,[0x05] = 0x05,[0x06] = 0x07,[0x07] = 0x05,
1895 [0x08] = 0x02,[0x09] = 0x02,[0x0a] = 0x02,[0x0b] = 0x02,
1896 [0x0c] = 0x06,[0x0d] = 0x02,[0x0e] = 0x04,[0x0f] = 0x04,
1897 [0x10] = 0x08,[0x11] = 0x09,[0x12] = 0x0a,[0x14] = 0x02,
1898 [0x15] = 0x01,[0x17] = 0x02,[0x18] = 0x01,[0x19] = 0x01,
1899 [0x1a] = 0x01,[0x1b] = 0x01,[0x1c] = 0x01,[0x1d] = 0x01,
1900 [0x1e] = 0x03,[0x1f] = 0x03,
1902 static const void *jump_table
[]= {
1903 [0x04] = emu_ldeb
,[0x05] = emu_lxdb
,[0x06] = emu_lxeb
,
1904 [0x07] = emu_mxdb
,[0x08] = emu_keb
, [0x09] = emu_ceb
,
1905 [0x0a] = emu_aeb
, [0x0b] = emu_seb
, [0x0c] = emu_mdeb
,
1906 [0x0d] = emu_deb
, [0x0e] = emu_maeb
,[0x0f] = emu_mseb
,
1907 [0x10] = emu_tceb
,[0x11] = emu_tcdb
,[0x12] = emu_tcxb
,
1908 [0x14] = emu_sqeb
,[0x15] = emu_sqdb
,[0x17] = emu_meeb
,
1909 [0x18] = emu_kdb
, [0x19] = emu_cdb
, [0x1a] = emu_adb
,
1910 [0x1b] = emu_sdb
, [0x1c] = emu_mdb
, [0x1d] = emu_ddb
,
1911 [0x1e] = emu_madb
,[0x1f] = emu_msdb
1914 switch (format_table
[opcode
[5]]) {
1915 case 1: /* RXE format, double constant */ {
1919 emu_store_regd((opcode
[1] >> 4) & 15);
1920 opc
= *((__u32
*) opcode
);
1921 dxb
= (__u64
*) calc_addr(regs
, opc
>> 16, opc
>> 12, opc
);
1922 mathemu_copy_from_user(&temp
, dxb
, 8);
1923 /* call the emulation function */
1924 _fex
= ((int (*)(struct pt_regs
*, int, double *))
1925 jump_table
[opcode
[5]])
1926 (regs
, opcode
[1] >> 4, (double *) &temp
);
1927 emu_load_regd((opcode
[1] >> 4) & 15);
1930 case 2: /* RXE format, float constant */ {
1934 emu_store_rege((opcode
[1] >> 4) & 15);
1935 opc
= *((__u32
*) opcode
);
1936 dxb
= (__u32
*) calc_addr(regs
, opc
>> 16, opc
>> 12, opc
);
1937 mathemu_get_user(temp
, dxb
);
1938 /* call the emulation function */
1939 _fex
= ((int (*)(struct pt_regs
*, int, float *))
1940 jump_table
[opcode
[5]])
1941 (regs
, opcode
[1] >> 4, (float *) &temp
);
1942 emu_load_rege((opcode
[1] >> 4) & 15);
1945 case 3: /* RXF format, double constant */ {
1949 emu_store_regd((opcode
[1] >> 4) & 15);
1950 emu_store_regd((opcode
[4] >> 4) & 15);
1951 opc
= *((__u32
*) opcode
);
1952 dxb
= (__u64
*) calc_addr(regs
, opc
>> 16, opc
>> 12, opc
);
1953 mathemu_copy_from_user(&temp
, dxb
, 8);
1954 /* call the emulation function */
1955 _fex
= ((int (*)(struct pt_regs
*, int, double *, int))
1956 jump_table
[opcode
[5]])
1957 (regs
, opcode
[1] >> 4, (double *) &temp
, opcode
[4] >> 4);
1958 emu_load_regd((opcode
[1] >> 4) & 15);
1961 case 4: /* RXF format, float constant */ {
1965 emu_store_rege((opcode
[1] >> 4) & 15);
1966 emu_store_rege((opcode
[4] >> 4) & 15);
1967 opc
= *((__u32
*) opcode
);
1968 dxb
= (__u32
*) calc_addr(regs
, opc
>> 16, opc
>> 12, opc
);
1969 mathemu_get_user(temp
, dxb
);
1970 /* call the emulation function */
1971 _fex
= ((int (*)(struct pt_regs
*, int, float *, int))
1972 jump_table
[opcode
[5]])
1973 (regs
, opcode
[1] >> 4, (float *) &temp
, opcode
[4] >> 4);
1974 emu_load_rege((opcode
[4] >> 4) & 15);
1977 case 5: /* RXE format, double constant */
1978 /* store double and load long double */
1982 if ((opcode
[1] >> 4) & 0x20)
1984 emu_store_regd((opcode
[1] >> 4) & 15);
1985 opc
= *((__u32
*) opcode
);
1986 dxb
= (__u64
*) calc_addr(regs
, opc
>> 16, opc
>> 12, opc
);
1987 mathemu_copy_from_user(&temp
, dxb
, 8);
1988 /* call the emulation function */
1989 _fex
= ((int (*)(struct pt_regs
*, int, double *))
1990 jump_table
[opcode
[5]])
1991 (regs
, opcode
[1] >> 4, (double *) &temp
);
1992 emu_load_regd((opcode
[1] >> 4) & 15);
1993 emu_load_regd(((opcode
[1] >> 4) & 15) + 2);
1996 case 6: /* RXE format, float constant */
1997 /* store float and load double */
2001 emu_store_rege((opcode
[1] >> 4) & 15);
2002 opc
= *((__u32
*) opcode
);
2003 dxb
= (__u32
*) calc_addr(regs
, opc
>> 16, opc
>> 12, opc
);
2004 mathemu_get_user(temp
, dxb
);
2005 /* call the emulation function */
2006 _fex
= ((int (*)(struct pt_regs
*, int, float *))
2007 jump_table
[opcode
[5]])
2008 (regs
, opcode
[1] >> 4, (float *) &temp
);
2009 emu_load_regd((opcode
[1] >> 4) & 15);
2012 case 7: /* RXE format, float constant */
2013 /* store float and load long double */
2017 if ((opcode
[1] >> 4) & 0x20)
2019 emu_store_rege((opcode
[1] >> 4) & 15);
2020 opc
= *((__u32
*) opcode
);
2021 dxb
= (__u32
*) calc_addr(regs
, opc
>> 16, opc
>> 12, opc
);
2022 mathemu_get_user(temp
, dxb
);
2023 /* call the emulation function */
2024 _fex
= ((int (*)(struct pt_regs
*, int, float *))
2025 jump_table
[opcode
[5]])
2026 (regs
, opcode
[1] >> 4, (float *) &temp
);
2027 emu_load_regd((opcode
[1] >> 4) & 15);
2028 emu_load_regd(((opcode
[1] >> 4) & 15) + 2);
2031 case 8: /* RXE format, RX address used as int value */ {
2035 emu_store_rege((opcode
[1] >> 4) & 15);
2036 opc
= *((__u32
*) opcode
);
2037 dxb
= (__u64
) calc_addr(regs
, opc
>> 16, opc
>> 12, opc
);
2038 /* call the emulation function */
2039 _fex
= ((int (*)(struct pt_regs
*, int, long))
2040 jump_table
[opcode
[5]])
2041 (regs
, opcode
[1] >> 4, dxb
);
2044 case 9: /* RXE format, RX address used as int value */ {
2048 emu_store_regd((opcode
[1] >> 4) & 15);
2049 opc
= *((__u32
*) opcode
);
2050 dxb
= (__u64
) calc_addr(regs
, opc
>> 16, opc
>> 12, opc
);
2051 /* call the emulation function */
2052 _fex
= ((int (*)(struct pt_regs
*, int, long))
2053 jump_table
[opcode
[5]])
2054 (regs
, opcode
[1] >> 4, dxb
);
2057 case 10: /* RXE format, RX address used as int value */ {
2061 if ((opcode
[1] >> 4) & 2)
2063 emu_store_regd((opcode
[1] >> 4) & 15);
2064 emu_store_regd(((opcode
[1] >> 4) & 15) + 2);
2065 opc
= *((__u32
*) opcode
);
2066 dxb
= (__u64
) calc_addr(regs
, opc
>> 16, opc
>> 12, opc
);
2067 /* call the emulation function */
2068 _fex
= ((int (*)(struct pt_regs
*, int, long))
2069 jump_table
[opcode
[5]])
2070 (regs
, opcode
[1] >> 4, dxb
);
2073 default: /* invalid operation */
2077 current
->thread
.fp_regs
.fpc
|= _fex
;
2078 if (current
->thread
.fp_regs
.fpc
& (_fex
<< 8))
2085 * Emulate LDR Rx,Ry with Rx or Ry not in {0, 2, 4, 6}
2087 int math_emu_ldr(__u8
*opcode
) {
2088 s390_fp_regs
*fp_regs
= ¤t
->thread
.fp_regs
;
2089 __u16 opc
= *((__u16
*) opcode
);
2091 if ((opc
& 0x90) == 0) { /* test if rx in {0,2,4,6} */
2092 /* we got an exception therfore ry can't be in {0,2,4,6} */
2093 __asm__
__volatile ( /* load rx from fp_regs.fprs[ry] */
2099 "a" (&fp_regs
->fprs
[opc
& 0xf].d
)
2101 } else if ((opc
& 0x9) == 0) { /* test if ry in {0,2,4,6} */
2102 __asm__
__volatile ( /* store ry to fp_regs.fprs[rx] */
2107 : "a" ((opc
& 0xf) << 4),
2108 "a" (&fp_regs
->fprs
[(opc
& 0xf0)>>4].d
)
2110 } else /* move fp_regs.fprs[ry] to fp_regs.fprs[rx] */
2111 fp_regs
->fprs
[(opc
& 0xf0) >> 4] = fp_regs
->fprs
[opc
& 0xf];
2116 * Emulate LER Rx,Ry with Rx or Ry not in {0, 2, 4, 6}
2118 int math_emu_ler(__u8
*opcode
) {
2119 s390_fp_regs
*fp_regs
= ¤t
->thread
.fp_regs
;
2120 __u16 opc
= *((__u16
*) opcode
);
2122 if ((opc
& 0x90) == 0) { /* test if rx in {0,2,4,6} */
2123 /* we got an exception therfore ry can't be in {0,2,4,6} */
2124 __asm__
__volatile ( /* load rx from fp_regs.fprs[ry] */
2130 "a" (&fp_regs
->fprs
[opc
& 0xf].f
)
2132 } else if ((opc
& 0x9) == 0) { /* test if ry in {0,2,4,6} */
2133 __asm__
__volatile ( /* store ry to fp_regs.fprs[rx] */
2138 : "a" ((opc
& 0xf) << 4),
2139 "a" (&fp_regs
->fprs
[(opc
& 0xf0) >> 4].f
)
2141 } else /* move fp_regs.fprs[ry] to fp_regs.fprs[rx] */
2142 fp_regs
->fprs
[(opc
& 0xf0) >> 4] = fp_regs
->fprs
[opc
& 0xf];
2147 * Emulate LD R,D(X,B) with R not in {0, 2, 4, 6}
2149 int math_emu_ld(__u8
*opcode
, struct pt_regs
* regs
) {
2150 s390_fp_regs
*fp_regs
= ¤t
->thread
.fp_regs
;
2151 __u32 opc
= *((__u32
*) opcode
);
2154 dxb
= (__u64
*) calc_addr(regs
, opc
>> 16, opc
>> 12, opc
);
2155 mathemu_copy_from_user(&fp_regs
->fprs
[(opc
>> 20) & 0xf].d
, dxb
, 8);
2160 * Emulate LE R,D(X,B) with R not in {0, 2, 4, 6}
2162 int math_emu_le(__u8
*opcode
, struct pt_regs
* regs
) {
2163 s390_fp_regs
*fp_regs
= ¤t
->thread
.fp_regs
;
2164 __u32 opc
= *((__u32
*) opcode
);
2167 dxb
= (__u32
*) calc_addr(regs
, opc
>> 16, opc
>> 12, opc
);
2168 mem
= (__u32
*) (&fp_regs
->fprs
[(opc
>> 20) & 0xf].f
);
2169 mathemu_get_user(mem
[0], dxb
);
2174 * Emulate STD R,D(X,B) with R not in {0, 2, 4, 6}
2176 int math_emu_std(__u8
*opcode
, struct pt_regs
* regs
) {
2177 s390_fp_regs
*fp_regs
= ¤t
->thread
.fp_regs
;
2178 __u32 opc
= *((__u32
*) opcode
);
2181 dxb
= (__u64
*) calc_addr(regs
, opc
>> 16, opc
>> 12, opc
);
2182 mathemu_copy_to_user(dxb
, &fp_regs
->fprs
[(opc
>> 20) & 0xf].d
, 8);
2187 * Emulate STE R,D(X,B) with R not in {0, 2, 4, 6}
2189 int math_emu_ste(__u8
*opcode
, struct pt_regs
* regs
) {
2190 s390_fp_regs
*fp_regs
= ¤t
->thread
.fp_regs
;
2191 __u32 opc
= *((__u32
*) opcode
);
2194 dxb
= (__u32
*) calc_addr(regs
, opc
>> 16, opc
>> 12, opc
);
2195 mem
= (__u32
*) (&fp_regs
->fprs
[(opc
>> 20) & 0xf].f
);
2196 mathemu_put_user(mem
[0], dxb
);
2203 int math_emu_lfpc(__u8
*opcode
, struct pt_regs
*regs
) {
2204 __u32 opc
= *((__u32
*) opcode
);
2207 dxb
= (__u32
*) calc_addr(regs
, 0, opc
>>12, opc
);
2208 mathemu_get_user(temp
, dxb
);
2209 if ((temp
& ~FPC_VALID_MASK
) != 0)
2211 current
->thread
.fp_regs
.fpc
= temp
;
2216 * Emulate STFPC D(B)
2218 int math_emu_stfpc(__u8
*opcode
, struct pt_regs
*regs
) {
2219 __u32 opc
= *((__u32
*) opcode
);
2222 dxb
= (__u32
*) calc_addr(regs
, 0, opc
>>12, opc
);
2223 mathemu_put_user(current
->thread
.fp_regs
.fpc
, dxb
);
2230 int math_emu_srnm(__u8
*opcode
, struct pt_regs
*regs
) {
2231 __u32 opc
= *((__u32
*) opcode
);
2234 temp
= calc_addr(regs
, 0, opc
>>12, opc
);
2235 current
->thread
.fp_regs
.fpc
&= ~3;
2236 current
->thread
.fp_regs
.fpc
|= (temp
& 3);
2240 /* broken compiler ... */
2242 __negdi2 (long long u
)
2255 w
.s
[0] = -uu
.s
[0] - ((int) w
.s
[1] != 0);