root/arch/powerpc/kvm/book3s_paired_singles.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. kvmppc_sync_qpr
  2. kvmppc_inject_pf
  3. kvmppc_emulate_fpr_load
  4. kvmppc_emulate_fpr_store
  5. kvmppc_emulate_psq_load
  6. kvmppc_emulate_psq_store
  7. inst_get_field
  8. kvmppc_inst_is_paired_single
  9. get_d_signext
  10. kvmppc_ps_three_in
  11. kvmppc_ps_two_in
  12. kvmppc_ps_one_in
  13. kvmppc_emulate_paired_single

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

/* [<][>][^][v][top][bottom][index][help] */