Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bbe9abbd authored by Nitin A Kamble's avatar Nitin A Kamble Committed by Avi Kivity
Browse files

KVM: x86 emulator: imlpement jump conditional relative



Implement emulation of instruction:
    jump conditional rel
    opcodes: 0x0f 0x80 - 0x0f 0x8f

Signed-off-by: default avatarNitin A Kamble <nitin.a.kamble@intel.com>
Signed-off-by: default avatarAvi Kivity <avi@qumranet.com>
parent 7de75248
Loading
Loading
Loading
Loading
+60 −1
Original line number Diff line number Diff line
@@ -188,7 +188,10 @@ static u16 twobyte_table[256] = {
	/* 0x70 - 0x7F */
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x80 - 0x8F */
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
	/* 0x90 - 0x9F */
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	/* 0xA0 - 0xA7 */
@@ -479,6 +482,41 @@ static int read_descriptor(struct x86_emulate_ctxt *ctxt,
	return rc;
}

static int test_cc(unsigned int condition, unsigned int flags)
{
	int rc = 0;

	switch ((condition & 15) >> 1) {
	case 0: /* o */
		rc |= (flags & EFLG_OF);
		break;
	case 1: /* b/c/nae */
		rc |= (flags & EFLG_CF);
		break;
	case 2: /* z/e */
		rc |= (flags & EFLG_ZF);
		break;
	case 3: /* be/na */
		rc |= (flags & (EFLG_CF|EFLG_ZF));
		break;
	case 4: /* s */
		rc |= (flags & EFLG_SF);
		break;
	case 5: /* p/pe */
		rc |= (flags & EFLG_PF);
		break;
	case 7: /* le/ng */
		rc |= (flags & EFLG_ZF);
		/* fall through */
	case 6: /* l/nge */
		rc |= (!(flags & EFLG_SF) != !(flags & EFLG_OF));
		break;
	}

	/* Odd condition identifiers (lsb == 1) have inverted sense. */
	return (!!rc ^ (condition & 1));
}

int
x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
{
@@ -1486,6 +1524,27 @@ x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
		}
		rc = X86EMUL_CONTINUE;
		break;
	case 0x80 ... 0x8f: /* jnz rel, etc*/ {
		long int rel;

		switch (op_bytes) {
		case 2:
			rel = insn_fetch(s16, 2, _eip);
			break;
		case 4:
			rel = insn_fetch(s32, 4, _eip);
			break;
		case 8:
			rel = insn_fetch(s64, 8, _eip);
			break;
		default:
			DPRINTF("jnz: Invalid op_bytes\n");
			goto cannot_emulate;
		}
		if (test_cc(b, _eflags))
			JMP_REL(rel);
		break;
	}
	case 0xc7:		/* Grp9 (cmpxchg8b) */
		{
			u64 old, new;