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