linux/arch/powerpc/kvm/book3s_paired_singles.c
<<
>>
Prefs
   1/*
   2 * This program is free software; you can redistribute it and/or modify
   3 * it under the terms of the GNU General Public License, version 2, as
   4 * published by the Free Software Foundation.
   5 *
   6 * This program is distributed in the hope that it will be useful,
   7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
   8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   9 * GNU General Public License for more details.
  10 *
  11 * You should have received a copy of the GNU General Public License
  12 * along with this program; if not, write to the Free Software
  13 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  14 *
  15 * Copyright Novell Inc 2010
  16 *
  17 * Authors: Alexander Graf <agraf@suse.de>
  18 */
  19
  20#include <asm/kvm.h>
  21#include <asm/kvm_ppc.h>
  22#include <asm/disassemble.h>
  23#include <asm/kvm_book3s.h>
  24#include <asm/kvm_fpu.h>
  25#include <asm/reg.h>
  26#include <asm/cacheflush.h>
  27#include <asm/switch_to.h>
  28#include <linux/vmalloc.h>
  29
  30/* #define DEBUG */
  31
  32#ifdef DEBUG
  33#define dprintk printk
  34#else
  35#define dprintk(...) do { } while(0);
  36#endif
  37
  38#define OP_LFS                  48
  39#define OP_LFSU                 49
  40#define OP_LFD                  50
  41#define OP_LFDU                 51
  42#define OP_STFS                 52
  43#define OP_STFSU                53
  44#define OP_STFD                 54
  45#define OP_STFDU                55
  46#define OP_PSQ_L                56
  47#define OP_PSQ_LU               57
  48#define OP_PSQ_ST               60
  49#define OP_PSQ_STU              61
  50
  51#define OP_31_LFSX              535
  52#define OP_31_LFSUX             567
  53#define OP_31_LFDX              599
  54#define OP_31_LFDUX             631
  55#define OP_31_STFSX             663
  56#define OP_31_STFSUX            695
  57#define OP_31_STFX              727
  58#define OP_31_STFUX             759
  59#define OP_31_LWIZX             887
  60#define OP_31_STFIWX            983
  61
  62#define OP_59_FADDS             21
  63#define OP_59_FSUBS             20
  64#define OP_59_FSQRTS            22
  65#define OP_59_FDIVS             18
  66#define OP_59_FRES              24
  67#define OP_59_FMULS             25
  68#define OP_59_FRSQRTES          26
  69#define OP_59_FMSUBS            28
  70#define OP_59_FMADDS            29
  71#define OP_59_FNMSUBS           30
  72#define OP_59_FNMADDS           31
  73
  74#define OP_63_FCMPU             0
  75#define OP_63_FCPSGN            8
  76#define OP_63_FRSP              12
  77#define OP_63_FCTIW             14
  78#define OP_63_FCTIWZ            15
  79#define OP_63_FDIV              18
  80#define OP_63_FADD              21
  81#define OP_63_FSQRT             22
  82#define OP_63_FSEL              23
  83#define OP_63_FRE               24
  84#define OP_63_FMUL              25
  85#define OP_63_FRSQRTE           26
  86#define OP_63_FMSUB             28
  87#define OP_63_FMADD             29
  88#define OP_63_FNMSUB            30
  89#define OP_63_FNMADD            31
  90#define OP_63_FCMPO             32
  91#define OP_63_MTFSB1            38 // XXX
  92#define OP_63_FSUB              20
  93#define OP_63_FNEG              40
  94#define OP_63_MCRFS             64
  95#define OP_63_MTFSB0            70
  96#define OP_63_FMR               72
  97#define OP_63_MTFSFI            134
  98#define OP_63_FABS              264
  99#define OP_63_MFFS              583
 100#define OP_63_MTFSF             711
 101
 102#define OP_4X_PS_CMPU0          0
 103#define OP_4X_PSQ_LX            6
 104#define OP_4XW_PSQ_STX          7
 105#define OP_4A_PS_SUM0           10
 106#define OP_4A_PS_SUM1           11
 107#define OP_4A_PS_MULS0          12
 108#define OP_4A_PS_MULS1          13
 109#define OP_4A_PS_MADDS0         14
 110#define OP_4A_PS_MADDS1         15
 111#define OP_4A_PS_DIV            18
 112#define OP_4A_PS_SUB            20
 113#define OP_4A_PS_ADD            21
 114#define OP_4A_PS_SEL            23
 115#define OP_4A_PS_RES            24
 116#define OP_4A_PS_MUL            25
 117#define OP_4A_PS_RSQRTE         26
 118#define OP_4A_PS_MSUB           28
 119#define OP_4A_PS_MADD           29
 120#define OP_4A_PS_NMSUB          30
 121#define OP_4A_PS_NMADD          31
 122#define OP_4X_PS_CMPO0          32
 123#define OP_4X_PSQ_LUX           38
 124#define OP_4XW_PSQ_STUX         39
 125#define OP_4X_PS_NEG            40
 126#define OP_4X_PS_CMPU1          64
 127#define OP_4X_PS_MR             72
 128#define OP_4X_PS_CMPO1          96
 129#define OP_4X_PS_NABS           136
 130#define OP_4X_PS_ABS            264
 131#define OP_4X_PS_MERGE00        528
 132#define OP_4X_PS_MERGE01        560
 133#define OP_4X_PS_MERGE10        592
 134#define OP_4X_PS_MERGE11        624
 135
 136#define SCALAR_NONE             0
 137#define SCALAR_HIGH             (1 << 0)
 138#define SCALAR_LOW              (1 << 1)
 139#define SCALAR_NO_PS0           (1 << 2)
 140#define SCALAR_NO_PS1           (1 << 3)
 141
 142#define GQR_ST_TYPE_MASK        0x00000007
 143#define GQR_ST_TYPE_SHIFT       0
 144#define GQR_ST_SCALE_MASK       0x00003f00
 145#define GQR_ST_SCALE_SHIFT      8
 146#define GQR_LD_TYPE_MASK        0x00070000
 147#define GQR_LD_TYPE_SHIFT       16
 148#define GQR_LD_SCALE_MASK       0x3f000000
 149#define GQR_LD_SCALE_SHIFT      24
 150
 151#define GQR_QUANTIZE_FLOAT      0
 152#define GQR_QUANTIZE_U8         4
 153#define GQR_QUANTIZE_U16        5
 154#define GQR_QUANTIZE_S8         6
 155#define GQR_QUANTIZE_S16        7
 156
 157#define FPU_LS_SINGLE           0
 158#define FPU_LS_DOUBLE           1
 159#define FPU_LS_SINGLE_LOW       2
 160
 161static inline void kvmppc_sync_qpr(struct kvm_vcpu *vcpu, int rt)
 162{
 163        kvm_cvt_df(&vcpu->arch.fpr[rt], &vcpu->arch.qpr[rt]);
 164}
 165
 166static void kvmppc_inject_pf(struct kvm_vcpu *vcpu, ulong eaddr, bool is_store)
 167{
 168        u64 dsisr;
 169        struct kvm_vcpu_arch_shared *shared = vcpu->arch.shared;
 170
 171        shared->msr = kvmppc_set_field(shared->msr, 33, 36, 0);
 172        shared->msr = kvmppc_set_field(shared->msr, 42, 47, 0);
 173        shared->dar = eaddr;
 174        /* Page Fault */
 175        dsisr = kvmppc_set_field(0, 33, 33, 1);
 176        if (is_store)
 177                shared->dsisr = kvmppc_set_field(dsisr, 38, 38, 1);
 178        kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_DATA_STORAGE);
 179}
 180
 181static int kvmppc_emulate_fpr_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
 182                                   int rs, ulong addr, int ls_type)
 183{
 184        int emulated = EMULATE_FAIL;
 185        int r;
 186        char tmp[8];
 187        int len = sizeof(u32);
 188
 189        if (ls_type == FPU_LS_DOUBLE)
 190                len = sizeof(u64);
 191
 192        /* read from memory */
 193        r = kvmppc_ld(vcpu, &addr, len, tmp, true);
 194        vcpu->arch.paddr_accessed = addr;
 195
 196        if (r < 0) {
 197                kvmppc_inject_pf(vcpu, addr, false);
 198                goto done_load;
 199        } else if (r == EMULATE_DO_MMIO) {
 200                emulated = kvmppc_handle_load(run, vcpu, KVM_MMIO_REG_FPR | rs,
 201                                              len, 1);
 202                goto done_load;
 203        }
 204
 205        emulated = EMULATE_DONE;
 206
 207        /* put in registers */
 208        switch (ls_type) {
 209        case FPU_LS_SINGLE:
 210                kvm_cvt_fd((u32*)tmp, &vcpu->arch.fpr[rs]);
 211                vcpu->arch.qpr[rs] = *((u32*)tmp);
 212                break;
 213        case FPU_LS_DOUBLE:
 214                vcpu->arch.fpr[rs] = *((u64*)tmp);
 215                break;
 216        }
 217
 218        dprintk(KERN_INFO "KVM: FPR_LD [0x%llx] at 0x%lx (%d)\n", *(u64*)tmp,
 219                          addr, len);
 220
 221done_load:
 222        return emulated;
 223}
 224
 225static int kvmppc_emulate_fpr_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
 226                                    int rs, ulong addr, int ls_type)
 227{
 228        int emulated = EMULATE_FAIL;
 229        int r;
 230        char tmp[8];
 231        u64 val;
 232        int len;
 233
 234        switch (ls_type) {
 235        case FPU_LS_SINGLE:
 236                kvm_cvt_df(&vcpu->arch.fpr[rs], (u32*)tmp);
 237                val = *((u32*)tmp);
 238                len = sizeof(u32);
 239                break;
 240        case FPU_LS_SINGLE_LOW:
 241                *((u32*)tmp) = vcpu->arch.fpr[rs];
 242                val = vcpu->arch.fpr[rs] & 0xffffffff;
 243                len = sizeof(u32);
 244                break;
 245        case FPU_LS_DOUBLE:
 246                *((u64*)tmp) = vcpu->arch.fpr[rs];
 247                val = vcpu->arch.fpr[rs];
 248                len = sizeof(u64);
 249                break;
 250        default:
 251                val = 0;
 252                len = 0;
 253        }
 254
 255        r = kvmppc_st(vcpu, &addr, len, tmp, true);
 256        vcpu->arch.paddr_accessed = addr;
 257        if (r < 0) {
 258                kvmppc_inject_pf(vcpu, addr, true);
 259        } else if (r == EMULATE_DO_MMIO) {
 260                emulated = kvmppc_handle_store(run, vcpu, val, len, 1);
 261        } else {
 262                emulated = EMULATE_DONE;
 263        }
 264
 265        dprintk(KERN_INFO "KVM: FPR_ST [0x%llx] at 0x%lx (%d)\n",
 266                          val, addr, len);
 267
 268        return emulated;
 269}
 270
 271static int kvmppc_emulate_psq_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
 272                                   int rs, ulong addr, bool w, int i)
 273{
 274        int emulated = EMULATE_FAIL;
 275        int r;
 276        float one = 1.0;
 277        u32 tmp[2];
 278
 279        /* read from memory */
 280        if (w) {
 281                r = kvmppc_ld(vcpu, &addr, sizeof(u32), tmp, true);
 282                memcpy(&tmp[1], &one, sizeof(u32));
 283        } else {
 284                r = kvmppc_ld(vcpu, &addr, sizeof(u32) * 2, tmp, true);
 285        }
 286        vcpu->arch.paddr_accessed = addr;
 287        if (r < 0) {
 288                kvmppc_inject_pf(vcpu, addr, false);
 289                goto done_load;
 290        } else if ((r == EMULATE_DO_MMIO) && w) {
 291                emulated = kvmppc_handle_load(run, vcpu, KVM_MMIO_REG_FPR | rs,
 292                                              4, 1);
 293                vcpu->arch.qpr[rs] = tmp[1];
 294                goto done_load;
 295        } else if (r == EMULATE_DO_MMIO) {
 296                emulated = kvmppc_handle_load(run, vcpu, KVM_MMIO_REG_FQPR | rs,
 297                                              8, 1);
 298                goto done_load;
 299        }
 300
 301        emulated = EMULATE_DONE;
 302
 303        /* put in registers */
 304        kvm_cvt_fd(&tmp[0], &vcpu->arch.fpr[rs]);
 305        vcpu->arch.qpr[rs] = tmp[1];
 306
 307        dprintk(KERN_INFO "KVM: PSQ_LD [0x%x, 0x%x] at 0x%lx (%d)\n", tmp[0],
 308                          tmp[1], addr, w ? 4 : 8);
 309
 310done_load:
 311        return emulated;
 312}
 313
 314static int kvmppc_emulate_psq_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
 315                                    int rs, ulong addr, bool w, int i)
 316{
 317        int emulated = EMULATE_FAIL;
 318        int r;
 319        u32 tmp[2];
 320        int len = w ? sizeof(u32) : sizeof(u64);
 321
 322        kvm_cvt_df(&vcpu->arch.fpr[rs], &tmp[0]);
 323        tmp[1] = vcpu->arch.qpr[rs];
 324
 325        r = kvmppc_st(vcpu, &addr, len, tmp, true);
 326        vcpu->arch.paddr_accessed = addr;
 327        if (r < 0) {
 328                kvmppc_inject_pf(vcpu, addr, true);
 329        } else if ((r == EMULATE_DO_MMIO) && w) {
 330                emulated = kvmppc_handle_store(run, vcpu, tmp[0], 4, 1);
 331        } else if (r == EMULATE_DO_MMIO) {
 332                u64 val = ((u64)tmp[0] << 32) | tmp[1];
 333                emulated = kvmppc_handle_store(run, vcpu, val, 8, 1);
 334        } else {
 335                emulated = EMULATE_DONE;
 336        }
 337
 338        dprintk(KERN_INFO "KVM: PSQ_ST [0x%x, 0x%x] at 0x%lx (%d)\n",
 339                          tmp[0], tmp[1], addr, len);
 340
 341        return emulated;
 342}
 343
 344/*
 345 * Cuts out inst bits with ordering according to spec.
 346 * That means the leftmost bit is zero. All given bits are included.
 347 */
 348static inline u32 inst_get_field(u32 inst, int msb, int lsb)
 349{
 350        return kvmppc_get_field(inst, msb + 32, lsb + 32);
 351}
 352
 353/*
 354 * Replaces inst bits with ordering according to spec.
 355 */
 356static inline u32 inst_set_field(u32 inst, int msb, int lsb, int value)
 357{
 358        return kvmppc_set_field(inst, msb + 32, lsb + 32, value);
 359}
 360
 361bool kvmppc_inst_is_paired_single(struct kvm_vcpu *vcpu, u32 inst)
 362{
 363        if (!(vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE))
 364                return false;
 365
 366        switch (get_op(inst)) {
 367        case OP_PSQ_L:
 368        case OP_PSQ_LU:
 369        case OP_PSQ_ST:
 370        case OP_PSQ_STU:
 371        case OP_LFS:
 372        case OP_LFSU:
 373        case OP_LFD:
 374        case OP_LFDU:
 375        case OP_STFS:
 376        case OP_STFSU:
 377        case OP_STFD:
 378        case OP_STFDU:
 379                return true;
 380        case 4:
 381                /* X form */
 382                switch (inst_get_field(inst, 21, 30)) {
 383                case OP_4X_PS_CMPU0:
 384                case OP_4X_PSQ_LX:
 385                case OP_4X_PS_CMPO0:
 386                case OP_4X_PSQ_LUX:
 387                case OP_4X_PS_NEG:
 388                case OP_4X_PS_CMPU1:
 389                case OP_4X_PS_MR:
 390                case OP_4X_PS_CMPO1:
 391                case OP_4X_PS_NABS:
 392                case OP_4X_PS_ABS:
 393                case OP_4X_PS_MERGE00:
 394                case OP_4X_PS_MERGE01:
 395                case OP_4X_PS_MERGE10:
 396                case OP_4X_PS_MERGE11:
 397                        return true;
 398                }
 399                /* XW form */
 400                switch (inst_get_field(inst, 25, 30)) {
 401                case OP_4XW_PSQ_STX:
 402                case OP_4XW_PSQ_STUX:
 403                        return true;
 404                }
 405                /* A form */
 406                switch (inst_get_field(inst, 26, 30)) {
 407                case OP_4A_PS_SUM1:
 408                case OP_4A_PS_SUM0:
 409                case OP_4A_PS_MULS0:
 410                case OP_4A_PS_MULS1:
 411                case OP_4A_PS_MADDS0:
 412                case OP_4A_PS_MADDS1:
 413                case OP_4A_PS_DIV:
 414                case OP_4A_PS_SUB:
 415                case OP_4A_PS_ADD:
 416                case OP_4A_PS_SEL:
 417                case OP_4A_PS_RES:
 418                case OP_4A_PS_MUL:
 419                case OP_4A_PS_RSQRTE:
 420                case OP_4A_PS_MSUB:
 421                case OP_4A_PS_MADD:
 422                case OP_4A_PS_NMSUB:
 423                case OP_4A_PS_NMADD:
 424                        return true;
 425                }
 426                break;
 427        case 59:
 428                switch (inst_get_field(inst, 21, 30)) {
 429                case OP_59_FADDS:
 430                case OP_59_FSUBS:
 431                case OP_59_FDIVS:
 432                case OP_59_FRES:
 433                case OP_59_FRSQRTES:
 434                        return true;
 435                }
 436                switch (inst_get_field(inst, 26, 30)) {
 437                case OP_59_FMULS:
 438                case OP_59_FMSUBS:
 439                case OP_59_FMADDS:
 440                case OP_59_FNMSUBS:
 441                case OP_59_FNMADDS:
 442                        return true;
 443                }
 444                break;
 445        case 63:
 446                switch (inst_get_field(inst, 21, 30)) {
 447                case OP_63_MTFSB0:
 448                case OP_63_MTFSB1:
 449                case OP_63_MTFSF:
 450                case OP_63_MTFSFI:
 451                case OP_63_MCRFS:
 452                case OP_63_MFFS:
 453                case OP_63_FCMPU:
 454                case OP_63_FCMPO:
 455                case OP_63_FNEG:
 456                case OP_63_FMR:
 457                case OP_63_FABS:
 458                case OP_63_FRSP:
 459                case OP_63_FDIV:
 460                case OP_63_FADD:
 461                case OP_63_FSUB:
 462                case OP_63_FCTIW:
 463                case OP_63_FCTIWZ:
 464                case OP_63_FRSQRTE:
 465                case OP_63_FCPSGN:
 466                        return true;
 467                }
 468                switch (inst_get_field(inst, 26, 30)) {
 469                case OP_63_FMUL:
 470                case OP_63_FSEL:
 471                case OP_63_FMSUB:
 472                case OP_63_FMADD:
 473                case OP_63_FNMSUB:
 474                case OP_63_FNMADD:
 475                        return true;
 476                }
 477                break;
 478        case 31:
 479                switch (inst_get_field(inst, 21, 30)) {
 480                case OP_31_LFSX:
 481                case OP_31_LFSUX:
 482                case OP_31_LFDX:
 483                case OP_31_LFDUX:
 484                case OP_31_STFSX:
 485                case OP_31_STFSUX:
 486                case OP_31_STFX:
 487                case OP_31_STFUX:
 488                case OP_31_STFIWX:
 489                        return true;
 490                }
 491                break;
 492        }
 493
 494        return false;
 495}
 496
 497static int get_d_signext(u32 inst)
 498{
 499        int d = inst & 0x8ff;
 500
 501        if (d & 0x800)
 502                return -(d & 0x7ff);
 503
 504        return (d & 0x7ff);
 505}
 506
 507static int kvmppc_ps_three_in(struct kvm_vcpu *vcpu, bool rc,
 508                                      int reg_out, int reg_in1, int reg_in2,
 509                                      int reg_in3, int scalar,
 510                                      void (*func)(u64 *fpscr,
 511                                                 u32 *dst, u32 *src1,
 512                                                 u32 *src2, u32 *src3))
 513{
 514        u32 *qpr = vcpu->arch.qpr;
 515        u64 *fpr = vcpu->arch.fpr;
 516        u32 ps0_out;
 517        u32 ps0_in1, ps0_in2, ps0_in3;
 518        u32 ps1_in1, ps1_in2, ps1_in3;
 519
 520        /* RC */
 521        WARN_ON(rc);
 522
 523        /* PS0 */
 524        kvm_cvt_df(&fpr[reg_in1], &ps0_in1);
 525        kvm_cvt_df(&fpr[reg_in2], &ps0_in2);
 526        kvm_cvt_df(&fpr[reg_in3], &ps0_in3);
 527
 528        if (scalar & SCALAR_LOW)
 529                ps0_in2 = qpr[reg_in2];
 530
 531        func(&vcpu->arch.fpscr, &ps0_out, &ps0_in1, &ps0_in2, &ps0_in3);
 532
 533        dprintk(KERN_INFO "PS3 ps0 -> f(0x%x, 0x%x, 0x%x) = 0x%x\n",
 534                          ps0_in1, ps0_in2, ps0_in3, ps0_out);
 535
 536        if (!(scalar & SCALAR_NO_PS0))
 537                kvm_cvt_fd(&ps0_out, &fpr[reg_out]);
 538
 539        /* PS1 */
 540        ps1_in1 = qpr[reg_in1];
 541        ps1_in2 = qpr[reg_in2];
 542        ps1_in3 = qpr[reg_in3];
 543
 544        if (scalar & SCALAR_HIGH)
 545                ps1_in2 = ps0_in2;
 546
 547        if (!(scalar & SCALAR_NO_PS1))
 548                func(&vcpu->arch.fpscr, &qpr[reg_out], &ps1_in1, &ps1_in2, &ps1_in3);
 549
 550        dprintk(KERN_INFO "PS3 ps1 -> f(0x%x, 0x%x, 0x%x) = 0x%x\n",
 551                          ps1_in1, ps1_in2, ps1_in3, qpr[reg_out]);
 552
 553        return EMULATE_DONE;
 554}
 555
 556static int kvmppc_ps_two_in(struct kvm_vcpu *vcpu, bool rc,
 557                                    int reg_out, int reg_in1, int reg_in2,
 558                                    int scalar,
 559                                    void (*func)(u64 *fpscr,
 560                                                 u32 *dst, u32 *src1,
 561                                                 u32 *src2))
 562{
 563        u32 *qpr = vcpu->arch.qpr;
 564        u64 *fpr = vcpu->arch.fpr;
 565        u32 ps0_out;
 566        u32 ps0_in1, ps0_in2;
 567        u32 ps1_out;
 568        u32 ps1_in1, ps1_in2;
 569
 570        /* RC */
 571        WARN_ON(rc);
 572
 573        /* PS0 */
 574        kvm_cvt_df(&fpr[reg_in1], &ps0_in1);
 575
 576        if (scalar & SCALAR_LOW)
 577                ps0_in2 = qpr[reg_in2];
 578        else
 579                kvm_cvt_df(&fpr[reg_in2], &ps0_in2);
 580
 581        func(&vcpu->arch.fpscr, &ps0_out, &ps0_in1, &ps0_in2);
 582
 583        if (!(scalar & SCALAR_NO_PS0)) {
 584                dprintk(KERN_INFO "PS2 ps0 -> f(0x%x, 0x%x) = 0x%x\n",
 585                                  ps0_in1, ps0_in2, ps0_out);
 586
 587                kvm_cvt_fd(&ps0_out, &fpr[reg_out]);
 588        }
 589
 590        /* PS1 */
 591        ps1_in1 = qpr[reg_in1];
 592        ps1_in2 = qpr[reg_in2];
 593
 594        if (scalar & SCALAR_HIGH)
 595                ps1_in2 = ps0_in2;
 596
 597        func(&vcpu->arch.fpscr, &ps1_out, &ps1_in1, &ps1_in2);
 598
 599        if (!(scalar & SCALAR_NO_PS1)) {
 600                qpr[reg_out] = ps1_out;
 601
 602                dprintk(KERN_INFO "PS2 ps1 -> f(0x%x, 0x%x) = 0x%x\n",
 603                                  ps1_in1, ps1_in2, qpr[reg_out]);
 604        }
 605
 606        return EMULATE_DONE;
 607}
 608
 609static int kvmppc_ps_one_in(struct kvm_vcpu *vcpu, bool rc,
 610                                    int reg_out, int reg_in,
 611                                    void (*func)(u64 *t,
 612                                                 u32 *dst, u32 *src1))
 613{
 614        u32 *qpr = vcpu->arch.qpr;
 615        u64 *fpr = vcpu->arch.fpr;
 616        u32 ps0_out, ps0_in;
 617        u32 ps1_in;
 618
 619        /* RC */
 620        WARN_ON(rc);
 621
 622        /* PS0 */
 623        kvm_cvt_df(&fpr[reg_in], &ps0_in);
 624        func(&vcpu->arch.fpscr, &ps0_out, &ps0_in);
 625
 626        dprintk(KERN_INFO "PS1 ps0 -> f(0x%x) = 0x%x\n",
 627                          ps0_in, ps0_out);
 628
 629        kvm_cvt_fd(&ps0_out, &fpr[reg_out]);
 630
 631        /* PS1 */
 632        ps1_in = qpr[reg_in];
 633        func(&vcpu->arch.fpscr, &qpr[reg_out], &ps1_in);
 634
 635        dprintk(KERN_INFO "PS1 ps1 -> f(0x%x) = 0x%x\n",
 636                          ps1_in, qpr[reg_out]);
 637
 638        return EMULATE_DONE;
 639}
 640
 641int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu)
 642{
 643        u32 inst = kvmppc_get_last_inst(vcpu);
 644        enum emulation_result emulated = EMULATE_DONE;
 645
 646        int ax_rd = inst_get_field(inst, 6, 10);
 647        int ax_ra = inst_get_field(inst, 11, 15);
 648        int ax_rb = inst_get_field(inst, 16, 20);
 649        int ax_rc = inst_get_field(inst, 21, 25);
 650        short full_d = inst_get_field(inst, 16, 31);
 651
 652        u64 *fpr_d = &vcpu->arch.fpr[ax_rd];
 653        u64 *fpr_a = &vcpu->arch.fpr[ax_ra];
 654        u64 *fpr_b = &vcpu->arch.fpr[ax_rb];
 655        u64 *fpr_c = &vcpu->arch.fpr[ax_rc];
 656
 657        bool rcomp = (inst & 1) ? true : false;
 658        u32 cr = kvmppc_get_cr(vcpu);
 659#ifdef DEBUG
 660        int i;
 661#endif
 662
 663        if (!kvmppc_inst_is_paired_single(vcpu, inst))
 664                return EMULATE_FAIL;
 665
 666        if (!(vcpu->arch.shared->msr & MSR_FP)) {
 667                kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL);
 668                return EMULATE_AGAIN;
 669        }
 670
 671        kvmppc_giveup_ext(vcpu, MSR_FP);
 672        preempt_disable();
 673        enable_kernel_fp();
 674        /* Do we need to clear FE0 / FE1 here? Don't think so. */
 675
 676#ifdef DEBUG
 677        for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++) {
 678                u32 f;
 679                kvm_cvt_df(&vcpu->arch.fpr[i], &f);
 680                dprintk(KERN_INFO "FPR[%d] = 0x%x / 0x%llx    QPR[%d] = 0x%x\n",
 681                        i, f, vcpu->arch.fpr[i], i, vcpu->arch.qpr[i]);
 682        }
 683#endif
 684
 685        switch (get_op(inst)) {
 686        case OP_PSQ_L:
 687        {
 688                ulong addr = ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0;
 689                bool w = inst_get_field(inst, 16, 16) ? true : false;
 690                int i = inst_get_field(inst, 17, 19);
 691
 692                addr += get_d_signext(inst);
 693                emulated = kvmppc_emulate_psq_load(run, vcpu, ax_rd, addr, w, i);
 694                break;
 695        }
 696        case OP_PSQ_LU:
 697        {
 698                ulong addr = kvmppc_get_gpr(vcpu, ax_ra);
 699                bool w = inst_get_field(inst, 16, 16) ? true : false;
 700                int i = inst_get_field(inst, 17, 19);
 701
 702                addr += get_d_signext(inst);
 703                emulated = kvmppc_emulate_psq_load(run, vcpu, ax_rd, addr, w, i);
 704
 705                if (emulated == EMULATE_DONE)
 706                        kvmppc_set_gpr(vcpu, ax_ra, addr);
 707                break;
 708        }
 709        case OP_PSQ_ST:
 710        {
 711                ulong addr = ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0;
 712                bool w = inst_get_field(inst, 16, 16) ? true : false;
 713                int i = inst_get_field(inst, 17, 19);
 714
 715                addr += get_d_signext(inst);
 716                emulated = kvmppc_emulate_psq_store(run, vcpu, ax_rd, addr, w, i);
 717                break;
 718        }
 719        case OP_PSQ_STU:
 720        {
 721                ulong addr = kvmppc_get_gpr(vcpu, ax_ra);
 722                bool w = inst_get_field(inst, 16, 16) ? true : false;
 723                int i = inst_get_field(inst, 17, 19);
 724
 725                addr += get_d_signext(inst);
 726                emulated = kvmppc_emulate_psq_store(run, vcpu, ax_rd, addr, w, i);
 727
 728                if (emulated == EMULATE_DONE)
 729                        kvmppc_set_gpr(vcpu, ax_ra, addr);
 730                break;
 731        }
 732        case 4:
 733                /* X form */
 734                switch (inst_get_field(inst, 21, 30)) {
 735                case OP_4X_PS_CMPU0:
 736                        /* XXX */
 737                        emulated = EMULATE_FAIL;
 738                        break;
 739                case OP_4X_PSQ_LX:
 740                {
 741                        ulong addr = ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0;
 742                        bool w = inst_get_field(inst, 21, 21) ? true : false;
 743                        int i = inst_get_field(inst, 22, 24);
 744
 745                        addr += kvmppc_get_gpr(vcpu, ax_rb);
 746                        emulated = kvmppc_emulate_psq_load(run, vcpu, ax_rd, addr, w, i);
 747                        break;
 748                }
 749                case OP_4X_PS_CMPO0:
 750                        /* XXX */
 751                        emulated = EMULATE_FAIL;
 752                        break;
 753                case OP_4X_PSQ_LUX:
 754                {
 755                        ulong addr = kvmppc_get_gpr(vcpu, ax_ra);
 756                        bool w = inst_get_field(inst, 21, 21) ? true : false;
 757                        int i = inst_get_field(inst, 22, 24);
 758
 759                        addr += kvmppc_get_gpr(vcpu, ax_rb);
 760                        emulated = kvmppc_emulate_psq_load(run, vcpu, ax_rd, addr, w, i);
 761
 762                        if (emulated == EMULATE_DONE)
 763                                kvmppc_set_gpr(vcpu, ax_ra, addr);
 764                        break;
 765                }
 766                case OP_4X_PS_NEG:
 767                        vcpu->arch.fpr[ax_rd] = vcpu->arch.fpr[ax_rb];
 768                        vcpu->arch.fpr[ax_rd] ^= 0x8000000000000000ULL;
 769                        vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb];
 770                        vcpu->arch.qpr[ax_rd] ^= 0x80000000;
 771                        break;
 772                case OP_4X_PS_CMPU1:
 773                        /* XXX */
 774                        emulated = EMULATE_FAIL;
 775                        break;
 776                case OP_4X_PS_MR:
 777                        WARN_ON(rcomp);
 778                        vcpu->arch.fpr[ax_rd] = vcpu->arch.fpr[ax_rb];
 779                        vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb];
 780                        break;
 781                case OP_4X_PS_CMPO1:
 782                        /* XXX */
 783                        emulated = EMULATE_FAIL;
 784                        break;
 785                case OP_4X_PS_NABS:
 786                        WARN_ON(rcomp);
 787                        vcpu->arch.fpr[ax_rd] = vcpu->arch.fpr[ax_rb];
 788                        vcpu->arch.fpr[ax_rd] |= 0x8000000000000000ULL;
 789                        vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb];
 790                        vcpu->arch.qpr[ax_rd] |= 0x80000000;
 791                        break;
 792                case OP_4X_PS_ABS:
 793                        WARN_ON(rcomp);
 794                        vcpu->arch.fpr[ax_rd] = vcpu->arch.fpr[ax_rb];
 795                        vcpu->arch.fpr[ax_rd] &= ~0x8000000000000000ULL;
 796                        vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb];
 797                        vcpu->arch.qpr[ax_rd] &= ~0x80000000;
 798                        break;
 799                case OP_4X_PS_MERGE00:
 800                        WARN_ON(rcomp);
 801                        vcpu->arch.fpr[ax_rd] = vcpu->arch.fpr[ax_ra];
 802                        /* vcpu->arch.qpr[ax_rd] = vcpu->arch.fpr[ax_rb]; */
 803                        kvm_cvt_df(&vcpu->arch.fpr[ax_rb],
 804                                   &vcpu->arch.qpr[ax_rd]);
 805                        break;
 806                case OP_4X_PS_MERGE01:
 807                        WARN_ON(rcomp);
 808                        vcpu->arch.fpr[ax_rd] = vcpu->arch.fpr[ax_ra];
 809                        vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb];
 810                        break;
 811                case OP_4X_PS_MERGE10:
 812                        WARN_ON(rcomp);
 813                        /* vcpu->arch.fpr[ax_rd] = vcpu->arch.qpr[ax_ra]; */
 814                        kvm_cvt_fd(&vcpu->arch.qpr[ax_ra],
 815                                   &vcpu->arch.fpr[ax_rd]);
 816                        /* vcpu->arch.qpr[ax_rd] = vcpu->arch.fpr[ax_rb]; */
 817                        kvm_cvt_df(&vcpu->arch.fpr[ax_rb],
 818                                   &vcpu->arch.qpr[ax_rd]);
 819                        break;
 820                case OP_4X_PS_MERGE11:
 821                        WARN_ON(rcomp);
 822                        /* vcpu->arch.fpr[ax_rd] = vcpu->arch.qpr[ax_ra]; */
 823                        kvm_cvt_fd(&vcpu->arch.qpr[ax_ra],
 824                                   &vcpu->arch.fpr[ax_rd]);
 825                        vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb];
 826                        break;
 827                }
 828                /* XW form */
 829                switch (inst_get_field(inst, 25, 30)) {
 830                case OP_4XW_PSQ_STX:
 831                {
 832                        ulong addr = ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0;
 833                        bool w = inst_get_field(inst, 21, 21) ? true : false;
 834                        int i = inst_get_field(inst, 22, 24);
 835
 836                        addr += kvmppc_get_gpr(vcpu, ax_rb);
 837                        emulated = kvmppc_emulate_psq_store(run, vcpu, ax_rd, addr, w, i);
 838                        break;
 839                }
 840                case OP_4XW_PSQ_STUX:
 841                {
 842                        ulong addr = kvmppc_get_gpr(vcpu, ax_ra);
 843                        bool w = inst_get_field(inst, 21, 21) ? true : false;
 844                        int i = inst_get_field(inst, 22, 24);
 845
 846                        addr += kvmppc_get_gpr(vcpu, ax_rb);
 847                        emulated = kvmppc_emulate_psq_store(run, vcpu, ax_rd, addr, w, i);
 848
 849                        if (emulated == EMULATE_DONE)
 850                                kvmppc_set_gpr(vcpu, ax_ra, addr);
 851                        break;
 852                }
 853                }
 854                /* A form */
 855                switch (inst_get_field(inst, 26, 30)) {
 856                case OP_4A_PS_SUM1:
 857                        emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
 858                                        ax_rb, ax_ra, SCALAR_NO_PS0 | SCALAR_HIGH, fps_fadds);
 859                        vcpu->arch.fpr[ax_rd] = vcpu->arch.fpr[ax_rc];
 860                        break;
 861                case OP_4A_PS_SUM0:
 862                        emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
 863                                        ax_ra, ax_rb, SCALAR_NO_PS1 | SCALAR_LOW, fps_fadds);
 864                        vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rc];
 865                        break;
 866                case OP_4A_PS_MULS0:
 867                        emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
 868                                        ax_ra, ax_rc, SCALAR_HIGH, fps_fmuls);
 869                        break;
 870                case OP_4A_PS_MULS1:
 871                        emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
 872                                        ax_ra, ax_rc, SCALAR_LOW, fps_fmuls);
 873                        break;
 874                case OP_4A_PS_MADDS0:
 875                        emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
 876                                        ax_ra, ax_rc, ax_rb, SCALAR_HIGH, fps_fmadds);
 877                        break;
 878                case OP_4A_PS_MADDS1:
 879                        emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
 880                                        ax_ra, ax_rc, ax_rb, SCALAR_LOW, fps_fmadds);
 881                        break;
 882                case OP_4A_PS_DIV:
 883                        emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
 884                                        ax_ra, ax_rb, SCALAR_NONE, fps_fdivs);
 885                        break;
 886                case OP_4A_PS_SUB:
 887                        emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
 888                                        ax_ra, ax_rb, SCALAR_NONE, fps_fsubs);
 889                        break;
 890                case OP_4A_PS_ADD:
 891                        emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
 892                                        ax_ra, ax_rb, SCALAR_NONE, fps_fadds);
 893                        break;
 894                case OP_4A_PS_SEL:
 895                        emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
 896                                        ax_ra, ax_rc, ax_rb, SCALAR_NONE, fps_fsel);
 897                        break;
 898                case OP_4A_PS_RES:
 899                        emulated = kvmppc_ps_one_in(vcpu, rcomp, ax_rd,
 900                                        ax_rb, fps_fres);
 901                        break;
 902                case OP_4A_PS_MUL:
 903                        emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
 904                                        ax_ra, ax_rc, SCALAR_NONE, fps_fmuls);
 905                        break;
 906                case OP_4A_PS_RSQRTE:
 907                        emulated = kvmppc_ps_one_in(vcpu, rcomp, ax_rd,
 908                                        ax_rb, fps_frsqrte);
 909                        break;
 910                case OP_4A_PS_MSUB:
 911                        emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
 912                                        ax_ra, ax_rc, ax_rb, SCALAR_NONE, fps_fmsubs);
 913                        break;
 914                case OP_4A_PS_MADD:
 915                        emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
 916                                        ax_ra, ax_rc, ax_rb, SCALAR_NONE, fps_fmadds);
 917                        break;
 918                case OP_4A_PS_NMSUB:
 919                        emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
 920                                        ax_ra, ax_rc, ax_rb, SCALAR_NONE, fps_fnmsubs);
 921                        break;
 922                case OP_4A_PS_NMADD:
 923                        emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
 924                                        ax_ra, ax_rc, ax_rb, SCALAR_NONE, fps_fnmadds);
 925                        break;
 926                }
 927                break;
 928
 929        /* Real FPU operations */
 930
 931        case OP_LFS:
 932        {
 933                ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) + full_d;
 934
 935                emulated = kvmppc_emulate_fpr_load(run, vcpu, ax_rd, addr,
 936                                                   FPU_LS_SINGLE);
 937                break;
 938        }
 939        case OP_LFSU:
 940        {
 941                ulong addr = kvmppc_get_gpr(vcpu, ax_ra) + full_d;
 942
 943                emulated = kvmppc_emulate_fpr_load(run, vcpu, ax_rd, addr,
 944                                                   FPU_LS_SINGLE);
 945
 946                if (emulated == EMULATE_DONE)
 947                        kvmppc_set_gpr(vcpu, ax_ra, addr);
 948                break;
 949        }
 950        case OP_LFD:
 951        {
 952                ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) + full_d;
 953
 954                emulated = kvmppc_emulate_fpr_load(run, vcpu, ax_rd, addr,
 955                                                   FPU_LS_DOUBLE);
 956                break;
 957        }
 958        case OP_LFDU:
 959        {
 960                ulong addr = kvmppc_get_gpr(vcpu, ax_ra) + full_d;
 961
 962                emulated = kvmppc_emulate_fpr_load(run, vcpu, ax_rd, addr,
 963                                                   FPU_LS_DOUBLE);
 964
 965                if (emulated == EMULATE_DONE)
 966                        kvmppc_set_gpr(vcpu, ax_ra, addr);
 967                break;
 968        }
 969        case OP_STFS:
 970        {
 971                ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) + full_d;
 972
 973                emulated = kvmppc_emulate_fpr_store(run, vcpu, ax_rd, addr,
 974                                                    FPU_LS_SINGLE);
 975                break;
 976        }
 977        case OP_STFSU:
 978        {
 979                ulong addr = kvmppc_get_gpr(vcpu, ax_ra) + full_d;
 980
 981                emulated = kvmppc_emulate_fpr_store(run, vcpu, ax_rd, addr,
 982                                                    FPU_LS_SINGLE);
 983
 984                if (emulated == EMULATE_DONE)
 985                        kvmppc_set_gpr(vcpu, ax_ra, addr);
 986                break;
 987        }
 988        case OP_STFD:
 989        {
 990                ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) + full_d;
 991
 992                emulated = kvmppc_emulate_fpr_store(run, vcpu, ax_rd, addr,
 993                                                    FPU_LS_DOUBLE);
 994                break;
 995        }
 996        case OP_STFDU:
 997        {
 998                ulong addr = kvmppc_get_gpr(vcpu, ax_ra) + full_d;
 999
1000                emulated = kvmppc_emulate_fpr_store(run, vcpu, ax_rd, addr,
1001                                                    FPU_LS_DOUBLE);
1002
1003                if (emulated == EMULATE_DONE)
1004                        kvmppc_set_gpr(vcpu, ax_ra, addr);
1005                break;
1006        }
1007        case 31:
1008                switch (inst_get_field(inst, 21, 30)) {
1009                case OP_31_LFSX:
1010                {
1011                        ulong addr = ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0;
1012
1013                        addr += kvmppc_get_gpr(vcpu, ax_rb);
1014                        emulated = kvmppc_emulate_fpr_load(run, vcpu, ax_rd,
1015                                                           addr, FPU_LS_SINGLE);
1016                        break;
1017                }
1018                case OP_31_LFSUX:
1019                {
1020                        ulong addr = kvmppc_get_gpr(vcpu, ax_ra) +
1021                                     kvmppc_get_gpr(vcpu, ax_rb);
1022
1023                        emulated = kvmppc_emulate_fpr_load(run, vcpu, ax_rd,
1024                                                           addr, FPU_LS_SINGLE);
1025
1026                        if (emulated == EMULATE_DONE)
1027                                kvmppc_set_gpr(vcpu, ax_ra, addr);
1028                        break;
1029                }
1030                case OP_31_LFDX:
1031                {
1032                        ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) +
1033                                     kvmppc_get_gpr(vcpu, ax_rb);
1034
1035                        emulated = kvmppc_emulate_fpr_load(run, vcpu, ax_rd,
1036                                                           addr, FPU_LS_DOUBLE);
1037                        break;
1038                }
1039                case OP_31_LFDUX:
1040                {
1041                        ulong addr = kvmppc_get_gpr(vcpu, ax_ra) +
1042                                     kvmppc_get_gpr(vcpu, ax_rb);
1043
1044                        emulated = kvmppc_emulate_fpr_load(run, vcpu, ax_rd,
1045                                                           addr, FPU_LS_DOUBLE);
1046
1047                        if (emulated == EMULATE_DONE)
1048                                kvmppc_set_gpr(vcpu, ax_ra, addr);
1049                        break;
1050                }
1051                case OP_31_STFSX:
1052                {
1053                        ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) +
1054                                     kvmppc_get_gpr(vcpu, ax_rb);
1055
1056                        emulated = kvmppc_emulate_fpr_store(run, vcpu, ax_rd,
1057                                                            addr, FPU_LS_SINGLE);
1058                        break;
1059                }
1060                case OP_31_STFSUX:
1061                {
1062                        ulong addr = kvmppc_get_gpr(vcpu, ax_ra) +
1063                                     kvmppc_get_gpr(vcpu, ax_rb);
1064
1065                        emulated = kvmppc_emulate_fpr_store(run, vcpu, ax_rd,
1066                                                            addr, FPU_LS_SINGLE);
1067
1068                        if (emulated == EMULATE_DONE)
1069                                kvmppc_set_gpr(vcpu, ax_ra, addr);
1070                        break;
1071                }
1072                case OP_31_STFX:
1073                {
1074                        ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) +
1075                                     kvmppc_get_gpr(vcpu, ax_rb);
1076
1077                        emulated = kvmppc_emulate_fpr_store(run, vcpu, ax_rd,
1078                                                            addr, FPU_LS_DOUBLE);
1079                        break;
1080                }
1081                case OP_31_STFUX:
1082                {
1083                        ulong addr = kvmppc_get_gpr(vcpu, ax_ra) +
1084                                     kvmppc_get_gpr(vcpu, ax_rb);
1085
1086                        emulated = kvmppc_emulate_fpr_store(run, vcpu, ax_rd,
1087                                                            addr, FPU_LS_DOUBLE);
1088
1089                        if (emulated == EMULATE_DONE)
1090                                kvmppc_set_gpr(vcpu, ax_ra, addr);
1091                        break;
1092                }
1093                case OP_31_STFIWX:
1094                {
1095                        ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) +
1096                                     kvmppc_get_gpr(vcpu, ax_rb);
1097
1098                        emulated = kvmppc_emulate_fpr_store(run, vcpu, ax_rd,
1099                                                            addr,
1100                                                            FPU_LS_SINGLE_LOW);
1101                        break;
1102                }
1103                        break;
1104                }
1105                break;
1106        case 59:
1107                switch (inst_get_field(inst, 21, 30)) {
1108                case OP_59_FADDS:
1109                        fpd_fadds(&vcpu->arch.fpscr, &cr, fpr_d, fpr_a, fpr_b);
1110                        kvmppc_sync_qpr(vcpu, ax_rd);
1111                        break;
1112                case OP_59_FSUBS:
1113                        fpd_fsubs(&vcpu->arch.fpscr, &cr, fpr_d, fpr_a, fpr_b);
1114                        kvmppc_sync_qpr(vcpu, ax_rd);
1115                        break;
1116                case OP_59_FDIVS:
1117                        fpd_fdivs(&vcpu->arch.fpscr, &cr, fpr_d, fpr_a, fpr_b);
1118                        kvmppc_sync_qpr(vcpu, ax_rd);
1119                        break;
1120                case OP_59_FRES:
1121                        fpd_fres(&vcpu->arch.fpscr, &cr, fpr_d, fpr_b);
1122                        kvmppc_sync_qpr(vcpu, ax_rd);
1123                        break;
1124                case OP_59_FRSQRTES:
1125                        fpd_frsqrtes(&vcpu->arch.fpscr, &cr, fpr_d, fpr_b);
1126                        kvmppc_sync_qpr(vcpu, ax_rd);
1127                        break;
1128                }
1129                switch (inst_get_field(inst, 26, 30)) {
1130                case OP_59_FMULS:
1131                        fpd_fmuls(&vcpu->arch.fpscr, &cr, fpr_d, fpr_a, fpr_c);
1132                        kvmppc_sync_qpr(vcpu, ax_rd);
1133                        break;
1134                case OP_59_FMSUBS:
1135                        fpd_fmsubs(&vcpu->arch.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
1136                        kvmppc_sync_qpr(vcpu, ax_rd);
1137                        break;
1138                case OP_59_FMADDS:
1139                        fpd_fmadds(&vcpu->arch.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
1140                        kvmppc_sync_qpr(vcpu, ax_rd);
1141                        break;
1142                case OP_59_FNMSUBS:
1143                        fpd_fnmsubs(&vcpu->arch.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
1144                        kvmppc_sync_qpr(vcpu, ax_rd);
1145                        break;
1146                case OP_59_FNMADDS:
1147                        fpd_fnmadds(&vcpu->arch.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
1148                        kvmppc_sync_qpr(vcpu, ax_rd);
1149                        break;
1150                }
1151                break;
1152        case 63:
1153                switch (inst_get_field(inst, 21, 30)) {
1154                case OP_63_MTFSB0:
1155                case OP_63_MTFSB1:
1156                case OP_63_MCRFS:
1157                case OP_63_MTFSFI:
1158                        /* XXX need to implement */
1159                        break;
1160                case OP_63_MFFS:
1161                        /* XXX missing CR */
1162                        *fpr_d = vcpu->arch.fpscr;
1163                        break;
1164                case OP_63_MTFSF:
1165                        /* XXX missing fm bits */
1166                        /* XXX missing CR */
1167                        vcpu->arch.fpscr = *fpr_b;
1168                        break;
1169                case OP_63_FCMPU:
1170                {
1171                        u32 tmp_cr;
1172                        u32 cr0_mask = 0xf0000000;
1173                        u32 cr_shift = inst_get_field(inst, 6, 8) * 4;
1174
1175                        fpd_fcmpu(&vcpu->arch.fpscr, &tmp_cr, fpr_a, fpr_b);
1176                        cr &= ~(cr0_mask >> cr_shift);
1177                        cr |= (cr & cr0_mask) >> cr_shift;
1178                        break;
1179                }
1180                case OP_63_FCMPO:
1181                {
1182                        u32 tmp_cr;
1183                        u32 cr0_mask = 0xf0000000;
1184                        u32 cr_shift = inst_get_field(inst, 6, 8) * 4;
1185
1186                        fpd_fcmpo(&vcpu->arch.fpscr, &tmp_cr, fpr_a, fpr_b);
1187                        cr &= ~(cr0_mask >> cr_shift);
1188                        cr |= (cr & cr0_mask) >> cr_shift;
1189                        break;
1190                }
1191                case OP_63_FNEG:
1192                        fpd_fneg(&vcpu->arch.fpscr, &cr, fpr_d, fpr_b);
1193                        break;
1194                case OP_63_FMR:
1195                        *fpr_d = *fpr_b;
1196                        break;
1197                case OP_63_FABS:
1198                        fpd_fabs(&vcpu->arch.fpscr, &cr, fpr_d, fpr_b);
1199                        break;
1200                case OP_63_FCPSGN:
1201                        fpd_fcpsgn(&vcpu->arch.fpscr, &cr, fpr_d, fpr_a, fpr_b);
1202                        break;
1203                case OP_63_FDIV:
1204                        fpd_fdiv(&vcpu->arch.fpscr, &cr, fpr_d, fpr_a, fpr_b);
1205                        break;
1206                case OP_63_FADD:
1207                        fpd_fadd(&vcpu->arch.fpscr, &cr, fpr_d, fpr_a, fpr_b);
1208                        break;
1209                case OP_63_FSUB:
1210                        fpd_fsub(&vcpu->arch.fpscr, &cr, fpr_d, fpr_a, fpr_b);
1211                        break;
1212                case OP_63_FCTIW:
1213                        fpd_fctiw(&vcpu->arch.fpscr, &cr, fpr_d, fpr_b);
1214                        break;
1215                case OP_63_FCTIWZ:
1216                        fpd_fctiwz(&vcpu->arch.fpscr, &cr, fpr_d, fpr_b);
1217                        break;
1218                case OP_63_FRSP:
1219                        fpd_frsp(&vcpu->arch.fpscr, &cr, fpr_d, fpr_b);
1220                        kvmppc_sync_qpr(vcpu, ax_rd);
1221                        break;
1222                case OP_63_FRSQRTE:
1223                {
1224                        double one = 1.0f;
1225
1226                        /* fD = sqrt(fB) */
1227                        fpd_fsqrt(&vcpu->arch.fpscr, &cr, fpr_d, fpr_b);
1228                        /* fD = 1.0f / fD */
1229                        fpd_fdiv(&vcpu->arch.fpscr, &cr, fpr_d, (u64*)&one, fpr_d);
1230                        break;
1231                }
1232                }
1233                switch (inst_get_field(inst, 26, 30)) {
1234                case OP_63_FMUL:
1235                        fpd_fmul(&vcpu->arch.fpscr, &cr, fpr_d, fpr_a, fpr_c);
1236                        break;
1237                case OP_63_FSEL:
1238                        fpd_fsel(&vcpu->arch.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
1239                        break;
1240                case OP_63_FMSUB:
1241                        fpd_fmsub(&vcpu->arch.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
1242                        break;
1243                case OP_63_FMADD:
1244                        fpd_fmadd(&vcpu->arch.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
1245                        break;
1246                case OP_63_FNMSUB:
1247                        fpd_fnmsub(&vcpu->arch.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
1248                        break;
1249                case OP_63_FNMADD:
1250                        fpd_fnmadd(&vcpu->arch.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
1251                        break;
1252                }
1253                break;
1254        }
1255
1256#ifdef DEBUG
1257        for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++) {
1258                u32 f;
1259                kvm_cvt_df(&vcpu->arch.fpr[i], &f);
1260                dprintk(KERN_INFO "FPR[%d] = 0x%x\n", i, f);
1261        }
1262#endif
1263
1264        if (rcomp)
1265                kvmppc_set_cr(vcpu, cr);
1266
1267        preempt_enable();
1268
1269        return emulated;
1270}
1271