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