Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/s390/math-emu/math.c
10817 views
1
/*
2
* arch/s390/math-emu/math.c
3
*
4
* S390 version
5
* Copyright (C) 1999-2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
6
* Author(s): Martin Schwidefsky ([email protected]),
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 therefore 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 therefore 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
}
2256
2257