OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [arch/] [s390/] [math-emu/] [math.c] - Blame information for rev 63

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.