diff mbox

[26/33] KVM: PPC: Add mtcrf instruction emulation

Message ID 1403472217-22263-27-git-send-email-agraf@suse.de (mailing list archive)
State New, archived
Headers show

Commit Message

Alexander Graf June 22, 2014, 9:23 p.m. UTC
This patch adds emulation support for the mtcrf instruction.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/powerpc/include/asm/ppc-opcode.h |  1 +
 arch/powerpc/kvm/emulate.c            | 25 +++++++++++++++++++++++++
 2 files changed, 26 insertions(+)
diff mbox

Patch

diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index e130156..86c510e 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -94,6 +94,7 @@ 
 #define OP_31_XOP_TRAP_64   68
 #define OP_31_XOP_DCBF      86
 #define OP_31_XOP_LBZX      87
+#define OP_31_XOP_MTCRF     144
 #define OP_31_XOP_STWX      151
 #define OP_31_XOP_STBX      215
 #define OP_31_XOP_LBZUX     119
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index aeadc30..d6e0e4b 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -521,6 +521,28 @@  int kvmppc_emulate_bc(struct kvm_vcpu *vcpu, u32 inst, bool is_32bit)
 	return EMULATE_AGAIN;
 }
 
+int kvmppc_emulate_mtcrf(struct kvm_vcpu *vcpu, u32 inst)
+{
+	u32 value = kvmppc_get_cr(vcpu);
+	u32 new_cr = kvmppc_get_gpr(vcpu, get_rs(inst));
+	u32 mask = 0;
+	int fxm = (inst >> 12) & 0xff;
+
+	if (fxm & 0x80) mask |= 0xf0000000;
+	if (fxm & 0x40) mask |= 0x0f000000;
+	if (fxm & 0x20) mask |= 0x00f00000;
+	if (fxm & 0x10) mask |= 0x000f0000;
+	if (fxm & 0x08) mask |= 0x0000f000;
+	if (fxm & 0x04) mask |= 0x00000f00;
+	if (fxm & 0x02) mask |= 0x000000f0;
+	if (fxm & 0x01) mask |= 0x0000000f;
+
+	value = value & ~mask;
+	value |= new_cr & mask;
+	kvmppc_set_cr(vcpu, value);
+	return EMULATE_DONE;
+}
+
 /* Emulates privileged and non-privileged instructions */
 int kvmppc_emulate_any_instruction(struct kvm_vcpu *vcpu)
 {
@@ -592,6 +614,9 @@  int kvmppc_emulate_any_instruction(struct kvm_vcpu *vcpu)
 		case OP_31_XOP_MFCR:
 			kvmppc_set_gpr(vcpu, get_rt(inst), kvmppc_get_cr(vcpu));
 			break;
+		case OP_31_XOP_MTCRF:
+			emulated = kvmppc_emulate_mtcrf(vcpu, inst);
+			break;
 		case OP_31_XOP_AND:
 			value = kvmppc_get_gpr(vcpu, get_rs(inst));
 			value &= kvmppc_get_gpr(vcpu, get_rb(inst));