File Index
Files and directories
Sign in
FILE

book3s_paired_singles.c

File preview with syntax highlighting.

linux-6.19.14/arch/powerpc/kvm/book3s_paired_singles.c C
   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
 150static 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
 155static 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
 172static int kvmppc_emulate_fpr_load(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(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
 212done_load:
 213	return emulated;
 214}
 215
 216static int kvmppc_emulate_fpr_store(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(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
 262static int kvmppc_emulate_psq_load(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(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(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
 301done_load:
 302	return emulated;
 303}
 304
 305static int kvmppc_emulate_psq_store(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(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(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 */
 339static inline u32 inst_get_field(u32 inst, int msb, int lsb)
 340{
 341	return kvmppc_get_field(inst, msb + 32, lsb + 32);
 342}
 343
 344static 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
 480static 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
 490static 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
 538static 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
 590static 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
 621int kvmppc_emulate_paired_single(struct kvm_vcpu *vcpu)
 622{
 623	u32 inst;
 624	ppc_inst_t pinst;
 625	enum emulation_result emulated = EMULATE_DONE;
 626	int ax_rd, ax_ra, ax_rb, ax_rc;
 627	short full_d;
 628	u64 *fpr_d, *fpr_a, *fpr_b, *fpr_c;
 629
 630	bool rcomp;
 631	u32 cr;
 632#ifdef DEBUG
 633	int i;
 634#endif
 635
 636	emulated = kvmppc_get_last_inst(vcpu, INST_GENERIC, &pinst);
 637	inst = ppc_inst_val(pinst);
 638	if (emulated != EMULATE_DONE)
 639		return emulated;
 640
 641	ax_rd = inst_get_field(inst, 6, 10);
 642	ax_ra = inst_get_field(inst, 11, 15);
 643	ax_rb = inst_get_field(inst, 16, 20);
 644	ax_rc = inst_get_field(inst, 21, 25);
 645	full_d = inst_get_field(inst, 16, 31);
 646
 647	fpr_d = &VCPU_FPR(vcpu, ax_rd);
 648	fpr_a = &VCPU_FPR(vcpu, ax_ra);
 649	fpr_b = &VCPU_FPR(vcpu, ax_rb);
 650	fpr_c = &VCPU_FPR(vcpu, ax_rc);
 651
 652	rcomp = (inst & 1) ? true : false;
 653	cr = kvmppc_get_cr(vcpu);
 654
 655	if (!kvmppc_inst_is_paired_single(vcpu, inst))
 656		return EMULATE_FAIL;
 657
 658	if (!(kvmppc_get_msr(vcpu) & MSR_FP)) {
 659		kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL);
 660		return EMULATE_AGAIN;
 661	}
 662
 663	kvmppc_giveup_ext(vcpu, MSR_FP);
 664	preempt_disable();
 665	enable_kernel_fp();
 666	/* Do we need to clear FE0 / FE1 here? Don't think so. */
 667
 668#ifdef DEBUG
 669	for (i = 0; i < ARRAY_SIZE(vcpu->arch.fp.fpr); i++) {
 670		u32 f;
 671		kvm_cvt_df(&VCPU_FPR(vcpu, i), &f);
 672		dprintk(KERN_INFO "FPR[%d] = 0x%x / 0x%llx    QPR[%d] = 0x%x\n",
 673			i, f, VCPU_FPR(vcpu, i), i, vcpu->arch.qpr[i]);
 674	}
 675#endif
 676
 677	switch (get_op(inst)) {
 678	case OP_PSQ_L:
 679	{
 680		ulong addr = ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0;
 681		bool w = inst_get_field(inst, 16, 16) ? true : false;
 682		int i = inst_get_field(inst, 17, 19);
 683
 684		addr += get_d_signext(inst);
 685		emulated = kvmppc_emulate_psq_load(vcpu, ax_rd, addr, w, i);
 686		break;
 687	}
 688	case OP_PSQ_LU:
 689	{
 690		ulong addr = kvmppc_get_gpr(vcpu, ax_ra);
 691		bool w = inst_get_field(inst, 16, 16) ? true : false;
 692		int i = inst_get_field(inst, 17, 19);
 693
 694		addr += get_d_signext(inst);
 695		emulated = kvmppc_emulate_psq_load(vcpu, ax_rd, addr, w, i);
 696
 697		if (emulated == EMULATE_DONE)
 698			kvmppc_set_gpr(vcpu, ax_ra, addr);
 699		break;
 700	}
 701	case OP_PSQ_ST:
 702	{
 703		ulong addr = ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0;
 704		bool w = inst_get_field(inst, 16, 16) ? true : false;
 705		int i = inst_get_field(inst, 17, 19);
 706
 707		addr += get_d_signext(inst);
 708		emulated = kvmppc_emulate_psq_store(vcpu, ax_rd, addr, w, i);
 709		break;
 710	}
 711	case OP_PSQ_STU:
 712	{
 713		ulong addr = kvmppc_get_gpr(vcpu, ax_ra);
 714		bool w = inst_get_field(inst, 16, 16) ? true : false;
 715		int i = inst_get_field(inst, 17, 19);
 716
 717		addr += get_d_signext(inst);
 718		emulated = kvmppc_emulate_psq_store(vcpu, ax_rd, addr, w, i);
 719
 720		if (emulated == EMULATE_DONE)
 721			kvmppc_set_gpr(vcpu, ax_ra, addr);
 722		break;
 723	}
 724	case 4:
 725		/* X form */
 726		switch (inst_get_field(inst, 21, 30)) {
 727		case OP_4X_PS_CMPU0:
 728			/* XXX */
 729			emulated = EMULATE_FAIL;
 730			break;
 731		case OP_4X_PSQ_LX:
 732		{
 733			ulong addr = ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0;
 734			bool w = inst_get_field(inst, 21, 21) ? true : false;
 735			int i = inst_get_field(inst, 22, 24);
 736
 737			addr += kvmppc_get_gpr(vcpu, ax_rb);
 738			emulated = kvmppc_emulate_psq_load(vcpu, ax_rd, addr, w, i);
 739			break;
 740		}
 741		case OP_4X_PS_CMPO0:
 742			/* XXX */
 743			emulated = EMULATE_FAIL;
 744			break;
 745		case OP_4X_PSQ_LUX:
 746		{
 747			ulong addr = kvmppc_get_gpr(vcpu, ax_ra);
 748			bool w = inst_get_field(inst, 21, 21) ? true : false;
 749			int i = inst_get_field(inst, 22, 24);
 750
 751			addr += kvmppc_get_gpr(vcpu, ax_rb);
 752			emulated = kvmppc_emulate_psq_load(vcpu, ax_rd, addr, w, i);
 753
 754			if (emulated == EMULATE_DONE)
 755				kvmppc_set_gpr(vcpu, ax_ra, addr);
 756			break;
 757		}
 758		case OP_4X_PS_NEG:
 759			VCPU_FPR(vcpu, ax_rd) = VCPU_FPR(vcpu, ax_rb);
 760			VCPU_FPR(vcpu, ax_rd) ^= 0x8000000000000000ULL;
 761			vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb];
 762			vcpu->arch.qpr[ax_rd] ^= 0x80000000;
 763			break;
 764		case OP_4X_PS_CMPU1:
 765			/* XXX */
 766			emulated = EMULATE_FAIL;
 767			break;
 768		case OP_4X_PS_MR:
 769			WARN_ON(rcomp);
 770			VCPU_FPR(vcpu, ax_rd) = VCPU_FPR(vcpu, ax_rb);
 771			vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb];
 772			break;
 773		case OP_4X_PS_CMPO1:
 774			/* XXX */
 775			emulated = EMULATE_FAIL;
 776			break;
 777		case OP_4X_PS_NABS:
 778			WARN_ON(rcomp);
 779			VCPU_FPR(vcpu, ax_rd) = VCPU_FPR(vcpu, ax_rb);
 780			VCPU_FPR(vcpu, ax_rd) |= 0x8000000000000000ULL;
 781			vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb];
 782			vcpu->arch.qpr[ax_rd] |= 0x80000000;
 783			break;
 784		case OP_4X_PS_ABS:
 785			WARN_ON(rcomp);
 786			VCPU_FPR(vcpu, ax_rd) = VCPU_FPR(vcpu, ax_rb);
 787			VCPU_FPR(vcpu, ax_rd) &= ~0x8000000000000000ULL;
 788			vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb];
 789			vcpu->arch.qpr[ax_rd] &= ~0x80000000;
 790			break;
 791		case OP_4X_PS_MERGE00:
 792			WARN_ON(rcomp);
 793			VCPU_FPR(vcpu, ax_rd) = VCPU_FPR(vcpu, ax_ra);
 794			/* vcpu->arch.qpr[ax_rd] = VCPU_FPR(vcpu, ax_rb); */
 795			kvm_cvt_df(&VCPU_FPR(vcpu, ax_rb),
 796				   &vcpu->arch.qpr[ax_rd]);
 797			break;
 798		case OP_4X_PS_MERGE01:
 799			WARN_ON(rcomp);
 800			VCPU_FPR(vcpu, ax_rd) = VCPU_FPR(vcpu, ax_ra);
 801			vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb];
 802			break;
 803		case OP_4X_PS_MERGE10:
 804			WARN_ON(rcomp);
 805			/* VCPU_FPR(vcpu, ax_rd) = vcpu->arch.qpr[ax_ra]; */
 806			kvm_cvt_fd(&vcpu->arch.qpr[ax_ra],
 807				   &VCPU_FPR(vcpu, ax_rd));
 808			/* vcpu->arch.qpr[ax_rd] = VCPU_FPR(vcpu, ax_rb); */
 809			kvm_cvt_df(&VCPU_FPR(vcpu, ax_rb),
 810				   &vcpu->arch.qpr[ax_rd]);
 811			break;
 812		case OP_4X_PS_MERGE11:
 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->arch.qpr[ax_rb];
 818			break;
 819		}
 820		/* XW form */
 821		switch (inst_get_field(inst, 25, 30)) {
 822		case OP_4XW_PSQ_STX:
 823		{
 824			ulong addr = ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0;
 825			bool w = inst_get_field(inst, 21, 21) ? true : false;
 826			int i = inst_get_field(inst, 22, 24);
 827
 828			addr += kvmppc_get_gpr(vcpu, ax_rb);
 829			emulated = kvmppc_emulate_psq_store(vcpu, ax_rd, addr, w, i);
 830			break;
 831		}
 832		case OP_4XW_PSQ_STUX:
 833		{
 834			ulong addr = kvmppc_get_gpr(vcpu, ax_ra);
 835			bool w = inst_get_field(inst, 21, 21) ? true : false;
 836			int i = inst_get_field(inst, 22, 24);
 837
 838			addr += kvmppc_get_gpr(vcpu, ax_rb);
 839			emulated = kvmppc_emulate_psq_store(vcpu, ax_rd, addr, w, i);
 840
 841			if (emulated == EMULATE_DONE)
 842				kvmppc_set_gpr(vcpu, ax_ra, addr);
 843			break;
 844		}
 845		}
 846		/* A form */
 847		switch (inst_get_field(inst, 26, 30)) {
 848		case OP_4A_PS_SUM1:
 849			emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
 850					ax_rb, ax_ra, SCALAR_NO_PS0 | SCALAR_HIGH, fps_fadds);
 851			VCPU_FPR(vcpu, ax_rd) = VCPU_FPR(vcpu, ax_rc);
 852			break;
 853		case OP_4A_PS_SUM0:
 854			emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
 855					ax_ra, ax_rb, SCALAR_NO_PS1 | SCALAR_LOW, fps_fadds);
 856			vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rc];
 857			break;
 858		case OP_4A_PS_MULS0:
 859			emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
 860					ax_ra, ax_rc, SCALAR_HIGH, fps_fmuls);
 861			break;
 862		case OP_4A_PS_MULS1:
 863			emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
 864					ax_ra, ax_rc, SCALAR_LOW, fps_fmuls);
 865			break;
 866		case OP_4A_PS_MADDS0:
 867			emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
 868					ax_ra, ax_rc, ax_rb, SCALAR_HIGH, fps_fmadds);
 869			break;
 870		case OP_4A_PS_MADDS1:
 871			emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
 872					ax_ra, ax_rc, ax_rb, SCALAR_LOW, fps_fmadds);
 873			break;
 874		case OP_4A_PS_DIV:
 875			emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
 876					ax_ra, ax_rb, SCALAR_NONE, fps_fdivs);
 877			break;
 878		case OP_4A_PS_SUB:
 879			emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
 880					ax_ra, ax_rb, SCALAR_NONE, fps_fsubs);
 881			break;
 882		case OP_4A_PS_ADD:
 883			emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
 884					ax_ra, ax_rb, SCALAR_NONE, fps_fadds);
 885			break;
 886		case OP_4A_PS_SEL:
 887			emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
 888					ax_ra, ax_rc, ax_rb, SCALAR_NONE, fps_fsel);
 889			break;
 890		case OP_4A_PS_RES:
 891			emulated = kvmppc_ps_one_in(vcpu, rcomp, ax_rd,
 892					ax_rb, fps_fres);
 893			break;
 894		case OP_4A_PS_MUL:
 895			emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
 896					ax_ra, ax_rc, SCALAR_NONE, fps_fmuls);
 897			break;
 898		case OP_4A_PS_RSQRTE:
 899			emulated = kvmppc_ps_one_in(vcpu, rcomp, ax_rd,
 900					ax_rb, fps_frsqrte);
 901			break;
 902		case OP_4A_PS_MSUB:
 903			emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
 904					ax_ra, ax_rc, ax_rb, SCALAR_NONE, fps_fmsubs);
 905			break;
 906		case OP_4A_PS_MADD:
 907			emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
 908					ax_ra, ax_rc, ax_rb, SCALAR_NONE, fps_fmadds);
 909			break;
 910		case OP_4A_PS_NMSUB:
 911			emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
 912					ax_ra, ax_rc, ax_rb, SCALAR_NONE, fps_fnmsubs);
 913			break;
 914		case OP_4A_PS_NMADD:
 915			emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
 916					ax_ra, ax_rc, ax_rb, SCALAR_NONE, fps_fnmadds);
 917			break;
 918		}
 919		break;
 920
 921	/* Real FPU operations */
 922
 923	case OP_LFS:
 924	{
 925		ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) + full_d;
 926
 927		emulated = kvmppc_emulate_fpr_load(vcpu, ax_rd, addr,
 928						   FPU_LS_SINGLE);
 929		break;
 930	}
 931	case OP_LFSU:
 932	{
 933		ulong addr = kvmppc_get_gpr(vcpu, ax_ra) + full_d;
 934
 935		emulated = kvmppc_emulate_fpr_load(vcpu, ax_rd, addr,
 936						   FPU_LS_SINGLE);
 937
 938		if (emulated == EMULATE_DONE)
 939			kvmppc_set_gpr(vcpu, ax_ra, addr);
 940		break;
 941	}
 942	case OP_LFD:
 943	{
 944		ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) + full_d;
 945
 946		emulated = kvmppc_emulate_fpr_load(vcpu, ax_rd, addr,
 947						   FPU_LS_DOUBLE);
 948		break;
 949	}
 950	case OP_LFDU:
 951	{
 952		ulong addr = kvmppc_get_gpr(vcpu, ax_ra) + full_d;
 953
 954		emulated = kvmppc_emulate_fpr_load(vcpu, ax_rd, addr,
 955						   FPU_LS_DOUBLE);
 956
 957		if (emulated == EMULATE_DONE)
 958			kvmppc_set_gpr(vcpu, ax_ra, addr);
 959		break;
 960	}
 961	case OP_STFS:
 962	{
 963		ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) + full_d;
 964
 965		emulated = kvmppc_emulate_fpr_store(vcpu, ax_rd, addr,
 966						    FPU_LS_SINGLE);
 967		break;
 968	}
 969	case OP_STFSU:
 970	{
 971		ulong addr = kvmppc_get_gpr(vcpu, ax_ra) + full_d;
 972
 973		emulated = kvmppc_emulate_fpr_store(vcpu, ax_rd, addr,
 974						    FPU_LS_SINGLE);
 975
 976		if (emulated == EMULATE_DONE)
 977			kvmppc_set_gpr(vcpu, ax_ra, addr);
 978		break;
 979	}
 980	case OP_STFD:
 981	{
 982		ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) + full_d;
 983
 984		emulated = kvmppc_emulate_fpr_store(vcpu, ax_rd, addr,
 985						    FPU_LS_DOUBLE);
 986		break;
 987	}
 988	case OP_STFDU:
 989	{
 990		ulong addr = kvmppc_get_gpr(vcpu, ax_ra) + full_d;
 991
 992		emulated = kvmppc_emulate_fpr_store(vcpu, ax_rd, addr,
 993						    FPU_LS_DOUBLE);
 994
 995		if (emulated == EMULATE_DONE)
 996			kvmppc_set_gpr(vcpu, ax_ra, addr);
 997		break;
 998	}
 999	case 31:
1000		switch (inst_get_field(inst, 21, 30)) {
1001		case OP_31_LFSX:
1002		{
1003			ulong addr = ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0;
1004
1005			addr += kvmppc_get_gpr(vcpu, ax_rb);
1006			emulated = kvmppc_emulate_fpr_load(vcpu, ax_rd,
1007							   addr, FPU_LS_SINGLE);
1008			break;
1009		}
1010		case OP_31_LFSUX:
1011		{
1012			ulong addr = kvmppc_get_gpr(vcpu, ax_ra) +
1013				     kvmppc_get_gpr(vcpu, ax_rb);
1014
1015			emulated = kvmppc_emulate_fpr_load(vcpu, ax_rd,
1016							   addr, FPU_LS_SINGLE);
1017
1018			if (emulated == EMULATE_DONE)
1019				kvmppc_set_gpr(vcpu, ax_ra, addr);
1020			break;
1021		}
1022		case OP_31_LFDX:
1023		{
1024			ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) +
1025				     kvmppc_get_gpr(vcpu, ax_rb);
1026
1027			emulated = kvmppc_emulate_fpr_load(vcpu, ax_rd,
1028							   addr, FPU_LS_DOUBLE);
1029			break;
1030		}
1031		case OP_31_LFDUX:
1032		{
1033			ulong addr = kvmppc_get_gpr(vcpu, ax_ra) +
1034				     kvmppc_get_gpr(vcpu, ax_rb);
1035
1036			emulated = kvmppc_emulate_fpr_load(vcpu, ax_rd,
1037							   addr, FPU_LS_DOUBLE);
1038
1039			if (emulated == EMULATE_DONE)
1040				kvmppc_set_gpr(vcpu, ax_ra, addr);
1041			break;
1042		}
1043		case OP_31_STFSX:
1044		{
1045			ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) +
1046				     kvmppc_get_gpr(vcpu, ax_rb);
1047
1048			emulated = kvmppc_emulate_fpr_store(vcpu, ax_rd,
1049							    addr, FPU_LS_SINGLE);
1050			break;
1051		}
1052		case OP_31_STFSUX:
1053		{
1054			ulong addr = kvmppc_get_gpr(vcpu, ax_ra) +
1055				     kvmppc_get_gpr(vcpu, ax_rb);
1056
1057			emulated = kvmppc_emulate_fpr_store(vcpu, ax_rd,
1058							    addr, FPU_LS_SINGLE);
1059
1060			if (emulated == EMULATE_DONE)
1061				kvmppc_set_gpr(vcpu, ax_ra, addr);
1062			break;
1063		}
1064		case OP_31_STFX:
1065		{
1066			ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) +
1067				     kvmppc_get_gpr(vcpu, ax_rb);
1068
1069			emulated = kvmppc_emulate_fpr_store(vcpu, ax_rd,
1070							    addr, FPU_LS_DOUBLE);
1071			break;
1072		}
1073		case OP_31_STFUX:
1074		{
1075			ulong addr = kvmppc_get_gpr(vcpu, ax_ra) +
1076				     kvmppc_get_gpr(vcpu, ax_rb);
1077
1078			emulated = kvmppc_emulate_fpr_store(vcpu, ax_rd,
1079							    addr, FPU_LS_DOUBLE);
1080
1081			if (emulated == EMULATE_DONE)
1082				kvmppc_set_gpr(vcpu, ax_ra, addr);
1083			break;
1084		}
1085		case OP_31_STFIWX:
1086		{
1087			ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) +
1088				     kvmppc_get_gpr(vcpu, ax_rb);
1089
1090			emulated = kvmppc_emulate_fpr_store(vcpu, ax_rd,
1091							    addr,
1092							    FPU_LS_SINGLE_LOW);
1093			break;
1094		}
1095			break;
1096		}
1097		break;
1098	case 59:
1099		switch (inst_get_field(inst, 21, 30)) {
1100		case OP_59_FADDS:
1101			fpd_fadds(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_b);
1102			kvmppc_sync_qpr(vcpu, ax_rd);
1103			break;
1104		case OP_59_FSUBS:
1105			fpd_fsubs(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_b);
1106			kvmppc_sync_qpr(vcpu, ax_rd);
1107			break;
1108		case OP_59_FDIVS:
1109			fpd_fdivs(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_b);
1110			kvmppc_sync_qpr(vcpu, ax_rd);
1111			break;
1112		case OP_59_FRES:
1113			fpd_fres(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_b);
1114			kvmppc_sync_qpr(vcpu, ax_rd);
1115			break;
1116		case OP_59_FRSQRTES:
1117			fpd_frsqrtes(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_b);
1118			kvmppc_sync_qpr(vcpu, ax_rd);
1119			break;
1120		}
1121		switch (inst_get_field(inst, 26, 30)) {
1122		case OP_59_FMULS:
1123			fpd_fmuls(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c);
1124			kvmppc_sync_qpr(vcpu, ax_rd);
1125			break;
1126		case OP_59_FMSUBS:
1127			fpd_fmsubs(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
1128			kvmppc_sync_qpr(vcpu, ax_rd);
1129			break;
1130		case OP_59_FMADDS:
1131			fpd_fmadds(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
1132			kvmppc_sync_qpr(vcpu, ax_rd);
1133			break;
1134		case OP_59_FNMSUBS:
1135			fpd_fnmsubs(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
1136			kvmppc_sync_qpr(vcpu, ax_rd);
1137			break;
1138		case OP_59_FNMADDS:
1139			fpd_fnmadds(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
1140			kvmppc_sync_qpr(vcpu, ax_rd);
1141			break;
1142		}
1143		break;
1144	case 63:
1145		switch (inst_get_field(inst, 21, 30)) {
1146		case OP_63_MTFSB0:
1147		case OP_63_MTFSB1:
1148		case OP_63_MCRFS:
1149		case OP_63_MTFSFI:
1150			/* XXX need to implement */
1151			break;
1152		case OP_63_MFFS:
1153			/* XXX missing CR */
1154			*fpr_d = vcpu->arch.fp.fpscr;
1155			break;
1156		case OP_63_MTFSF:
1157			/* XXX missing fm bits */
1158			/* XXX missing CR */
1159			vcpu->arch.fp.fpscr = *fpr_b;
1160			break;
1161		case OP_63_FCMPU:
1162		{
1163			u32 tmp_cr;
1164			u32 cr0_mask = 0xf0000000;
1165			u32 cr_shift = inst_get_field(inst, 6, 8) * 4;
1166
1167			fpd_fcmpu(&vcpu->arch.fp.fpscr, &tmp_cr, fpr_a, fpr_b);
1168			cr &= ~(cr0_mask >> cr_shift);
1169			cr |= (cr & cr0_mask) >> cr_shift;
1170			break;
1171		}
1172		case OP_63_FCMPO:
1173		{
1174			u32 tmp_cr;
1175			u32 cr0_mask = 0xf0000000;
1176			u32 cr_shift = inst_get_field(inst, 6, 8) * 4;
1177
1178			fpd_fcmpo(&vcpu->arch.fp.fpscr, &tmp_cr, fpr_a, fpr_b);
1179			cr &= ~(cr0_mask >> cr_shift);
1180			cr |= (cr & cr0_mask) >> cr_shift;
1181			break;
1182		}
1183		case OP_63_FNEG:
1184			fpd_fneg(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_b);
1185			break;
1186		case OP_63_FMR:
1187			*fpr_d = *fpr_b;
1188			break;
1189		case OP_63_FABS:
1190			fpd_fabs(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_b);
1191			break;
1192		case OP_63_FCPSGN:
1193			fpd_fcpsgn(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_b);
1194			break;
1195		case OP_63_FDIV:
1196			fpd_fdiv(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_b);
1197			break;
1198		case OP_63_FADD:
1199			fpd_fadd(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_b);
1200			break;
1201		case OP_63_FSUB:
1202			fpd_fsub(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_b);
1203			break;
1204		case OP_63_FCTIW:
1205			fpd_fctiw(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_b);
1206			break;
1207		case OP_63_FCTIWZ:
1208			fpd_fctiwz(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_b);
1209			break;
1210		case OP_63_FRSP:
1211			fpd_frsp(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_b);
1212			kvmppc_sync_qpr(vcpu, ax_rd);
1213			break;
1214		case OP_63_FRSQRTE:
1215		{
1216			double one = 1.0f;
1217
1218			/* fD = sqrt(fB) */
1219			fpd_fsqrt(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_b);
1220			/* fD = 1.0f / fD */
1221			fpd_fdiv(&vcpu->arch.fp.fpscr, &cr, fpr_d, (u64*)&one, fpr_d);
1222			break;
1223		}
1224		}
1225		switch (inst_get_field(inst, 26, 30)) {
1226		case OP_63_FMUL:
1227			fpd_fmul(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c);
1228			break;
1229		case OP_63_FSEL:
1230			fpd_fsel(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
1231			break;
1232		case OP_63_FMSUB:
1233			fpd_fmsub(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
1234			break;
1235		case OP_63_FMADD:
1236			fpd_fmadd(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
1237			break;
1238		case OP_63_FNMSUB:
1239			fpd_fnmsub(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
1240			break;
1241		case OP_63_FNMADD:
1242			fpd_fnmadd(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
1243			break;
1244		}
1245		break;
1246	}
1247
1248#ifdef DEBUG
1249	for (i = 0; i < ARRAY_SIZE(vcpu->arch.fp.fpr); i++) {
1250		u32 f;
1251		kvm_cvt_df(&VCPU_FPR(vcpu, i), &f);
1252		dprintk(KERN_INFO "FPR[%d] = 0x%x\n", i, f);
1253	}
1254#endif
1255
1256	if (rcomp)
1257		kvmppc_set_cr(vcpu, cr);
1258
1259	disable_kernel_fp();
1260	preempt_enable();
1261
1262	return emulated;
1263}
~/ Read-only file preview.