diff options
author | Nitin A Kamble <nitin.a.kamble@intel.com> | 2007-09-15 03:23:07 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2007-10-13 04:18:28 -0400 |
commit | bbe9abbdaca366510db1f2df25f4c7b48cba38eb (patch) | |
tree | 31b2019825d5b1e61916bb132ca4439d147b30dc /drivers | |
parent | 7de752482c71e1ef72ac9650deaeb6d293b8416d (diff) |
KVM: x86 emulator: imlpement jump conditional relative
Implement emulation of instruction:
jump conditional rel
opcodes: 0x0f 0x80 - 0x0f 0x8f
Signed-off-by: Nitin A Kamble <nitin.a.kamble@intel.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/kvm/x86_emulate.c | 61 |
1 files changed, 60 insertions, 1 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index e4ce34c52ba1..ba53e59f558a 100644 --- a/drivers/kvm/x86_emulate.c +++ b/drivers/kvm/x86_emulate.c | |||
@@ -188,7 +188,10 @@ static u16 twobyte_table[256] = { | |||
188 | /* 0x70 - 0x7F */ | 188 | /* 0x70 - 0x7F */ |
189 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 189 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
190 | /* 0x80 - 0x8F */ | 190 | /* 0x80 - 0x8F */ |
191 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 191 | ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, |
192 | ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, | ||
193 | ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, | ||
194 | ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, | ||
192 | /* 0x90 - 0x9F */ | 195 | /* 0x90 - 0x9F */ |
193 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 196 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
194 | /* 0xA0 - 0xA7 */ | 197 | /* 0xA0 - 0xA7 */ |
@@ -479,6 +482,41 @@ static int read_descriptor(struct x86_emulate_ctxt *ctxt, | |||
479 | return rc; | 482 | return rc; |
480 | } | 483 | } |
481 | 484 | ||
485 | static int test_cc(unsigned int condition, unsigned int flags) | ||
486 | { | ||
487 | int rc = 0; | ||
488 | |||
489 | switch ((condition & 15) >> 1) { | ||
490 | case 0: /* o */ | ||
491 | rc |= (flags & EFLG_OF); | ||
492 | break; | ||
493 | case 1: /* b/c/nae */ | ||
494 | rc |= (flags & EFLG_CF); | ||
495 | break; | ||
496 | case 2: /* z/e */ | ||
497 | rc |= (flags & EFLG_ZF); | ||
498 | break; | ||
499 | case 3: /* be/na */ | ||
500 | rc |= (flags & (EFLG_CF|EFLG_ZF)); | ||
501 | break; | ||
502 | case 4: /* s */ | ||
503 | rc |= (flags & EFLG_SF); | ||
504 | break; | ||
505 | case 5: /* p/pe */ | ||
506 | rc |= (flags & EFLG_PF); | ||
507 | break; | ||
508 | case 7: /* le/ng */ | ||
509 | rc |= (flags & EFLG_ZF); | ||
510 | /* fall through */ | ||
511 | case 6: /* l/nge */ | ||
512 | rc |= (!(flags & EFLG_SF) != !(flags & EFLG_OF)); | ||
513 | break; | ||
514 | } | ||
515 | |||
516 | /* Odd condition identifiers (lsb == 1) have inverted sense. */ | ||
517 | return (!!rc ^ (condition & 1)); | ||
518 | } | ||
519 | |||
482 | int | 520 | int |
483 | x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | 521 | x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) |
484 | { | 522 | { |
@@ -1486,6 +1524,27 @@ twobyte_special_insn: | |||
1486 | } | 1524 | } |
1487 | rc = X86EMUL_CONTINUE; | 1525 | rc = X86EMUL_CONTINUE; |
1488 | break; | 1526 | break; |
1527 | case 0x80 ... 0x8f: /* jnz rel, etc*/ { | ||
1528 | long int rel; | ||
1529 | |||
1530 | switch (op_bytes) { | ||
1531 | case 2: | ||
1532 | rel = insn_fetch(s16, 2, _eip); | ||
1533 | break; | ||
1534 | case 4: | ||
1535 | rel = insn_fetch(s32, 4, _eip); | ||
1536 | break; | ||
1537 | case 8: | ||
1538 | rel = insn_fetch(s64, 8, _eip); | ||
1539 | break; | ||
1540 | default: | ||
1541 | DPRINTF("jnz: Invalid op_bytes\n"); | ||
1542 | goto cannot_emulate; | ||
1543 | } | ||
1544 | if (test_cc(b, _eflags)) | ||
1545 | JMP_REL(rel); | ||
1546 | break; | ||
1547 | } | ||
1489 | case 0xc7: /* Grp9 (cmpxchg8b) */ | 1548 | case 0xc7: /* Grp9 (cmpxchg8b) */ |
1490 | { | 1549 | { |
1491 | u64 old, new; | 1550 | u64 old, new; |