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