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