linux/arch/s390/math-emu/math.c
<<
>>
Prefs
   1/*
   2 *  S390 version
   3 *    Copyright IBM Corp. 1999, 2001
   4 *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
   5 *
   6 * 'math.c' emulates IEEE instructions on a S390 processor
   7 *          that does not have the IEEE fpu (all processors before G5).
   8 */
   9
  10#include <linux/types.h>
  11#include <linux/sched.h>
  12#include <linux/mm.h>
  13#include <asm/uaccess.h>
  14#include <asm/lowcore.h>
  15
  16#include <asm/sfp-util.h>
  17#include <math-emu/soft-fp.h>
  18#include <math-emu/single.h>
  19#include <math-emu/double.h>
  20#include <math-emu/quad.h>
  21
  22#define FPC_VALID_MASK          0xF8F8FF03
  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
  63typedef union {
  64        long double ld;
  65        struct {
  66                __u64 high;
  67                __u64 low;
  68        } w;
  69} mathemu_ldcv;
  70
  71#ifdef CONFIG_SYSCTL
  72int 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
  99static 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
 117static 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 */
 129static 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 */
 146static 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 */
 168static 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 */
 183static 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 */
 198static 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 */
 213static 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 */
 228static 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 */
 249static 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 */
 265static 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 */
 281static 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 */
 297static 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 */
 313static 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 */
 337static 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 */
 356static 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 */
 375static 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 */
 394static 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 */
 413static 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 */
 430static 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 */
 444static 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 */
 458static 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 */
 481static 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 */
 501static 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 */
 521static 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 */
 542static 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 */
 556static 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 */
 570static 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 */
 584static 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 */
 598static 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 */
 604static 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 */
 610static 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 */
 616static 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 */
 632static 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 */
 644static 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 */
 656static 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 */
 675static 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 */
 689static 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 */
 703static 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 */
 728static 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 */
 749static 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 */
 769static 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 */
 785static 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 */
 801static 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 */
 817static 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 */
 833static 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 */
 846static 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 */
 859static 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 */
 885static 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 */
 903static 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 */
 921static 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 */
 947static 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 */
 965static 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 */
 983static 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 */
 999static 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 */
1015static 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 */
1028static 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 */
1049static 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 */
1063static 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 */
1077static 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 */
1096static 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 */
1115static 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 */
1129static 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 */
1143static 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 */
1159static 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 */
1175static 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 */
1191static 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 */
1207static 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 */
1223static 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 */
1239static 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 */
1255static 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 */
1271static 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 */
1287static 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 */
1303static 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 */
1314static 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 */
1333static 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 */
1347static 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 */
1361static 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 */
1375static 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 */
1389static 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 */
1411static 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 */
1426static 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 */
1441static 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 */
1456static 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 */
1471static 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 */
1505static 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 */
1536static 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
1566static 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
1578static 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
1590static 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
1603static 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
1615int 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
1877static 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    
1889int 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 */
2086int 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 */
2116int 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 */
2146int 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 */
2159int 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 */
2173int 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 */
2186int 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 */
2200int 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 */
2215int 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 */
2227int 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 ... */
2238long 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