From patchwork Wed Aug 30 08:26:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?UTF-8?q?Sergio=20Andr=C3=A9s=20G=C3=B3mez=20Del=20Real?= X-Patchwork-Id: 9929635 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 526F760309 for ; Wed, 30 Aug 2017 13:41:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 22B74285E3 for ; Wed, 30 Aug 2017 13:41:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 14B10285E6; Wed, 30 Aug 2017 13:41:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 48B0B286FD for ; Wed, 30 Aug 2017 13:40:22 +0000 (UTC) Received: from localhost ([::1]:50662 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dn3ED-0003oQ-Pr for patchwork-qemu-devel@patchwork.kernel.org; Wed, 30 Aug 2017 09:40:21 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60691) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dmyM7-0002q1-Lp for qemu-devel@nongnu.org; Wed, 30 Aug 2017 04:28:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dmyLe-0000MZ-Ej for qemu-devel@nongnu.org; Wed, 30 Aug 2017 04:28:11 -0400 Received: from mail-ua0-x22f.google.com ([2607:f8b0:400c:c08::22f]:35901) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dmyLd-0000M8-Sy for qemu-devel@nongnu.org; Wed, 30 Aug 2017 04:27:42 -0400 Received: by mail-ua0-x22f.google.com with SMTP id 105so16922378uad.3 for ; Wed, 30 Aug 2017 01:27:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ioC8BDRfkXpIYYEzOla1BUXg3jQfVBydmKXFOO9EucQ=; b=JXbE/eVzZAD3E+0rJDJ58zhtckahUvSCrV5V+0gkx17QFxoFjgwS2ObQBu+RRc1glD U4AKhqDYMdAN06QU1IDDfnVf9pMwGSr1NfTBZIMdQzJlqWWQu2WOUcRWAhc9Yc5Jv0s3 SpgdtDujFyQ3D8BUb1WKnS0hXwJTqhRDxkwFb0Sy+Rw5YWPa4XcuiqkiAzjFlqV8HPPL 4j/pvW3mM0Ll2IWqYAXDdgdF0zpIaAGXJE6PGoe1FXRJD0aTEMO4ZZKYsXWtQURWMfC/ /8wVRgSmOxFTTlMn+Cz/Do1uPqVxsYUEgNilJGtYCJzZ80SKrCx28vnXD2N/HRN+v405 xuQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ioC8BDRfkXpIYYEzOla1BUXg3jQfVBydmKXFOO9EucQ=; b=kaX91WHyV1cLfBQ0A3poWj55XHcVcFZtNPvKCmGJS4cfqoHkH0nc8vijax0jZFTSFo lXzzs5V+Q9XufYmlPGWjp7Cr0gqpzPX2pMexo9a+W+5W20JilZyL2Jy+dakpIs3djb8q cEy9gbIwry6ArzVezxnpdE9Ugbt+T3iRjXLHlJSGc/ky8q0LHNmiVxq6jE5A10qmqrjL yGUkpS6YIOClj9/yfb/GfyoGxstjoS+skjbxplJzK8cK8vCXjcEpUHWnG+7Fg6rrE2+k ZFP6SPydSd+Z3n5r3aV6udcY9QaPi/UkeR6zQhGhsoAzHHtKcrra7EvecxGyQMJNPowi BLjg== X-Gm-Message-State: AHYfb5hFsHFEHPNW4pt9y5eKn5wv3oEePxLNQJHv8wv6cDt6YmSQ7Mi5 Z2bSbUmJiy7iGKJK X-Received: by 10.176.85.151 with SMTP id v23mr457550uaa.195.1504081659355; Wed, 30 Aug 2017 01:27:39 -0700 (PDT) Received: from localhost.localdomain ([191.109.6.85]) by smtp.gmail.com with ESMTPSA id h74sm1079197vka.8.2017.08.30.01.27.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 30 Aug 2017 01:27:38 -0700 (PDT) From: Sergio Andres Gomez Del Real X-Google-Original-From: Sergio Andres Gomez Del Real To: qemu-devel@nongnu.org Date: Wed, 30 Aug 2017 03:26:53 -0500 Message-Id: <20170830082702.3011-5-Sergio.G.DelReal@gmail.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170830082702.3011-1-Sergio.G.DelReal@gmail.com> References: <20170830082702.3011-1-Sergio.G.DelReal@gmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400c:c08::22f X-Mailman-Approved-At: Wed, 30 Aug 2017 09:38:00 -0400 Subject: [Qemu-devel] [PATCH v2 04/13] hvf: run hvf code through checkpatch.pl and fix style issues X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Sergio Andres Gomez Del Real Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP Signed-off-by: Sergio Andres Gomez Del Real --- cpus.c | 134 +- include/sysemu/hvf.h | 41 +- target/i386/hvf-all.c | 829 +++++++------ target/i386/hvf-i386.h | 2 +- target/i386/hvf-utils/vmcs.h | 484 ++++---- target/i386/hvf-utils/vmx.h | 92 +- target/i386/hvf-utils/x86.c | 86 +- target/i386/hvf-utils/x86.h | 112 +- target/i386/hvf-utils/x86_cpuid.c | 337 ++--- target/i386/hvf-utils/x86_cpuid.h | 7 +- target/i386/hvf-utils/x86_decode.c | 2402 ++++++++++++++++++++++-------------- target/i386/hvf-utils/x86_decode.h | 30 +- target/i386/hvf-utils/x86_descr.h | 29 +- target/i386/hvf-utils/x86_emu.c | 1337 ++++++++++---------- target/i386/hvf-utils/x86_emu.h | 15 + target/i386/hvf-utils/x86_flags.c | 52 +- target/i386/hvf-utils/x86_flags.h | 101 +- target/i386/hvf-utils/x86_mmu.c | 85 +- target/i386/hvf-utils/x86_mmu.h | 6 +- target/i386/hvf-utils/x86hvf.c | 106 +- target/i386/hvf-utils/x86hvf.h | 5 +- 21 files changed, 3554 insertions(+), 2738 deletions(-) diff --git a/cpus.c b/cpus.c index a2cd9dfa5d..d77aadf86f 100644 --- a/cpus.c +++ b/cpus.c @@ -37,6 +37,7 @@ #include "sysemu/hw_accel.h" #include "sysemu/kvm.h" #include "sysemu/hax.h" +#include "sysemu/hvf.h" #include "qmp-commands.h" #include "exec/exec-all.h" @@ -81,6 +82,9 @@ static unsigned int throttle_percentage; #define CPU_THROTTLE_PCT_MAX 99 #define CPU_THROTTLE_TIMESLICE_NS 10000000 +/* For temporary buffers for forming a name */ +#define VCPU_THREAD_NAME_SIZE 16 + bool cpu_is_stopped(CPUState *cpu) { return cpu->stopped || !runstate_is_running(); @@ -900,6 +904,9 @@ void cpu_synchronize_all_states(void) CPU_FOREACH(cpu) { cpu_synchronize_state(cpu); + if (hvf_enabled()) { + hvf_cpu_synchronize_state(cpu); + } } } @@ -909,6 +916,9 @@ void cpu_synchronize_all_post_reset(void) CPU_FOREACH(cpu) { cpu_synchronize_post_reset(cpu); + if (hvf_enabled()) { + hvf_cpu_synchronize_post_reset(cpu); + } } } @@ -918,6 +928,9 @@ void cpu_synchronize_all_post_init(void) CPU_FOREACH(cpu) { cpu_synchronize_post_init(cpu); + if (hvf_enabled()) { + hvf_cpu_synchronize_post_init(cpu); + } } } @@ -1098,6 +1111,77 @@ static void qemu_kvm_wait_io_event(CPUState *cpu) qemu_wait_io_event_common(cpu); } +static void qemu_hvf_wait_io_event(CPUState *cpu) +{ + while (cpu_thread_is_idle(cpu)) { + qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex); + } + qemu_wait_io_event_common(cpu); +} + +/* The HVF-specific vCPU thread function. This one should only run when the host + * CPU supports the VMX "unrestricted guest" feature. */ +static void *qemu_hvf_cpu_thread_fn(void *arg) +{ + CPUState *cpu = arg; + + int r; + + assert(hvf_enabled()); + + rcu_register_thread(); + + qemu_mutex_lock_iothread(); + qemu_thread_get_self(cpu->thread); + + cpu->thread_id = qemu_get_thread_id(); + cpu->can_do_io = 1; + current_cpu = cpu; + + hvf_init_vcpu(cpu); + + /* signal CPU creation */ + cpu->created = true; + qemu_cond_signal(&qemu_cpu_cond); + + do { + if (cpu_can_run(cpu)) { + r = hvf_vcpu_exec(cpu); + if (r == EXCP_DEBUG) { + cpu_handle_guest_debug(cpu); + } + } + qemu_hvf_wait_io_event(cpu); + } while (!cpu->unplug || cpu_can_run(cpu)); + + hvf_vcpu_destroy(cpu); + cpu->created = false; + qemu_cond_signal(&qemu_cpu_cond); + qemu_mutex_unlock_iothread(); + return NULL; +} + +static void qemu_hvf_start_vcpu(CPUState *cpu) +{ + char thread_name[VCPU_THREAD_NAME_SIZE]; + + /* HVF currently does not support TCG, and only runs in + * unrestricted-guest mode. */ + assert(hvf_enabled()); + + cpu->thread = g_malloc0(sizeof(QemuThread)); + cpu->halt_cond = g_malloc0(sizeof(QemuCond)); + qemu_cond_init(cpu->halt_cond); + + snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/HVF", + cpu->cpu_index); + qemu_thread_create(cpu->thread, thread_name, qemu_hvf_cpu_thread_fn, + cpu, QEMU_THREAD_JOINABLE); + while (!cpu->created) { + qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex); + } +} + static void *qemu_kvm_cpu_thread_fn(void *arg) { CPUState *cpu = arg; @@ -1434,48 +1518,6 @@ static void *qemu_hax_cpu_thread_fn(void *arg) return NULL; } -/* The HVF-specific vCPU thread function. This one should only run when the host - * CPU supports the VMX "unrestricted guest" feature. */ -static void *qemu_hvf_cpu_thread_fn(void *arg) -{ - CPUState *cpu = arg; - - int r; - - assert(hvf_enabled()); - - rcu_register_thread(); - - qemu_mutex_lock_iothread(); - qemu_thread_get_self(cpu->thread); - - cpu->thread_id = qemu_get_thread_id(); - cpu->can_do_io = 1; - current_cpu = cpu; - - hvf_init_vcpu(cpu); - - /* signal CPU creation */ - cpu->created = true; - qemu_cond_signal(&qemu_cpu_cond); - - do { - if (cpu_can_run(cpu)) { - r = hvf_vcpu_exec(cpu); - if (r == EXCP_DEBUG) { - cpu_handle_guest_debug(cpu); - } - } - qemu_hvf_wait_io_event(cpu); - } while (!cpu->unplug || cpu_can_run(cpu)); - - hvf_vcpu_destroy(cpu); - cpu->created = false; - qemu_cond_signal(&qemu_cpu_cond); - qemu_mutex_unlock_iothread(); - return NULL; -} - #ifdef _WIN32 static void CALLBACK dummy_apc_func(ULONG_PTR unused) { @@ -1564,6 +1606,9 @@ static void qemu_cpu_kick_thread(CPUState *cpu) fprintf(stderr, "qemu:%s: %s", __func__, strerror(err)); exit(1); } + if (hvf_enabled()) { + cpu_exit(cpu); + } #else /* _WIN32 */ if (!qemu_cpu_is_self(cpu)) { if (!QueueUserAPC(dummy_apc_func, cpu->hThread, 0)) { @@ -1698,9 +1743,6 @@ void cpu_remove_sync(CPUState *cpu) } } -/* For temporary buffers for forming a name */ -#define VCPU_THREAD_NAME_SIZE 16 - static void qemu_tcg_init_vcpu(CPUState *cpu) { char thread_name[VCPU_THREAD_NAME_SIZE]; @@ -1816,6 +1858,8 @@ void qemu_init_vcpu(CPUState *cpu) qemu_kvm_start_vcpu(cpu); } else if (hax_enabled()) { qemu_hax_start_vcpu(cpu); + } else if (hvf_enabled()) { + qemu_hvf_start_vcpu(cpu); } else if (tcg_enabled()) { qemu_tcg_init_vcpu(cpu); } else { diff --git a/include/sysemu/hvf.h b/include/sysemu/hvf.h index 752a78eaa4..944b014596 100644 --- a/include/sysemu/hvf.h +++ b/include/sysemu/hvf.h @@ -15,15 +15,24 @@ #include "config-host.h" #include "qemu/osdep.h" #include "qemu-common.h" -#include "hw/hw.h" -#include "target/i386/cpu.h" #include "qemu/bitops.h" #include "exec/memory.h" #include "sysemu/accel.h" + +extern int hvf_disabled; +#ifdef CONFIG_HVF #include #include #include - +#include "target/i386/cpu.h" +#include "hw/hw.h" +uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx, + int reg); +#define hvf_enabled() !hvf_disabled +#else +#define hvf_enabled() 0 +#define hvf_get_supported_cpuid(func, idx, reg) 0 +#endif typedef struct hvf_slot { uint64_t start; @@ -41,7 +50,6 @@ struct hvf_vcpu_caps { uint64_t vmx_cap_preemption_timer; }; -int __hvf_set_memory(hvf_slot *); typedef struct HVFState { AccelState parent; hvf_slot slots[32]; @@ -56,19 +64,16 @@ void hvf_handle_io(CPUArchState *, uint16_t, void *, int, int, int); hvf_slot *hvf_find_overlap_slot(uint64_t, uint64_t); -/* Returns 1 if HVF is available and enabled, 0 otherwise. */ -int hvf_enabled(void); - -/* Disable HVF if |disable| is 1, otherwise, enable it iff it is supported by the host CPU. - * Use hvf_enabled() after this to get the result. */ +/* Disable HVF if |disable| is 1, otherwise, enable it iff it is supported by + * the host CPU. Use hvf_enabled() after this to get the result. */ void hvf_disable(int disable); -/* Returns non-0 if the host CPU supports the VMX "unrestricted guest" feature which - * allows the virtual CPU to directly run in "real mode". If true, this allows QEMU to run - * several vCPU threads in parallel (see cpus.c). Otherwise, only a a single TCG thread - * can run, and it will call HVF to run the current instructions, except in case of - * "real mode" (paging disabled, typically at boot time), or MMIO operations. */ -// int hvf_ug_platform(void); does not apply to HVF; assume we must be in UG mode +/* Returns non-0 if the host CPU supports the VMX "unrestricted guest" feature + * which allows the virtual CPU to directly run in "real mode". If true, this + * allows QEMU to run several vCPU threads in parallel (see cpus.c). Otherwise, + * only a a single TCG thread can run, and it will call HVF to run the current + * instructions, except in case of "real mode" (paging disabled, typically at + * boot time), or MMIO operations. */ int hvf_sync_vcpus(void); @@ -82,14 +87,12 @@ void _hvf_cpu_synchronize_post_init(CPUState *, run_on_cpu_data); void hvf_vcpu_destroy(CPUState *); void hvf_raise_event(CPUState *); -// void hvf_reset_vcpu_state(void *opaque); +/* void hvf_reset_vcpu_state(void *opaque); */ void vmx_reset_vcpu(CPUState *); -void __hvf_cpu_synchronize_state(CPUState *, run_on_cpu_data); -void __hvf_cpu_synchronize_post_reset(CPUState *, run_on_cpu_data); void vmx_update_tpr(CPUState *); void update_apic_tpr(CPUState *); -int apic_get_highest_priority_irr(DeviceState *); int hvf_put_registers(CPUState *); +void vmx_clear_int_window_exiting(CPUState *cpu); #define TYPE_HVF_ACCEL ACCEL_CLASS_NAME("hvf") diff --git a/target/i386/hvf-all.c b/target/i386/hvf-all.c index 0a1a5134f8..6aba6b4eea 100644 --- a/target/i386/hvf-all.c +++ b/target/i386/hvf-all.c @@ -1,19 +1,20 @@ -// Copyright 2008 IBM Corporation -// 2008 Red Hat, Inc. -// Copyright 2011 Intel Corporation -// Copyright 2016 Veertu, Inc. -// Copyright 2017 The Android Open Source Project -// -// QEMU Hypervisor.framework support -// -// This software is licensed under the terms of the GNU General Public -// License version 2, as published by the Free Software Foundation, and -// may be copied, distributed, and modified under those terms. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +/* Copyright 2008 IBM Corporation + * 2008 Red Hat, Inc. + * Copyright 2011 Intel Corporation + * Copyright 2016 Veertu, Inc. + * Copyright 2017 The Android Open Source Project + * + * QEMU Hypervisor.framework support + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #include "qemu/osdep.h" #include "qemu-common.h" @@ -46,48 +47,51 @@ pthread_rwlock_t mem_lock = PTHREAD_RWLOCK_INITIALIZER; HVFState *hvf_state; -static int hvf_disabled = 1; +int hvf_disabled = 1; static void assert_hvf_ok(hv_return_t ret) { - if (ret == HV_SUCCESS) + if (ret == HV_SUCCESS) { return; + } switch (ret) { - case HV_ERROR: - fprintf(stderr, "Error: HV_ERROR\n"); - break; - case HV_BUSY: - fprintf(stderr, "Error: HV_BUSY\n"); - break; - case HV_BAD_ARGUMENT: - fprintf(stderr, "Error: HV_BAD_ARGUMENT\n"); - break; - case HV_NO_RESOURCES: - fprintf(stderr, "Error: HV_NO_RESOURCES\n"); - break; - case HV_NO_DEVICE: - fprintf(stderr, "Error: HV_NO_DEVICE\n"); - break; - case HV_UNSUPPORTED: - fprintf(stderr, "Error: HV_UNSUPPORTED\n"); - break; - default: - fprintf(stderr, "Unknown Error\n"); + case HV_ERROR: + error_report("Error: HV_ERROR\n"); + break; + case HV_BUSY: + error_report("Error: HV_BUSY\n"); + break; + case HV_BAD_ARGUMENT: + error_report("Error: HV_BAD_ARGUMENT\n"); + break; + case HV_NO_RESOURCES: + error_report("Error: HV_NO_RESOURCES\n"); + break; + case HV_NO_DEVICE: + error_report("Error: HV_NO_DEVICE\n"); + break; + case HV_UNSUPPORTED: + error_report("Error: HV_UNSUPPORTED\n"); + break; + default: + error_report("Unknown Error\n"); } abort(); } -// Memory slots///////////////////////////////////////////////////////////////// - -hvf_slot *hvf_find_overlap_slot(uint64_t start, uint64_t end) { +/* Memory slots */ +hvf_slot *hvf_find_overlap_slot(uint64_t start, uint64_t end) +{ hvf_slot *slot; int x; for (x = 0; x < hvf_state->num_slots; ++x) { slot = &hvf_state->slots[x]; - if (slot->size && start < (slot->start + slot->size) && end > slot->start) + if (slot->size && start < (slot->start + slot->size) && + end > slot->start) { return slot; + } } return NULL; } @@ -100,13 +104,12 @@ struct mac_slot { }; struct mac_slot mac_slots[32]; -#define ALIGN(x, y) (((x)+(y)-1) & ~((y)-1)) +#define ALIGN(x, y) (((x) + (y) - 1) & ~((y) - 1)) -int __hvf_set_memory(hvf_slot *slot) +static int do_hvf_set_memory(hvf_slot *slot) { struct mac_slot *macslot; hv_memory_flags_t flags; - pthread_rwlock_wrlock(&mem_lock); hv_return_t ret; macslot = &mac_slots[slot->slot_id]; @@ -120,7 +123,6 @@ int __hvf_set_memory(hvf_slot *slot) } if (!slot->size) { - pthread_rwlock_unlock(&mem_lock); return 0; } @@ -131,16 +133,17 @@ int __hvf_set_memory(hvf_slot *slot) macslot->size = slot->size; ret = hv_vm_map((hv_uvaddr_t)slot->mem, slot->start, slot->size, flags); assert_hvf_ok(ret); - pthread_rwlock_unlock(&mem_lock); return 0; } -void hvf_set_phys_mem(MemoryRegionSection* section, bool add) +void hvf_set_phys_mem(MemoryRegionSection *section, bool add) { hvf_slot *mem; MemoryRegion *area = section->mr; - if (!memory_region_is_ram(area)) return; + if (!memory_region_is_ram(area)) { + return; + } mem = hvf_find_overlap_slot( section->offset_within_address_space, @@ -148,33 +151,38 @@ void hvf_set_phys_mem(MemoryRegionSection* section, bool add) if (mem && add) { if (mem->size == int128_get64(section->size) && - mem->start == section->offset_within_address_space && - mem->mem == (memory_region_get_ram_ptr(area) + section->offset_within_region)) - return; // Same region was attempted to register, go away. + mem->start == section->offset_within_address_space && + mem->mem == (memory_region_get_ram_ptr(area) + + section->offset_within_region)) { + return; /* Same region was attempted to register, go away. */ + } } - // Region needs to be reset. set the size to 0 and remap it. + /* Region needs to be reset. set the size to 0 and remap it. */ if (mem) { mem->size = 0; - if (__hvf_set_memory(mem)) { - fprintf(stderr, "Failed to reset overlapping slot\n"); + if (do_hvf_set_memory(mem)) { + error_report("Failed to reset overlapping slot\n"); abort(); } } - if (!add) return; + if (!add) { + return; + } - // Now make a new slot. + /* Now make a new slot. */ int x; for (x = 0; x < hvf_state->num_slots; ++x) { mem = &hvf_state->slots[x]; - if (!mem->size) + if (!mem->size) { break; + } } if (x == hvf_state->num_slots) { - fprintf(stderr, "No free slots\n"); + error_report("No free slots\n"); abort(); } @@ -182,36 +190,26 @@ void hvf_set_phys_mem(MemoryRegionSection* section, bool add) mem->mem = memory_region_get_ram_ptr(area) + section->offset_within_region; mem->start = section->offset_within_address_space; - if (__hvf_set_memory(mem)) { - fprintf(stderr, "Error registering new memory slot\n"); + if (do_hvf_set_memory(mem)) { + error_report("Error registering new memory slot\n"); abort(); } } -/* return -1 if no bit is set */ -static int get_highest_priority_int(uint32_t *tab) -{ - int i; - for (i = 7; i >= 0; i--) { - if (tab[i] != 0) { - return i * 32 + apic_fls_bit(tab[i]); - } - } - return -1; -} - void vmx_update_tpr(CPUState *cpu) { - // TODO: need integrate APIC handling + /* TODO: need integrate APIC handling */ X86CPU *x86_cpu = X86_CPU(cpu); int tpr = cpu_get_apic_tpr(x86_cpu->apic_state) << 4; int irr = apic_get_highest_priority_irr(x86_cpu->apic_state); wreg(cpu->hvf_fd, HV_X86_TPR, tpr); - if (irr == -1) + if (irr == -1) { wvmcs(cpu->hvf_fd, VMCS_TPR_THRESHOLD, 0); - else - wvmcs(cpu->hvf_fd, VMCS_TPR_THRESHOLD, (irr > tpr) ? tpr >> 4 : irr >> 4); + } else { + wvmcs(cpu->hvf_fd, VMCS_TPR_THRESHOLD, (irr > tpr) ? tpr >> 4 : + irr >> 4); + } } void update_apic_tpr(CPUState *cpu) @@ -223,7 +221,7 @@ void update_apic_tpr(CPUState *cpu) #define VECTORING_INFO_VECTOR_MASK 0xff -// TODO: taskswitch handling +/* TODO: taskswitch handling */ static void save_state_to_tss32(CPUState *cpu, struct x86_tss_segment32 *tss) { /* CR3 and ldt selector are not saved intentionally */ @@ -263,13 +261,20 @@ static void load_state_from_tss32(CPUState *cpu, struct x86_tss_segment32 *tss) RSI(cpu) = tss->esi; RDI(cpu) = tss->edi; - vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->ldt}}, REG_SEG_LDTR); - vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->es}}, REG_SEG_ES); - vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->cs}}, REG_SEG_CS); - vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->ss}}, REG_SEG_SS); - vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->ds}}, REG_SEG_DS); - vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->fs}}, REG_SEG_FS); - vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->gs}}, REG_SEG_GS); + vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->ldt}}, + REG_SEG_LDTR); + vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->es}}, + REG_SEG_ES); + vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->cs}}, + REG_SEG_CS); + vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->ss}}, + REG_SEG_SS); + vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->ds}}, + REG_SEG_DS); + vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->fs}}, + REG_SEG_FS); + vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->gs}}, + REG_SEG_GS); #if 0 load_segment(cpu, REG_SEG_LDTR, tss->ldt); @@ -282,8 +287,10 @@ static void load_state_from_tss32(CPUState *cpu, struct x86_tss_segment32 *tss) #endif } -static int task_switch_32(CPUState *cpu, x68_segment_selector tss_sel, x68_segment_selector old_tss_sel, - uint64_t old_tss_base, struct x86_segment_descriptor *new_desc) +static int task_switch_32(CPUState *cpu, x68_segment_selector tss_sel, + x68_segment_selector old_tss_sel, + uint64_t old_tss_base, + struct x86_segment_descriptor *new_desc) { struct x86_tss_segment32 tss_seg; uint32_t new_tss_base = x86_segment_base(new_desc); @@ -293,19 +300,22 @@ static int task_switch_32(CPUState *cpu, x68_segment_selector tss_sel, x68_segme vmx_read_mem(cpu, &tss_seg, old_tss_base, sizeof(tss_seg)); save_state_to_tss32(cpu, &tss_seg); - vmx_write_mem(cpu, old_tss_base + eip_offset, &tss_seg.eip, ldt_sel_offset - eip_offset); + vmx_write_mem(cpu, old_tss_base + eip_offset, &tss_seg.eip, ldt_sel_offset - + eip_offset); vmx_read_mem(cpu, &tss_seg, new_tss_base, sizeof(tss_seg)); if (old_tss_sel.sel != 0xffff) { tss_seg.prev_tss = old_tss_sel.sel; - vmx_write_mem(cpu, new_tss_base, &tss_seg.prev_tss, sizeof(tss_seg.prev_tss)); + vmx_write_mem(cpu, new_tss_base, &tss_seg.prev_tss, + sizeof(tss_seg.prev_tss)); } load_state_from_tss32(cpu, &tss_seg); return 0; } -static void vmx_handle_task_switch(CPUState *cpu, x68_segment_selector tss_sel, int reason, bool gate_valid, uint8_t gate, uint64_t gate_type) +static void vmx_handle_task_switch(CPUState *cpu, x68_segment_selector tss_sel, + int reason, bool gate_valid, uint8_t gate, uint64_t gate_type) { uint64_t rip = rreg(cpu->hvf_fd, HV_X86_RIP); if (!gate_valid || (gate_type != VMCS_INTR_T_HWEXCEPTION && @@ -336,12 +346,14 @@ static void vmx_handle_task_switch(CPUState *cpu, x68_segment_selector tss_sel, dpl = task_gate_desc.dpl; x68_segment_selector cs = vmx_read_segment_selector(cpu, REG_SEG_CS); - if (tss_sel.rpl > dpl || cs.rpl > dpl) - ;//DPRINTF("emulate_gp"); + if (tss_sel.rpl > dpl || cs.rpl > dpl) { + VM_PANIC("emulate_gp"); + } } desc_limit = x86_segment_limit(&next_tss_desc); - if (!next_tss_desc.p || ((desc_limit < 0x67 && (next_tss_desc.type & 8)) || desc_limit < 0x2b)) { + if (!next_tss_desc.p || ((desc_limit < 0x67 && (next_tss_desc.type & 8)) || + desc_limit < 0x2b)) { VM_PANIC("emulate_ts"); } @@ -350,22 +362,27 @@ static void vmx_handle_task_switch(CPUState *cpu, x68_segment_selector tss_sel, x86_write_segment_descriptor(cpu, &curr_tss_desc, old_tss_sel); } - if (reason == TSR_IRET) + if (reason == TSR_IRET) { EFLAGS(cpu) &= ~RFLAGS_NT; + } - if (reason != TSR_CALL && reason != TSR_IDT_GATE) + if (reason != TSR_CALL && reason != TSR_IDT_GATE) { old_tss_sel.sel = 0xffff; + } if (reason != TSR_IRET) { next_tss_desc.type |= (1 << 1); /* set busy flag */ x86_write_segment_descriptor(cpu, &next_tss_desc, tss_sel); } - if (next_tss_desc.type & 8) - ret = task_switch_32(cpu, tss_sel, old_tss_sel, old_tss_base, &next_tss_desc); - else - //ret = task_switch_16(cpu, tss_sel, old_tss_sel, old_tss_base, &next_tss_desc); + if (next_tss_desc.type & 8) { + ret = task_switch_32(cpu, tss_sel, old_tss_sel, old_tss_base, + &next_tss_desc); + } else { + /*ret = task_switch_16(cpu, tss_sel, old_tss_sel, old_tss_base, + * &next_tss_desc);*/ VM_PANIC("task_switch_16"); + } macvm_set_cr0(cpu->hvf_fd, rvmcs(cpu->hvf_fd, VMCS_GUEST_CR0) | CR0_TS); x86_segment_descriptor_to_vmx(cpu, tss_sel, &next_tss_desc, &vmx_seg); @@ -377,7 +394,7 @@ static void vmx_handle_task_switch(CPUState *cpu, x68_segment_selector tss_sel, hv_vcpu_flush(cpu->hvf_fd); } -static void hvf_handle_interrupt(CPUState * cpu, int mask) +static void hvf_handle_interrupt(CPUState *cpu, int mask) { cpu->interrupt_request |= mask; if (!qemu_cpu_is_self(cpu)) { @@ -385,7 +402,7 @@ static void hvf_handle_interrupt(CPUState * cpu, int mask) } } -void hvf_handle_io(CPUArchState * env, uint16_t port, void* buffer, +void hvf_handle_io(CPUArchState *env, uint16_t port, void *buffer, int direction, int size, int count) { int i; @@ -398,24 +415,26 @@ void hvf_handle_io(CPUArchState * env, uint16_t port, void* buffer, ptr += size; } } -// -// TODO: synchronize vcpu state -void __hvf_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg) + +/* TODO: synchronize vcpu state */ +static void do_hvf_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg) { - CPUState *cpu_state = cpu;//(CPUState *)data; - if (cpu_state->hvf_vcpu_dirty == 0) + CPUState *cpu_state = cpu; + if (cpu_state->hvf_vcpu_dirty == 0) { hvf_get_registers(cpu_state); + } cpu_state->hvf_vcpu_dirty = 1; } void hvf_cpu_synchronize_state(CPUState *cpu_state) { - if (cpu_state->hvf_vcpu_dirty == 0) - run_on_cpu(cpu_state, __hvf_cpu_synchronize_state, RUN_ON_CPU_NULL); + if (cpu_state->hvf_vcpu_dirty == 0) { + run_on_cpu(cpu_state, do_hvf_cpu_synchronize_state, RUN_ON_CPU_NULL); + } } -void __hvf_cpu_synchronize_post_reset(CPUState *cpu, run_on_cpu_data arg) +static void do_hvf_cpu_synchronize_post_reset(CPUState *cpu, run_on_cpu_data arg) { CPUState *cpu_state = cpu; hvf_put_registers(cpu_state); @@ -424,7 +443,7 @@ void __hvf_cpu_synchronize_post_reset(CPUState *cpu, run_on_cpu_data arg) void hvf_cpu_synchronize_post_reset(CPUState *cpu_state) { - run_on_cpu(cpu_state, __hvf_cpu_synchronize_post_reset, RUN_ON_CPU_NULL); + run_on_cpu(cpu_state, do_hvf_cpu_synchronize_post_reset, RUN_ON_CPU_NULL); } void _hvf_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg) @@ -438,44 +457,45 @@ void hvf_cpu_synchronize_post_init(CPUState *cpu_state) { run_on_cpu(cpu_state, _hvf_cpu_synchronize_post_init, RUN_ON_CPU_NULL); } - -// TODO: ept fault handlig -void vmx_clear_int_window_exiting(CPUState *cpu); + +/* TODO: ept fault handlig */ static bool ept_emulation_fault(uint64_t ept_qual) { - int read, write; - - /* EPT fault on an instruction fetch doesn't make sense here */ - if (ept_qual & EPT_VIOLATION_INST_FETCH) - return false; - - /* EPT fault must be a read fault or a write fault */ - read = ept_qual & EPT_VIOLATION_DATA_READ ? 1 : 0; - write = ept_qual & EPT_VIOLATION_DATA_WRITE ? 1 : 0; - if ((read | write) == 0) - return false; - - /* - * The EPT violation must have been caused by accessing a - * guest-physical address that is a translation of a guest-linear - * address. - */ - if ((ept_qual & EPT_VIOLATION_GLA_VALID) == 0 || - (ept_qual & EPT_VIOLATION_XLAT_VALID) == 0) { - return false; - } - - return true; + int read, write; + + /* EPT fault on an instruction fetch doesn't make sense here */ + if (ept_qual & EPT_VIOLATION_INST_FETCH) { + return false; + } + + /* EPT fault must be a read fault or a write fault */ + read = ept_qual & EPT_VIOLATION_DATA_READ ? 1 : 0; + write = ept_qual & EPT_VIOLATION_DATA_WRITE ? 1 : 0; + if ((read | write) == 0) { + return false; + } + + /* + * The EPT violation must have been caused by accessing a + * guest-physical address that is a translation of a guest-linear + * address. + */ + if ((ept_qual & EPT_VIOLATION_GLA_VALID) == 0 || + (ept_qual & EPT_VIOLATION_XLAT_VALID) == 0) { + return false; + } + + return true; } -static void hvf_region_add(MemoryListener * listener, - MemoryRegionSection * section) +static void hvf_region_add(MemoryListener *listener, + MemoryRegionSection *section) { hvf_set_phys_mem(section, true); } -static void hvf_region_del(MemoryListener * listener, - MemoryRegionSection * section) +static void hvf_region_del(MemoryListener *listener, + MemoryRegionSection *section) { hvf_set_phys_mem(section, false); } @@ -486,70 +506,69 @@ static MemoryListener hvf_memory_listener = { .region_del = hvf_region_del, }; -static MemoryListener hvf_io_listener = { - .priority = 10, -}; - void vmx_reset_vcpu(CPUState *cpu) { + /* TODO: this shouldn't be needed; there is already a call to + * cpu_synchronize_all_post_reset in vl.c + */ wvmcs(cpu->hvf_fd, VMCS_ENTRY_CTLS, 0); wvmcs(cpu->hvf_fd, VMCS_GUEST_IA32_EFER, 0); macvm_set_cr0(cpu->hvf_fd, 0x60000010); - + wvmcs(cpu->hvf_fd, VMCS_CR4_MASK, CR4_VMXE_MASK); wvmcs(cpu->hvf_fd, VMCS_CR4_SHADOW, 0x0); wvmcs(cpu->hvf_fd, VMCS_GUEST_CR4, CR4_VMXE_MASK); - - // set VMCS guest state fields + + /* set VMCS guest state fields */ wvmcs(cpu->hvf_fd, VMCS_GUEST_CS_SELECTOR, 0xf000); wvmcs(cpu->hvf_fd, VMCS_GUEST_CS_LIMIT, 0xffff); wvmcs(cpu->hvf_fd, VMCS_GUEST_CS_ACCESS_RIGHTS, 0x9b); wvmcs(cpu->hvf_fd, VMCS_GUEST_CS_BASE, 0xffff0000); - + wvmcs(cpu->hvf_fd, VMCS_GUEST_DS_SELECTOR, 0); wvmcs(cpu->hvf_fd, VMCS_GUEST_DS_LIMIT, 0xffff); wvmcs(cpu->hvf_fd, VMCS_GUEST_DS_ACCESS_RIGHTS, 0x93); wvmcs(cpu->hvf_fd, VMCS_GUEST_DS_BASE, 0); - + wvmcs(cpu->hvf_fd, VMCS_GUEST_ES_SELECTOR, 0); wvmcs(cpu->hvf_fd, VMCS_GUEST_ES_LIMIT, 0xffff); wvmcs(cpu->hvf_fd, VMCS_GUEST_ES_ACCESS_RIGHTS, 0x93); wvmcs(cpu->hvf_fd, VMCS_GUEST_ES_BASE, 0); - + wvmcs(cpu->hvf_fd, VMCS_GUEST_FS_SELECTOR, 0); wvmcs(cpu->hvf_fd, VMCS_GUEST_FS_LIMIT, 0xffff); wvmcs(cpu->hvf_fd, VMCS_GUEST_FS_ACCESS_RIGHTS, 0x93); wvmcs(cpu->hvf_fd, VMCS_GUEST_FS_BASE, 0); - + wvmcs(cpu->hvf_fd, VMCS_GUEST_GS_SELECTOR, 0); wvmcs(cpu->hvf_fd, VMCS_GUEST_GS_LIMIT, 0xffff); wvmcs(cpu->hvf_fd, VMCS_GUEST_GS_ACCESS_RIGHTS, 0x93); wvmcs(cpu->hvf_fd, VMCS_GUEST_GS_BASE, 0); - + wvmcs(cpu->hvf_fd, VMCS_GUEST_SS_SELECTOR, 0); wvmcs(cpu->hvf_fd, VMCS_GUEST_SS_LIMIT, 0xffff); wvmcs(cpu->hvf_fd, VMCS_GUEST_SS_ACCESS_RIGHTS, 0x93); wvmcs(cpu->hvf_fd, VMCS_GUEST_SS_BASE, 0); - + wvmcs(cpu->hvf_fd, VMCS_GUEST_LDTR_SELECTOR, 0); wvmcs(cpu->hvf_fd, VMCS_GUEST_LDTR_LIMIT, 0); wvmcs(cpu->hvf_fd, VMCS_GUEST_LDTR_ACCESS_RIGHTS, 0x10000); wvmcs(cpu->hvf_fd, VMCS_GUEST_LDTR_BASE, 0); - + wvmcs(cpu->hvf_fd, VMCS_GUEST_TR_SELECTOR, 0); wvmcs(cpu->hvf_fd, VMCS_GUEST_TR_LIMIT, 0); wvmcs(cpu->hvf_fd, VMCS_GUEST_TR_ACCESS_RIGHTS, 0x83); wvmcs(cpu->hvf_fd, VMCS_GUEST_TR_BASE, 0); - + wvmcs(cpu->hvf_fd, VMCS_GUEST_GDTR_LIMIT, 0); wvmcs(cpu->hvf_fd, VMCS_GUEST_GDTR_BASE, 0); - + wvmcs(cpu->hvf_fd, VMCS_GUEST_IDTR_LIMIT, 0); wvmcs(cpu->hvf_fd, VMCS_GUEST_IDTR_BASE, 0); - - //wvmcs(cpu->hvf_fd, VMCS_GUEST_CR2, 0x0); + + /*wvmcs(cpu->hvf_fd, VMCS_GUEST_CR2, 0x0);*/ wvmcs(cpu->hvf_fd, VMCS_GUEST_CR3, 0x0); - + wreg(cpu->hvf_fd, HV_X86_RIP, 0xfff0); wreg(cpu->hvf_fd, HV_X86_RDX, 0x623); wreg(cpu->hvf_fd, HV_X86_RFLAGS, 0x2); @@ -560,9 +579,10 @@ void vmx_reset_vcpu(CPUState *cpu) { wreg(cpu->hvf_fd, HV_X86_RSI, 0x0); wreg(cpu->hvf_fd, HV_X86_RDI, 0x0); wreg(cpu->hvf_fd, HV_X86_RBP, 0x0); - - for (int i = 0; i < 8; i++) - wreg(cpu->hvf_fd, HV_X86_R8+i, 0x0); + + for (int i = 0; i < 8; i++) { + wreg(cpu->hvf_fd, HV_X86_R8 + i, 0x0); + } hv_vm_sync_tsc(0); cpu->halted = 0; @@ -570,7 +590,7 @@ void vmx_reset_vcpu(CPUState *cpu) { hv_vcpu_flush(cpu->hvf_fd); } -void hvf_vcpu_destroy(CPUState* cpu) +void hvf_vcpu_destroy(CPUState *cpu) { hv_return_t ret = hv_vcpu_destroy((hv_vcpuid_t)cpu->hvf_fd); assert_hvf_ok(ret); @@ -580,11 +600,12 @@ static void dummy_signal(int sig) { } -int hvf_init_vcpu(CPUState * cpu) { +int hvf_init_vcpu(CPUState *cpu) +{ X86CPU *x86cpu; - - // init cpu signals + + /* init cpu signals */ sigset_t set; struct sigaction sigact; @@ -600,42 +621,55 @@ int hvf_init_vcpu(CPUState * cpu) { init_decoder(cpu); init_cpuid(cpu); - cpu->hvf_caps = (struct hvf_vcpu_caps*)g_malloc0(sizeof(struct hvf_vcpu_caps)); - cpu->hvf_x86 = (struct hvf_x86_state*)g_malloc0(sizeof(struct hvf_x86_state)); + hvf_state->hvf_caps = (struct hvf_vcpu_caps *)g_malloc0(sizeof(struct hvf_vcpu_caps)); + cpu->hvf_x86 = (struct hvf_x86_state *)g_malloc0(sizeof(struct hvf_x86_state)); r = hv_vcpu_create((hv_vcpuid_t *)&cpu->hvf_fd, HV_VCPU_DEFAULT); cpu->hvf_vcpu_dirty = 1; assert_hvf_ok(r); - if (hv_vmx_read_capability(HV_VMX_CAP_PINBASED, &cpu->hvf_caps->vmx_cap_pinbased)) - abort(); - if (hv_vmx_read_capability(HV_VMX_CAP_PROCBASED, &cpu->hvf_caps->vmx_cap_procbased)) - abort(); - if (hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cpu->hvf_caps->vmx_cap_procbased2)) - abort(); - if (hv_vmx_read_capability(HV_VMX_CAP_ENTRY, &cpu->hvf_caps->vmx_cap_entry)) - abort(); - - /* set VMCS control fields */ - wvmcs(cpu->hvf_fd, VMCS_PIN_BASED_CTLS, cap2ctrl(cpu->hvf_caps->vmx_cap_pinbased, 0)); - wvmcs(cpu->hvf_fd, VMCS_PRI_PROC_BASED_CTLS, cap2ctrl(cpu->hvf_caps->vmx_cap_procbased, - VMCS_PRI_PROC_BASED_CTLS_HLT | - VMCS_PRI_PROC_BASED_CTLS_MWAIT | - VMCS_PRI_PROC_BASED_CTLS_TSC_OFFSET | - VMCS_PRI_PROC_BASED_CTLS_TPR_SHADOW) | - VMCS_PRI_PROC_BASED_CTLS_SEC_CONTROL); - wvmcs(cpu->hvf_fd, VMCS_SEC_PROC_BASED_CTLS, - cap2ctrl(cpu->hvf_caps->vmx_cap_procbased2,VMCS_PRI_PROC_BASED2_CTLS_APIC_ACCESSES)); - - wvmcs(cpu->hvf_fd, VMCS_ENTRY_CTLS, cap2ctrl(cpu->hvf_caps->vmx_cap_entry, 0)); - wvmcs(cpu->hvf_fd, VMCS_EXCEPTION_BITMAP, 0); /* Double fault */ + if (hv_vmx_read_capability(HV_VMX_CAP_PINBASED, + &hvf_state->hvf_caps->vmx_cap_pinbased)) { + abort(); + } + if (hv_vmx_read_capability(HV_VMX_CAP_PROCBASED, + &hvf_state->hvf_caps->vmx_cap_procbased)) { + abort(); + } + if (hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, + &hvf_state->hvf_caps->vmx_cap_procbased2)) { + abort(); + } + if (hv_vmx_read_capability(HV_VMX_CAP_ENTRY, + &hvf_state->hvf_caps->vmx_cap_entry)) { + abort(); + } + + /* set VMCS control fields */ + wvmcs(cpu->hvf_fd, VMCS_PIN_BASED_CTLS, + cap2ctrl(hvf_state->hvf_caps->vmx_cap_pinbased, 0)); + wvmcs(cpu->hvf_fd, VMCS_PRI_PROC_BASED_CTLS, + cap2ctrl(hvf_state->hvf_caps->vmx_cap_procbased, + VMCS_PRI_PROC_BASED_CTLS_HLT | + VMCS_PRI_PROC_BASED_CTLS_MWAIT | + VMCS_PRI_PROC_BASED_CTLS_TSC_OFFSET | + VMCS_PRI_PROC_BASED_CTLS_TPR_SHADOW) | + VMCS_PRI_PROC_BASED_CTLS_SEC_CONTROL); + wvmcs(cpu->hvf_fd, VMCS_SEC_PROC_BASED_CTLS, + cap2ctrl(hvf_state->hvf_caps->vmx_cap_procbased2, + VMCS_PRI_PROC_BASED2_CTLS_APIC_ACCESSES)); + + wvmcs(cpu->hvf_fd, VMCS_ENTRY_CTLS, cap2ctrl(hvf_state->hvf_caps->vmx_cap_entry, + 0)); + wvmcs(cpu->hvf_fd, VMCS_EXCEPTION_BITMAP, 0); /* Double fault */ wvmcs(cpu->hvf_fd, VMCS_TPR_THRESHOLD, 0); vmx_reset_vcpu(cpu); x86cpu = X86_CPU(cpu); - x86cpu->env.kvm_xsave_buf = qemu_memalign(4096, sizeof(struct hvf_xsave_buf)); + x86cpu->env.kvm_xsave_buf = qemu_memalign(4096, + sizeof(struct hvf_xsave_buf)); hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_STAR, 1); hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_LSTAR, 1); @@ -645,7 +679,7 @@ int hvf_init_vcpu(CPUState * cpu) { hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_GSBASE, 1); hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_KERNELGSBASE, 1); hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_TSC_AUX, 1); - //hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_TSC, 1); + /*hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_TSC, 1);*/ hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_SYSENTER_CS, 1); hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_SYSENTER_EIP, 1); hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_SYSENTER_ESP, 1); @@ -653,12 +687,13 @@ int hvf_init_vcpu(CPUState * cpu) { return 0; } -int hvf_enabled() { return !hvf_disabled; } -void hvf_disable(int shouldDisable) { +void hvf_disable(int shouldDisable) +{ hvf_disabled = shouldDisable; } -int hvf_vcpu_exec(CPUState* cpu) { +int hvf_vcpu_exec(CPUState *cpu) +{ X86CPU *x86_cpu = X86_CPU(cpu); CPUX86State *env = &x86_cpu->env; int ret = 0; @@ -678,7 +713,8 @@ int hvf_vcpu_exec(CPUState* cpu) { cpu->hvf_x86->interruptable = !(rvmcs(cpu->hvf_fd, VMCS_GUEST_INTERRUPTIBILITY) & - (VMCS_INTERRUPTIBILITY_STI_BLOCKING | VMCS_INTERRUPTIBILITY_MOVSS_BLOCKING)); + (VMCS_INTERRUPTIBILITY_STI_BLOCKING | + VMCS_INTERRUPTIBILITY_MOVSS_BLOCKING)); hvf_inject_interrupts(cpu); vmx_update_tpr(cpu); @@ -696,14 +732,13 @@ int hvf_vcpu_exec(CPUState* cpu) { /* handle VMEXIT */ uint64_t exit_reason = rvmcs(cpu->hvf_fd, VMCS_EXIT_REASON); uint64_t exit_qual = rvmcs(cpu->hvf_fd, VMCS_EXIT_QUALIFICATION); - uint32_t ins_len = (uint32_t)rvmcs(cpu->hvf_fd, VMCS_EXIT_INSTRUCTION_LENGTH); + uint32_t ins_len = (uint32_t)rvmcs(cpu->hvf_fd, + VMCS_EXIT_INSTRUCTION_LENGTH); uint64_t idtvec_info = rvmcs(cpu->hvf_fd, VMCS_IDT_VECTORING_INFO); rip = rreg(cpu->hvf_fd, HV_X86_RIP); RFLAGS(cpu) = rreg(cpu->hvf_fd, HV_X86_RFLAGS); env->eflags = RFLAGS(cpu); - trace_hvf_vm_exit(exit_reason, exit_qual); - qemu_mutex_lock_iothread(); update_apic_tpr(cpu); @@ -711,239 +746,226 @@ int hvf_vcpu_exec(CPUState* cpu) { ret = 0; switch (exit_reason) { - case EXIT_REASON_HLT: { - macvm_set_rip(cpu, rip + ins_len); - if (!((cpu->interrupt_request & CPU_INTERRUPT_HARD) && (EFLAGS(cpu) & IF_MASK)) - && !(cpu->interrupt_request & CPU_INTERRUPT_NMI) && - !(idtvec_info & VMCS_IDT_VEC_VALID)) { - cpu->halted = 1; - ret = EXCP_HLT; - } - ret = EXCP_INTERRUPT; - break; + case EXIT_REASON_HLT: { + macvm_set_rip(cpu, rip + ins_len); + if (!((cpu->interrupt_request & CPU_INTERRUPT_HARD) && + (EFLAGS(cpu) & IF_MASK)) + && !(cpu->interrupt_request & CPU_INTERRUPT_NMI) && + !(idtvec_info & VMCS_IDT_VEC_VALID)) { + cpu->halted = 1; + ret = EXCP_HLT; } - case EXIT_REASON_MWAIT: { - ret = EXCP_INTERRUPT; - break; - } - /* Need to check if MMIO or unmmaped fault */ - case EXIT_REASON_EPT_FAULT: - { - hvf_slot *slot; - addr_t gpa = rvmcs(cpu->hvf_fd, VMCS_GUEST_PHYSICAL_ADDRESS); - trace_hvf_vm_exit_gpa(gpa); - - if ((idtvec_info & VMCS_IDT_VEC_VALID) == 0 && (exit_qual & EXIT_QUAL_NMIUDTI) != 0) - vmx_set_nmi_blocking(cpu); - - slot = hvf_find_overlap_slot(gpa, gpa); - // mmio - if (ept_emulation_fault(exit_qual) && !slot) { - struct x86_decode decode; - - load_regs(cpu); - cpu->hvf_x86->fetch_rip = rip; - - decode_instruction(cpu, &decode); - exec_instruction(cpu, &decode); - store_regs(cpu); - break; - } -#ifdef DIRTY_VGA_TRACKING - if (slot) { - bool read = exit_qual & EPT_VIOLATION_DATA_READ ? 1 : 0; - bool write = exit_qual & EPT_VIOLATION_DATA_WRITE ? 1 : 0; - if (!read && !write) - break; - int flags = HV_MEMORY_READ | HV_MEMORY_EXEC; - if (write) flags |= HV_MEMORY_WRITE; - - pthread_rwlock_wrlock(&mem_lock); - if (write) - mark_slot_page_dirty(slot, gpa); - hv_vm_protect(gpa & ~0xfff, 4096, flags); - pthread_rwlock_unlock(&mem_lock); - } -#endif - break; + ret = EXCP_INTERRUPT; + break; + } + case EXIT_REASON_MWAIT: { + ret = EXCP_INTERRUPT; + break; + } + /* Need to check if MMIO or unmmaped fault */ + case EXIT_REASON_EPT_FAULT: + { + hvf_slot *slot; + addr_t gpa = rvmcs(cpu->hvf_fd, VMCS_GUEST_PHYSICAL_ADDRESS); + + if (((idtvec_info & VMCS_IDT_VEC_VALID) == 0) && + ((exit_qual & EXIT_QUAL_NMIUDTI) != 0)) { + vmx_set_nmi_blocking(cpu); } - case EXIT_REASON_INOUT: - { - uint32_t in = (exit_qual & 8) != 0; - uint32_t size = (exit_qual & 7) + 1; - uint32_t string = (exit_qual & 16) != 0; - uint32_t port = exit_qual >> 16; - //uint32_t rep = (exit_qual & 0x20) != 0; -#if 1 - if (!string && in) { - uint64_t val = 0; - load_regs(cpu); - hvf_handle_io(env, port, &val, 0, size, 1); - if (size == 1) AL(cpu) = val; - else if (size == 2) AX(cpu) = val; - else if (size == 4) RAX(cpu) = (uint32_t)val; - else VM_PANIC("size"); - RIP(cpu) += ins_len; - store_regs(cpu); - break; - } else if (!string && !in) { - RAX(cpu) = rreg(cpu->hvf_fd, HV_X86_RAX); - hvf_handle_io(env, port, &RAX(cpu), 1, size, 1); - macvm_set_rip(cpu, rip + ins_len); - break; - } -#endif + slot = hvf_find_overlap_slot(gpa, gpa); + /* mmio */ + if (ept_emulation_fault(exit_qual) && !slot) { struct x86_decode decode; load_regs(cpu); cpu->hvf_x86->fetch_rip = rip; decode_instruction(cpu, &decode); - VM_PANIC_ON(ins_len != decode.len); exec_instruction(cpu, &decode); store_regs(cpu); - break; } - case EXIT_REASON_CPUID: { - uint32_t rax = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RAX); - uint32_t rbx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RBX); - uint32_t rcx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RCX); - uint32_t rdx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RDX); - - get_cpuid_func(cpu, rax, rcx, &rax, &rbx, &rcx, &rdx); - - wreg(cpu->hvf_fd, HV_X86_RAX, rax); - wreg(cpu->hvf_fd, HV_X86_RBX, rbx); - wreg(cpu->hvf_fd, HV_X86_RCX, rcx); - wreg(cpu->hvf_fd, HV_X86_RDX, rdx); - - macvm_set_rip(cpu, rip + ins_len); - break; - } - case EXIT_REASON_XSETBV: { - X86CPU *x86_cpu = X86_CPU(cpu); - CPUX86State *env = &x86_cpu->env; - uint32_t eax = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RAX); - uint32_t ecx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RCX); - uint32_t edx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RDX); - - if (ecx) { - macvm_set_rip(cpu, rip + ins_len); - break; - } - env->xcr0 = ((uint64_t)edx << 32) | eax; - wreg(cpu->hvf_fd, HV_X86_XCR0, env->xcr0 | 1); - macvm_set_rip(cpu, rip + ins_len); - break; - } - case EXIT_REASON_INTR_WINDOW: - vmx_clear_int_window_exiting(cpu); - ret = EXCP_INTERRUPT; - break; - case EXIT_REASON_NMI_WINDOW: - vmx_clear_nmi_window_exiting(cpu); - ret = EXCP_INTERRUPT; - break; - case EXIT_REASON_EXT_INTR: - /* force exit and allow io handling */ - ret = EXCP_INTERRUPT; - break; - case EXIT_REASON_RDMSR: - case EXIT_REASON_WRMSR: - { - load_regs(cpu); - if (exit_reason == EXIT_REASON_RDMSR) - simulate_rdmsr(cpu); - else - simulate_wrmsr(cpu); - RIP(cpu) += rvmcs(cpu->hvf_fd, VMCS_EXIT_INSTRUCTION_LENGTH); - store_regs(cpu); - break; - } - case EXIT_REASON_CR_ACCESS: { - int cr; - int reg; +#ifdef DIRTY_VGA_TRACKING + /* TODO: handle dirty page tracking */ +#endif + break; + } + case EXIT_REASON_INOUT: + { + uint32_t in = (exit_qual & 8) != 0; + uint32_t size = (exit_qual & 7) + 1; + uint32_t string = (exit_qual & 16) != 0; + uint32_t port = exit_qual >> 16; + /*uint32_t rep = (exit_qual & 0x20) != 0;*/ +#if 1 + if (!string && in) { + uint64_t val = 0; load_regs(cpu); - cr = exit_qual & 15; - reg = (exit_qual >> 8) & 15; - - switch (cr) { - case 0x0: { - macvm_set_cr0(cpu->hvf_fd, RRX(cpu, reg)); - break; - } - case 4: { - macvm_set_cr4(cpu->hvf_fd, RRX(cpu, reg)); - break; - } - case 8: { - X86CPU *x86_cpu = X86_CPU(cpu); - if (exit_qual & 0x10) { - RRX(cpu, reg) = cpu_get_apic_tpr(x86_cpu->apic_state); - } - else { - int tpr = RRX(cpu, reg); - cpu_set_apic_tpr(x86_cpu->apic_state, tpr); - ret = EXCP_INTERRUPT; - } - break; - } - default: - fprintf(stderr, "Unrecognized CR %d\n", cr); - abort(); + hvf_handle_io(env, port, &val, 0, size, 1); + if (size == 1) { + AL(cpu) = val; + } else if (size == 2) { + AX(cpu) = val; + } else if (size == 4) { + RAX(cpu) = (uint32_t)val; + } else { + VM_PANIC("size"); } RIP(cpu) += ins_len; store_regs(cpu); break; + } else if (!string && !in) { + RAX(cpu) = rreg(cpu->hvf_fd, HV_X86_RAX); + hvf_handle_io(env, port, &RAX(cpu), 1, size, 1); + macvm_set_rip(cpu, rip + ins_len); + break; } - case EXIT_REASON_APIC_ACCESS: { // TODO - struct x86_decode decode; +#endif + struct x86_decode decode; - load_regs(cpu); - cpu->hvf_x86->fetch_rip = rip; + load_regs(cpu); + cpu->hvf_x86->fetch_rip = rip; - decode_instruction(cpu, &decode); - exec_instruction(cpu, &decode); - store_regs(cpu); + decode_instruction(cpu, &decode); + VM_PANIC_ON(ins_len != decode.len); + exec_instruction(cpu, &decode); + store_regs(cpu); + + break; + } + case EXIT_REASON_CPUID: { + uint32_t rax = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RAX); + uint32_t rbx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RBX); + uint32_t rcx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RCX); + uint32_t rdx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RDX); + + cpu_x86_cpuid(env, rax, rcx, &rax, &rbx, &rcx, &rdx); + + wreg(cpu->hvf_fd, HV_X86_RAX, rax); + wreg(cpu->hvf_fd, HV_X86_RBX, rbx); + wreg(cpu->hvf_fd, HV_X86_RCX, rcx); + wreg(cpu->hvf_fd, HV_X86_RDX, rdx); + + macvm_set_rip(cpu, rip + ins_len); + break; + } + case EXIT_REASON_XSETBV: { + X86CPU *x86_cpu = X86_CPU(cpu); + CPUX86State *env = &x86_cpu->env; + uint32_t eax = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RAX); + uint32_t ecx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RCX); + uint32_t edx = (uint32_t)rreg(cpu->hvf_fd, HV_X86_RDX); + + if (ecx) { + macvm_set_rip(cpu, rip + ins_len); break; } - case EXIT_REASON_TPR: { - ret = 1; - break; + env->xcr0 = ((uint64_t)edx << 32) | eax; + wreg(cpu->hvf_fd, HV_X86_XCR0, env->xcr0 | 1); + macvm_set_rip(cpu, rip + ins_len); + break; + } + case EXIT_REASON_INTR_WINDOW: + vmx_clear_int_window_exiting(cpu); + ret = EXCP_INTERRUPT; + break; + case EXIT_REASON_NMI_WINDOW: + vmx_clear_nmi_window_exiting(cpu); + ret = EXCP_INTERRUPT; + break; + case EXIT_REASON_EXT_INTR: + /* force exit and allow io handling */ + ret = EXCP_INTERRUPT; + break; + case EXIT_REASON_RDMSR: + case EXIT_REASON_WRMSR: + { + load_regs(cpu); + if (exit_reason == EXIT_REASON_RDMSR) { + simulate_rdmsr(cpu); + } else { + simulate_wrmsr(cpu); } - case EXIT_REASON_TASK_SWITCH: { - uint64_t vinfo = rvmcs(cpu->hvf_fd, VMCS_IDT_VECTORING_INFO); - x68_segment_selector sel = {.sel = exit_qual & 0xffff}; - vmx_handle_task_switch(cpu, sel, (exit_qual >> 30) & 0x3, - vinfo & VMCS_INTR_VALID, vinfo & VECTORING_INFO_VECTOR_MASK, vinfo & VMCS_INTR_T_MASK); + RIP(cpu) += rvmcs(cpu->hvf_fd, VMCS_EXIT_INSTRUCTION_LENGTH); + store_regs(cpu); + break; + } + case EXIT_REASON_CR_ACCESS: { + int cr; + int reg; + + load_regs(cpu); + cr = exit_qual & 15; + reg = (exit_qual >> 8) & 15; + + switch (cr) { + case 0x0: { + macvm_set_cr0(cpu->hvf_fd, RRX(cpu, reg)); break; } - case EXIT_REASON_TRIPLE_FAULT: { - //addr_t gpa = rvmcs(cpu->hvf_fd, VMCS_GUEST_PHYSICAL_ADDRESS); - qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); - usleep(1000 * 100); - ret = EXCP_INTERRUPT; + case 4: { + macvm_set_cr4(cpu->hvf_fd, RRX(cpu, reg)); break; } - case EXIT_REASON_RDPMC: - wreg(cpu->hvf_fd, HV_X86_RAX, 0); - wreg(cpu->hvf_fd, HV_X86_RDX, 0); - macvm_set_rip(cpu, rip + ins_len); - break; - case VMX_REASON_VMCALL: - // TODO: maybe just take this out? - // if (g_hypervisor_iface) { - // load_regs(cpu); - // g_hypervisor_iface->hypercall_handler(cpu); - // RIP(cpu) += rvmcs(cpu->hvf_fd, VMCS_EXIT_INSTRUCTION_LENGTH); - // store_regs(cpu); - // } + case 8: { + X86CPU *x86_cpu = X86_CPU(cpu); + if (exit_qual & 0x10) { + RRX(cpu, reg) = cpu_get_apic_tpr(x86_cpu->apic_state); + } else { + int tpr = RRX(cpu, reg); + cpu_set_apic_tpr(x86_cpu->apic_state, tpr); + ret = EXCP_INTERRUPT; + } break; + } default: - fprintf(stderr, "%llx: unhandled exit %llx\n", rip, exit_reason); + error_report("Unrecognized CR %d\n", cr); + abort(); + } + RIP(cpu) += ins_len; + store_regs(cpu); + break; + } + case EXIT_REASON_APIC_ACCESS: { /* TODO */ + struct x86_decode decode; + + load_regs(cpu); + cpu->hvf_x86->fetch_rip = rip; + + decode_instruction(cpu, &decode); + exec_instruction(cpu, &decode); + store_regs(cpu); + break; + } + case EXIT_REASON_TPR: { + ret = 1; + break; + } + case EXIT_REASON_TASK_SWITCH: { + uint64_t vinfo = rvmcs(cpu->hvf_fd, VMCS_IDT_VECTORING_INFO); + x68_segment_selector sel = {.sel = exit_qual & 0xffff}; + vmx_handle_task_switch(cpu, sel, (exit_qual >> 30) & 0x3, + vinfo & VMCS_INTR_VALID, vinfo & VECTORING_INFO_VECTOR_MASK, vinfo + & VMCS_INTR_T_MASK); + break; + } + case EXIT_REASON_TRIPLE_FAULT: { + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + ret = EXCP_INTERRUPT; + break; + } + case EXIT_REASON_RDPMC: + wreg(cpu->hvf_fd, HV_X86_RAX, 0); + wreg(cpu->hvf_fd, HV_X86_RDX, 0); + macvm_set_rip(cpu, rip + ins_len); + break; + case VMX_REASON_VMCALL: + /* TODO: inject #GP fault */ + break; + default: + error_report("%llx: unhandled exit %llx\n", rip, exit_reason); } } while (ret == 0); @@ -963,17 +985,16 @@ static int hvf_accel_init(MachineState *ms) assert_hvf_ok(ret); s = (HVFState *)g_malloc0(sizeof(HVFState)); - + s->num_slots = 32; for (x = 0; x < s->num_slots; ++x) { s->slots[x].size = 0; s->slots[x].slot_id = x; } - + hvf_state = s; cpu_interrupt_handler = hvf_handle_interrupt; memory_listener_register(&hvf_memory_listener, &address_space_memory); - memory_listener_register(&hvf_io_listener, &address_space_io); return 0; } diff --git a/target/i386/hvf-i386.h b/target/i386/hvf-i386.h index f3f958058a..797718ce34 100644 --- a/target/i386/hvf-i386.h +++ b/target/i386/hvf-i386.h @@ -41,7 +41,7 @@ struct hvf_state { /* Functions exported to host specific mode */ /* Host specific functions */ -int hvf_inject_interrupt(CPUArchState * env, int vector); +int hvf_inject_interrupt(CPUArchState *env, int vector); int hvf_vcpu_run(struct hvf_vcpu_state *vcpu); #endif diff --git a/target/i386/hvf-utils/vmcs.h b/target/i386/hvf-utils/vmcs.h index 6f7ccb361a..c410dcfaaa 100644 --- a/target/i386/hvf-utils/vmcs.h +++ b/target/i386/hvf-utils/vmcs.h @@ -27,326 +27,326 @@ */ #ifndef _VMCS_H_ -#define _VMCS_H_ +#define _VMCS_H_ #include #include -#define VMCS_INITIAL 0xffffffffffffffff +#define VMCS_INITIAL 0xffffffffffffffff -#define VMCS_IDENT(encoding) ((encoding) | 0x80000000) +#define VMCS_IDENT(encoding) ((encoding) | 0x80000000) /* * VMCS field encodings from Appendix H, Intel Architecture Manual Vol3B. */ -#define VMCS_INVALID_ENCODING 0xffffffff +#define VMCS_INVALID_ENCODING 0xffffffff /* 16-bit control fields */ -#define VMCS_VPID 0x00000000 -#define VMCS_PIR_VECTOR 0x00000002 +#define VMCS_VPID 0x00000000 +#define VMCS_PIR_VECTOR 0x00000002 /* 16-bit guest-state fields */ -#define VMCS_GUEST_ES_SELECTOR 0x00000800 -#define VMCS_GUEST_CS_SELECTOR 0x00000802 -#define VMCS_GUEST_SS_SELECTOR 0x00000804 -#define VMCS_GUEST_DS_SELECTOR 0x00000806 -#define VMCS_GUEST_FS_SELECTOR 0x00000808 -#define VMCS_GUEST_GS_SELECTOR 0x0000080A -#define VMCS_GUEST_LDTR_SELECTOR 0x0000080C -#define VMCS_GUEST_TR_SELECTOR 0x0000080E -#define VMCS_GUEST_INTR_STATUS 0x00000810 +#define VMCS_GUEST_ES_SELECTOR 0x00000800 +#define VMCS_GUEST_CS_SELECTOR 0x00000802 +#define VMCS_GUEST_SS_SELECTOR 0x00000804 +#define VMCS_GUEST_DS_SELECTOR 0x00000806 +#define VMCS_GUEST_FS_SELECTOR 0x00000808 +#define VMCS_GUEST_GS_SELECTOR 0x0000080A +#define VMCS_GUEST_LDTR_SELECTOR 0x0000080C +#define VMCS_GUEST_TR_SELECTOR 0x0000080E +#define VMCS_GUEST_INTR_STATUS 0x00000810 /* 16-bit host-state fields */ -#define VMCS_HOST_ES_SELECTOR 0x00000C00 -#define VMCS_HOST_CS_SELECTOR 0x00000C02 -#define VMCS_HOST_SS_SELECTOR 0x00000C04 -#define VMCS_HOST_DS_SELECTOR 0x00000C06 -#define VMCS_HOST_FS_SELECTOR 0x00000C08 -#define VMCS_HOST_GS_SELECTOR 0x00000C0A -#define VMCS_HOST_TR_SELECTOR 0x00000C0C +#define VMCS_HOST_ES_SELECTOR 0x00000C00 +#define VMCS_HOST_CS_SELECTOR 0x00000C02 +#define VMCS_HOST_SS_SELECTOR 0x00000C04 +#define VMCS_HOST_DS_SELECTOR 0x00000C06 +#define VMCS_HOST_FS_SELECTOR 0x00000C08 +#define VMCS_HOST_GS_SELECTOR 0x00000C0A +#define VMCS_HOST_TR_SELECTOR 0x00000C0C /* 64-bit control fields */ -#define VMCS_IO_BITMAP_A 0x00002000 -#define VMCS_IO_BITMAP_B 0x00002002 -#define VMCS_MSR_BITMAP 0x00002004 -#define VMCS_EXIT_MSR_STORE 0x00002006 -#define VMCS_EXIT_MSR_LOAD 0x00002008 -#define VMCS_ENTRY_MSR_LOAD 0x0000200A -#define VMCS_EXECUTIVE_VMCS 0x0000200C -#define VMCS_TSC_OFFSET 0x00002010 -#define VMCS_VIRTUAL_APIC 0x00002012 -#define VMCS_APIC_ACCESS 0x00002014 -#define VMCS_PIR_DESC 0x00002016 -#define VMCS_EPTP 0x0000201A -#define VMCS_EOI_EXIT0 0x0000201C -#define VMCS_EOI_EXIT1 0x0000201E -#define VMCS_EOI_EXIT2 0x00002020 -#define VMCS_EOI_EXIT3 0x00002022 -#define VMCS_EOI_EXIT(vector) (VMCS_EOI_EXIT0 + ((vector) / 64) * 2) +#define VMCS_IO_BITMAP_A 0x00002000 +#define VMCS_IO_BITMAP_B 0x00002002 +#define VMCS_MSR_BITMAP 0x00002004 +#define VMCS_EXIT_MSR_STORE 0x00002006 +#define VMCS_EXIT_MSR_LOAD 0x00002008 +#define VMCS_ENTRY_MSR_LOAD 0x0000200A +#define VMCS_EXECUTIVE_VMCS 0x0000200C +#define VMCS_TSC_OFFSET 0x00002010 +#define VMCS_VIRTUAL_APIC 0x00002012 +#define VMCS_APIC_ACCESS 0x00002014 +#define VMCS_PIR_DESC 0x00002016 +#define VMCS_EPTP 0x0000201A +#define VMCS_EOI_EXIT0 0x0000201C +#define VMCS_EOI_EXIT1 0x0000201E +#define VMCS_EOI_EXIT2 0x00002020 +#define VMCS_EOI_EXIT3 0x00002022 +#define VMCS_EOI_EXIT(vector) (VMCS_EOI_EXIT0 + ((vector) / 64) * 2) /* 64-bit read-only fields */ -#define VMCS_GUEST_PHYSICAL_ADDRESS 0x00002400 +#define VMCS_GUEST_PHYSICAL_ADDRESS 0x00002400 /* 64-bit guest-state fields */ -#define VMCS_LINK_POINTER 0x00002800 -#define VMCS_GUEST_IA32_DEBUGCTL 0x00002802 -#define VMCS_GUEST_IA32_PAT 0x00002804 -#define VMCS_GUEST_IA32_EFER 0x00002806 -#define VMCS_GUEST_IA32_PERF_GLOBAL_CTRL 0x00002808 -#define VMCS_GUEST_PDPTE0 0x0000280A -#define VMCS_GUEST_PDPTE1 0x0000280C -#define VMCS_GUEST_PDPTE2 0x0000280E -#define VMCS_GUEST_PDPTE3 0x00002810 +#define VMCS_LINK_POINTER 0x00002800 +#define VMCS_GUEST_IA32_DEBUGCTL 0x00002802 +#define VMCS_GUEST_IA32_PAT 0x00002804 +#define VMCS_GUEST_IA32_EFER 0x00002806 +#define VMCS_GUEST_IA32_PERF_GLOBAL_CTRL 0x00002808 +#define VMCS_GUEST_PDPTE0 0x0000280A +#define VMCS_GUEST_PDPTE1 0x0000280C +#define VMCS_GUEST_PDPTE2 0x0000280E +#define VMCS_GUEST_PDPTE3 0x00002810 /* 64-bit host-state fields */ -#define VMCS_HOST_IA32_PAT 0x00002C00 -#define VMCS_HOST_IA32_EFER 0x00002C02 -#define VMCS_HOST_IA32_PERF_GLOBAL_CTRL 0x00002C04 +#define VMCS_HOST_IA32_PAT 0x00002C00 +#define VMCS_HOST_IA32_EFER 0x00002C02 +#define VMCS_HOST_IA32_PERF_GLOBAL_CTRL 0x00002C04 /* 32-bit control fields */ -#define VMCS_PIN_BASED_CTLS 0x00004000 -#define VMCS_PRI_PROC_BASED_CTLS 0x00004002 -#define VMCS_EXCEPTION_BITMAP 0x00004004 -#define VMCS_PF_ERROR_MASK 0x00004006 -#define VMCS_PF_ERROR_MATCH 0x00004008 -#define VMCS_CR3_TARGET_COUNT 0x0000400A -#define VMCS_EXIT_CTLS 0x0000400C -#define VMCS_EXIT_MSR_STORE_COUNT 0x0000400E -#define VMCS_EXIT_MSR_LOAD_COUNT 0x00004010 -#define VMCS_ENTRY_CTLS 0x00004012 -#define VMCS_ENTRY_MSR_LOAD_COUNT 0x00004014 -#define VMCS_ENTRY_INTR_INFO 0x00004016 -#define VMCS_ENTRY_EXCEPTION_ERROR 0x00004018 -#define VMCS_ENTRY_INST_LENGTH 0x0000401A -#define VMCS_TPR_THRESHOLD 0x0000401C -#define VMCS_SEC_PROC_BASED_CTLS 0x0000401E -#define VMCS_PLE_GAP 0x00004020 -#define VMCS_PLE_WINDOW 0x00004022 +#define VMCS_PIN_BASED_CTLS 0x00004000 +#define VMCS_PRI_PROC_BASED_CTLS 0x00004002 +#define VMCS_EXCEPTION_BITMAP 0x00004004 +#define VMCS_PF_ERROR_MASK 0x00004006 +#define VMCS_PF_ERROR_MATCH 0x00004008 +#define VMCS_CR3_TARGET_COUNT 0x0000400A +#define VMCS_EXIT_CTLS 0x0000400C +#define VMCS_EXIT_MSR_STORE_COUNT 0x0000400E +#define VMCS_EXIT_MSR_LOAD_COUNT 0x00004010 +#define VMCS_ENTRY_CTLS 0x00004012 +#define VMCS_ENTRY_MSR_LOAD_COUNT 0x00004014 +#define VMCS_ENTRY_INTR_INFO 0x00004016 +#define VMCS_ENTRY_EXCEPTION_ERROR 0x00004018 +#define VMCS_ENTRY_INST_LENGTH 0x0000401A +#define VMCS_TPR_THRESHOLD 0x0000401C +#define VMCS_SEC_PROC_BASED_CTLS 0x0000401E +#define VMCS_PLE_GAP 0x00004020 +#define VMCS_PLE_WINDOW 0x00004022 /* 32-bit read-only data fields */ -#define VMCS_INSTRUCTION_ERROR 0x00004400 -#define VMCS_EXIT_REASON 0x00004402 -#define VMCS_EXIT_INTR_INFO 0x00004404 -#define VMCS_EXIT_INTR_ERRCODE 0x00004406 -#define VMCS_IDT_VECTORING_INFO 0x00004408 -#define VMCS_IDT_VECTORING_ERROR 0x0000440A -#define VMCS_EXIT_INSTRUCTION_LENGTH 0x0000440C -#define VMCS_EXIT_INSTRUCTION_INFO 0x0000440E +#define VMCS_INSTRUCTION_ERROR 0x00004400 +#define VMCS_EXIT_REASON 0x00004402 +#define VMCS_EXIT_INTR_INFO 0x00004404 +#define VMCS_EXIT_INTR_ERRCODE 0x00004406 +#define VMCS_IDT_VECTORING_INFO 0x00004408 +#define VMCS_IDT_VECTORING_ERROR 0x0000440A +#define VMCS_EXIT_INSTRUCTION_LENGTH 0x0000440C +#define VMCS_EXIT_INSTRUCTION_INFO 0x0000440E /* 32-bit guest-state fields */ -#define VMCS_GUEST_ES_LIMIT 0x00004800 -#define VMCS_GUEST_CS_LIMIT 0x00004802 -#define VMCS_GUEST_SS_LIMIT 0x00004804 -#define VMCS_GUEST_DS_LIMIT 0x00004806 -#define VMCS_GUEST_FS_LIMIT 0x00004808 -#define VMCS_GUEST_GS_LIMIT 0x0000480A -#define VMCS_GUEST_LDTR_LIMIT 0x0000480C -#define VMCS_GUEST_TR_LIMIT 0x0000480E -#define VMCS_GUEST_GDTR_LIMIT 0x00004810 -#define VMCS_GUEST_IDTR_LIMIT 0x00004812 -#define VMCS_GUEST_ES_ACCESS_RIGHTS 0x00004814 -#define VMCS_GUEST_CS_ACCESS_RIGHTS 0x00004816 -#define VMCS_GUEST_SS_ACCESS_RIGHTS 0x00004818 -#define VMCS_GUEST_DS_ACCESS_RIGHTS 0x0000481A -#define VMCS_GUEST_FS_ACCESS_RIGHTS 0x0000481C -#define VMCS_GUEST_GS_ACCESS_RIGHTS 0x0000481E -#define VMCS_GUEST_LDTR_ACCESS_RIGHTS 0x00004820 -#define VMCS_GUEST_TR_ACCESS_RIGHTS 0x00004822 -#define VMCS_GUEST_INTERRUPTIBILITY 0x00004824 -#define VMCS_GUEST_ACTIVITY 0x00004826 -#define VMCS_GUEST_SMBASE 0x00004828 -#define VMCS_GUEST_IA32_SYSENTER_CS 0x0000482A -#define VMCS_PREEMPTION_TIMER_VALUE 0x0000482E +#define VMCS_GUEST_ES_LIMIT 0x00004800 +#define VMCS_GUEST_CS_LIMIT 0x00004802 +#define VMCS_GUEST_SS_LIMIT 0x00004804 +#define VMCS_GUEST_DS_LIMIT 0x00004806 +#define VMCS_GUEST_FS_LIMIT 0x00004808 +#define VMCS_GUEST_GS_LIMIT 0x0000480A +#define VMCS_GUEST_LDTR_LIMIT 0x0000480C +#define VMCS_GUEST_TR_LIMIT 0x0000480E +#define VMCS_GUEST_GDTR_LIMIT 0x00004810 +#define VMCS_GUEST_IDTR_LIMIT 0x00004812 +#define VMCS_GUEST_ES_ACCESS_RIGHTS 0x00004814 +#define VMCS_GUEST_CS_ACCESS_RIGHTS 0x00004816 +#define VMCS_GUEST_SS_ACCESS_RIGHTS 0x00004818 +#define VMCS_GUEST_DS_ACCESS_RIGHTS 0x0000481A +#define VMCS_GUEST_FS_ACCESS_RIGHTS 0x0000481C +#define VMCS_GUEST_GS_ACCESS_RIGHTS 0x0000481E +#define VMCS_GUEST_LDTR_ACCESS_RIGHTS 0x00004820 +#define VMCS_GUEST_TR_ACCESS_RIGHTS 0x00004822 +#define VMCS_GUEST_INTERRUPTIBILITY 0x00004824 +#define VMCS_GUEST_ACTIVITY 0x00004826 +#define VMCS_GUEST_SMBASE 0x00004828 +#define VMCS_GUEST_IA32_SYSENTER_CS 0x0000482A +#define VMCS_PREEMPTION_TIMER_VALUE 0x0000482E /* 32-bit host state fields */ -#define VMCS_HOST_IA32_SYSENTER_CS 0x00004C00 +#define VMCS_HOST_IA32_SYSENTER_CS 0x00004C00 /* Natural Width control fields */ -#define VMCS_CR0_MASK 0x00006000 -#define VMCS_CR4_MASK 0x00006002 -#define VMCS_CR0_SHADOW 0x00006004 -#define VMCS_CR4_SHADOW 0x00006006 -#define VMCS_CR3_TARGET0 0x00006008 -#define VMCS_CR3_TARGET1 0x0000600A -#define VMCS_CR3_TARGET2 0x0000600C -#define VMCS_CR3_TARGET3 0x0000600E +#define VMCS_CR0_MASK 0x00006000 +#define VMCS_CR4_MASK 0x00006002 +#define VMCS_CR0_SHADOW 0x00006004 +#define VMCS_CR4_SHADOW 0x00006006 +#define VMCS_CR3_TARGET0 0x00006008 +#define VMCS_CR3_TARGET1 0x0000600A +#define VMCS_CR3_TARGET2 0x0000600C +#define VMCS_CR3_TARGET3 0x0000600E /* Natural Width read-only fields */ -#define VMCS_EXIT_QUALIFICATION 0x00006400 -#define VMCS_IO_RCX 0x00006402 -#define VMCS_IO_RSI 0x00006404 -#define VMCS_IO_RDI 0x00006406 -#define VMCS_IO_RIP 0x00006408 -#define VMCS_GUEST_LINEAR_ADDRESS 0x0000640A +#define VMCS_EXIT_QUALIFICATION 0x00006400 +#define VMCS_IO_RCX 0x00006402 +#define VMCS_IO_RSI 0x00006404 +#define VMCS_IO_RDI 0x00006406 +#define VMCS_IO_RIP 0x00006408 +#define VMCS_GUEST_LINEAR_ADDRESS 0x0000640A /* Natural Width guest-state fields */ -#define VMCS_GUEST_CR0 0x00006800 -#define VMCS_GUEST_CR3 0x00006802 -#define VMCS_GUEST_CR4 0x00006804 -#define VMCS_GUEST_ES_BASE 0x00006806 -#define VMCS_GUEST_CS_BASE 0x00006808 -#define VMCS_GUEST_SS_BASE 0x0000680A -#define VMCS_GUEST_DS_BASE 0x0000680C -#define VMCS_GUEST_FS_BASE 0x0000680E -#define VMCS_GUEST_GS_BASE 0x00006810 -#define VMCS_GUEST_LDTR_BASE 0x00006812 -#define VMCS_GUEST_TR_BASE 0x00006814 -#define VMCS_GUEST_GDTR_BASE 0x00006816 -#define VMCS_GUEST_IDTR_BASE 0x00006818 -#define VMCS_GUEST_DR7 0x0000681A -#define VMCS_GUEST_RSP 0x0000681C -#define VMCS_GUEST_RIP 0x0000681E -#define VMCS_GUEST_RFLAGS 0x00006820 -#define VMCS_GUEST_PENDING_DBG_EXCEPTIONS 0x00006822 -#define VMCS_GUEST_IA32_SYSENTER_ESP 0x00006824 -#define VMCS_GUEST_IA32_SYSENTER_EIP 0x00006826 +#define VMCS_GUEST_CR0 0x00006800 +#define VMCS_GUEST_CR3 0x00006802 +#define VMCS_GUEST_CR4 0x00006804 +#define VMCS_GUEST_ES_BASE 0x00006806 +#define VMCS_GUEST_CS_BASE 0x00006808 +#define VMCS_GUEST_SS_BASE 0x0000680A +#define VMCS_GUEST_DS_BASE 0x0000680C +#define VMCS_GUEST_FS_BASE 0x0000680E +#define VMCS_GUEST_GS_BASE 0x00006810 +#define VMCS_GUEST_LDTR_BASE 0x00006812 +#define VMCS_GUEST_TR_BASE 0x00006814 +#define VMCS_GUEST_GDTR_BASE 0x00006816 +#define VMCS_GUEST_IDTR_BASE 0x00006818 +#define VMCS_GUEST_DR7 0x0000681A +#define VMCS_GUEST_RSP 0x0000681C +#define VMCS_GUEST_RIP 0x0000681E +#define VMCS_GUEST_RFLAGS 0x00006820 +#define VMCS_GUEST_PENDING_DBG_EXCEPTIONS 0x00006822 +#define VMCS_GUEST_IA32_SYSENTER_ESP 0x00006824 +#define VMCS_GUEST_IA32_SYSENTER_EIP 0x00006826 /* Natural Width host-state fields */ -#define VMCS_HOST_CR0 0x00006C00 -#define VMCS_HOST_CR3 0x00006C02 -#define VMCS_HOST_CR4 0x00006C04 -#define VMCS_HOST_FS_BASE 0x00006C06 -#define VMCS_HOST_GS_BASE 0x00006C08 -#define VMCS_HOST_TR_BASE 0x00006C0A -#define VMCS_HOST_GDTR_BASE 0x00006C0C -#define VMCS_HOST_IDTR_BASE 0x00006C0E -#define VMCS_HOST_IA32_SYSENTER_ESP 0x00006C10 -#define VMCS_HOST_IA32_SYSENTER_EIP 0x00006C12 -#define VMCS_HOST_RSP 0x00006C14 -#define VMCS_HOST_RIP 0x00006c16 +#define VMCS_HOST_CR0 0x00006C00 +#define VMCS_HOST_CR3 0x00006C02 +#define VMCS_HOST_CR4 0x00006C04 +#define VMCS_HOST_FS_BASE 0x00006C06 +#define VMCS_HOST_GS_BASE 0x00006C08 +#define VMCS_HOST_TR_BASE 0x00006C0A +#define VMCS_HOST_GDTR_BASE 0x00006C0C +#define VMCS_HOST_IDTR_BASE 0x00006C0E +#define VMCS_HOST_IA32_SYSENTER_ESP 0x00006C10 +#define VMCS_HOST_IA32_SYSENTER_EIP 0x00006C12 +#define VMCS_HOST_RSP 0x00006C14 +#define VMCS_HOST_RIP 0x00006c16 /* * VM instruction error numbers */ -#define VMRESUME_WITH_NON_LAUNCHED_VMCS 5 +#define VMRESUME_WITH_NON_LAUNCHED_VMCS 5 /* * VMCS exit reasons */ -#define EXIT_REASON_EXCEPTION 0 -#define EXIT_REASON_EXT_INTR 1 -#define EXIT_REASON_TRIPLE_FAULT 2 -#define EXIT_REASON_INIT 3 -#define EXIT_REASON_SIPI 4 -#define EXIT_REASON_IO_SMI 5 -#define EXIT_REASON_SMI 6 -#define EXIT_REASON_INTR_WINDOW 7 -#define EXIT_REASON_NMI_WINDOW 8 -#define EXIT_REASON_TASK_SWITCH 9 -#define EXIT_REASON_CPUID 10 -#define EXIT_REASON_GETSEC 11 -#define EXIT_REASON_HLT 12 -#define EXIT_REASON_INVD 13 -#define EXIT_REASON_INVLPG 14 -#define EXIT_REASON_RDPMC 15 -#define EXIT_REASON_RDTSC 16 -#define EXIT_REASON_RSM 17 -#define EXIT_REASON_VMCALL 18 -#define EXIT_REASON_VMCLEAR 19 -#define EXIT_REASON_VMLAUNCH 20 -#define EXIT_REASON_VMPTRLD 21 -#define EXIT_REASON_VMPTRST 22 -#define EXIT_REASON_VMREAD 23 -#define EXIT_REASON_VMRESUME 24 -#define EXIT_REASON_VMWRITE 25 -#define EXIT_REASON_VMXOFF 26 -#define EXIT_REASON_VMXON 27 -#define EXIT_REASON_CR_ACCESS 28 -#define EXIT_REASON_DR_ACCESS 29 -#define EXIT_REASON_INOUT 30 -#define EXIT_REASON_RDMSR 31 -#define EXIT_REASON_WRMSR 32 -#define EXIT_REASON_INVAL_VMCS 33 -#define EXIT_REASON_INVAL_MSR 34 -#define EXIT_REASON_MWAIT 36 -#define EXIT_REASON_MTF 37 -#define EXIT_REASON_MONITOR 39 -#define EXIT_REASON_PAUSE 40 -#define EXIT_REASON_MCE_DURING_ENTRY 41 -#define EXIT_REASON_TPR 43 -#define EXIT_REASON_APIC_ACCESS 44 -#define EXIT_REASON_VIRTUALIZED_EOI 45 -#define EXIT_REASON_GDTR_IDTR 46 -#define EXIT_REASON_LDTR_TR 47 -#define EXIT_REASON_EPT_FAULT 48 -#define EXIT_REASON_EPT_MISCONFIG 49 -#define EXIT_REASON_INVEPT 50 -#define EXIT_REASON_RDTSCP 51 -#define EXIT_REASON_VMX_PREEMPT 52 -#define EXIT_REASON_INVVPID 53 -#define EXIT_REASON_WBINVD 54 -#define EXIT_REASON_XSETBV 55 -#define EXIT_REASON_APIC_WRITE 56 +#define EXIT_REASON_EXCEPTION 0 +#define EXIT_REASON_EXT_INTR 1 +#define EXIT_REASON_TRIPLE_FAULT 2 +#define EXIT_REASON_INIT 3 +#define EXIT_REASON_SIPI 4 +#define EXIT_REASON_IO_SMI 5 +#define EXIT_REASON_SMI 6 +#define EXIT_REASON_INTR_WINDOW 7 +#define EXIT_REASON_NMI_WINDOW 8 +#define EXIT_REASON_TASK_SWITCH 9 +#define EXIT_REASON_CPUID 10 +#define EXIT_REASON_GETSEC 11 +#define EXIT_REASON_HLT 12 +#define EXIT_REASON_INVD 13 +#define EXIT_REASON_INVLPG 14 +#define EXIT_REASON_RDPMC 15 +#define EXIT_REASON_RDTSC 16 +#define EXIT_REASON_RSM 17 +#define EXIT_REASON_VMCALL 18 +#define EXIT_REASON_VMCLEAR 19 +#define EXIT_REASON_VMLAUNCH 20 +#define EXIT_REASON_VMPTRLD 21 +#define EXIT_REASON_VMPTRST 22 +#define EXIT_REASON_VMREAD 23 +#define EXIT_REASON_VMRESUME 24 +#define EXIT_REASON_VMWRITE 25 +#define EXIT_REASON_VMXOFF 26 +#define EXIT_REASON_VMXON 27 +#define EXIT_REASON_CR_ACCESS 28 +#define EXIT_REASON_DR_ACCESS 29 +#define EXIT_REASON_INOUT 30 +#define EXIT_REASON_RDMSR 31 +#define EXIT_REASON_WRMSR 32 +#define EXIT_REASON_INVAL_VMCS 33 +#define EXIT_REASON_INVAL_MSR 34 +#define EXIT_REASON_MWAIT 36 +#define EXIT_REASON_MTF 37 +#define EXIT_REASON_MONITOR 39 +#define EXIT_REASON_PAUSE 40 +#define EXIT_REASON_MCE_DURING_ENTR 41 +#define EXIT_REASON_TPR 43 +#define EXIT_REASON_APIC_ACCESS 44 +#define EXIT_REASON_VIRTUALIZED_EOI 45 +#define EXIT_REASON_GDTR_IDTR 46 +#define EXIT_REASON_LDTR_TR 47 +#define EXIT_REASON_EPT_FAULT 48 +#define EXIT_REASON_EPT_MISCONFIG 49 +#define EXIT_REASON_INVEPT 50 +#define EXIT_REASON_RDTSCP 51 +#define EXIT_REASON_VMX_PREEMPT 52 +#define EXIT_REASON_INVVPID 53 +#define EXIT_REASON_WBINVD 54 +#define EXIT_REASON_XSETBV 55 +#define EXIT_REASON_APIC_WRITE 56 /* * NMI unblocking due to IRET. * * Applies to VM-exits due to hardware exception or EPT fault. */ -#define EXIT_QUAL_NMIUDTI (1 << 12) +#define EXIT_QUAL_NMIUDTI (1 << 12) /* * VMCS interrupt information fields */ -#define VMCS_INTR_VALID (1U << 31) -#define VMCS_INTR_T_MASK 0x700 /* Interruption-info type */ -#define VMCS_INTR_T_HWINTR (0 << 8) -#define VMCS_INTR_T_NMI (2 << 8) -#define VMCS_INTR_T_HWEXCEPTION (3 << 8) -#define VMCS_INTR_T_SWINTR (4 << 8) -#define VMCS_INTR_T_PRIV_SWEXCEPTION (5 << 8) -#define VMCS_INTR_T_SWEXCEPTION (6 << 8) -#define VMCS_INTR_DEL_ERRCODE (1 << 11) +#define VMCS_INTR_VALID (1U << 31) +#define VMCS_INTR_T_MASK 0x700 /* Interruption-info type */ +#define VMCS_INTR_T_HWINTR (0 << 8) +#define VMCS_INTR_T_NMI (2 << 8) +#define VMCS_INTR_T_HWEXCEPTION (3 << 8) +#define VMCS_INTR_T_SWINTR (4 << 8) +#define VMCS_INTR_T_PRIV_SWEXCEPTION (5 << 8) +#define VMCS_INTR_T_SWEXCEPTION (6 << 8) +#define VMCS_INTR_DEL_ERRCODE (1 << 11) /* * VMCS IDT-Vectoring information fields */ -#define VMCS_IDT_VEC_VALID (1U << 31) -#define VMCS_IDT_VEC_TYPE 0x700 -#define VMCS_IDT_VEC_ERRCODE_VALID (1U << 11) -#define VMCS_IDT_VEC_HWINTR (0 << 8) -#define VMCS_IDT_VEC_NMI (2 << 8) -#define VMCS_IDT_VEC_HWEXCEPTION (3 << 8) -#define VMCS_IDT_VEC_SWINTR (4 << 8) +#define VMCS_IDT_VEC_VALID (1U << 31) +#define VMCS_IDT_VEC_TYPE 0x700 +#define VMCS_IDT_VEC_ERRCODE_VALID (1U << 11) +#define VMCS_IDT_VEC_HWINTR (0 << 8) +#define VMCS_IDT_VEC_NMI (2 << 8) +#define VMCS_IDT_VEC_HWEXCEPTION (3 << 8) +#define VMCS_IDT_VEC_SWINTR (4 << 8) /* * VMCS Guest interruptibility field */ -#define VMCS_INTERRUPTIBILITY_STI_BLOCKING (1 << 0) -#define VMCS_INTERRUPTIBILITY_MOVSS_BLOCKING (1 << 1) -#define VMCS_INTERRUPTIBILITY_SMI_BLOCKING (1 << 2) -#define VMCS_INTERRUPTIBILITY_NMI_BLOCKING (1 << 3) +#define VMCS_INTERRUPTIBILITY_STI_BLOCKING (1 << 0) +#define VMCS_INTERRUPTIBILITY_MOVSS_BLOCKING (1 << 1) +#define VMCS_INTERRUPTIBILITY_SMI_BLOCKING (1 << 2) +#define VMCS_INTERRUPTIBILITY_NMI_BLOCKING (1 << 3) /* * Exit qualification for EXIT_REASON_INVAL_VMCS */ -#define EXIT_QUAL_NMI_WHILE_STI_BLOCKING 3 +#define EXIT_QUAL_NMI_WHILE_STI_BLOCKING 3 /* * Exit qualification for EPT violation */ -#define EPT_VIOLATION_DATA_READ (1UL << 0) -#define EPT_VIOLATION_DATA_WRITE (1UL << 1) -#define EPT_VIOLATION_INST_FETCH (1UL << 2) -#define EPT_VIOLATION_GPA_READABLE (1UL << 3) -#define EPT_VIOLATION_GPA_WRITEABLE (1UL << 4) -#define EPT_VIOLATION_GPA_EXECUTABLE (1UL << 5) -#define EPT_VIOLATION_GLA_VALID (1UL << 7) -#define EPT_VIOLATION_XLAT_VALID (1UL << 8) +#define EPT_VIOLATION_DATA_READ (1UL << 0) +#define EPT_VIOLATION_DATA_WRITE (1UL << 1) +#define EPT_VIOLATION_INST_FETCH (1UL << 2) +#define EPT_VIOLATION_GPA_READABLE (1UL << 3) +#define EPT_VIOLATION_GPA_WRITEABLE (1UL << 4) +#define EPT_VIOLATION_GPA_EXECUTABLE (1UL << 5) +#define EPT_VIOLATION_GLA_VALID (1UL << 7) +#define EPT_VIOLATION_XLAT_VALID (1UL << 8) /* * Exit qualification for APIC-access VM exit */ -#define APIC_ACCESS_OFFSET(qual) ((qual) & 0xFFF) -#define APIC_ACCESS_TYPE(qual) (((qual) >> 12) & 0xF) +#define APIC_ACCESS_OFFSET(qual) ((qual) & 0xFFF) +#define APIC_ACCESS_TYPE(qual) (((qual) >> 12) & 0xF) /* * Exit qualification for APIC-write VM exit */ -#define APIC_WRITE_OFFSET(qual) ((qual) & 0xFFF) +#define APIC_WRITE_OFFSET(qual) ((qual) & 0xFFF) -#define VMCS_PRI_PROC_BASED_CTLS_INT_WINDOW_EXITING (1 << 2) -#define VMCS_PRI_PROC_BASED_CTLS_TSC_OFFSET (1 << 3) -#define VMCS_PRI_PROC_BASED_CTLS_HLT (1 << 7) +#define VMCS_PRI_PROC_BASED_CTLS_INT_WINDOW_EXITING (1 << 2) +#define VMCS_PRI_PROC_BASED_CTLS_TSC_OFFSET (1 << 3) +#define VMCS_PRI_PROC_BASED_CTLS_HLT (1 << 7) #define VMCS_PRI_PROC_BASED_CTLS_MWAIT (1 << 10) #define VMCS_PRI_PROC_BASED_CTLS_TSC (1 << 12) #define VMCS_PRI_PROC_BASED_CTLS_CR8_LOAD (1 << 19) @@ -359,10 +359,10 @@ #define VMCS_PRI_PROC_BASED2_CTLS_X2APIC (1 << 4) enum task_switch_reason { - TSR_CALL, - TSR_IRET, + TSR_CALL, + TSR_IRET, TSR_JMP, - TSR_IDT_GATE, /* task gate in IDT */ + TSR_IDT_GATE, /* task gate in IDT */ }; #endif diff --git a/target/i386/hvf-utils/vmx.h b/target/i386/hvf-utils/vmx.h index 8a080e6777..d086c8d253 100644 --- a/target/i386/hvf-utils/vmx.h +++ b/target/i386/hvf-utils/vmx.h @@ -31,45 +31,45 @@ #include "exec/address-spaces.h" -static uint64_t inline rreg(hv_vcpuid_t vcpu, hv_x86_reg_t reg) +static inline uint64_t rreg(hv_vcpuid_t vcpu, hv_x86_reg_t reg) { - uint64_t v; + uint64_t v; - if (hv_vcpu_read_register(vcpu, reg, &v)) { - abort(); - } + if (hv_vcpu_read_register(vcpu, reg, &v)) { + abort(); + } - return v; + return v; } /* write GPR */ -static void inline wreg(hv_vcpuid_t vcpu, hv_x86_reg_t reg, uint64_t v) +static inline void wreg(hv_vcpuid_t vcpu, hv_x86_reg_t reg, uint64_t v) { - if (hv_vcpu_write_register(vcpu, reg, v)) { - abort(); - } + if (hv_vcpu_write_register(vcpu, reg, v)) { + abort(); + } } /* read VMCS field */ -static uint64_t inline rvmcs(hv_vcpuid_t vcpu, uint32_t field) +static inline uint64_t rvmcs(hv_vcpuid_t vcpu, uint32_t field) { - uint64_t v; + uint64_t v; - hv_vmx_vcpu_read_vmcs(vcpu, field, &v); + hv_vmx_vcpu_read_vmcs(vcpu, field, &v); - return v; + return v; } /* write VMCS field */ -static void inline wvmcs(hv_vcpuid_t vcpu, uint32_t field, uint64_t v) +static inline void wvmcs(hv_vcpuid_t vcpu, uint32_t field, uint64_t v) { - hv_vmx_vcpu_write_vmcs(vcpu, field, v); + hv_vmx_vcpu_write_vmcs(vcpu, field, v); } /* desired control word constrained by hardware/hypervisor capabilities */ -static uint64_t inline cap2ctrl(uint64_t cap, uint64_t ctrl) +static inline uint64_t cap2ctrl(uint64_t cap, uint64_t ctrl) { - return (ctrl | (cap & 0xffffffff)) & (cap >> 32); + return (ctrl | (cap & 0xffffffff)) & (cap >> 32); } #define VM_ENTRY_GUEST_LMA (1LL << 9) @@ -91,11 +91,14 @@ static void enter_long_mode(hv_vcpuid_t vcpu, uint64_t cr0, uint64_t efer) efer |= EFER_LMA; wvmcs(vcpu, VMCS_GUEST_IA32_EFER, efer); entry_ctls = rvmcs(vcpu, VMCS_ENTRY_CTLS); - wvmcs(vcpu, VMCS_ENTRY_CTLS, rvmcs(vcpu, VMCS_ENTRY_CTLS) | VM_ENTRY_GUEST_LMA); + wvmcs(vcpu, VMCS_ENTRY_CTLS, rvmcs(vcpu, VMCS_ENTRY_CTLS) | + VM_ENTRY_GUEST_LMA); uint64_t guest_tr_ar = rvmcs(vcpu, VMCS_GUEST_TR_ACCESS_RIGHTS); - if ((efer & EFER_LME) && (guest_tr_ar & AR_TYPE_MASK) != AR_TYPE_BUSY_64_TSS) { - wvmcs(vcpu, VMCS_GUEST_TR_ACCESS_RIGHTS, (guest_tr_ar & ~AR_TYPE_MASK) | AR_TYPE_BUSY_64_TSS); + if ((efer & EFER_LME) && + (guest_tr_ar & AR_TYPE_MASK) != AR_TYPE_BUSY_64_TSS) { + wvmcs(vcpu, VMCS_GUEST_TR_ACCESS_RIGHTS, + (guest_tr_ar & ~AR_TYPE_MASK) | AR_TYPE_BUSY_64_TSS); } } @@ -110,39 +113,45 @@ static void exit_long_mode(hv_vcpuid_t vcpu, uint64_t cr0, uint64_t efer) wvmcs(vcpu, VMCS_GUEST_IA32_EFER, efer); } -static void inline macvm_set_cr0(hv_vcpuid_t vcpu, uint64_t cr0) +static inline void macvm_set_cr0(hv_vcpuid_t vcpu, uint64_t cr0) { int i; uint64_t pdpte[4] = {0, 0, 0, 0}; uint64_t efer = rvmcs(vcpu, VMCS_GUEST_IA32_EFER); uint64_t old_cr0 = rvmcs(vcpu, VMCS_GUEST_CR0); - if ((cr0 & CR0_PG) && (rvmcs(vcpu, VMCS_GUEST_CR4) & CR4_PAE) && !(efer & EFER_LME)) - address_space_rw(&address_space_memory, rvmcs(vcpu, VMCS_GUEST_CR3) & ~0x1f, + if ((cr0 & CR0_PG) && (rvmcs(vcpu, VMCS_GUEST_CR4) & CR4_PAE) && + !(efer & EFER_LME)) { + address_space_rw(&address_space_memory, + rvmcs(vcpu, VMCS_GUEST_CR3) & ~0x1f, MEMTXATTRS_UNSPECIFIED, (uint8_t *)pdpte, 32, 0); + } - for (i = 0; i < 4; i++) + for (i = 0; i < 4; i++) { wvmcs(vcpu, VMCS_GUEST_PDPTE0 + i * 2, pdpte[i]); + } wvmcs(vcpu, VMCS_CR0_MASK, CR0_CD | CR0_NE | CR0_PG); wvmcs(vcpu, VMCS_CR0_SHADOW, cr0); cr0 &= ~CR0_CD; - wvmcs(vcpu, VMCS_GUEST_CR0, cr0 | CR0_NE| CR0_ET); + wvmcs(vcpu, VMCS_GUEST_CR0, cr0 | CR0_NE | CR0_ET); if (efer & EFER_LME) { - if (!(old_cr0 & CR0_PG) && (cr0 & CR0_PG)) - enter_long_mode(vcpu, cr0, efer); - if (/*(old_cr0 & CR0_PG) &&*/ !(cr0 & CR0_PG)) + if (!(old_cr0 & CR0_PG) && (cr0 & CR0_PG)) { + enter_long_mode(vcpu, cr0, efer); + } + if (/*(old_cr0 & CR0_PG) &&*/ !(cr0 & CR0_PG)) { exit_long_mode(vcpu, cr0, efer); + } } hv_vcpu_invalidate_tlb(vcpu); hv_vcpu_flush(vcpu); } -static void inline macvm_set_cr4(hv_vcpuid_t vcpu, uint64_t cr4) +static inline void macvm_set_cr4(hv_vcpuid_t vcpu, uint64_t cr4) { uint64_t guest_cr4 = cr4 | CR4_VMXE; @@ -153,7 +162,7 @@ static void inline macvm_set_cr4(hv_vcpuid_t vcpu, uint64_t cr4) hv_vcpu_flush(vcpu); } -static void inline macvm_set_rip(CPUState *cpu, uint64_t rip) +static inline void macvm_set_rip(CPUState *cpu, uint64_t rip) { uint64_t val; @@ -162,39 +171,44 @@ static void inline macvm_set_rip(CPUState *cpu, uint64_t rip) /* after moving forward in rip, we need to clean INTERRUPTABILITY */ val = rvmcs(cpu->hvf_fd, VMCS_GUEST_INTERRUPTIBILITY); - if (val & (VMCS_INTERRUPTIBILITY_STI_BLOCKING | VMCS_INTERRUPTIBILITY_MOVSS_BLOCKING)) + if (val & (VMCS_INTERRUPTIBILITY_STI_BLOCKING | + VMCS_INTERRUPTIBILITY_MOVSS_BLOCKING)) { wvmcs(cpu->hvf_fd, VMCS_GUEST_INTERRUPTIBILITY, - val & ~(VMCS_INTERRUPTIBILITY_STI_BLOCKING | VMCS_INTERRUPTIBILITY_MOVSS_BLOCKING)); + val & ~(VMCS_INTERRUPTIBILITY_STI_BLOCKING | + VMCS_INTERRUPTIBILITY_MOVSS_BLOCKING)); + } } -static void inline vmx_clear_nmi_blocking(CPUState *cpu) +static inline void vmx_clear_nmi_blocking(CPUState *cpu) { uint32_t gi = (uint32_t) rvmcs(cpu->hvf_fd, VMCS_GUEST_INTERRUPTIBILITY); gi &= ~VMCS_INTERRUPTIBILITY_NMI_BLOCKING; wvmcs(cpu->hvf_fd, VMCS_GUEST_INTERRUPTIBILITY, gi); } -static void inline vmx_set_nmi_blocking(CPUState *cpu) +static inline void vmx_set_nmi_blocking(CPUState *cpu) { uint32_t gi = (uint32_t)rvmcs(cpu->hvf_fd, VMCS_GUEST_INTERRUPTIBILITY); gi |= VMCS_INTERRUPTIBILITY_NMI_BLOCKING; wvmcs(cpu->hvf_fd, VMCS_GUEST_INTERRUPTIBILITY, gi); } -static void inline vmx_set_nmi_window_exiting(CPUState *cpu) +static inline void vmx_set_nmi_window_exiting(CPUState *cpu) { uint64_t val; val = rvmcs(cpu->hvf_fd, VMCS_PRI_PROC_BASED_CTLS); - wvmcs(cpu->hvf_fd, VMCS_PRI_PROC_BASED_CTLS, val | VMCS_PRI_PROC_BASED_CTLS_NMI_WINDOW_EXITING); + wvmcs(cpu->hvf_fd, VMCS_PRI_PROC_BASED_CTLS, val | + VMCS_PRI_PROC_BASED_CTLS_NMI_WINDOW_EXITING); } -static void inline vmx_clear_nmi_window_exiting(CPUState *cpu) +static inline void vmx_clear_nmi_window_exiting(CPUState *cpu) { uint64_t val; val = rvmcs(cpu->hvf_fd, VMCS_PRI_PROC_BASED_CTLS); - wvmcs(cpu->hvf_fd, VMCS_PRI_PROC_BASED_CTLS, val & ~VMCS_PRI_PROC_BASED_CTLS_NMI_WINDOW_EXITING); + wvmcs(cpu->hvf_fd, VMCS_PRI_PROC_BASED_CTLS, val & + ~VMCS_PRI_PROC_BASED_CTLS_NMI_WINDOW_EXITING); } #endif diff --git a/target/i386/hvf-utils/x86.c b/target/i386/hvf-utils/x86.c index e3db2c9c8b..07eb5a8586 100644 --- a/target/i386/hvf-utils/x86.c +++ b/target/i386/hvf-utils/x86.c @@ -26,35 +26,38 @@ #include "x86_mmu.h" #include "x86_descr.h" -static uint32_t x86_segment_access_rights(struct x86_segment_descriptor *var) +/* static uint32_t x86_segment_access_rights(struct x86_segment_descriptor *var) { - uint32_t ar; - - if (!var->p) { - ar = 1 << 16; - return ar; - } - - ar = var->type & 15; - ar |= (var->s & 1) << 4; - ar |= (var->dpl & 3) << 5; - ar |= (var->p & 1) << 7; - ar |= (var->avl & 1) << 12; - ar |= (var->l & 1) << 13; - ar |= (var->db & 1) << 14; - ar |= (var->g & 1) << 15; - return ar; -} - -bool x86_read_segment_descriptor(struct CPUState *cpu, struct x86_segment_descriptor *desc, x68_segment_selector sel) + uint32_t ar; + + if (!var->p) { + ar = 1 << 16; + return ar; + } + + ar = var->type & 15; + ar |= (var->s & 1) << 4; + ar |= (var->dpl & 3) << 5; + ar |= (var->p & 1) << 7; + ar |= (var->avl & 1) << 12; + ar |= (var->l & 1) << 13; + ar |= (var->db & 1) << 14; + ar |= (var->g & 1) << 15; + return ar; +}*/ + +bool x86_read_segment_descriptor(struct CPUState *cpu, + struct x86_segment_descriptor *desc, + x68_segment_selector sel) { addr_t base; uint32_t limit; ZERO_INIT(*desc); - // valid gdt descriptors start from index 1 - if (!sel.index && GDT_SEL == sel.ti) + /* valid gdt descriptors start from index 1 */ + if (!sel.index && GDT_SEL == sel.ti) { return false; + } if (GDT_SEL == sel.ti) { base = rvmcs(cpu->hvf_fd, VMCS_GUEST_GDTR_BASE); @@ -64,18 +67,21 @@ bool x86_read_segment_descriptor(struct CPUState *cpu, struct x86_segment_descri limit = rvmcs(cpu->hvf_fd, VMCS_GUEST_LDTR_LIMIT); } - if (sel.index * 8 >= limit) + if (sel.index * 8 >= limit) { return false; + } vmx_read_mem(cpu, desc, base + sel.index * 8, sizeof(*desc)); return true; } -bool x86_write_segment_descriptor(struct CPUState *cpu, struct x86_segment_descriptor *desc, x68_segment_selector sel) +bool x86_write_segment_descriptor(struct CPUState *cpu, + struct x86_segment_descriptor *desc, + x68_segment_selector sel) { addr_t base; uint32_t limit; - + if (GDT_SEL == sel.ti) { base = rvmcs(cpu->hvf_fd, VMCS_GUEST_GDTR_BASE); limit = rvmcs(cpu->hvf_fd, VMCS_GUEST_GDTR_LIMIT); @@ -83,23 +89,24 @@ bool x86_write_segment_descriptor(struct CPUState *cpu, struct x86_segment_descr base = rvmcs(cpu->hvf_fd, VMCS_GUEST_LDTR_BASE); limit = rvmcs(cpu->hvf_fd, VMCS_GUEST_LDTR_LIMIT); } - + if (sel.index * 8 >= limit) { - printf("%s: gdt limit\n", __FUNCTION__); + printf("%s: gdt limit\n", __func__); return false; } vmx_write_mem(cpu, base + sel.index * 8, desc, sizeof(*desc)); return true; } -bool x86_read_call_gate(struct CPUState *cpu, struct x86_call_gate *idt_desc, int gate) +bool x86_read_call_gate(struct CPUState *cpu, struct x86_call_gate *idt_desc, + int gate) { addr_t base = rvmcs(cpu->hvf_fd, VMCS_GUEST_IDTR_BASE); uint32_t limit = rvmcs(cpu->hvf_fd, VMCS_GUEST_IDTR_LIMIT); ZERO_INIT(*idt_desc); if (gate * 8 >= limit) { - printf("%s: idt limit\n", __FUNCTION__); + printf("%s: idt limit\n", __func__); return false; } @@ -120,7 +127,7 @@ bool x86_is_real(struct CPUState *cpu) bool x86_is_v8086(struct CPUState *cpu) { - return (x86_is_protected(cpu) && (RFLAGS(cpu) & RFLAGS_VM)); + return x86_is_protected(cpu) && (RFLAGS(cpu) & RFLAGS_VM); } bool x86_is_long_mode(struct CPUState *cpu) @@ -153,17 +160,18 @@ addr_t linear_addr(struct CPUState *cpu, addr_t addr, x86_reg_segment seg) return vmx_read_segment_base(cpu, seg) + addr; } -addr_t linear_addr_size(struct CPUState *cpu, addr_t addr, int size, x86_reg_segment seg) +addr_t linear_addr_size(struct CPUState *cpu, addr_t addr, int size, + x86_reg_segment seg) { switch (size) { - case 2: - addr = (uint16_t)addr; - break; - case 4: - addr = (uint32_t)addr; - break; - default: - break; + case 2: + addr = (uint16_t)addr; + break; + case 4: + addr = (uint32_t)addr; + break; + default: + break; } return linear_addr(cpu, addr, seg); } diff --git a/target/i386/hvf-utils/x86.h b/target/i386/hvf-utils/x86.h index 5dffdd6568..435b49ae04 100644 --- a/target/i386/hvf-utils/x86.h +++ b/target/i386/hvf-utils/x86.h @@ -25,26 +25,26 @@ #include "qemu-common.h" #include "x86_flags.h" -// exceptions +/* exceptions */ typedef enum x86_exception { - EXCEPTION_DE, // divide error - EXCEPTION_DB, // debug fault - EXCEPTION_NMI, // non-maskable interrupt - EXCEPTION_BP, // breakpoint trap - EXCEPTION_OF, // overflow trap - EXCEPTION_BR, // boundary range exceeded fault - EXCEPTION_UD, // undefined opcode - EXCEPTION_NM, // device not available - EXCEPTION_DF, // double fault - EXCEPTION_RSVD, // not defined - EXCEPTION_TS, // invalid TSS fault - EXCEPTION_NP, // not present fault - EXCEPTION_GP, // general protection fault - EXCEPTION_PF, // page fault - EXCEPTION_RSVD2, // not defined + EXCEPTION_DE, /* divide error */ + EXCEPTION_DB, /* debug fault */ + EXCEPTION_NMI, /* non-maskable interrupt */ + EXCEPTION_BP, /* breakpoint trap */ + EXCEPTION_OF, /* overflow trap */ + EXCEPTION_BR, /* boundary range exceeded fault */ + EXCEPTION_UD, /* undefined opcode */ + EXCEPTION_NM, /* device not available */ + EXCEPTION_DF, /* double fault */ + EXCEPTION_RSVD, /* not defined */ + EXCEPTION_TS, /* invalid TSS fault */ + EXCEPTION_NP, /* not present fault */ + EXCEPTION_GP, /* general protection fault */ + EXCEPTION_PF, /* page fault */ + EXCEPTION_RSVD2, /* not defined */ } x86_exception; -// general purpose regs +/* general purpose regs */ typedef enum x86_reg_name { REG_RAX = 0, REG_RCX = 1, @@ -64,7 +64,7 @@ typedef enum x86_reg_name { REG_R15 = 15, } x86_reg_name; -// segment regs +/* segment regs */ typedef enum x86_reg_segment { REG_SEG_ES = 0, REG_SEG_CS = 1, @@ -76,24 +76,23 @@ typedef enum x86_reg_segment { REG_SEG_TR = 7, } x86_reg_segment; -typedef struct x86_register -{ +typedef struct x86_register { union { struct { - uint64_t rrx; // full 64 bit + uint64_t rrx; /* full 64 bit */ }; struct { - uint32_t erx; // low 32 bit part + uint32_t erx; /* low 32 bit part */ uint32_t hi32_unused1; }; struct { - uint16_t rx; // low 16 bit part + uint16_t rx; /* low 16 bit part */ uint16_t hi16_unused1; uint32_t hi32_unused2; }; struct { - uint8_t lx; // low 8 bit part - uint8_t hx; // high 8 bit + uint8_t lx; /* low 8 bit part */ + uint8_t hx; /* high 8 bit */ uint16_t hi16_unused2; uint32_t hi32_unused3; }; @@ -120,7 +119,7 @@ typedef enum x86_rflags { RFLAGS_ID = (1L << 21), } x86_rflags; -// rflags register +/* rflags register */ typedef struct x86_reg_flags { union { struct { @@ -205,7 +204,7 @@ typedef enum x86_reg_cr4 { CR4_SMEP = (1L << 20), } x86_reg_cr4; -// 16 bit Task State Segment +/* 16 bit Task State Segment */ typedef struct x86_tss_segment16 { uint16_t link; uint16_t sp0; @@ -231,9 +230,8 @@ typedef struct x86_tss_segment16 { uint16_t ldtr; } __attribute__((packed)) x86_tss_segment16; -// 32 bit Task State Segment -typedef struct x86_tss_segment32 -{ +/* 32 bit Task State Segment */ +typedef struct x86_tss_segment32 { uint32_t prev_tss; uint32_t esp0; uint32_t ss0; @@ -263,9 +261,8 @@ typedef struct x86_tss_segment32 uint16_t iomap_base; } __attribute__ ((__packed__)) x86_tss_segment32; -// 64 bit Task State Segment -typedef struct x86_tss_segment64 -{ +/* 64 bit Task State Segment */ +typedef struct x86_tss_segment64 { uint32_t unused; uint64_t rsp0; uint64_t rsp1; @@ -283,7 +280,7 @@ typedef struct x86_tss_segment64 uint16_t iomap_base; } __attribute__ ((__packed__)) x86_tss_segment64; -// segment descriptors +/* segment descriptors */ typedef struct x86_segment_descriptor { uint64_t limit0:16; uint64_t base0:16; @@ -305,7 +302,8 @@ static inline uint32_t x86_segment_base(x86_segment_descriptor *desc) return (uint32_t)((desc->base2 << 24) | (desc->base1 << 16) | desc->base0); } -static inline void x86_set_segment_base(x86_segment_descriptor *desc, uint32_t base) +static inline void x86_set_segment_base(x86_segment_descriptor *desc, + uint32_t base) { desc->base2 = base >> 24; desc->base1 = (base >> 16) & 0xff; @@ -315,12 +313,14 @@ static inline void x86_set_segment_base(x86_segment_descriptor *desc, uint32_t b static inline uint32_t x86_segment_limit(x86_segment_descriptor *desc) { uint32_t limit = (uint32_t)((desc->limit1 << 16) | desc->limit0); - if (desc->g) + if (desc->g) { return (limit << 12) | 0xfff; + } return limit; } -static inline void x86_set_segment_limit(x86_segment_descriptor *desc, uint32_t limit) +static inline void x86_set_segment_limit(x86_segment_descriptor *desc, + uint32_t limit) { desc->limit0 = limit & 0xffff; desc->limit1 = limit >> 16; @@ -356,11 +356,11 @@ typedef struct x68_segment_selector { }; } __attribute__ ((__packed__)) x68_segment_selector; -// Definition of hvf_x86_state is here +/* Definition of hvf_x86_state is here */ struct hvf_x86_state { int hlt; uint64_t init_tsc; - + int interruptable; uint64_t exp_rip; uint64_t fetch_rip; @@ -370,7 +370,7 @@ struct hvf_x86_state { struct lazy_flags lflags; struct x86_efer efer; uint8_t mmio_buf[4096]; - uint8_t* apic_page; + uint8_t *apic_page; }; /* @@ -380,7 +380,7 @@ struct hvf_xsave_buf { uint32_t data[1024]; }; -// useful register access macros +/* useful register access macros */ #define RIP(cpu) (cpu->hvf_x86->rip) #define EIP(cpu) ((uint32_t)cpu->hvf_x86->rip) #define RFLAGS(cpu) (cpu->hvf_x86->rflags.rflags) @@ -436,13 +436,18 @@ struct hvf_xsave_buf { #define DH(cpu) RH(cpu, REG_RDX) #define BH(cpu) RH(cpu, REG_RBX) -// deal with GDT/LDT descriptors in memory -bool x86_read_segment_descriptor(struct CPUState *cpu, struct x86_segment_descriptor *desc, x68_segment_selector sel); -bool x86_write_segment_descriptor(struct CPUState *cpu, struct x86_segment_descriptor *desc, x68_segment_selector sel); +/* deal with GDT/LDT descriptors in memory */ +bool x86_read_segment_descriptor(struct CPUState *cpu, + struct x86_segment_descriptor *desc, + x68_segment_selector sel); +bool x86_write_segment_descriptor(struct CPUState *cpu, + struct x86_segment_descriptor *desc, + x68_segment_selector sel); -bool x86_read_call_gate(struct CPUState *cpu, struct x86_call_gate *idt_desc, int gate); +bool x86_read_call_gate(struct CPUState *cpu, struct x86_call_gate *idt_desc, + int gate); -// helpers +/* helpers */ bool x86_is_protected(struct CPUState *cpu); bool x86_is_real(struct CPUState *cpu); bool x86_is_v8086(struct CPUState *cpu); @@ -452,19 +457,20 @@ bool x86_is_paging_mode(struct CPUState *cpu); bool x86_is_pae_enabled(struct CPUState *cpu); addr_t linear_addr(struct CPUState *cpu, addr_t addr, x86_reg_segment seg); -addr_t linear_addr_size(struct CPUState *cpu, addr_t addr, int size, x86_reg_segment seg); +addr_t linear_addr_size(struct CPUState *cpu, addr_t addr, int size, + x86_reg_segment seg); addr_t linear_rip(struct CPUState *cpu, addr_t rip); static inline uint64_t rdtscp(void) { uint64_t tsc; - __asm__ __volatile__("rdtscp; " // serializing read of tsc - "shl $32,%%rdx; " // shift higher 32 bits stored in rdx up - "or %%rdx,%%rax" // and or onto rax - : "=a"(tsc) // output to tsc variable + __asm__ __volatile__("rdtscp; " /* serializing read of tsc */ + "shl $32,%%rdx; " /* shift higher 32 bits stored in rdx up */ + "or %%rdx,%%rax" /* and or onto rax */ + : "=a"(tsc) /* output to tsc variable */ : - : "%rcx", "%rdx"); // rcx and rdx are clobbered - + : "%rcx", "%rdx"); /* rcx and rdx are clobbered */ + return tsc; } diff --git a/target/i386/hvf-utils/x86_cpuid.c b/target/i386/hvf-utils/x86_cpuid.c index e496cf001c..5d63bca8fd 100644 --- a/target/i386/hvf-utils/x86_cpuid.c +++ b/target/i386/hvf-utils/x86_cpuid.c @@ -41,10 +41,10 @@ struct x86_cpuid builtin_cpus[] = { .model = 3, .stepping = 3, .features = PPRO_FEATURES, - .ext_features = /*CPUID_EXT_SSE3 |*/ CPUID_EXT_POPCNT, CPUID_MTRR | CPUID_CLFLUSH, - CPUID_PSE36, + .ext_features = /*CPUID_EXT_SSE3 |*/ CPUID_EXT_POPCNT, CPUID_MTRR | + CPUID_CLFLUSH, CPUID_PSE36, .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, - .ext3_features = 0,//CPUID_EXT3_LAHF_LM, + .ext3_features = 0, /* CPUID_EXT3_LAHF_LM, */ .xlevel = 0x80000004, .model_id = "vmx32", }, @@ -92,14 +92,15 @@ struct x86_cpuid builtin_cpus[] = { }, }; -static struct x86_cpuid *_cpuid = NULL; +static struct x86_cpuid *_cpuid; -void init_cpuid(struct CPUState* cpu) +void init_cpuid(struct CPUState *cpu) { - _cpuid = &builtin_cpus[2]; // core2duo + _cpuid = &builtin_cpus[2]; /* core2duo */ } -void get_cpuid_func(struct CPUState* cpu, int func, int cnt, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) +void get_cpuid_func(struct CPUState *cpu, int func, int cnt, uint32_t *eax, + uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { uint32_t h_rax, h_rbx, h_rcx, h_rdx; host_cpuid(func, cnt, &h_rax, &h_rbx, &h_rcx, &h_rdx); @@ -107,164 +108,172 @@ void get_cpuid_func(struct CPUState* cpu, int func, int cnt, uint32_t *eax, uint *eax = *ebx = *ecx = *edx = 0; - switch(func) { - case 0: - *eax = _cpuid->level; - *ebx = _cpuid->vendor1; - *edx = _cpuid->vendor2; - *ecx = _cpuid->vendor3; - break; - case 1: - *eax = h_rax;//_cpuid->stepping | (_cpuid->model << 3) | (_cpuid->family << 6); - *ebx = (apic_id << 24) | (h_rbx & 0x00ffffff); - *ecx = h_rcx; - *edx = h_rdx; + switch (func) { + case 0: + *eax = _cpuid->level; + *ebx = _cpuid->vendor1; + *edx = _cpuid->vendor2; + *ecx = _cpuid->vendor3; + break; + case 1: + *eax = h_rax;/*_cpuid->stepping | (_cpuid->model << 3) | + (_cpuid->family << 6); */ + *ebx = (apic_id << 24) | (h_rbx & 0x00ffffff); + *ecx = h_rcx; + *edx = h_rdx; - if (cpu->nr_cores * cpu->nr_threads > 1) { - *ebx |= (cpu->nr_cores * cpu->nr_threads) << 16; - *edx |= 1 << 28; /* Enable Hyper-Threading */ - } + if (cpu->nr_cores * cpu->nr_threads > 1) { + *ebx |= (cpu->nr_cores * cpu->nr_threads) << 16; + *edx |= 1 << 28; /* Enable Hyper-Threading */ + } - *ecx = *ecx & ~(CPUID_EXT_OSXSAVE | CPUID_EXT_MONITOR | CPUID_EXT_X2APIC | - CPUID_EXT_VMX | CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_TM2 | CPUID_EXT_PCID | - CPUID_EXT_EST | CPUID_EXT_SSE42 | CPUID_EXT_SSE41); - *ecx |= CPUID_EXT_HYPERVISOR; - break; - case 2: - /* cache info: needed for Pentium Pro compatibility */ - *eax = h_rax; - *ebx = h_rbx; - *ecx = h_rcx; - *edx = h_rdx; - break; - case 4: - /* cache info: needed for Core compatibility */ - *eax = h_rax; - *ebx = h_rbx; - *ecx = h_rcx; - *edx = h_rdx; - break; - case 5: - /* mwait info: needed for Core compatibility */ - *eax = h_rax; - *ebx = h_rbx; - *ecx = h_rcx; - *edx = h_rdx; - break; - case 6: - /* Thermal and Power Leaf */ - *eax = 0; - *ebx = 0; - *ecx = 0; - *edx = 0; - break; - case 7: - *eax = h_rax; - *ebx = h_rbx & ~(CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512PF | CPUID_7_0_EBX_AVX512ER | CPUID_7_0_EBX_AVX512CD | - CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_INVPCID); - *ecx = h_rcx & ~(CPUID_7_0_ECX_AVX512BMI); - *edx = h_rdx; - break; - case 9: - /* Direct Cache Access Information Leaf */ - *eax = h_rax; - *ebx = h_rbx; - *ecx = h_rcx; - *edx = h_rdx; - break; - case 0xA: - /* Architectural Performance Monitoring Leaf */ - *eax = 0; - *ebx = 0; - *ecx = 0; - *edx = 0; - break; - case 0xB: - /* CPU Topology Leaf */ - *eax = 0; - *ebx = 0; /* Means that we don't support this leaf */ - *ecx = 0; - *edx = 0; - break; - case 0xD: - *eax = h_rax; - if (!cnt) - *eax &= (XSTATE_FP_MASK | XSTATE_SSE_MASK | XSTATE_YMM_MASK); - if (1 == cnt) - *eax &= (CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC); - *ebx = h_rbx; - *ecx = h_rcx; - *edx = h_rdx; - break; - case 0x80000000: - *eax = _cpuid->xlevel; - *ebx = _cpuid->vendor1; - *edx = _cpuid->vendor2; - *ecx = _cpuid->vendor3; - break; - case 0x80000001: - *eax = h_rax;//_cpuid->stepping | (_cpuid->model << 3) | (_cpuid->family << 6); - *ebx = 0; - *ecx = _cpuid->ext3_features & h_rcx; - *edx = _cpuid->ext2_features & h_rdx; - break; - case 0x80000002: - case 0x80000003: - case 0x80000004: - *eax = h_rax; - *ebx = h_rbx; - *ecx = h_rcx; - *edx = h_rdx; - break; - case 0x80000005: - /* cache info (L1 cache) */ - *eax = h_rax; - *ebx = h_rbx; - *ecx = h_rcx; - *edx = h_rdx; - break; - case 0x80000006: - /* cache info (L2 cache) */ - *eax = h_rax; - *ebx = h_rbx; - *ecx = h_rcx; - *edx = h_rdx; - break; - case 0x80000007: - *eax = 0; - *ebx = 0; - *ecx = 0; - *edx = 0; /* Note - We disable invariant TSC (bit 8) in purpose */ - break; - case 0x80000008: - /* virtual & phys address size in low 2 bytes. */ - *eax = h_rax; - *ebx = 0; - *ecx = 0; - *edx = 0; - break; - case 0x8000000A: - *eax = 0; - *ebx = 0; - *ecx = 0; - *edx = 0; - break; - case 0x80000019: - *eax = h_rax; - *ebx = h_rbx; - *ecx = 0; - *edx = 0; - case 0xC0000000: - *eax = _cpuid->xlevel2; - *ebx = 0; - *ecx = 0; - *edx = 0; - break; - default: - *eax = 0; - *ebx = 0; - *ecx = 0; - *edx = 0; - break; + *ecx = *ecx & ~(CPUID_EXT_OSXSAVE | CPUID_EXT_MONITOR | + CPUID_EXT_X2APIC | CPUID_EXT_VMX | + CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_TM2 | + CPUID_EXT_PCID | CPUID_EXT_EST | CPUID_EXT_SSE42 | + CPUID_EXT_SSE41); + *ecx |= CPUID_EXT_HYPERVISOR; + break; + case 2: + /* cache info: needed for Pentium Pro compatibility */ + *eax = h_rax; + *ebx = h_rbx; + *ecx = h_rcx; + *edx = h_rdx; + break; + case 4: + /* cache info: needed for Core compatibility */ + *eax = h_rax; + *ebx = h_rbx; + *ecx = h_rcx; + *edx = h_rdx; + break; + case 5: + /* mwait info: needed for Core compatibility */ + *eax = h_rax; + *ebx = h_rbx; + *ecx = h_rcx; + *edx = h_rdx; + break; + case 6: + /* Thermal and Power Leaf */ + *eax = 0; + *ebx = 0; + *ecx = 0; + *edx = 0; + break; + case 7: + *eax = h_rax; + *ebx = h_rbx & ~(CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512PF | + CPUID_7_0_EBX_AVX512ER | CPUID_7_0_EBX_AVX512CD | + CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512VL | + CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_INVPCID); + *ecx = h_rcx & ~(CPUID_7_0_ECX_AVX512BMI); + *edx = h_rdx; + break; + case 9: + /* Direct Cache Access Information Leaf */ + *eax = h_rax; + *ebx = h_rbx; + *ecx = h_rcx; + *edx = h_rdx; + break; + case 0xA: + /* Architectural Performance Monitoring Leaf */ + *eax = 0; + *ebx = 0; + *ecx = 0; + *edx = 0; + break; + case 0xB: + /* CPU Topology Leaf */ + *eax = 0; + *ebx = 0; /* Means that we don't support this leaf */ + *ecx = 0; + *edx = 0; + break; + case 0xD: + *eax = h_rax; + if (!cnt) { + *eax &= (XSTATE_FP_MASK | XSTATE_SSE_MASK | XSTATE_YMM_MASK); + } + if (1 == cnt) { + *eax &= (CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC); + } + *ebx = h_rbx; + *ecx = h_rcx; + *edx = h_rdx; + break; + case 0x80000000: + *eax = _cpuid->xlevel; + *ebx = _cpuid->vendor1; + *edx = _cpuid->vendor2; + *ecx = _cpuid->vendor3; + break; + case 0x80000001: + *eax = h_rax;/*_cpuid->stepping | (_cpuid->model << 3) | + (_cpuid->family << 6);*/ + *ebx = 0; + *ecx = _cpuid->ext3_features & h_rcx; + *edx = _cpuid->ext2_features & h_rdx; + break; + case 0x80000002: + case 0x80000003: + case 0x80000004: + *eax = h_rax; + *ebx = h_rbx; + *ecx = h_rcx; + *edx = h_rdx; + break; + case 0x80000005: + /* cache info (L1 cache) */ + *eax = h_rax; + *ebx = h_rbx; + *ecx = h_rcx; + *edx = h_rdx; + break; + case 0x80000006: + /* cache info (L2 cache) */ + *eax = h_rax; + *ebx = h_rbx; + *ecx = h_rcx; + *edx = h_rdx; + break; + case 0x80000007: + *eax = 0; + *ebx = 0; + *ecx = 0; + *edx = 0; /* Note - We disable invariant TSC (bit 8) in purpose */ + break; + case 0x80000008: + /* virtual & phys address size in low 2 bytes. */ + *eax = h_rax; + *ebx = 0; + *ecx = 0; + *edx = 0; + break; + case 0x8000000A: + *eax = 0; + *ebx = 0; + *ecx = 0; + *edx = 0; + break; + case 0x80000019: + *eax = h_rax; + *ebx = h_rbx; + *ecx = 0; + *edx = 0; + case 0xC0000000: + *eax = _cpuid->xlevel2; + *ebx = 0; + *ecx = 0; + *edx = 0; + break; + default: + *eax = 0; + *ebx = 0; + *ecx = 0; + *edx = 0; + break; } } diff --git a/target/i386/hvf-utils/x86_cpuid.h b/target/i386/hvf-utils/x86_cpuid.h index 02f2f115b0..ab10b84b61 100644 --- a/target/i386/hvf-utils/x86_cpuid.h +++ b/target/i386/hvf-utils/x86_cpuid.h @@ -35,7 +35,7 @@ struct x86_cpuid { uint32_t features, ext_features, ext2_features, ext3_features; uint32_t kvm_features, svm_features; uint32_t xlevel; - char model_id[48]; + char model_id[50]; int vendor_override; uint32_t flags; uint32_t xlevel2; @@ -44,8 +44,9 @@ struct x86_cpuid { struct CPUState; -void init_cpuid(struct CPUState* cpu); -void get_cpuid_func(struct CPUState *cpu, int func, int cnt, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx); +void init_cpuid(struct CPUState *cpu); +void get_cpuid_func(struct CPUState *cpu, int func, int cnt, uint32_t *eax, + uint32_t *ebx, uint32_t *ecx, uint32_t *edx); #endif /* __CPUID_H__ */ diff --git a/target/i386/hvf-utils/x86_decode.c b/target/i386/hvf-utils/x86_decode.c index b4d8e22449..4faf82f721 100644 --- a/target/i386/hvf-utils/x86_decode.c +++ b/target/i386/hvf-utils/x86_decode.c @@ -29,9 +29,11 @@ static void decode_invalid(CPUState *cpu, struct x86_decode *decode) { - printf("%llx: failed to decode instruction ", cpu->hvf_x86->fetch_rip - decode->len); - for (int i = 0; i < decode->opcode_len; i++) + printf("%llx: failed to decode instruction ", cpu->hvf_x86->fetch_rip - + decode->len); + for (int i = 0; i < decode->opcode_len; i++) { printf("%x ", decode->opcode[i]); + } printf("\n"); VM_PANIC("decoder failed\n"); } @@ -39,43 +41,44 @@ static void decode_invalid(CPUState *cpu, struct x86_decode *decode) uint64_t sign(uint64_t val, int size) { switch (size) { - case 1: - val = (int8_t)val; - break; - case 2: - val = (int16_t)val; - break; - case 4: - val = (int32_t)val; - break; - case 8: - val = (int64_t)val; - break; - default: - VM_PANIC_EX("%s invalid size %d\n", __FUNCTION__, size); - break; + case 1: + val = (int8_t)val; + break; + case 2: + val = (int16_t)val; + break; + case 4: + val = (int32_t)val; + break; + case 8: + val = (int64_t)val; + break; + default: + VM_PANIC_EX("%s invalid size %d\n", __func__, size); + break; } return val; } -static inline uint64_t decode_bytes(CPUState *cpu, struct x86_decode *decode, int size) +static inline uint64_t decode_bytes(CPUState *cpu, struct x86_decode *decode, + int size) { addr_t val = 0; - + switch (size) { - case 1: - case 2: - case 4: - case 8: - break; - default: - VM_PANIC_EX("%s invalid size %d\n", __FUNCTION__, size); - break; + case 1: + case 2: + case 4: + case 8: + break; + default: + VM_PANIC_EX("%s invalid size %d\n", __func__, size); + break; } addr_t va = linear_rip(cpu, RIP(cpu)) + decode->len; vmx_read_mem(cpu, &val, va, size); decode->len += size; - + return val; } @@ -99,68 +102,76 @@ static inline uint64_t decode_qword(CPUState *cpu, struct x86_decode *decode) return decode_bytes(cpu, decode, 8); } -static void decode_modrm_rm(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +static void decode_modrm_rm(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op) { op->type = X86_VAR_RM; } -static void decode_modrm_reg(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +static void decode_modrm_reg(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op) { op->type = X86_VAR_REG; op->reg = decode->modrm.reg; op->ptr = get_reg_ref(cpu, op->reg, decode->rex.r, decode->operand_size); } -static void decode_rax(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +static void decode_rax(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op) { op->type = X86_VAR_REG; op->reg = REG_RAX; op->ptr = get_reg_ref(cpu, op->reg, 0, decode->operand_size); } -static inline void decode_immediate(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *var, int size) +static inline void decode_immediate(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *var, int size) { var->type = X86_VAR_IMMEDIATE; var->size = size; switch (size) { - case 1: - var->val = decode_byte(cpu, decode); - break; - case 2: - var->val = decode_word(cpu, decode); - break; - case 4: - var->val = decode_dword(cpu, decode); - break; - case 8: - var->val = decode_qword(cpu, decode); - break; - default: - VM_PANIC_EX("bad size %d\n", size); + case 1: + var->val = decode_byte(cpu, decode); + break; + case 2: + var->val = decode_word(cpu, decode); + break; + case 4: + var->val = decode_dword(cpu, decode); + break; + case 8: + var->val = decode_qword(cpu, decode); + break; + default: + VM_PANIC_EX("bad size %d\n", size); } } -static void decode_imm8(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +static void decode_imm8(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op) { decode_immediate(cpu, decode, op, 1); op->type = X86_VAR_IMMEDIATE; } -static void decode_imm8_signed(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +static void decode_imm8_signed(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op) { decode_immediate(cpu, decode, op, 1); op->val = sign(op->val, 1); op->type = X86_VAR_IMMEDIATE; } -static void decode_imm16(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +static void decode_imm16(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op) { decode_immediate(cpu, decode, op, 2); op->type = X86_VAR_IMMEDIATE; } -static void decode_imm(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +static void decode_imm(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op) { if (8 == decode->operand_size) { decode_immediate(cpu, decode, op, 4); @@ -171,20 +182,23 @@ static void decode_imm(CPUState *cpu, struct x86_decode *decode, struct x86_deco op->type = X86_VAR_IMMEDIATE; } -static void decode_imm_signed(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +static void decode_imm_signed(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op) { decode_immediate(cpu, decode, op, decode->operand_size); op->val = sign(op->val, decode->operand_size); op->type = X86_VAR_IMMEDIATE; } -static void decode_imm_1(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +static void decode_imm_1(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op) { op->type = X86_VAR_IMMEDIATE; op->val = 1; } -static void decode_imm_0(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +static void decode_imm_0(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op) { op->type = X86_VAR_IMMEDIATE; op->val = 0; @@ -194,54 +208,54 @@ static void decode_imm_0(CPUState *cpu, struct x86_decode *decode, struct x86_de static void decode_pushseg(CPUState *cpu, struct x86_decode *decode) { uint8_t op = (decode->opcode_len > 1) ? decode->opcode[1] : decode->opcode[0]; - + decode->op[0].type = X86_VAR_REG; switch (op) { - case 0xe: - decode->op[0].reg = REG_SEG_CS; - break; - case 0x16: - decode->op[0].reg = REG_SEG_SS; - break; - case 0x1e: - decode->op[0].reg = REG_SEG_DS; - break; - case 0x06: - decode->op[0].reg = REG_SEG_ES; - break; - case 0xa0: - decode->op[0].reg = REG_SEG_FS; - break; - case 0xa8: - decode->op[0].reg = REG_SEG_GS; - break; + case 0xe: + decode->op[0].reg = REG_SEG_CS; + break; + case 0x16: + decode->op[0].reg = REG_SEG_SS; + break; + case 0x1e: + decode->op[0].reg = REG_SEG_DS; + break; + case 0x06: + decode->op[0].reg = REG_SEG_ES; + break; + case 0xa0: + decode->op[0].reg = REG_SEG_FS; + break; + case 0xa8: + decode->op[0].reg = REG_SEG_GS; + break; } } static void decode_popseg(CPUState *cpu, struct x86_decode *decode) { uint8_t op = (decode->opcode_len > 1) ? decode->opcode[1] : decode->opcode[0]; - + decode->op[0].type = X86_VAR_REG; switch (op) { - case 0xf: - decode->op[0].reg = REG_SEG_CS; - break; - case 0x17: - decode->op[0].reg = REG_SEG_SS; - break; - case 0x1f: - decode->op[0].reg = REG_SEG_DS; - break; - case 0x07: - decode->op[0].reg = REG_SEG_ES; - break; - case 0xa1: - decode->op[0].reg = REG_SEG_FS; - break; - case 0xa9: - decode->op[0].reg = REG_SEG_GS; - break; + case 0xf: + decode->op[0].reg = REG_SEG_CS; + break; + case 0x17: + decode->op[0].reg = REG_SEG_SS; + break; + case 0x1f: + decode->op[0].reg = REG_SEG_DS; + break; + case 0x07: + decode->op[0].reg = REG_SEG_ES; + break; + case 0xa1: + decode->op[0].reg = REG_SEG_FS; + break; + case 0xa9: + decode->op[0].reg = REG_SEG_GS; + break; } } @@ -249,36 +263,41 @@ static void decode_incgroup(CPUState *cpu, struct x86_decode *decode) { decode->op[0].type = X86_VAR_REG; decode->op[0].reg = decode->opcode[0] - 0x40; - decode->op[0].ptr = get_reg_ref(cpu, decode->op[0].reg, decode->rex.b, decode->operand_size); + decode->op[0].ptr = get_reg_ref(cpu, decode->op[0].reg, decode->rex.b, + decode->operand_size); } static void decode_decgroup(CPUState *cpu, struct x86_decode *decode) { decode->op[0].type = X86_VAR_REG; decode->op[0].reg = decode->opcode[0] - 0x48; - decode->op[0].ptr = get_reg_ref(cpu, decode->op[0].reg, decode->rex.b, decode->operand_size); + decode->op[0].ptr = get_reg_ref(cpu, decode->op[0].reg, decode->rex.b, + decode->operand_size); } static void decode_incgroup2(CPUState *cpu, struct x86_decode *decode) { - if (!decode->modrm.reg) + if (!decode->modrm.reg) { decode->cmd = X86_DECODE_CMD_INC; - else if (1 == decode->modrm.reg) + } else if (1 == decode->modrm.reg) { decode->cmd = X86_DECODE_CMD_DEC; + } } static void decode_pushgroup(CPUState *cpu, struct x86_decode *decode) { decode->op[0].type = X86_VAR_REG; decode->op[0].reg = decode->opcode[0] - 0x50; - decode->op[0].ptr = get_reg_ref(cpu, decode->op[0].reg, decode->rex.b, decode->operand_size); + decode->op[0].ptr = get_reg_ref(cpu, decode->op[0].reg, decode->rex.b, + decode->operand_size); } static void decode_popgroup(CPUState *cpu, struct x86_decode *decode) { decode->op[0].type = X86_VAR_REG; decode->op[0].reg = decode->opcode[0] - 0x58; - decode->op[0].ptr = get_reg_ref(cpu, decode->op[0].reg, decode->rex.b, decode->operand_size); + decode->op[0].ptr = get_reg_ref(cpu, decode->op[0].reg, decode->rex.b, + decode->operand_size); } static void decode_jxx(CPUState *cpu, struct x86_decode *decode) @@ -340,18 +359,18 @@ static void decode_f7group(CPUState *cpu, struct x86_decode *decode) decode_modrm_rm(cpu, decode, &decode->op[0]); switch (decode->modrm.reg) { - case 0: - case 1: - decode_imm(cpu, decode, &decode->op[1]); - break; - case 2: - break; - case 3: - decode->op[1].type = X86_VAR_IMMEDIATE; - decode->op[1].val = 0; - break; - default: - break; + case 0: + case 1: + decode_imm(cpu, decode, &decode->op[1]); + break; + case 2: + break; + case 3: + decode->op[1].type = X86_VAR_IMMEDIATE; + decode->op[1].val = 0; + break; + default: + break; } } @@ -359,18 +378,21 @@ static void decode_xchgroup(CPUState *cpu, struct x86_decode *decode) { decode->op[0].type = X86_VAR_REG; decode->op[0].reg = decode->opcode[0] - 0x90; - decode->op[0].ptr = get_reg_ref(cpu, decode->op[0].reg, decode->rex.b, decode->operand_size); + decode->op[0].ptr = get_reg_ref(cpu, decode->op[0].reg, decode->rex.b, + decode->operand_size); } static void decode_movgroup(CPUState *cpu, struct x86_decode *decode) { decode->op[0].type = X86_VAR_REG; decode->op[0].reg = decode->opcode[0] - 0xb8; - decode->op[0].ptr = get_reg_ref(cpu, decode->op[0].reg, decode->rex.b, decode->operand_size); + decode->op[0].ptr = get_reg_ref(cpu, decode->op[0].reg, decode->rex.b, + decode->operand_size); decode_immediate(cpu, decode, &decode->op[1], decode->operand_size); } -static void fetch_moffs(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +static void fetch_moffs(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op) { op->type = X86_VAR_OFFSET; op->ptr = decode_bytes(cpu, decode, decode->addressing_size); @@ -380,11 +402,13 @@ static void decode_movgroup8(CPUState *cpu, struct x86_decode *decode) { decode->op[0].type = X86_VAR_REG; decode->op[0].reg = decode->opcode[0] - 0xb0; - decode->op[0].ptr = get_reg_ref(cpu, decode->op[0].reg, decode->rex.b, decode->operand_size); + decode->op[0].ptr = get_reg_ref(cpu, decode->op[0].reg, decode->rex.b, + decode->operand_size); decode_immediate(cpu, decode, &decode->op[1], decode->operand_size); } -static void decode_rcx(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +static void decode_rcx(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op) { op->type = X86_VAR_REG; op->reg = REG_RCX; @@ -396,10 +420,14 @@ struct decode_tbl { enum x86_decode_cmd cmd; uint8_t operand_size; bool is_modrm; - void (*decode_op1)(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op1); - void (*decode_op2)(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op2); - void (*decode_op3)(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op3); - void (*decode_op4)(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op4); + void (*decode_op1)(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op1); + void (*decode_op2)(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op2); + void (*decode_op3)(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op3); + void (*decode_op4)(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op4); void (*decode_postfix)(CPUState *cpu, struct x86_decode *decode); addr_t flags_mask; }; @@ -412,13 +440,16 @@ struct decode_x87_tbl { uint8_t operand_size; bool rev; bool pop; - void (*decode_op1)(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op1); - void (*decode_op2)(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op2); + void (*decode_op1)(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op1); + void (*decode_op2)(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op2); void (*decode_postfix)(CPUState *cpu, struct x86_decode *decode); addr_t flags_mask; }; -struct decode_tbl invl_inst = {0x0, 0, 0, false, NULL, NULL, NULL, NULL, decode_invalid}; +struct decode_tbl invl_inst = {0x0, 0, 0, false, NULL, NULL, NULL, NULL, + decode_invalid}; struct decode_tbl _decode_tbl1[255]; struct decode_tbl _decode_tbl2[255]; @@ -427,28 +458,35 @@ struct decode_x87_tbl _decode_tbl3[255]; static void decode_x87_ins(CPUState *cpu, struct x86_decode *decode) { struct decode_x87_tbl *decoder; - + decode->is_fpu = true; int mode = decode->modrm.mod == 3 ? 1 : 0; - int index = ((decode->opcode[0] & 0xf) << 4) | (mode << 3) | decode->modrm.reg; - + int index = ((decode->opcode[0] & 0xf) << 4) | (mode << 3) | + decode->modrm.reg; + decoder = &_decode_tbl3[index]; - + decode->cmd = decoder->cmd; - if (decoder->operand_size) + if (decoder->operand_size) { decode->operand_size = decoder->operand_size; + } decode->flags_mask = decoder->flags_mask; decode->fpop_stack = decoder->pop; decode->frev = decoder->rev; - - if (decoder->decode_op1) + + if (decoder->decode_op1) { decoder->decode_op1(cpu, decode, &decode->op[0]); - if (decoder->decode_op2) + } + if (decoder->decode_op2) { decoder->decode_op2(cpu, decode, &decode->op[1]); - if (decoder->decode_postfix) + } + if (decoder->decode_postfix) { decoder->decode_postfix(cpu, decode); - - VM_PANIC_ON_EX(!decode->cmd, "x87 opcode %x %x (%x %x) not decoded\n", decode->opcode[0], decode->modrm.modrm, decoder->modrm_reg, decoder->modrm_mod); + } + + VM_PANIC_ON_EX(!decode->cmd, "x87 opcode %x %x (%x %x) not decoded\n", + decode->opcode[0], decode->modrm.modrm, decoder->modrm_reg, + decoder->modrm_mod); } static void decode_ffgroup(CPUState *cpu, struct x86_decode *decode) @@ -465,8 +503,9 @@ static void decode_ffgroup(CPUState *cpu, struct x86_decode *decode) X86_DECODE_CMD_INVL }; decode->cmd = group[decode->modrm.reg]; - if (decode->modrm.reg > 2) + if (decode->modrm.reg > 2) { decode->flags_mask = 0; + } } static void decode_sldtgroup(CPUState *cpu, struct x86_decode *decode) @@ -482,7 +521,8 @@ static void decode_sldtgroup(CPUState *cpu, struct x86_decode *decode) X86_DECODE_CMD_INVL }; decode->cmd = group[decode->modrm.reg]; - printf("%llx: decode_sldtgroup: %d\n", cpu->hvf_x86->fetch_rip, decode->modrm.reg); + printf("%llx: decode_sldtgroup: %d\n", cpu->hvf_x86->fetch_rip, + decode->modrm.reg); } static void decode_lidtgroup(CPUState *cpu, struct x86_decode *decode) @@ -524,28 +564,34 @@ static void decode_x87_general(CPUState *cpu, struct x86_decode *decode) decode->is_fpu = true; } -static void decode_x87_modrm_floatp(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +static void decode_x87_modrm_floatp(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op) { op->type = X87_VAR_FLOATP; } -static void decode_x87_modrm_intp(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +static void decode_x87_modrm_intp(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op) { op->type = X87_VAR_INTP; } -static void decode_x87_modrm_bytep(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +static void decode_x87_modrm_bytep(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op) { op->type = X87_VAR_BYTEP; } -static void decode_x87_modrm_st0(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +static void decode_x87_modrm_st0(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op) { op->type = X87_VAR_REG; op->reg = 0; } -static void decode_decode_x87_modrm_st0(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +static void decode_decode_x87_modrm_st0(CPUState *cpu, + struct x86_decode *decode, + struct x86_decode_op *op) { op->type = X87_VAR_REG; op->reg = decode->modrm.modrm & 7; @@ -556,35 +602,35 @@ static void decode_aegroup(CPUState *cpu, struct x86_decode *decode) { decode->is_fpu = true; switch (decode->modrm.reg) { - case 0: - decode->cmd = X86_DECODE_CMD_FXSAVE; - decode_x87_modrm_bytep(cpu, decode, &decode->op[0]); - break; - case 1: - decode_x87_modrm_bytep(cpu, decode, &decode->op[0]); - decode->cmd = X86_DECODE_CMD_FXRSTOR; - break; - case 5: - if (decode->modrm.modrm == 0xe8) { - decode->cmd = X86_DECODE_CMD_LFENCE; - } else { - VM_PANIC("xrstor"); - } - break; - case 6: - VM_PANIC_ON(decode->modrm.modrm != 0xf0); - decode->cmd = X86_DECODE_CMD_MFENCE; - break; - case 7: - if (decode->modrm.modrm == 0xf8) { - decode->cmd = X86_DECODE_CMD_SFENCE; - } else { - decode->cmd = X86_DECODE_CMD_CLFLUSH; - } - break; - default: - VM_PANIC_ON_EX(1, "0xae: reg %d\n", decode->modrm.reg); - break; + case 0: + decode->cmd = X86_DECODE_CMD_FXSAVE; + decode_x87_modrm_bytep(cpu, decode, &decode->op[0]); + break; + case 1: + decode_x87_modrm_bytep(cpu, decode, &decode->op[0]); + decode->cmd = X86_DECODE_CMD_FXRSTOR; + break; + case 5: + if (decode->modrm.modrm == 0xe8) { + decode->cmd = X86_DECODE_CMD_LFENCE; + } else { + VM_PANIC("xrstor"); + } + break; + case 6: + VM_PANIC_ON(decode->modrm.modrm != 0xf0); + decode->cmd = X86_DECODE_CMD_MFENCE; + break; + case 7: + if (decode->modrm.modrm == 0xf8) { + decode->cmd = X86_DECODE_CMD_SFENCE; + } else { + decode->cmd = X86_DECODE_CMD_CLFLUSH; + } + break; + default: + VM_PANIC_ON_EX(1, "0xae: reg %d\n", decode->modrm.reg); + break; } } @@ -592,568 +638,1003 @@ static void decode_bswap(CPUState *cpu, struct x86_decode *decode) { decode->op[0].type = X86_VAR_REG; decode->op[0].reg = decode->opcode[1] - 0xc8; - decode->op[0].ptr = get_reg_ref(cpu, decode->op[0].reg, decode->rex.b, decode->operand_size); + decode->op[0].ptr = get_reg_ref(cpu, decode->op[0].reg, decode->rex.b, + decode->operand_size); } static void decode_d9_4(CPUState *cpu, struct x86_decode *decode) { - switch(decode->modrm.modrm) { - case 0xe0: - // FCHS - decode->cmd = X86_DECODE_CMD_FCHS; - break; - case 0xe1: - decode->cmd = X86_DECODE_CMD_FABS; - break; - case 0xe4: - VM_PANIC_ON_EX(1, "FTST"); - break; - case 0xe5: - // FXAM - decode->cmd = X86_DECODE_CMD_FXAM; - break; - default: - VM_PANIC_ON_EX(1, "FLDENV"); - break; + switch (decode->modrm.modrm) { + case 0xe0: + /* FCHS */ + decode->cmd = X86_DECODE_CMD_FCHS; + break; + case 0xe1: + decode->cmd = X86_DECODE_CMD_FABS; + break; + case 0xe4: + VM_PANIC_ON_EX(1, "FTST"); + break; + case 0xe5: + /* FXAM */ + decode->cmd = X86_DECODE_CMD_FXAM; + break; + default: + VM_PANIC_ON_EX(1, "FLDENV"); + break; } } static void decode_db_4(CPUState *cpu, struct x86_decode *decode) { switch (decode->modrm.modrm) { - case 0xe0: - VM_PANIC_ON_EX(1, "unhandled FNENI: %x %x\n", decode->opcode[0], decode->modrm.modrm); - break; - case 0xe1: - VM_PANIC_ON_EX(1, "unhandled FNDISI: %x %x\n", decode->opcode[0], decode->modrm.modrm); - break; - case 0xe2: - VM_PANIC_ON_EX(1, "unhandled FCLEX: %x %x\n", decode->opcode[0], decode->modrm.modrm); - break; - case 0xe3: - decode->cmd = X86_DECODE_CMD_FNINIT; - break; - case 0xe4: - decode->cmd = X86_DECODE_CMD_FNSETPM; - break; - default: - VM_PANIC_ON_EX(1, "unhandled fpu opcode: %x %x\n", decode->opcode[0], decode->modrm.modrm); - break; + case 0xe0: + VM_PANIC_ON_EX(1, "unhandled FNENI: %x %x\n", decode->opcode[0], + decode->modrm.modrm); + break; + case 0xe1: + VM_PANIC_ON_EX(1, "unhandled FNDISI: %x %x\n", decode->opcode[0], + decode->modrm.modrm); + break; + case 0xe2: + VM_PANIC_ON_EX(1, "unhandled FCLEX: %x %x\n", decode->opcode[0], + decode->modrm.modrm); + break; + case 0xe3: + decode->cmd = X86_DECODE_CMD_FNINIT; + break; + case 0xe4: + decode->cmd = X86_DECODE_CMD_FNSETPM; + break; + default: + VM_PANIC_ON_EX(1, "unhandled fpu opcode: %x %x\n", decode->opcode[0], + decode->modrm.modrm); + break; } } #define RFLAGS_MASK_NONE 0 -#define RFLAGS_MASK_OSZAPC (RFLAGS_OF | RFLAGS_SF | RFLAGS_ZF | RFLAGS_AF | RFLAGS_PF | RFLAGS_CF) -#define RFLAGS_MASK_LAHF (RFLAGS_SF | RFLAGS_ZF | RFLAGS_AF | RFLAGS_PF | RFLAGS_CF) +#define RFLAGS_MASK_OSZAPC (RFLAGS_OF | RFLAGS_SF | RFLAGS_ZF | RFLAGS_AF | \ + RFLAGS_PF | RFLAGS_CF) +#define RFLAGS_MASK_LAHF (RFLAGS_SF | RFLAGS_ZF | RFLAGS_AF | RFLAGS_PF | \ + RFLAGS_CF) #define RFLAGS_MASK_CF (RFLAGS_CF) #define RFLAGS_MASK_IF (RFLAGS_IF) #define RFLAGS_MASK_TF (RFLAGS_TF) #define RFLAGS_MASK_DF (RFLAGS_DF) #define RFLAGS_MASK_ZF (RFLAGS_ZF) -struct decode_tbl _1op_inst[] = -{ - {0x0, X86_DECODE_CMD_ADD, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x1, X86_DECODE_CMD_ADD, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x2, X86_DECODE_CMD_ADD, 1, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x3, X86_DECODE_CMD_ADD, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x4, X86_DECODE_CMD_ADD, 1, false, decode_rax, decode_imm8, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x5, X86_DECODE_CMD_ADD, 0, false, decode_rax, decode_imm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x6, X86_DECODE_CMD_PUSH_SEG, 0, false, false, NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, - {0x7, X86_DECODE_CMD_POP_SEG, 0, false, false, NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, - {0x8, X86_DECODE_CMD_OR, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x9, X86_DECODE_CMD_OR, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xa, X86_DECODE_CMD_OR, 1, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xb, X86_DECODE_CMD_OR, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xc, X86_DECODE_CMD_OR, 1, false, decode_rax, decode_imm8, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xd, X86_DECODE_CMD_OR, 0, false, decode_rax, decode_imm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0xe, X86_DECODE_CMD_PUSH_SEG, 0, false, false, NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, - {0xf, X86_DECODE_CMD_POP_SEG, 0, false, false, NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, - - {0x10, X86_DECODE_CMD_ADC, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x11, X86_DECODE_CMD_ADC, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x12, X86_DECODE_CMD_ADC, 1, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x13, X86_DECODE_CMD_ADC, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x14, X86_DECODE_CMD_ADC, 1, false, decode_rax, decode_imm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x15, X86_DECODE_CMD_ADC, 0, false, decode_rax, decode_imm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0x16, X86_DECODE_CMD_PUSH_SEG, 0, false, false, NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, - {0x17, X86_DECODE_CMD_POP_SEG, 0, false, false, NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, - - {0x18, X86_DECODE_CMD_SBB, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x19, X86_DECODE_CMD_SBB, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x1a, X86_DECODE_CMD_SBB, 1, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x1b, X86_DECODE_CMD_SBB, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x1c, X86_DECODE_CMD_SBB, 1, false, decode_rax, decode_imm8, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x1d, X86_DECODE_CMD_SBB, 0, false, decode_rax, decode_imm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0x1e, X86_DECODE_CMD_PUSH_SEG, 0, false, false, NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, - {0x1f, X86_DECODE_CMD_POP_SEG, 0, false, false, NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, - - {0x20, X86_DECODE_CMD_AND, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x21, X86_DECODE_CMD_AND, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x22, X86_DECODE_CMD_AND, 1, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x23, X86_DECODE_CMD_AND, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x24, X86_DECODE_CMD_AND, 1, false, decode_rax, decode_imm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x25, X86_DECODE_CMD_AND, 0, false, decode_rax, decode_imm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x28, X86_DECODE_CMD_SUB, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x29, X86_DECODE_CMD_SUB, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x2a, X86_DECODE_CMD_SUB, 1, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x2b, X86_DECODE_CMD_SUB, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x2c, X86_DECODE_CMD_SUB, 1, false, decode_rax, decode_imm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x2d, X86_DECODE_CMD_SUB, 0, false, decode_rax, decode_imm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x2f, X86_DECODE_CMD_DAS, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x30, X86_DECODE_CMD_XOR, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x31, X86_DECODE_CMD_XOR, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x32, X86_DECODE_CMD_XOR, 1, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x33, X86_DECODE_CMD_XOR, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x34, X86_DECODE_CMD_XOR, 1, false, decode_rax, decode_imm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x35, X86_DECODE_CMD_XOR, 0, false, decode_rax, decode_imm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0x38, X86_DECODE_CMD_CMP, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x39, X86_DECODE_CMD_CMP, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x3a, X86_DECODE_CMD_CMP, 1, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x3b, X86_DECODE_CMD_CMP, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x3c, X86_DECODE_CMD_CMP, 1, false, decode_rax, decode_imm8, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x3d, X86_DECODE_CMD_CMP, 0, false, decode_rax, decode_imm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0x3f, X86_DECODE_CMD_AAS, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0x40, X86_DECODE_CMD_INC, 0, false, NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, - {0x41, X86_DECODE_CMD_INC, 0, false, NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, - {0x42, X86_DECODE_CMD_INC, 0, false, NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, - {0x43, X86_DECODE_CMD_INC, 0, false, NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, - {0x44, X86_DECODE_CMD_INC, 0, false, NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, - {0x45, X86_DECODE_CMD_INC, 0, false, NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, - {0x46, X86_DECODE_CMD_INC, 0, false, NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, - {0x47, X86_DECODE_CMD_INC, 0, false, NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, - - {0x48, X86_DECODE_CMD_DEC, 0, false, NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, - {0x49, X86_DECODE_CMD_DEC, 0, false, NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, - {0x4a, X86_DECODE_CMD_DEC, 0, false, NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, - {0x4b, X86_DECODE_CMD_DEC, 0, false, NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, - {0x4c, X86_DECODE_CMD_DEC, 0, false, NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, - {0x4d, X86_DECODE_CMD_DEC, 0, false, NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, - {0x4e, X86_DECODE_CMD_DEC, 0, false, NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, - {0x4f, X86_DECODE_CMD_DEC, 0, false, NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, - - {0x50, X86_DECODE_CMD_PUSH, 0, false, NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, - {0x51, X86_DECODE_CMD_PUSH, 0, false, NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, - {0x52, X86_DECODE_CMD_PUSH, 0, false, NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, - {0x53, X86_DECODE_CMD_PUSH, 0, false, NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, - {0x54, X86_DECODE_CMD_PUSH, 0, false, NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, - {0x55, X86_DECODE_CMD_PUSH, 0, false, NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, - {0x56, X86_DECODE_CMD_PUSH, 0, false, NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, - {0x57, X86_DECODE_CMD_PUSH, 0, false, NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, - - {0x58, X86_DECODE_CMD_POP, 0, false, NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, - {0x59, X86_DECODE_CMD_POP, 0, false, NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, - {0x5a, X86_DECODE_CMD_POP, 0, false, NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, - {0x5b, X86_DECODE_CMD_POP, 0, false, NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, - {0x5c, X86_DECODE_CMD_POP, 0, false, NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, - {0x5d, X86_DECODE_CMD_POP, 0, false, NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, - {0x5e, X86_DECODE_CMD_POP, 0, false, NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, - {0x5f, X86_DECODE_CMD_POP, 0, false, NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, - - {0x60, X86_DECODE_CMD_PUSHA, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x61, X86_DECODE_CMD_POPA, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0x68, X86_DECODE_CMD_PUSH, 0, false, decode_imm, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x6a, X86_DECODE_CMD_PUSH, 0, false, decode_imm8_signed, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x69, X86_DECODE_CMD_IMUL_3, 0, true, decode_modrm_reg, decode_modrm_rm, decode_imm, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x6b, X86_DECODE_CMD_IMUL_3, 0, true, decode_modrm_reg, decode_modrm_rm, decode_imm8_signed, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0x6c, X86_DECODE_CMD_INS, 1, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x6d, X86_DECODE_CMD_INS, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x6e, X86_DECODE_CMD_OUTS, 1, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x6f, X86_DECODE_CMD_OUTS, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0x70, X86_DECODE_CMD_JXX, 1, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x71, X86_DECODE_CMD_JXX, 1, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x72, X86_DECODE_CMD_JXX, 1, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x73, X86_DECODE_CMD_JXX, 1, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x74, X86_DECODE_CMD_JXX, 1, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x75, X86_DECODE_CMD_JXX, 1, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x76, X86_DECODE_CMD_JXX, 1, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x77, X86_DECODE_CMD_JXX, 1, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x78, X86_DECODE_CMD_JXX, 1, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x79, X86_DECODE_CMD_JXX, 1, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x7a, X86_DECODE_CMD_JXX, 1, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x7b, X86_DECODE_CMD_JXX, 1, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x7c, X86_DECODE_CMD_JXX, 1, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x7d, X86_DECODE_CMD_JXX, 1, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x7e, X86_DECODE_CMD_JXX, 1, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x7f, X86_DECODE_CMD_JXX, 1, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - - {0x80, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8, NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC}, - {0x81, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm, NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC}, - {0x82, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8, NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC}, - {0x83, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8_signed, NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC}, - {0x84, X86_DECODE_CMD_TST, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x85, X86_DECODE_CMD_TST, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x86, X86_DECODE_CMD_XCHG, 1, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x87, X86_DECODE_CMD_XCHG, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x88, X86_DECODE_CMD_MOV, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x89, X86_DECODE_CMD_MOV, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x8a, X86_DECODE_CMD_MOV, 1, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x8b, X86_DECODE_CMD_MOV, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x8c, X86_DECODE_CMD_MOV_FROM_SEG, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x8d, X86_DECODE_CMD_LEA, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x8e, X86_DECODE_CMD_MOV_TO_SEG, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x8f, X86_DECODE_CMD_POP, 0, true, decode_modrm_rm, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0x90, X86_DECODE_CMD_NOP, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x91, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, - {0x92, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, - {0x93, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, - {0x94, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, - {0x95, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, - {0x96, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, - {0x97, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, - - {0x98, X86_DECODE_CMD_CBW, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x99, X86_DECODE_CMD_CWD, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0x9a, X86_DECODE_CMD_CALL_FAR, 0, false, NULL, NULL, NULL, NULL, decode_farjmp, RFLAGS_MASK_NONE}, - - {0x9c, X86_DECODE_CMD_PUSHF, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - //{0x9d, X86_DECODE_CMD_POPF, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_POPF}, - {0x9e, X86_DECODE_CMD_SAHF, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x9f, X86_DECODE_CMD_LAHF, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_LAHF}, - - {0xa0, X86_DECODE_CMD_MOV, 1, false, decode_rax, fetch_moffs, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xa1, X86_DECODE_CMD_MOV, 0, false, decode_rax, fetch_moffs, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xa2, X86_DECODE_CMD_MOV, 1, false, fetch_moffs, decode_rax, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xa3, X86_DECODE_CMD_MOV, 0, false, fetch_moffs, decode_rax, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xa4, X86_DECODE_CMD_MOVS, 1, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xa5, X86_DECODE_CMD_MOVS, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xa6, X86_DECODE_CMD_CMPS, 1, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xa7, X86_DECODE_CMD_CMPS, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xaa, X86_DECODE_CMD_STOS, 1, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xab, X86_DECODE_CMD_STOS, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xac, X86_DECODE_CMD_LODS, 1, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xad, X86_DECODE_CMD_LODS, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xae, X86_DECODE_CMD_SCAS, 1, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xaf, X86_DECODE_CMD_SCAS, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0xa8, X86_DECODE_CMD_TST, 1, false, decode_rax, decode_imm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xa9, X86_DECODE_CMD_TST, 0, false, decode_rax, decode_imm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0xb0, X86_DECODE_CMD_MOV, 1, false, NULL, NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, - {0xb1, X86_DECODE_CMD_MOV, 1, false, NULL, NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, - {0xb2, X86_DECODE_CMD_MOV, 1, false, NULL, NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, - {0xb3, X86_DECODE_CMD_MOV, 1, false, NULL, NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, - {0xb4, X86_DECODE_CMD_MOV, 1, false, NULL, NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, - {0xb5, X86_DECODE_CMD_MOV, 1, false, NULL, NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, - {0xb6, X86_DECODE_CMD_MOV, 1, false, NULL, NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, - {0xb7, X86_DECODE_CMD_MOV, 1, false, NULL, NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, - - {0xb8, X86_DECODE_CMD_MOV, 0, false, NULL, NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, - {0xb9, X86_DECODE_CMD_MOV, 0, false, NULL, NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, - {0xba, X86_DECODE_CMD_MOV, 0, false, NULL, NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, - {0xbb, X86_DECODE_CMD_MOV, 0, false, NULL, NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, - {0xbc, X86_DECODE_CMD_MOV, 0, false, NULL, NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, - {0xbd, X86_DECODE_CMD_MOV, 0, false, NULL, NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, - {0xbe, X86_DECODE_CMD_MOV, 0, false, NULL, NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, - {0xbf, X86_DECODE_CMD_MOV, 0, false, NULL, NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, - - {0xc0, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8, NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, - {0xc1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8, NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, - - {0xc2, X86_DECODE_RET_NEAR, 0, false, decode_imm16, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xc3, X86_DECODE_RET_NEAR, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xc4, X86_DECODE_CMD_LES, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xc5, X86_DECODE_CMD_LDS, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xc6, X86_DECODE_CMD_MOV, 1, true, decode_modrm_rm, decode_imm8, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xc7, X86_DECODE_CMD_MOV, 0, true, decode_modrm_rm, decode_imm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xc8, X86_DECODE_CMD_ENTER, 0, false, decode_imm16, decode_imm8, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xc9, X86_DECODE_CMD_LEAVE, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xca, X86_DECODE_RET_FAR, 0, false, decode_imm16, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xcb, X86_DECODE_RET_FAR, 0, false, decode_imm_0, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xcd, X86_DECODE_CMD_INT, 0, false, decode_imm8, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - //{0xcf, X86_DECODE_CMD_IRET, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_IRET}, - - {0xd0, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm_1, NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, - {0xd1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm_1, NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, - {0xd2, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_rcx, NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, - {0xd3, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_rcx, NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, - - {0xd4, X86_DECODE_CMD_AAM, 0, false, decode_imm8, NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xd5, X86_DECODE_CMD_AAD, 0, false, decode_imm8, NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0xd7, X86_DECODE_CMD_XLAT, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xd8, X86_DECODE_CMD_INVL, 0, true, NULL, NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, - {0xd9, X86_DECODE_CMD_INVL, 0, true, NULL, NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, - {0xda, X86_DECODE_CMD_INVL, 0, true, NULL, NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, - {0xdb, X86_DECODE_CMD_INVL, 0, true, NULL, NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, - {0xdc, X86_DECODE_CMD_INVL, 0, true, NULL, NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, - {0xdd, X86_DECODE_CMD_INVL, 0, true, NULL, NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, - {0xde, X86_DECODE_CMD_INVL, 0, true, NULL, NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, - {0xdf, X86_DECODE_CMD_INVL, 0, true, NULL, NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, - - {0xe0, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xe1, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xe2, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xe3, X86_DECODE_CMD_JCXZ, 1, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - - {0xe4, X86_DECODE_CMD_IN, 1, false, decode_imm8, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xe5, X86_DECODE_CMD_IN, 0, false, decode_imm8, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xe6, X86_DECODE_CMD_OUT, 1, false, decode_imm8, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xe7, X86_DECODE_CMD_OUT, 0, false, decode_imm8, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xe8, X86_DECODE_CMD_CALL_NEAR, 0, false, decode_imm_signed, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xe9, X86_DECODE_CMD_JMP_NEAR, 0, false, decode_imm_signed, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xea, X86_DECODE_CMD_JMP_FAR, 0, false, NULL, NULL, NULL, NULL, decode_farjmp, RFLAGS_MASK_NONE}, - {0xeb, X86_DECODE_CMD_JMP_NEAR, 1, false, decode_imm8_signed, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xec, X86_DECODE_CMD_IN, 1, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xed, X86_DECODE_CMD_IN, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xee, X86_DECODE_CMD_OUT, 1, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xef, X86_DECODE_CMD_OUT, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xf4, X86_DECODE_CMD_HLT, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xf5, X86_DECODE_CMD_CMC, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF}, - - {0xf6, X86_DECODE_CMD_INVL, 1, true, NULL, NULL, NULL, NULL, decode_f7group, RFLAGS_MASK_OSZAPC}, - {0xf7, X86_DECODE_CMD_INVL, 0, true, NULL, NULL, NULL, NULL, decode_f7group, RFLAGS_MASK_OSZAPC}, - - {0xf8, X86_DECODE_CMD_CLC, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF}, - {0xf9, X86_DECODE_CMD_STC, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF}, - - {0xfa, X86_DECODE_CMD_CLI, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_IF}, - {0xfb, X86_DECODE_CMD_STI, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_IF}, - {0xfc, X86_DECODE_CMD_CLD, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_DF}, - {0xfd, X86_DECODE_CMD_STD, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_DF}, - {0xfe, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, NULL, NULL, NULL, decode_incgroup2, RFLAGS_MASK_OSZAPC}, - {0xff, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, NULL, NULL, NULL, decode_ffgroup, RFLAGS_MASK_OSZAPC}, +struct decode_tbl _1op_inst[] = { + {0x0, X86_DECODE_CMD_ADD, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, + NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x1, X86_DECODE_CMD_ADD, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, + NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x2, X86_DECODE_CMD_ADD, 1, true, decode_modrm_reg, decode_modrm_rm, NULL, + NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x3, X86_DECODE_CMD_ADD, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, + NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x4, X86_DECODE_CMD_ADD, 1, false, decode_rax, decode_imm8, NULL, NULL, + NULL, RFLAGS_MASK_OSZAPC}, + {0x5, X86_DECODE_CMD_ADD, 0, false, decode_rax, decode_imm, NULL, NULL, + NULL, RFLAGS_MASK_OSZAPC}, + {0x6, X86_DECODE_CMD_PUSH_SEG, 0, false, false, NULL, NULL, NULL, + decode_pushseg, RFLAGS_MASK_NONE}, + {0x7, X86_DECODE_CMD_POP_SEG, 0, false, false, NULL, NULL, NULL, + decode_popseg, RFLAGS_MASK_NONE}, + {0x8, X86_DECODE_CMD_OR, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, + NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x9, X86_DECODE_CMD_OR, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, + NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xa, X86_DECODE_CMD_OR, 1, true, decode_modrm_reg, decode_modrm_rm, NULL, + NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xb, X86_DECODE_CMD_OR, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xc, X86_DECODE_CMD_OR, 1, false, decode_rax, decode_imm8, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xd, X86_DECODE_CMD_OR, 0, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0xe, X86_DECODE_CMD_PUSH_SEG, 0, false, false, + NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, + {0xf, X86_DECODE_CMD_POP_SEG, 0, false, false, + NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, + + {0x10, X86_DECODE_CMD_ADC, 1, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x11, X86_DECODE_CMD_ADC, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x12, X86_DECODE_CMD_ADC, 1, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x13, X86_DECODE_CMD_ADC, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x14, X86_DECODE_CMD_ADC, 1, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x15, X86_DECODE_CMD_ADC, 0, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0x16, X86_DECODE_CMD_PUSH_SEG, 0, false, false, + NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, + {0x17, X86_DECODE_CMD_POP_SEG, 0, false, false, + NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, + + {0x18, X86_DECODE_CMD_SBB, 1, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x19, X86_DECODE_CMD_SBB, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x1a, X86_DECODE_CMD_SBB, 1, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x1b, X86_DECODE_CMD_SBB, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x1c, X86_DECODE_CMD_SBB, 1, false, decode_rax, decode_imm8, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x1d, X86_DECODE_CMD_SBB, 0, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0x1e, X86_DECODE_CMD_PUSH_SEG, 0, false, false, + NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, + {0x1f, X86_DECODE_CMD_POP_SEG, 0, false, false, + NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, + + {0x20, X86_DECODE_CMD_AND, 1, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x21, X86_DECODE_CMD_AND, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x22, X86_DECODE_CMD_AND, 1, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x23, X86_DECODE_CMD_AND, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x24, X86_DECODE_CMD_AND, 1, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x25, X86_DECODE_CMD_AND, 0, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x28, X86_DECODE_CMD_SUB, 1, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x29, X86_DECODE_CMD_SUB, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x2a, X86_DECODE_CMD_SUB, 1, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x2b, X86_DECODE_CMD_SUB, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x2c, X86_DECODE_CMD_SUB, 1, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x2d, X86_DECODE_CMD_SUB, 0, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x2f, X86_DECODE_CMD_DAS, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x30, X86_DECODE_CMD_XOR, 1, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x31, X86_DECODE_CMD_XOR, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x32, X86_DECODE_CMD_XOR, 1, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x33, X86_DECODE_CMD_XOR, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x34, X86_DECODE_CMD_XOR, 1, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x35, X86_DECODE_CMD_XOR, 0, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0x38, X86_DECODE_CMD_CMP, 1, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x39, X86_DECODE_CMD_CMP, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x3a, X86_DECODE_CMD_CMP, 1, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x3b, X86_DECODE_CMD_CMP, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x3c, X86_DECODE_CMD_CMP, 1, false, decode_rax, decode_imm8, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x3d, X86_DECODE_CMD_CMP, 0, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0x3f, X86_DECODE_CMD_AAS, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0x40, X86_DECODE_CMD_INC, 0, false, + NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + {0x41, X86_DECODE_CMD_INC, 0, false, + NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + {0x42, X86_DECODE_CMD_INC, 0, false, + NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + {0x43, X86_DECODE_CMD_INC, 0, false, + NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + {0x44, X86_DECODE_CMD_INC, 0, false, + NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + {0x45, X86_DECODE_CMD_INC, 0, false, + NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + {0x46, X86_DECODE_CMD_INC, 0, false, + NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + {0x47, X86_DECODE_CMD_INC, 0, false, + NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + + {0x48, X86_DECODE_CMD_DEC, 0, false, + NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + {0x49, X86_DECODE_CMD_DEC, 0, false, + NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + {0x4a, X86_DECODE_CMD_DEC, 0, false, + NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + {0x4b, X86_DECODE_CMD_DEC, 0, false, + NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + {0x4c, X86_DECODE_CMD_DEC, 0, false, + NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + {0x4d, X86_DECODE_CMD_DEC, 0, false, + NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + {0x4e, X86_DECODE_CMD_DEC, 0, false, + NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + {0x4f, X86_DECODE_CMD_DEC, 0, false, + NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + + {0x50, X86_DECODE_CMD_PUSH, 0, false, + NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + {0x51, X86_DECODE_CMD_PUSH, 0, false, + NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + {0x52, X86_DECODE_CMD_PUSH, 0, false, + NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + {0x53, X86_DECODE_CMD_PUSH, 0, false, + NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + {0x54, X86_DECODE_CMD_PUSH, 0, false, + NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + {0x55, X86_DECODE_CMD_PUSH, 0, false, + NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + {0x56, X86_DECODE_CMD_PUSH, 0, false, + NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + {0x57, X86_DECODE_CMD_PUSH, 0, false, + NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + + {0x58, X86_DECODE_CMD_POP, 0, false, + NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + {0x59, X86_DECODE_CMD_POP, 0, false, + NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + {0x5a, X86_DECODE_CMD_POP, 0, false, + NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + {0x5b, X86_DECODE_CMD_POP, 0, false, + NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + {0x5c, X86_DECODE_CMD_POP, 0, false, + NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + {0x5d, X86_DECODE_CMD_POP, 0, false, + NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + {0x5e, X86_DECODE_CMD_POP, 0, false, + NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + {0x5f, X86_DECODE_CMD_POP, 0, false, + NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + + {0x60, X86_DECODE_CMD_PUSHA, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x61, X86_DECODE_CMD_POPA, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0x68, X86_DECODE_CMD_PUSH, 0, false, decode_imm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x6a, X86_DECODE_CMD_PUSH, 0, false, decode_imm8_signed, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x69, X86_DECODE_CMD_IMUL_3, 0, true, decode_modrm_reg, + decode_modrm_rm, decode_imm, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x6b, X86_DECODE_CMD_IMUL_3, 0, true, decode_modrm_reg, decode_modrm_rm, + decode_imm8_signed, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0x6c, X86_DECODE_CMD_INS, 1, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x6d, X86_DECODE_CMD_INS, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x6e, X86_DECODE_CMD_OUTS, 1, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x6f, X86_DECODE_CMD_OUTS, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0x70, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x71, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x72, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x73, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x74, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x75, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x76, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x77, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x78, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x79, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x7a, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x7b, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x7c, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x7d, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x7e, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x7f, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + + {0x80, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8, + NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC}, + {0x81, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm, + NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC}, + {0x82, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8, + NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC}, + {0x83, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8_signed, + NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC}, + {0x84, X86_DECODE_CMD_TST, 1, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x85, X86_DECODE_CMD_TST, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x86, X86_DECODE_CMD_XCHG, 1, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x87, X86_DECODE_CMD_XCHG, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x88, X86_DECODE_CMD_MOV, 1, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x89, X86_DECODE_CMD_MOV, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x8a, X86_DECODE_CMD_MOV, 1, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x8b, X86_DECODE_CMD_MOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x8c, X86_DECODE_CMD_MOV_FROM_SEG, 0, true, decode_modrm_rm, + decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x8d, X86_DECODE_CMD_LEA, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x8e, X86_DECODE_CMD_MOV_TO_SEG, 0, true, decode_modrm_reg, + decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x8f, X86_DECODE_CMD_POP, 0, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0x90, X86_DECODE_CMD_NOP, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x91, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, + NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + {0x92, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, + NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + {0x93, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, + NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + {0x94, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, + NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + {0x95, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, + NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + {0x96, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, + NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + {0x97, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, + NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + + {0x98, X86_DECODE_CMD_CBW, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x99, X86_DECODE_CMD_CWD, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0x9a, X86_DECODE_CMD_CALL_FAR, 0, false, NULL, + NULL, NULL, NULL, decode_farjmp, RFLAGS_MASK_NONE}, + + {0x9c, X86_DECODE_CMD_PUSHF, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + /*{0x9d, X86_DECODE_CMD_POPF, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_POPF},*/ + {0x9e, X86_DECODE_CMD_SAHF, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x9f, X86_DECODE_CMD_LAHF, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_LAHF}, + + {0xa0, X86_DECODE_CMD_MOV, 1, false, decode_rax, fetch_moffs, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xa1, X86_DECODE_CMD_MOV, 0, false, decode_rax, fetch_moffs, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xa2, X86_DECODE_CMD_MOV, 1, false, fetch_moffs, decode_rax, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xa3, X86_DECODE_CMD_MOV, 0, false, fetch_moffs, decode_rax, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xa4, X86_DECODE_CMD_MOVS, 1, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xa5, X86_DECODE_CMD_MOVS, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xa6, X86_DECODE_CMD_CMPS, 1, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xa7, X86_DECODE_CMD_CMPS, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xaa, X86_DECODE_CMD_STOS, 1, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xab, X86_DECODE_CMD_STOS, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xac, X86_DECODE_CMD_LODS, 1, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xad, X86_DECODE_CMD_LODS, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xae, X86_DECODE_CMD_SCAS, 1, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xaf, X86_DECODE_CMD_SCAS, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0xa8, X86_DECODE_CMD_TST, 1, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xa9, X86_DECODE_CMD_TST, 0, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0xb0, X86_DECODE_CMD_MOV, 1, false, NULL, + NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + {0xb1, X86_DECODE_CMD_MOV, 1, false, NULL, + NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + {0xb2, X86_DECODE_CMD_MOV, 1, false, NULL, + NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + {0xb3, X86_DECODE_CMD_MOV, 1, false, NULL, + NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + {0xb4, X86_DECODE_CMD_MOV, 1, false, NULL, + NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + {0xb5, X86_DECODE_CMD_MOV, 1, false, NULL, + NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + {0xb6, X86_DECODE_CMD_MOV, 1, false, NULL, + NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + {0xb7, X86_DECODE_CMD_MOV, 1, false, NULL, + NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + + {0xb8, X86_DECODE_CMD_MOV, 0, false, NULL, + NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + {0xb9, X86_DECODE_CMD_MOV, 0, false, NULL, + NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + {0xba, X86_DECODE_CMD_MOV, 0, false, NULL, + NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + {0xbb, X86_DECODE_CMD_MOV, 0, false, NULL, + NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + {0xbc, X86_DECODE_CMD_MOV, 0, false, NULL, + NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + {0xbd, X86_DECODE_CMD_MOV, 0, false, NULL, + NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + {0xbe, X86_DECODE_CMD_MOV, 0, false, NULL, + NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + {0xbf, X86_DECODE_CMD_MOV, 0, false, NULL, + NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + + {0xc0, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8, + NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, + {0xc1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8, + NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, + + {0xc2, X86_DECODE_RET_NEAR, 0, false, decode_imm16, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xc3, X86_DECODE_RET_NEAR, 0, false, NULL, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xc4, X86_DECODE_CMD_LES, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xc5, X86_DECODE_CMD_LDS, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xc6, X86_DECODE_CMD_MOV, 1, true, decode_modrm_rm, decode_imm8, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xc7, X86_DECODE_CMD_MOV, 0, true, decode_modrm_rm, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xc8, X86_DECODE_CMD_ENTER, 0, false, decode_imm16, decode_imm8, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xc9, X86_DECODE_CMD_LEAVE, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xca, X86_DECODE_RET_FAR, 0, false, decode_imm16, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xcb, X86_DECODE_RET_FAR, 0, false, decode_imm_0, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xcd, X86_DECODE_CMD_INT, 0, false, decode_imm8, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + /*{0xcf, X86_DECODE_CMD_IRET, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_IRET},*/ + + {0xd0, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm_1, + NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, + {0xd1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm_1, + NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, + {0xd2, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_rcx, + NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, + {0xd3, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_rcx, + NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, + + {0xd4, X86_DECODE_CMD_AAM, 0, false, decode_imm8, + NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xd5, X86_DECODE_CMD_AAD, 0, false, decode_imm8, + NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0xd7, X86_DECODE_CMD_XLAT, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xd8, X86_DECODE_CMD_INVL, 0, true, NULL, + NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + {0xd9, X86_DECODE_CMD_INVL, 0, true, NULL, + NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + {0xda, X86_DECODE_CMD_INVL, 0, true, NULL, + NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + {0xdb, X86_DECODE_CMD_INVL, 0, true, NULL, + NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + {0xdc, X86_DECODE_CMD_INVL, 0, true, NULL, + NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + {0xdd, X86_DECODE_CMD_INVL, 0, true, NULL, + NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + {0xde, X86_DECODE_CMD_INVL, 0, true, NULL, + NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + {0xdf, X86_DECODE_CMD_INVL, 0, true, NULL, + NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + + {0xe0, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xe1, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xe2, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xe3, X86_DECODE_CMD_JCXZ, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + + {0xe4, X86_DECODE_CMD_IN, 1, false, decode_imm8, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xe5, X86_DECODE_CMD_IN, 0, false, decode_imm8, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xe6, X86_DECODE_CMD_OUT, 1, false, decode_imm8, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xe7, X86_DECODE_CMD_OUT, 0, false, decode_imm8, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xe8, X86_DECODE_CMD_CALL_NEAR, 0, false, decode_imm_signed, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xe9, X86_DECODE_CMD_JMP_NEAR, 0, false, decode_imm_signed, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xea, X86_DECODE_CMD_JMP_FAR, 0, false, + NULL, NULL, NULL, NULL, decode_farjmp, RFLAGS_MASK_NONE}, + {0xeb, X86_DECODE_CMD_JMP_NEAR, 1, false, decode_imm8_signed, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xec, X86_DECODE_CMD_IN, 1, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xed, X86_DECODE_CMD_IN, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xee, X86_DECODE_CMD_OUT, 1, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xef, X86_DECODE_CMD_OUT, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xf4, X86_DECODE_CMD_HLT, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xf5, X86_DECODE_CMD_CMC, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF}, + + {0xf6, X86_DECODE_CMD_INVL, 1, true, + NULL, NULL, NULL, NULL, decode_f7group, RFLAGS_MASK_OSZAPC}, + {0xf7, X86_DECODE_CMD_INVL, 0, true, + NULL, NULL, NULL, NULL, decode_f7group, RFLAGS_MASK_OSZAPC}, + + {0xf8, X86_DECODE_CMD_CLC, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF}, + {0xf9, X86_DECODE_CMD_STC, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF}, + + {0xfa, X86_DECODE_CMD_CLI, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_IF}, + {0xfb, X86_DECODE_CMD_STI, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_IF}, + {0xfc, X86_DECODE_CMD_CLD, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_DF}, + {0xfd, X86_DECODE_CMD_STD, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_DF}, + {0xfe, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, + NULL, NULL, NULL, decode_incgroup2, RFLAGS_MASK_OSZAPC}, + {0xff, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, + NULL, NULL, NULL, decode_ffgroup, RFLAGS_MASK_OSZAPC}, }; -struct decode_tbl _2op_inst[] = -{ - {0x0, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, NULL, NULL, NULL, decode_sldtgroup, RFLAGS_MASK_NONE}, - {0x1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, NULL, NULL, NULL, decode_lidtgroup, RFLAGS_MASK_NONE}, - {0x6, X86_DECODE_CMD_CLTS, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_TF}, - {0x9, X86_DECODE_CMD_WBINVD, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x18, X86_DECODE_CMD_PREFETCH, 0, true, NULL, NULL, NULL, NULL, decode_x87_general, RFLAGS_MASK_NONE}, - {0x1f, X86_DECODE_CMD_NOP, 0, true, decode_modrm_rm, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x20, X86_DECODE_CMD_MOV_FROM_CR, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x21, X86_DECODE_CMD_MOV_FROM_DR, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x22, X86_DECODE_CMD_MOV_TO_CR, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x23, X86_DECODE_CMD_MOV_TO_DR, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x30, X86_DECODE_CMD_WRMSR, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x31, X86_DECODE_CMD_RDTSC, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x32, X86_DECODE_CMD_RDMSR, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x40, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x41, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x42, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x43, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x44, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x45, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x46, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x47, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x48, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x49, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x4a, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x4b, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x4c, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x4d, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x4e, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x4f, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x77, X86_DECODE_CMD_EMMS, 0, false, NULL, NULL, NULL, NULL, decode_x87_general, RFLAGS_MASK_NONE}, - {0x82, X86_DECODE_CMD_JXX, 0, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x83, X86_DECODE_CMD_JXX, 0, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x84, X86_DECODE_CMD_JXX, 0, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x85, X86_DECODE_CMD_JXX, 0, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x86, X86_DECODE_CMD_JXX, 0, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x87, X86_DECODE_CMD_JXX, 0, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x88, X86_DECODE_CMD_JXX, 0, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x89, X86_DECODE_CMD_JXX, 0, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x8a, X86_DECODE_CMD_JXX, 0, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x8b, X86_DECODE_CMD_JXX, 0, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x8c, X86_DECODE_CMD_JXX, 0, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x8d, X86_DECODE_CMD_JXX, 0, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x8e, X86_DECODE_CMD_JXX, 0, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x8f, X86_DECODE_CMD_JXX, 0, false, NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x90, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x91, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x92, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x93, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x94, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x95, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x96, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x97, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x98, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x99, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x9a, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x9b, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x9c, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x9d, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x9e, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x9f, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xb0, X86_DECODE_CMD_CMPXCHG, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xb1, X86_DECODE_CMD_CMPXCHG, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xb6, X86_DECODE_CMD_MOVZX, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xb7, X86_DECODE_CMD_MOVZX, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xb8, X86_DECODE_CMD_POPCNT, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xbe, X86_DECODE_CMD_MOVSX, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xbf, X86_DECODE_CMD_MOVSX, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xa0, X86_DECODE_CMD_PUSH_SEG, 0, false, false, NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, - {0xa1, X86_DECODE_CMD_POP_SEG, 0, false, false, NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, - {0xa2, X86_DECODE_CMD_CPUID, 0, false, NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xa3, X86_DECODE_CMD_BT, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_CF}, - {0xa4, X86_DECODE_CMD_SHLD, 0, true, decode_modrm_rm, decode_modrm_reg, decode_imm8, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xa5, X86_DECODE_CMD_SHLD, 0, true, decode_modrm_rm, decode_modrm_reg, decode_rcx, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xa8, X86_DECODE_CMD_PUSH_SEG, 0, false, false, NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, - {0xa9, X86_DECODE_CMD_POP_SEG, 0, false, false, NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, - {0xab, X86_DECODE_CMD_BTS, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_CF}, - {0xac, X86_DECODE_CMD_SHRD, 0, true, decode_modrm_rm, decode_modrm_reg, decode_imm8, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xad, X86_DECODE_CMD_SHRD, 0, true, decode_modrm_rm, decode_modrm_reg, decode_rcx, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0xae, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, NULL, NULL, NULL, decode_aegroup, RFLAGS_MASK_NONE}, - - {0xaf, X86_DECODE_CMD_IMUL_2, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xb2, X86_DECODE_CMD_LSS, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xb3, X86_DECODE_CMD_BTR, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xba, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8, NULL, NULL, decode_btgroup, RFLAGS_MASK_OSZAPC}, - {0xbb, X86_DECODE_CMD_BTC, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xbc, X86_DECODE_CMD_BSF, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xbd, X86_DECODE_CMD_BSR, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0xc1, X86_DECODE_CMD_XADD, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0xc7, X86_DECODE_CMD_CMPXCHG8B, 0, true, decode_modrm_rm, NULL, NULL, NULL, NULL, RFLAGS_MASK_ZF}, - - {0xc8, X86_DECODE_CMD_BSWAP, 0, false, NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, - {0xc9, X86_DECODE_CMD_BSWAP, 0, false, NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, - {0xca, X86_DECODE_CMD_BSWAP, 0, false, NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, - {0xcb, X86_DECODE_CMD_BSWAP, 0, false, NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, - {0xcc, X86_DECODE_CMD_BSWAP, 0, false, NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, - {0xcd, X86_DECODE_CMD_BSWAP, 0, false, NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, - {0xce, X86_DECODE_CMD_BSWAP, 0, false, NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, - {0xcf, X86_DECODE_CMD_BSWAP, 0, false, NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, +struct decode_tbl _2op_inst[] = { + {0x0, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, + NULL, NULL, NULL, decode_sldtgroup, RFLAGS_MASK_NONE}, + {0x1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, + NULL, NULL, NULL, decode_lidtgroup, RFLAGS_MASK_NONE}, + {0x6, X86_DECODE_CMD_CLTS, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_TF}, + {0x9, X86_DECODE_CMD_WBINVD, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x18, X86_DECODE_CMD_PREFETCH, 0, true, + NULL, NULL, NULL, NULL, decode_x87_general, RFLAGS_MASK_NONE}, + {0x1f, X86_DECODE_CMD_NOP, 0, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x20, X86_DECODE_CMD_MOV_FROM_CR, 0, true, decode_modrm_rm, + decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x21, X86_DECODE_CMD_MOV_FROM_DR, 0, true, decode_modrm_rm, + decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x22, X86_DECODE_CMD_MOV_TO_CR, 0, true, decode_modrm_reg, + decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x23, X86_DECODE_CMD_MOV_TO_DR, 0, true, decode_modrm_reg, + decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x30, X86_DECODE_CMD_WRMSR, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x31, X86_DECODE_CMD_RDTSC, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x32, X86_DECODE_CMD_RDMSR, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x40, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x41, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x42, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x43, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x44, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x45, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x46, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x47, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x48, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x49, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x4a, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x4b, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x4c, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x4d, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x4e, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x4f, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x77, X86_DECODE_CMD_EMMS, 0, false, + NULL, NULL, NULL, NULL, decode_x87_general, RFLAGS_MASK_NONE}, + {0x82, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x83, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x84, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x85, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x86, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x87, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x88, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x89, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x8a, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x8b, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x8c, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x8d, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x8e, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x8f, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x90, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x91, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x92, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x93, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x94, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x95, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x96, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x97, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x98, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x99, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x9a, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x9b, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x9c, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x9d, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x9e, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x9f, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xb0, X86_DECODE_CMD_CMPXCHG, 1, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xb1, X86_DECODE_CMD_CMPXCHG, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xb6, X86_DECODE_CMD_MOVZX, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xb7, X86_DECODE_CMD_MOVZX, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xb8, X86_DECODE_CMD_POPCNT, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xbe, X86_DECODE_CMD_MOVSX, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xbf, X86_DECODE_CMD_MOVSX, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xa0, X86_DECODE_CMD_PUSH_SEG, 0, false, false, + NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, + {0xa1, X86_DECODE_CMD_POP_SEG, 0, false, false, + NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, + {0xa2, X86_DECODE_CMD_CPUID, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xa3, X86_DECODE_CMD_BT, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_CF}, + {0xa4, X86_DECODE_CMD_SHLD, 0, true, decode_modrm_rm, decode_modrm_reg, + decode_imm8, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xa5, X86_DECODE_CMD_SHLD, 0, true, decode_modrm_rm, decode_modrm_reg, + decode_rcx, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xa8, X86_DECODE_CMD_PUSH_SEG, 0, false, false, + NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, + {0xa9, X86_DECODE_CMD_POP_SEG, 0, false, false, + NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, + {0xab, X86_DECODE_CMD_BTS, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_CF}, + {0xac, X86_DECODE_CMD_SHRD, 0, true, decode_modrm_rm, decode_modrm_reg, + decode_imm8, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xad, X86_DECODE_CMD_SHRD, 0, true, decode_modrm_rm, decode_modrm_reg, + decode_rcx, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0xae, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, + NULL, NULL, NULL, decode_aegroup, RFLAGS_MASK_NONE}, + + {0xaf, X86_DECODE_CMD_IMUL_2, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xb2, X86_DECODE_CMD_LSS, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xb3, X86_DECODE_CMD_BTR, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xba, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8, + NULL, NULL, decode_btgroup, RFLAGS_MASK_OSZAPC}, + {0xbb, X86_DECODE_CMD_BTC, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xbc, X86_DECODE_CMD_BSF, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xbd, X86_DECODE_CMD_BSR, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0xc1, X86_DECODE_CMD_XADD, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0xc7, X86_DECODE_CMD_CMPXCHG8B, 0, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_ZF}, + + {0xc8, X86_DECODE_CMD_BSWAP, 0, false, + NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + {0xc9, X86_DECODE_CMD_BSWAP, 0, false, + NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + {0xca, X86_DECODE_CMD_BSWAP, 0, false, + NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + {0xcb, X86_DECODE_CMD_BSWAP, 0, false, + NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + {0xcc, X86_DECODE_CMD_BSWAP, 0, false, + NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + {0xcd, X86_DECODE_CMD_BSWAP, 0, false, + NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + {0xce, X86_DECODE_CMD_BSWAP, 0, false, + NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + {0xcf, X86_DECODE_CMD_BSWAP, 0, false, + NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, }; -struct decode_x87_tbl invl_inst_x87 = {0x0, 0, 0, 0, 0, false, false, NULL, NULL, decode_invalid, 0}; - -struct decode_x87_tbl _x87_inst[] = -{ - {0xd8, 0, 3, X86_DECODE_CMD_FADD, 10, false, false, decode_x87_modrm_st0, decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xd8, 0, 0, X86_DECODE_CMD_FADD, 4, false, false, decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - {0xd8, 1, 3, X86_DECODE_CMD_FMUL, 10, false, false, decode_x87_modrm_st0, decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xd8, 1, 0, X86_DECODE_CMD_FMUL, 4, false, false, decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - {0xd8, 4, 3, X86_DECODE_CMD_FSUB, 10, false, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xd8, 4, 0, X86_DECODE_CMD_FSUB, 4, false, false, decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - {0xd8, 5, 3, X86_DECODE_CMD_FSUB, 10, true, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xd8, 5, 0, X86_DECODE_CMD_FSUB, 4, true, false, decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - {0xd8, 6, 3, X86_DECODE_CMD_FDIV, 10, false, false, decode_x87_modrm_st0,decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xd8, 6, 0, X86_DECODE_CMD_FDIV, 4, false, false, decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - {0xd8, 7, 3, X86_DECODE_CMD_FDIV, 10, true, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xd8, 7, 0, X86_DECODE_CMD_FDIV, 4, true, false, decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - - {0xd9, 0, 3, X86_DECODE_CMD_FLD, 10, false, false, decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, - {0xd9, 0, 0, X86_DECODE_CMD_FLD, 4, false, false, decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xd9, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xd9, 1, 0, X86_DECODE_CMD_INVL, 10, false, false, decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, - {0xd9, 2, 3, X86_DECODE_CMD_INVL, 10, false, false, decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, - {0xd9, 2, 0, X86_DECODE_CMD_FST, 4, false, false, decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xd9, 3, 3, X86_DECODE_CMD_INVL, 10, false, false, decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, - {0xd9, 3, 0, X86_DECODE_CMD_FST, 4, false, true, decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xd9, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, decode_x87_modrm_st0, NULL, decode_d9_4, RFLAGS_MASK_NONE}, - {0xd9, 4, 0, X86_DECODE_CMD_INVL, 4, false, false, decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, - {0xd9, 5, 3, X86_DECODE_CMD_FLDxx, 10, false, false, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xd9, 5, 0, X86_DECODE_CMD_FLDCW, 2, false, false, decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, - // - {0xd9, 7, 3, X86_DECODE_CMD_FNSTCW, 2, false, false, decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, - {0xd9, 7, 0, X86_DECODE_CMD_FNSTCW, 2, false, false, decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xda, 0, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xda, 0, 0, X86_DECODE_CMD_FADD, 4, false, false, decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - {0xda, 1, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xda, 1, 0, X86_DECODE_CMD_FMUL, 4, false, false, decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - {0xda, 2, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xda, 3, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xda, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xda, 4, 0, X86_DECODE_CMD_FSUB, 4, false, false, decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - {0xda, 5, 3, X86_DECODE_CMD_FUCOM, 10, false, true, decode_x87_modrm_st0, decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xda, 5, 0, X86_DECODE_CMD_FSUB, 4, true, false, decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - {0xda, 6, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xda, 6, 0, X86_DECODE_CMD_FDIV, 4, false, false, decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - {0xda, 7, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xda, 7, 0, X86_DECODE_CMD_FDIV, 4, true, false, decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - - {0xdb, 0, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdb, 0, 0, X86_DECODE_CMD_FLD, 4, false, false, decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdb, 1, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdb, 2, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdb, 2, 0, X86_DECODE_CMD_FST, 4, false, false, decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdb, 3, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdb, 3, 0, X86_DECODE_CMD_FST, 4, false, true, decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdb, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, decode_db_4, RFLAGS_MASK_NONE}, - {0xdb, 4, 0, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdb, 5, 3, X86_DECODE_CMD_FUCOMI, 10, false, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdb, 5, 0, X86_DECODE_CMD_FLD, 10, false, false, decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdb, 7, 0, X86_DECODE_CMD_FST, 10, false, true, decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xdc, 0, 3, X86_DECODE_CMD_FADD, 10, false, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdc, 0, 0, X86_DECODE_CMD_FADD, 8, false, false, decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - {0xdc, 1, 3, X86_DECODE_CMD_FMUL, 10, false, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdc, 1, 0, X86_DECODE_CMD_FMUL, 8, false, false, decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - {0xdc, 4, 3, X86_DECODE_CMD_FSUB, 10, true, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdc, 4, 0, X86_DECODE_CMD_FSUB, 8, false, false, decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - {0xdc, 5, 3, X86_DECODE_CMD_FSUB, 10, false, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdc, 5, 0, X86_DECODE_CMD_FSUB, 8, true, false, decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - {0xdc, 6, 3, X86_DECODE_CMD_FDIV, 10, true, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdc, 6, 0, X86_DECODE_CMD_FDIV, 8, false, false, decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - {0xdc, 7, 3, X86_DECODE_CMD_FDIV, 10, false, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdc, 7, 0, X86_DECODE_CMD_FDIV, 8, true, false, decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - - {0xdd, 0, 0, X86_DECODE_CMD_FLD, 8, false, false, decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdd, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdd, 2, 3, X86_DECODE_CMD_FST, 10, false, false, decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdd, 2, 0, X86_DECODE_CMD_FST, 8, false, false, decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdd, 3, 3, X86_DECODE_CMD_FST, 10, false, true, decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdd, 3, 0, X86_DECODE_CMD_FST, 8, false, true, decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdd, 4, 3, X86_DECODE_CMD_FUCOM, 10, false, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdd, 4, 0, X86_DECODE_CMD_FRSTOR, 8, false, false, decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdd, 5, 3, X86_DECODE_CMD_FUCOM, 10, false, true, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdd, 7, 0, X86_DECODE_CMD_FNSTSW, 0, false, false, decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdd, 7, 3, X86_DECODE_CMD_FNSTSW, 0, false, false, decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xde, 0, 3, X86_DECODE_CMD_FADD, 10, false, true, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xde, 0, 0, X86_DECODE_CMD_FADD, 2, false, false, decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - {0xde, 1, 3, X86_DECODE_CMD_FMUL, 10, false, true, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xde, 1, 0, X86_DECODE_CMD_FMUL, 2, false, false, decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - {0xde, 4, 3, X86_DECODE_CMD_FSUB, 10, true, true, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xde, 4, 0, X86_DECODE_CMD_FSUB, 2, false, false, decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - {0xde, 5, 3, X86_DECODE_CMD_FSUB, 10, false, true, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xde, 5, 0, X86_DECODE_CMD_FSUB, 2, true, false, decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - {0xde, 6, 3, X86_DECODE_CMD_FDIV, 10, true, true, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xde, 6, 0, X86_DECODE_CMD_FDIV, 2, false, false, decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - {0xde, 7, 3, X86_DECODE_CMD_FDIV, 10, false, true, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xde, 7, 0, X86_DECODE_CMD_FDIV, 2, true, false, decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - - {0xdf, 0, 0, X86_DECODE_CMD_FLD, 2, false, false, decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdf, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdf, 2, 3, X86_DECODE_CMD_FST, 10, false, true, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdf, 2, 0, X86_DECODE_CMD_FST, 2, false, false, decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdf, 3, 3, X86_DECODE_CMD_FST, 10, false, true, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdf, 3, 0, X86_DECODE_CMD_FST, 2, false, true, decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdf, 4, 3, X86_DECODE_CMD_FNSTSW, 2, false, true, decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdf, 5, 3, X86_DECODE_CMD_FUCOMI, 10, false, true, decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdf, 5, 0, X86_DECODE_CMD_FLD, 8, false, false, decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdf, 7, 0, X86_DECODE_CMD_FST, 8, false, true, decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, +struct decode_x87_tbl invl_inst_x87 = {0x0, 0, 0, 0, 0, false, false, NULL, + NULL, decode_invalid, 0}; + +struct decode_x87_tbl _x87_inst[] = { + {0xd8, 0, 3, X86_DECODE_CMD_FADD, 10, false, false, + decode_x87_modrm_st0, decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xd8, 0, 0, X86_DECODE_CMD_FADD, 4, false, false, decode_x87_modrm_st0, + decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + {0xd8, 1, 3, X86_DECODE_CMD_FMUL, 10, false, false, decode_x87_modrm_st0, + decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xd8, 1, 0, X86_DECODE_CMD_FMUL, 4, false, false, decode_x87_modrm_st0, + decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + {0xd8, 4, 3, X86_DECODE_CMD_FSUB, 10, false, false, decode_x87_modrm_st0, + decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xd8, 4, 0, X86_DECODE_CMD_FSUB, 4, false, false, decode_x87_modrm_st0, + decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + {0xd8, 5, 3, X86_DECODE_CMD_FSUB, 10, true, false, decode_x87_modrm_st0, + decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xd8, 5, 0, X86_DECODE_CMD_FSUB, 4, true, false, decode_x87_modrm_st0, + decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + {0xd8, 6, 3, X86_DECODE_CMD_FDIV, 10, false, false, decode_x87_modrm_st0, + decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xd8, 6, 0, X86_DECODE_CMD_FDIV, 4, false, false, decode_x87_modrm_st0, + decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + {0xd8, 7, 3, X86_DECODE_CMD_FDIV, 10, true, false, decode_x87_modrm_st0, + decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xd8, 7, 0, X86_DECODE_CMD_FDIV, 4, true, false, decode_x87_modrm_st0, + decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + + {0xd9, 0, 3, X86_DECODE_CMD_FLD, 10, false, false, + decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, + {0xd9, 0, 0, X86_DECODE_CMD_FLD, 4, false, false, + decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xd9, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false, decode_x87_modrm_st0, + decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xd9, 1, 0, X86_DECODE_CMD_INVL, 10, false, false, + decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, + {0xd9, 2, 3, X86_DECODE_CMD_INVL, 10, false, false, + decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, + {0xd9, 2, 0, X86_DECODE_CMD_FST, 4, false, false, + decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xd9, 3, 3, X86_DECODE_CMD_INVL, 10, false, false, + decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, + {0xd9, 3, 0, X86_DECODE_CMD_FST, 4, false, true, + decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xd9, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, + decode_x87_modrm_st0, NULL, decode_d9_4, RFLAGS_MASK_NONE}, + {0xd9, 4, 0, X86_DECODE_CMD_INVL, 4, false, false, + decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + {0xd9, 5, 3, X86_DECODE_CMD_FLDxx, 10, false, false, NULL, NULL, NULL, + RFLAGS_MASK_NONE}, + {0xd9, 5, 0, X86_DECODE_CMD_FLDCW, 2, false, false, + decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xd9, 7, 3, X86_DECODE_CMD_FNSTCW, 2, false, false, + decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + {0xd9, 7, 0, X86_DECODE_CMD_FNSTCW, 2, false, false, + decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xda, 0, 3, X86_DECODE_CMD_FCMOV, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xda, 0, 0, X86_DECODE_CMD_FADD, 4, false, false, decode_x87_modrm_st0, + decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + {0xda, 1, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, + decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xda, 1, 0, X86_DECODE_CMD_FMUL, 4, false, false, decode_x87_modrm_st0, + decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + {0xda, 2, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, + decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xda, 3, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, + decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xda, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL, + RFLAGS_MASK_NONE}, + {0xda, 4, 0, X86_DECODE_CMD_FSUB, 4, false, false, decode_x87_modrm_st0, + decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + {0xda, 5, 3, X86_DECODE_CMD_FUCOM, 10, false, true, decode_x87_modrm_st0, + decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xda, 5, 0, X86_DECODE_CMD_FSUB, 4, true, false, decode_x87_modrm_st0, + decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + {0xda, 6, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL, + RFLAGS_MASK_NONE}, + {0xda, 6, 0, X86_DECODE_CMD_FDIV, 4, false, false, decode_x87_modrm_st0, + decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + {0xda, 7, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL, + RFLAGS_MASK_NONE}, + {0xda, 7, 0, X86_DECODE_CMD_FDIV, 4, true, false, decode_x87_modrm_st0, + decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + + {0xdb, 0, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, + decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdb, 0, 0, X86_DECODE_CMD_FLD, 4, false, false, + decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdb, 1, 3, X86_DECODE_CMD_FCMOV, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdb, 2, 3, X86_DECODE_CMD_FCMOV, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdb, 2, 0, X86_DECODE_CMD_FST, 4, false, false, + decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdb, 3, 3, X86_DECODE_CMD_FCMOV, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdb, 3, 0, X86_DECODE_CMD_FST, 4, false, true, + decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdb, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, + decode_db_4, RFLAGS_MASK_NONE}, + {0xdb, 4, 0, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL, + RFLAGS_MASK_NONE}, + {0xdb, 5, 3, X86_DECODE_CMD_FUCOMI, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdb, 5, 0, X86_DECODE_CMD_FLD, 10, false, false, + decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdb, 7, 0, X86_DECODE_CMD_FST, 10, false, true, + decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xdc, 0, 3, X86_DECODE_CMD_FADD, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdc, 0, 0, X86_DECODE_CMD_FADD, 8, false, false, + decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + {0xdc, 1, 3, X86_DECODE_CMD_FMUL, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdc, 1, 0, X86_DECODE_CMD_FMUL, 8, false, false, + decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + {0xdc, 4, 3, X86_DECODE_CMD_FSUB, 10, true, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdc, 4, 0, X86_DECODE_CMD_FSUB, 8, false, false, + decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + {0xdc, 5, 3, X86_DECODE_CMD_FSUB, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdc, 5, 0, X86_DECODE_CMD_FSUB, 8, true, false, + decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + {0xdc, 6, 3, X86_DECODE_CMD_FDIV, 10, true, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdc, 6, 0, X86_DECODE_CMD_FDIV, 8, false, false, + decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + {0xdc, 7, 3, X86_DECODE_CMD_FDIV, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdc, 7, 0, X86_DECODE_CMD_FDIV, 8, true, false, + decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + + {0xdd, 0, 0, X86_DECODE_CMD_FLD, 8, false, false, + decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdd, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdd, 2, 3, X86_DECODE_CMD_FST, 10, false, false, + decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdd, 2, 0, X86_DECODE_CMD_FST, 8, false, false, + decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdd, 3, 3, X86_DECODE_CMD_FST, 10, false, true, + decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdd, 3, 0, X86_DECODE_CMD_FST, 8, false, true, + decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdd, 4, 3, X86_DECODE_CMD_FUCOM, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdd, 4, 0, X86_DECODE_CMD_FRSTOR, 8, false, false, + decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdd, 5, 3, X86_DECODE_CMD_FUCOM, 10, false, true, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdd, 7, 0, X86_DECODE_CMD_FNSTSW, 0, false, false, + decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdd, 7, 3, X86_DECODE_CMD_FNSTSW, 0, false, false, + decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xde, 0, 3, X86_DECODE_CMD_FADD, 10, false, true, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xde, 0, 0, X86_DECODE_CMD_FADD, 2, false, false, + decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + {0xde, 1, 3, X86_DECODE_CMD_FMUL, 10, false, true, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xde, 1, 0, X86_DECODE_CMD_FMUL, 2, false, false, + decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + {0xde, 4, 3, X86_DECODE_CMD_FSUB, 10, true, true, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xde, 4, 0, X86_DECODE_CMD_FSUB, 2, false, false, + decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + {0xde, 5, 3, X86_DECODE_CMD_FSUB, 10, false, true, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xde, 5, 0, X86_DECODE_CMD_FSUB, 2, true, false, + decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + {0xde, 6, 3, X86_DECODE_CMD_FDIV, 10, true, true, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xde, 6, 0, X86_DECODE_CMD_FDIV, 2, false, false, + decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + {0xde, 7, 3, X86_DECODE_CMD_FDIV, 10, false, true, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xde, 7, 0, X86_DECODE_CMD_FDIV, 2, true, false, + decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + + {0xdf, 0, 0, X86_DECODE_CMD_FLD, 2, false, false, + decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdf, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdf, 2, 3, X86_DECODE_CMD_FST, 10, false, true, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdf, 2, 0, X86_DECODE_CMD_FST, 2, false, false, + decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdf, 3, 3, X86_DECODE_CMD_FST, 10, false, true, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdf, 3, 0, X86_DECODE_CMD_FST, 2, false, true, + decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdf, 4, 3, X86_DECODE_CMD_FNSTSW, 2, false, true, + decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdf, 5, 3, X86_DECODE_CMD_FUCOMI, 10, false, true, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdf, 5, 0, X86_DECODE_CMD_FLD, 8, false, false, + decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdf, 7, 0, X86_DECODE_CMD_FST, 8, false, true, + decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, }; -void calc_modrm_operand16(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +void calc_modrm_operand16(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op) { addr_t ptr = 0; x86_reg_segment seg = REG_SEG_DS; @@ -1163,43 +1644,45 @@ void calc_modrm_operand16(CPUState *cpu, struct x86_decode *decode, struct x86_d goto calc_addr; } - if (decode->displacement_size) + if (decode->displacement_size) { ptr = sign(decode->displacement, decode->displacement_size); + } switch (decode->modrm.rm) { - case 0: - ptr += BX(cpu) + SI(cpu); - break; - case 1: - ptr += BX(cpu) + DI(cpu); - break; - case 2: - ptr += BP(cpu) + SI(cpu); - seg = REG_SEG_SS; - break; - case 3: - ptr += BP(cpu) + DI(cpu); - seg = REG_SEG_SS; - break; - case 4: - ptr += SI(cpu); - break; - case 5: - ptr += DI(cpu); - break; - case 6: - ptr += BP(cpu); - seg = REG_SEG_SS; - break; - case 7: - ptr += BX(cpu); - break; + case 0: + ptr += BX(cpu) + SI(cpu); + break; + case 1: + ptr += BX(cpu) + DI(cpu); + break; + case 2: + ptr += BP(cpu) + SI(cpu); + seg = REG_SEG_SS; + break; + case 3: + ptr += BP(cpu) + DI(cpu); + seg = REG_SEG_SS; + break; + case 4: + ptr += SI(cpu); + break; + case 5: + ptr += DI(cpu); + break; + case 6: + ptr += BP(cpu); + seg = REG_SEG_SS; + break; + case 7: + ptr += BX(cpu); + break; } calc_addr: - if (X86_DECODE_CMD_LEA == decode->cmd) + if (X86_DECODE_CMD_LEA == decode->cmd) { op->ptr = (uint16_t)ptr; - else + } else { op->ptr = decode_linear_addr(cpu, decode, (uint16_t)ptr, seg); + } } addr_t get_reg_ref(CPUState *cpu, int reg, int is_extended, int size) @@ -1207,24 +1690,25 @@ addr_t get_reg_ref(CPUState *cpu, int reg, int is_extended, int size) addr_t ptr = 0; int which = 0; - if (is_extended) + if (is_extended) { reg |= REG_R8; + } switch (size) { - case 1: - if (is_extended || reg < 4) { - which = 1; - ptr = (addr_t)&RL(cpu, reg); - } else { - which = 2; - ptr = (addr_t)&RH(cpu, reg - 4); - } - break; - default: - which = 3; - ptr = (addr_t)&RRX(cpu, reg); - break; + case 1: + if (is_extended || reg < 4) { + which = 1; + ptr = (addr_t)&RL(cpu, reg); + } else { + which = 2; + ptr = (addr_t)&RH(cpu, reg - 4); + } + break; + default: + which = 3; + ptr = (addr_t)&RRX(cpu, reg); + break; } return ptr; } @@ -1232,11 +1716,12 @@ addr_t get_reg_ref(CPUState *cpu, int reg, int is_extended, int size) addr_t get_reg_val(CPUState *cpu, int reg, int is_extended, int size) { addr_t val = 0; - memcpy(&val, (void*)get_reg_ref(cpu, reg, is_extended, size), size); + memcpy(&val, (void *)get_reg_ref(cpu, reg, is_extended, size), size); return val; } -static addr_t get_sib_val(CPUState *cpu, struct x86_decode *decode, x86_reg_segment *sel) +static addr_t get_sib_val(CPUState *cpu, struct x86_decode *decode, + x86_reg_segment *sel) { addr_t base = 0; addr_t scaled_index = 0; @@ -1247,52 +1732,61 @@ static addr_t get_sib_val(CPUState *cpu, struct x86_decode *decode, x86_reg_segm *sel = REG_SEG_DS; if (decode->modrm.mod || base_reg != REG_RBP) { - if (decode->rex.b) + if (decode->rex.b) { base_reg |= REG_R8; - if (REG_RSP == base_reg || REG_RBP == base_reg) + } + if (REG_RSP == base_reg || REG_RBP == base_reg) { *sel = REG_SEG_SS; + } base = get_reg_val(cpu, decode->sib.base, decode->rex.b, addr_size); } - if (decode->rex.x) + if (decode->rex.x) { index_reg |= REG_R8; + } - if (index_reg != REG_RSP) - scaled_index = get_reg_val(cpu, index_reg, decode->rex.x, addr_size) << decode->sib.scale; + if (index_reg != REG_RSP) { + scaled_index = get_reg_val(cpu, index_reg, decode->rex.x, addr_size) << + decode->sib.scale; + } return base + scaled_index; } -void calc_modrm_operand32(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +void calc_modrm_operand32(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op) { x86_reg_segment seg = REG_SEG_DS; addr_t ptr = 0; int addr_size = decode->addressing_size; - if (decode->displacement_size) + if (decode->displacement_size) { ptr = sign(decode->displacement, decode->displacement_size); + } if (4 == decode->modrm.rm) { ptr += get_sib_val(cpu, decode, &seg); - } - else if (!decode->modrm.mod && 5 == decode->modrm.rm) { - if (x86_is_long_mode(cpu)) + } else if (!decode->modrm.mod && 5 == decode->modrm.rm) { + if (x86_is_long_mode(cpu)) { ptr += RIP(cpu) + decode->len; - else + } else { ptr = decode->displacement; - } - else { - if (REG_RBP == decode->modrm.rm || REG_RSP == decode->modrm.rm) + } + } else { + if (REG_RBP == decode->modrm.rm || REG_RSP == decode->modrm.rm) { seg = REG_SEG_SS; + } ptr += get_reg_val(cpu, decode->modrm.rm, decode->rex.b, addr_size); } - if (X86_DECODE_CMD_LEA == decode->cmd) + if (X86_DECODE_CMD_LEA == decode->cmd) { op->ptr = (uint32_t)ptr; - else + } else { op->ptr = decode_linear_addr(cpu, decode, (uint32_t)ptr, seg); + } } -void calc_modrm_operand64(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +void calc_modrm_operand64(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op) { x86_reg_segment seg = REG_SEG_DS; int32_t offset = 0; @@ -1300,46 +1794,51 @@ void calc_modrm_operand64(CPUState *cpu, struct x86_decode *decode, struct x86_d int rm = decode->modrm.rm; addr_t ptr; int src = decode->modrm.rm; - - if (decode->displacement_size) + + if (decode->displacement_size) { offset = sign(decode->displacement, decode->displacement_size); + } - if (4 == rm) + if (4 == rm) { ptr = get_sib_val(cpu, decode, &seg) + offset; - else if (0 == mod && 5 == rm) + } else if (0 == mod && 5 == rm) { ptr = RIP(cpu) + decode->len + (int32_t) offset; - else + } else { ptr = get_reg_val(cpu, src, decode->rex.b, 8) + (int64_t) offset; - - if (X86_DECODE_CMD_LEA == decode->cmd) + } + + if (X86_DECODE_CMD_LEA == decode->cmd) { op->ptr = ptr; - else + } else { op->ptr = decode_linear_addr(cpu, decode, ptr, seg); + } } -void calc_modrm_operand(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op) +void calc_modrm_operand(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op) { if (3 == decode->modrm.mod) { op->reg = decode->modrm.reg; op->type = X86_VAR_REG; - op->ptr = get_reg_ref(cpu, decode->modrm.rm, decode->rex.b, decode->operand_size); + op->ptr = get_reg_ref(cpu, decode->modrm.rm, decode->rex.b, + decode->operand_size); return; } switch (decode->addressing_size) { - case 2: - calc_modrm_operand16(cpu, decode, op); - break; - case 4: - calc_modrm_operand32(cpu, decode, op); - break; - case 8: - calc_modrm_operand64(cpu, decode, op); - break; - default: - VM_PANIC_EX("unsupported address size %d\n", decode->addressing_size); - break; + case 2: + calc_modrm_operand16(cpu, decode, op); + break; + case 4: + calc_modrm_operand32(cpu, decode, op); + break; + case 8: + calc_modrm_operand64(cpu, decode, op); + break; + default: + VM_PANIC_EX("unsupported address size %d\n", decode->addressing_size); + break; } } @@ -1348,36 +1847,36 @@ static void decode_prefix(CPUState *cpu, struct x86_decode *decode) while (1) { uint8_t byte = decode_byte(cpu, decode); switch (byte) { - case PREFIX_LOCK: - decode->lock = byte; - break; - case PREFIX_REPN: - case PREFIX_REP: - decode->rep = byte; - break; - case PREFIX_CS_SEG_OVEERIDE: - case PREFIX_SS_SEG_OVEERIDE: - case PREFIX_DS_SEG_OVEERIDE: - case PREFIX_ES_SEG_OVEERIDE: - case PREFIX_FS_SEG_OVEERIDE: - case PREFIX_GS_SEG_OVEERIDE: - decode->segment_override = byte; - break; - case PREFIX_OP_SIZE_OVERRIDE: - decode->op_size_override = byte; - break; - case PREFIX_ADDR_SIZE_OVERRIDE: - decode->addr_size_override = byte; + case PREFIX_LOCK: + decode->lock = byte; + break; + case PREFIX_REPN: + case PREFIX_REP: + decode->rep = byte; + break; + case PREFIX_CS_SEG_OVEERIDE: + case PREFIX_SS_SEG_OVEERIDE: + case PREFIX_DS_SEG_OVEERIDE: + case PREFIX_ES_SEG_OVEERIDE: + case PREFIX_FS_SEG_OVEERIDE: + case PREFIX_GS_SEG_OVEERIDE: + decode->segment_override = byte; + break; + case PREFIX_OP_SIZE_OVERRIDE: + decode->op_size_override = byte; + break; + case PREFIX_ADDR_SIZE_OVERRIDE: + decode->addr_size_override = byte; + break; + case PREFIX_REX ... (PREFIX_REX + 0xf): + if (x86_is_long_mode(cpu)) { + decode->rex.rex = byte; break; - case PREFIX_REX ... (PREFIX_REX + 0xf): - if (x86_is_long_mode(cpu)) { - decode->rex.rex = byte; - break; - } - // fall through when not in long mode - default: - decode->len--; - return; + } + /* fall through when not in long mode */ + default: + decode->len--; + return; } } } @@ -1386,33 +1885,36 @@ void set_addressing_size(CPUState *cpu, struct x86_decode *decode) { decode->addressing_size = -1; if (x86_is_real(cpu) || x86_is_v8086(cpu)) { - if (decode->addr_size_override) + if (decode->addr_size_override) { decode->addressing_size = 4; - else + } else { decode->addressing_size = 2; - } - else if (!x86_is_long_mode(cpu)) { - // protected + } + } else if (!x86_is_long_mode(cpu)) { + /* protected */ struct vmx_segment cs; vmx_read_segment_descriptor(cpu, &cs, REG_SEG_CS); - // check db + /* check db */ if ((cs.ar >> 14) & 1) { - if (decode->addr_size_override) + if (decode->addr_size_override) { decode->addressing_size = 2; - else + } else { decode->addressing_size = 4; + } } else { - if (decode->addr_size_override) + if (decode->addr_size_override) { decode->addressing_size = 4; - else + } else { decode->addressing_size = 2; + } } } else { - // long - if (decode->addr_size_override) + /* long */ + if (decode->addr_size_override) { decode->addressing_size = 4; - else + } else { decode->addressing_size = 8; + } } } @@ -1420,99 +1922,98 @@ void set_operand_size(CPUState *cpu, struct x86_decode *decode) { decode->operand_size = -1; if (x86_is_real(cpu) || x86_is_v8086(cpu)) { - if (decode->op_size_override) + if (decode->op_size_override) { decode->operand_size = 4; - else + } else { decode->operand_size = 2; - } - else if (!x86_is_long_mode(cpu)) { - // protected + } + } else if (!x86_is_long_mode(cpu)) { + /* protected */ struct vmx_segment cs; vmx_read_segment_descriptor(cpu, &cs, REG_SEG_CS); - // check db + /* check db */ if ((cs.ar >> 14) & 1) { - if (decode->op_size_override) + if (decode->op_size_override) { decode->operand_size = 2; - else + } else{ decode->operand_size = 4; + } } else { - if (decode->op_size_override) + if (decode->op_size_override) { decode->operand_size = 4; - else + } else { decode->operand_size = 2; + } } } else { - // long - if (decode->op_size_override) + /* long */ + if (decode->op_size_override) { decode->operand_size = 2; - else + } else { decode->operand_size = 4; + } - if (decode->rex.w) + if (decode->rex.w) { decode->operand_size = 8; + } } } static void decode_sib(CPUState *cpu, struct x86_decode *decode) { - if ((decode->modrm.mod != 3) && (4 == decode->modrm.rm) && (decode->addressing_size != 2)) { + if ((decode->modrm.mod != 3) && (4 == decode->modrm.rm) && + (decode->addressing_size != 2)) { decode->sib.sib = decode_byte(cpu, decode); decode->sib_present = true; } } -/* 16 bit modrm - * mod R/M - * 00 [BX+SI] [BX+DI] [BP+SI] [BP+DI] [SI] [DI] [disp16] [BX] - * 01 [BX+SI+disp8] [BX+DI+disp8] [BP+SI+disp8] [BP+DI+disp8] [SI+disp8] [DI+disp8] [BP+disp8] [BX+disp8] - * 10 [BX+SI+disp16] [BX+DI+disp16] [BP+SI+disp16] [BP+DI+disp16] [SI+disp16] [DI+disp16] [BP+disp16] [BX+disp16] - * 11 - - - - - - - - - */ -int disp16_tbl[4][8] = - {{0, 0, 0, 0, 0, 0, 2, 0}, +/* 16 bit modrm */ +int disp16_tbl[4][8] = { + {0, 0, 0, 0, 0, 0, 2, 0}, {1, 1, 1, 1, 1, 1, 1, 1}, {2, 2, 2, 2, 2, 2, 2, 2}, - {0, 0, 0, 0, 0, 0, 0, 0}}; + {0, 0, 0, 0, 0, 0, 0, 0} +}; -/* - 32/64-bit modrm - Mod - 00 [r/m] [r/m] [r/m] [r/m] [SIB] [RIP/EIP1,2+disp32] [r/m] [r/m] - 01 [r/m+disp8] [r/m+disp8] [r/m+disp8] [r/m+disp8] [SIB+disp8] [r/m+disp8] [SIB+disp8] [r/m+disp8] - 10 [r/m+disp32] [r/m+disp32] [r/m+disp32] [r/m+disp32] [SIB+disp32] [r/m+disp32] [SIB+disp32] [r/m+disp32] - 11 - - - - - - - - - */ -int disp32_tbl[4][8] = - {{0, 0, 0, 0, -1, 4, 0, 0}, +/* 32/64-bit modrm */ +int disp32_tbl[4][8] = { + {0, 0, 0, 0, -1, 4, 0, 0}, {1, 1, 1, 1, 1, 1, 1, 1}, {4, 4, 4, 4, 4, 4, 4, 4}, - {0, 0, 0, 0, 0, 0, 0, 0}}; + {0, 0, 0, 0, 0, 0, 0, 0} +}; static inline void decode_displacement(CPUState *cpu, struct x86_decode *decode) { int addressing_size = decode->addressing_size; int mod = decode->modrm.mod; int rm = decode->modrm.rm; - + decode->displacement_size = 0; switch (addressing_size) { - case 2: - decode->displacement_size = disp16_tbl[mod][rm]; - if (decode->displacement_size) - decode->displacement = (uint16_t)decode_bytes(cpu, decode, decode->displacement_size); - break; - case 4: - case 8: - if (-1 == disp32_tbl[mod][rm]) { - if (5 == decode->sib.base) - decode->displacement_size = 4; + case 2: + decode->displacement_size = disp16_tbl[mod][rm]; + if (decode->displacement_size) { + decode->displacement = (uint16_t)decode_bytes(cpu, decode, + decode->displacement_size); + } + break; + case 4: + case 8: + if (-1 == disp32_tbl[mod][rm]) { + if (5 == decode->sib.base) { + decode->displacement_size = 4; } - else - decode->displacement_size = disp32_tbl[mod][rm]; - - if (decode->displacement_size) - decode->displacement = (uint32_t)decode_bytes(cpu, decode, decode->displacement_size); - break; + } else { + decode->displacement_size = disp32_tbl[mod][rm]; + } + + if (decode->displacement_size) { + decode->displacement = (uint32_t)decode_bytes(cpu, decode, + decode->displacement_size); + } + break; } } @@ -1520,40 +2021,52 @@ static inline void decode_modrm(CPUState *cpu, struct x86_decode *decode) { decode->modrm.modrm = decode_byte(cpu, decode); decode->is_modrm = true; - + decode_sib(cpu, decode); decode_displacement(cpu, decode); } -static inline void decode_opcode_general(CPUState *cpu, struct x86_decode *decode, uint8_t opcode, struct decode_tbl *inst_decoder) +static inline void decode_opcode_general(CPUState *cpu, + struct x86_decode *decode, + uint8_t opcode, + struct decode_tbl *inst_decoder) { decode->cmd = inst_decoder->cmd; - if (inst_decoder->operand_size) + if (inst_decoder->operand_size) { decode->operand_size = inst_decoder->operand_size; + } decode->flags_mask = inst_decoder->flags_mask; - - if (inst_decoder->is_modrm) + + if (inst_decoder->is_modrm) { decode_modrm(cpu, decode); - if (inst_decoder->decode_op1) + } + if (inst_decoder->decode_op1) { inst_decoder->decode_op1(cpu, decode, &decode->op[0]); - if (inst_decoder->decode_op2) + } + if (inst_decoder->decode_op2) { inst_decoder->decode_op2(cpu, decode, &decode->op[1]); - if (inst_decoder->decode_op3) + } + if (inst_decoder->decode_op3) { inst_decoder->decode_op3(cpu, decode, &decode->op[2]); - if (inst_decoder->decode_op4) + } + if (inst_decoder->decode_op4) { inst_decoder->decode_op4(cpu, decode, &decode->op[3]); - if (inst_decoder->decode_postfix) + } + if (inst_decoder->decode_postfix) { inst_decoder->decode_postfix(cpu, decode); + } } -static inline void decode_opcode_1(CPUState *cpu, struct x86_decode *decode, uint8_t opcode) +static inline void decode_opcode_1(CPUState *cpu, struct x86_decode *decode, + uint8_t opcode) { struct decode_tbl *inst_decoder = &_decode_tbl1[opcode]; decode_opcode_general(cpu, decode, opcode, inst_decoder); } -static inline void decode_opcode_2(CPUState *cpu, struct x86_decode *decode, uint8_t opcode) +static inline void decode_opcode_2(CPUState *cpu, struct x86_decode *decode, + uint8_t opcode) { struct decode_tbl *inst_decoder = &_decode_tbl2[opcode]; decode_opcode_general(cpu, decode, opcode, inst_decoder); @@ -1562,7 +2075,7 @@ static inline void decode_opcode_2(CPUState *cpu, struct x86_decode *decode, uin static void decode_opcodes(CPUState *cpu, struct x86_decode *decode) { uint8_t opcode; - + opcode = decode_byte(cpu, decode); decode->opcode[decode->opcode_len++] = opcode; if (opcode != OPCODE_ESCAPE) { @@ -1583,21 +2096,24 @@ uint32_t decode_instruction(CPUState *cpu, struct x86_decode *decode) set_operand_size(cpu, decode); decode_opcodes(cpu, decode); - + return decode->len; } void init_decoder(CPUState *cpu) { int i; - - for (i = 0; i < ARRAY_SIZE(_decode_tbl2); i++) + + for (i = 0; i < ARRAY_SIZE(_decode_tbl2); i++) { memcpy(_decode_tbl1, &invl_inst, sizeof(invl_inst)); - for (i = 0; i < ARRAY_SIZE(_decode_tbl2); i++) + } + for (i = 0; i < ARRAY_SIZE(_decode_tbl2); i++) { memcpy(_decode_tbl2, &invl_inst, sizeof(invl_inst)); - for (i = 0; i < ARRAY_SIZE(_decode_tbl3); i++) + } + for (i = 0; i < ARRAY_SIZE(_decode_tbl3); i++) { memcpy(_decode_tbl3, &invl_inst, sizeof(invl_inst_x87)); - + } + for (i = 0; i < ARRAY_SIZE(_1op_inst); i++) { _decode_tbl1[_1op_inst[i].opcode] = _1op_inst[i]; } @@ -1605,7 +2121,9 @@ void init_decoder(CPUState *cpu) _decode_tbl2[_2op_inst[i].opcode] = _2op_inst[i]; } for (i = 0; i < ARRAY_SIZE(_x87_inst); i++) { - int index = ((_x87_inst[i].opcode & 0xf) << 4) | ((_x87_inst[i].modrm_mod & 1) << 3) | _x87_inst[i].modrm_reg; + int index = ((_x87_inst[i].opcode & 0xf) << 4) | + ((_x87_inst[i].modrm_mod & 1) << 3) | + _x87_inst[i].modrm_reg; _decode_tbl3[index] = _x87_inst[i]; } } @@ -1613,47 +2131,55 @@ void init_decoder(CPUState *cpu) const char *decode_cmd_to_string(enum x86_decode_cmd cmd) { - static const char *cmds[] = {"INVL", "PUSH", "PUSH_SEG", "POP", "POP_SEG", "MOV", "MOVSX", "MOVZX", "CALL_NEAR", - "CALL_NEAR_ABS_INDIRECT", "CALL_FAR_ABS_INDIRECT", "CMD_CALL_FAR", "RET_NEAR", "RET_FAR", "ADD", "OR", - "ADC", "SBB", "AND", "SUB", "XOR", "CMP", "INC", "DEC", "TST", "NOT", "NEG", "JMP_NEAR", "JMP_NEAR_ABS_INDIRECT", - "JMP_FAR", "JMP_FAR_ABS_INDIRECT", "LEA", "JXX", - "JCXZ", "SETXX", "MOV_TO_SEG", "MOV_FROM_SEG", "CLI", "STI", "CLD", "STD", "STC", - "CLC", "OUT", "IN", "INS", "OUTS", "LIDT", "SIDT", "LGDT", "SGDT", "SMSW", "LMSW", "RDTSCP", "INVLPG", "MOV_TO_CR", - "MOV_FROM_CR", "MOV_TO_DR", "MOV_FROM_DR", "PUSHF", "POPF", "CPUID", "ROL", "ROR", "RCL", "RCR", "SHL", "SAL", - "SHR","SHRD", "SHLD", "SAR", "DIV", "IDIV", "MUL", "IMUL_3", "IMUL_2", "IMUL_1", "MOVS", "CMPS", "SCAS", - "LODS", "STOS", "BSWAP", "XCHG", "RDTSC", "RDMSR", "WRMSR", "ENTER", "LEAVE", "BT", "BTS", "BTC", "BTR", "BSF", - "BSR", "IRET", "INT", "POPA", "PUSHA", "CWD", "CBW", "DAS", "AAD", "AAM", "AAS", "LOOP", "SLDT", "STR", "LLDT", - "LTR", "VERR", "VERW", "SAHF", "LAHF", "WBINVD", "LDS", "LSS", "LES", "LGS", "LFS", "CMC", "XLAT", "NOP", "CMOV", - "CLTS", "XADD", "HLT", "CMPXCHG8B", "CMPXCHG", "POPCNT", - "FNINIT", "FLD", "FLDxx", "FNSTCW", "FNSTSW", "FNSETPM", "FSAVE", "FRSTOR", "FXSAVE", "FXRSTOR", "FDIV", "FMUL", - "FSUB", "FADD", "EMMS", "MFENCE", "SFENCE", "LFENCE", "PREFETCH", "FST", "FABS", "FUCOM", "FUCOMI", "FLDCW", + static const char *cmds[] = {"INVL", "PUSH", "PUSH_SEG", "POP", "POP_SEG", + "MOV", "MOVSX", "MOVZX", "CALL_NEAR", "CALL_NEAR_ABS_INDIRECT", + "CALL_FAR_ABS_INDIRECT", "CMD_CALL_FAR", "RET_NEAR", "RET_FAR", "ADD", + "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP", "INC", "DEC", "TST", + "NOT", "NEG", "JMP_NEAR", "JMP_NEAR_ABS_INDIRECT", "JMP_FAR", + "JMP_FAR_ABS_INDIRECT", "LEA", "JXX", "JCXZ", "SETXX", "MOV_TO_SEG", + "MOV_FROM_SEG", "CLI", "STI", "CLD", "STD", "STC", "CLC", "OUT", "IN", + "INS", "OUTS", "LIDT", "SIDT", "LGDT", "SGDT", "SMSW", "LMSW", + "RDTSCP", "INVLPG", "MOV_TO_CR", "MOV_FROM_CR", "MOV_TO_DR", + "MOV_FROM_DR", "PUSHF", "POPF", "CPUID", "ROL", "ROR", "RCL", "RCR", + "SHL", "SAL", "SHR", "SHRD", "SHLD", "SAR", "DIV", "IDIV", "MUL", + "IMUL_3", "IMUL_2", "IMUL_1", "MOVS", "CMPS", "SCAS", "LODS", "STOS", + "BSWAP", "XCHG", "RDTSC", "RDMSR", "WRMSR", "ENTER", "LEAVE", "BT", + "BTS", "BTC", "BTR", "BSF", "BSR", "IRET", "INT", "POPA", "PUSHA", + "CWD", "CBW", "DAS", "AAD", "AAM", "AAS", "LOOP", "SLDT", "STR", "LLDT", + "LTR", "VERR", "VERW", "SAHF", "LAHF", "WBINVD", "LDS", "LSS", "LES", + "LGS", "LFS", "CMC", "XLAT", "NOP", "CMOV", "CLTS", "XADD", "HLT", + "CMPXCHG8B", "CMPXCHG", "POPCNT", "FNINIT", "FLD", "FLDxx", "FNSTCW", + "FNSTSW", "FNSETPM", "FSAVE", "FRSTOR", "FXSAVE", "FXRSTOR", "FDIV", + "FMUL", "FSUB", "FADD", "EMMS", "MFENCE", "SFENCE", "LFENCE", + "PREFETCH", "FST", "FABS", "FUCOM", "FUCOMI", "FLDCW", "FXCH", "FCHS", "FCMOV", "FRNDINT", "FXAM", "LAST"}; return cmds[cmd]; } -addr_t decode_linear_addr(struct CPUState *cpu, struct x86_decode *decode, addr_t addr, x86_reg_segment seg) +addr_t decode_linear_addr(struct CPUState *cpu, struct x86_decode *decode, + addr_t addr, x86_reg_segment seg) { switch (decode->segment_override) { - case PREFIX_CS_SEG_OVEERIDE: - seg = REG_SEG_CS; - break; - case PREFIX_SS_SEG_OVEERIDE: - seg = REG_SEG_SS; - break; - case PREFIX_DS_SEG_OVEERIDE: - seg = REG_SEG_DS; - break; - case PREFIX_ES_SEG_OVEERIDE: - seg = REG_SEG_ES; - break; - case PREFIX_FS_SEG_OVEERIDE: - seg = REG_SEG_FS; - break; - case PREFIX_GS_SEG_OVEERIDE: - seg = REG_SEG_GS; - break; - default: - break; + case PREFIX_CS_SEG_OVEERIDE: + seg = REG_SEG_CS; + break; + case PREFIX_SS_SEG_OVEERIDE: + seg = REG_SEG_SS; + break; + case PREFIX_DS_SEG_OVEERIDE: + seg = REG_SEG_DS; + break; + case PREFIX_ES_SEG_OVEERIDE: + seg = REG_SEG_ES; + break; + case PREFIX_FS_SEG_OVEERIDE: + seg = REG_SEG_FS; + break; + case PREFIX_GS_SEG_OVEERIDE: + seg = REG_SEG_GS; + break; + default: + break; } return linear_addr_size(cpu, addr, decode->addressing_size, seg); } diff --git a/target/i386/hvf-utils/x86_decode.h b/target/i386/hvf-utils/x86_decode.h index 3a22d7d1a5..b6763e1ba1 100644 --- a/target/i386/hvf-utils/x86_decode.h +++ b/target/i386/hvf-utils/x86_decode.h @@ -25,20 +25,20 @@ #include "x86.h" typedef enum x86_prefix { - // group 1 + /* group 1 */ PREFIX_LOCK = 0xf0, PREFIX_REPN = 0xf2, PREFIX_REP = 0xf3, - // group 2 + /* group 2 */ PREFIX_CS_SEG_OVEERIDE = 0x2e, PREFIX_SS_SEG_OVEERIDE = 0x36, PREFIX_DS_SEG_OVEERIDE = 0x3e, PREFIX_ES_SEG_OVEERIDE = 0x26, PREFIX_FS_SEG_OVEERIDE = 0x64, PREFIX_GS_SEG_OVEERIDE = 0x65, - // group 3 + /* group 3 */ PREFIX_OP_SIZE_OVERRIDE = 0x66, - // group 4 + /* group 4 */ PREFIX_ADDR_SIZE_OVERRIDE = 0x67, PREFIX_REX = 0x40, @@ -46,7 +46,7 @@ typedef enum x86_prefix { enum x86_decode_cmd { X86_DECODE_CMD_INVL = 0, - + X86_DECODE_CMD_PUSH, X86_DECODE_CMD_PUSH_SEG, X86_DECODE_CMD_POP, @@ -177,7 +177,7 @@ enum x86_decode_cmd { X86_DECODE_CMD_CMPXCHG8B, X86_DECODE_CMD_CMPXCHG, X86_DECODE_CMD_POPCNT, - + X86_DECODE_CMD_FNINIT, X86_DECODE_CMD_FLD, X86_DECODE_CMD_FLDxx, @@ -255,7 +255,7 @@ typedef enum x86_var_type { X86_VAR_REG, X86_VAR_RM, - // for floating point computations + /* for floating point computations */ X87_VAR_REG, X87_VAR_FLOATP, X87_VAR_INTP, @@ -308,7 +308,17 @@ uint32_t decode_instruction(CPUState *cpu, struct x86_decode *decode); addr_t get_reg_ref(CPUState *cpu, int reg, int is_extended, int size); addr_t get_reg_val(CPUState *cpu, int reg, int is_extended, int size); -void calc_modrm_operand(CPUState *cpu, struct x86_decode *decode, struct x86_decode_op *op); -addr_t decode_linear_addr(struct CPUState *cpu, struct x86_decode *decode, addr_t addr, x86_reg_segment seg); +void calc_modrm_operand(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op); +addr_t decode_linear_addr(struct CPUState *cpu, struct x86_decode *decode, + addr_t addr, x86_reg_segment seg); -void init_decoder(CPUState* cpu); +void init_decoder(CPUState *cpu); +void calc_modrm_operand16(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op); +void calc_modrm_operand32(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op); +void calc_modrm_operand64(CPUState *cpu, struct x86_decode *decode, + struct x86_decode_op *op); +void set_addressing_size(CPUState *cpu, struct x86_decode *decode); +void set_operand_size(CPUState *cpu, struct x86_decode *decode); diff --git a/target/i386/hvf-utils/x86_descr.h b/target/i386/hvf-utils/x86_descr.h index 78fb1bc420..f5e247782b 100644 --- a/target/i386/hvf-utils/x86_descr.h +++ b/target/i386/hvf-utils/x86_descr.h @@ -27,14 +27,29 @@ typedef struct vmx_segment { uint64_t ar; } vmx_segment; -// deal with vmstate descriptors -void vmx_read_segment_descriptor(struct CPUState *cpu, struct vmx_segment *desc, x86_reg_segment seg); -void vmx_write_segment_descriptor(CPUState *cpu, struct vmx_segment *desc, x86_reg_segment seg); +/* deal with vmstate descriptors */ +void vmx_read_segment_descriptor(struct CPUState *cpu, + struct vmx_segment *desc, x86_reg_segment seg); +void vmx_write_segment_descriptor(CPUState *cpu, struct vmx_segment *desc, + x86_reg_segment seg); -x68_segment_selector vmx_read_segment_selector(struct CPUState *cpu, x86_reg_segment seg); -void vmx_write_segment_selector(struct CPUState *cpu, x68_segment_selector selector, x86_reg_segment seg); +x68_segment_selector vmx_read_segment_selector(struct CPUState *cpu, + x86_reg_segment seg); +void vmx_write_segment_selector(struct CPUState *cpu, + x68_segment_selector selector, + x86_reg_segment seg); uint64_t vmx_read_segment_base(struct CPUState *cpu, x86_reg_segment seg); -void vmx_write_segment_base(struct CPUState *cpu, x86_reg_segment seg, uint64_t base); +void vmx_write_segment_base(struct CPUState *cpu, x86_reg_segment seg, + uint64_t base); -void x86_segment_descriptor_to_vmx(struct CPUState *cpu, x68_segment_selector selector, struct x86_segment_descriptor *desc, struct vmx_segment *vmx_desc); +void x86_segment_descriptor_to_vmx(struct CPUState *cpu, + x68_segment_selector selector, + struct x86_segment_descriptor *desc, + struct vmx_segment *vmx_desc); + +uint32_t vmx_read_segment_limit(CPUState *cpu, x86_reg_segment seg); +uint32_t vmx_read_segment_ar(CPUState *cpu, x86_reg_segment seg); +void vmx_segment_to_x86_descriptor(struct CPUState *cpu, + struct vmx_segment *vmx_desc, + struct x86_segment_descriptor *desc); diff --git a/target/i386/hvf-utils/x86_emu.c b/target/i386/hvf-utils/x86_emu.c index 8b5efc76f0..dc33cd2576 100644 --- a/target/i386/hvf-utils/x86_emu.c +++ b/target/i386/hvf-utils/x86_emu.c @@ -45,8 +45,8 @@ #include "vmcs.h" #include "vmx.h" -static void print_debug(struct CPUState *cpu); -void hvf_handle_io(struct CPUState *cpu, uint16_t port, void *data, int direction, int size, uint32_t count); +void hvf_handle_io(struct CPUState *cpu, uint16_t port, void *data, + int direction, int size, uint32_t count); #define EXEC_2OP_LOGIC_CMD(cpu, decode, cmd, FLAGS_FUNC, save_res) \ { \ @@ -57,8 +57,9 @@ void hvf_handle_io(struct CPUState *cpu, uint16_t port, void *data, int directio uint8_t v1 = (uint8_t)decode->op[0].val; \ uint8_t v2 = (uint8_t)decode->op[1].val; \ uint8_t diff = v1 cmd v2; \ - if (save_res) \ + if (save_res) { \ write_val_ext(cpu, decode->op[0].ptr, diff, 1); \ + } \ FLAGS_FUNC##_8(diff); \ break; \ } \ @@ -67,8 +68,9 @@ void hvf_handle_io(struct CPUState *cpu, uint16_t port, void *data, int directio uint16_t v1 = (uint16_t)decode->op[0].val; \ uint16_t v2 = (uint16_t)decode->op[1].val; \ uint16_t diff = v1 cmd v2; \ - if (save_res) \ + if (save_res) { \ write_val_ext(cpu, decode->op[0].ptr, diff, 2); \ + } \ FLAGS_FUNC##_16(diff); \ break; \ } \ @@ -77,8 +79,9 @@ void hvf_handle_io(struct CPUState *cpu, uint16_t port, void *data, int directio uint32_t v1 = (uint32_t)decode->op[0].val; \ uint32_t v2 = (uint32_t)decode->op[1].val; \ uint32_t diff = v1 cmd v2; \ - if (save_res) \ + if (save_res) { \ write_val_ext(cpu, decode->op[0].ptr, diff, 4); \ + } \ FLAGS_FUNC##_32(diff); \ break; \ } \ @@ -97,8 +100,9 @@ void hvf_handle_io(struct CPUState *cpu, uint16_t port, void *data, int directio uint8_t v1 = (uint8_t)decode->op[0].val; \ uint8_t v2 = (uint8_t)decode->op[1].val; \ uint8_t diff = v1 cmd v2; \ - if (save_res) \ + if (save_res) { \ write_val_ext(cpu, decode->op[0].ptr, diff, 1); \ + } \ FLAGS_FUNC##_8(v1, v2, diff); \ break; \ } \ @@ -107,8 +111,9 @@ void hvf_handle_io(struct CPUState *cpu, uint16_t port, void *data, int directio uint16_t v1 = (uint16_t)decode->op[0].val; \ uint16_t v2 = (uint16_t)decode->op[1].val; \ uint16_t diff = v1 cmd v2; \ - if (save_res) \ + if (save_res) { \ write_val_ext(cpu, decode->op[0].ptr, diff, 2); \ + } \ FLAGS_FUNC##_16(v1, v2, diff); \ break; \ } \ @@ -117,8 +122,9 @@ void hvf_handle_io(struct CPUState *cpu, uint16_t port, void *data, int directio uint32_t v1 = (uint32_t)decode->op[0].val; \ uint32_t v2 = (uint32_t)decode->op[1].val; \ uint32_t diff = v1 cmd v2; \ - if (save_res) \ + if (save_res) { \ write_val_ext(cpu, decode->op[0].ptr, diff, 4); \ + } \ FLAGS_FUNC##_32(v1, v2, diff); \ break; \ } \ @@ -127,63 +133,63 @@ void hvf_handle_io(struct CPUState *cpu, uint16_t port, void *data, int directio } \ } -addr_t read_reg(struct CPUState* cpu, int reg, int size) +addr_t read_reg(struct CPUState *cpu, int reg, int size) { switch (size) { - case 1: - return cpu->hvf_x86->regs[reg].lx; - case 2: - return cpu->hvf_x86->regs[reg].rx; - case 4: - return cpu->hvf_x86->regs[reg].erx; - case 8: - return cpu->hvf_x86->regs[reg].rrx; - default: - VM_PANIC_ON("read_reg size"); + case 1: + return cpu->hvf_x86->regs[reg].lx; + case 2: + return cpu->hvf_x86->regs[reg].rx; + case 4: + return cpu->hvf_x86->regs[reg].erx; + case 8: + return cpu->hvf_x86->regs[reg].rrx; + default: + VM_PANIC_ON("read_reg size"); } return 0; } -void write_reg(struct CPUState* cpu, int reg, addr_t val, int size) +void write_reg(struct CPUState *cpu, int reg, addr_t val, int size) { switch (size) { - case 1: - cpu->hvf_x86->regs[reg].lx = val; - break; - case 2: - cpu->hvf_x86->regs[reg].rx = val; - break; - case 4: - cpu->hvf_x86->regs[reg].rrx = (uint32_t)val; - break; - case 8: - cpu->hvf_x86->regs[reg].rrx = val; - break; - default: - VM_PANIC_ON("write_reg size"); + case 1: + cpu->hvf_x86->regs[reg].lx = val; + break; + case 2: + cpu->hvf_x86->regs[reg].rx = val; + break; + case 4: + cpu->hvf_x86->regs[reg].rrx = (uint32_t)val; + break; + case 8: + cpu->hvf_x86->regs[reg].rrx = val; + break; + default: + VM_PANIC_ON("write_reg size"); } } addr_t read_val_from_reg(addr_t reg_ptr, int size) { addr_t val; - + switch (size) { - case 1: - val = *(uint8_t*)reg_ptr; - break; - case 2: - val = *(uint16_t*)reg_ptr; - break; - case 4: - val = *(uint32_t*)reg_ptr; - break; - case 8: - val = *(uint64_t*)reg_ptr; - break; - default: - VM_PANIC_ON_EX(1, "read_val: Unknown size %d\n", size); - break; + case 1: + val = *(uint8_t *)reg_ptr; + break; + case 2: + val = *(uint16_t *)reg_ptr; + break; + case 4: + val = *(uint32_t *)reg_ptr; + break; + case 8: + val = *(uint64_t *)reg_ptr; + break; + default: + VM_PANIC_ON_EX(1, "read_val: Unknown size %d\n", size); + break; } return val; } @@ -191,30 +197,32 @@ addr_t read_val_from_reg(addr_t reg_ptr, int size) void write_val_to_reg(addr_t reg_ptr, addr_t val, int size) { switch (size) { - case 1: - *(uint8_t*)reg_ptr = val; - break; - case 2: - *(uint16_t*)reg_ptr = val; - break; - case 4: - *(uint64_t*)reg_ptr = (uint32_t)val; - break; - case 8: - *(uint64_t*)reg_ptr = val; - break; - default: - VM_PANIC("write_val: Unknown size\n"); - break; + case 1: + *(uint8_t *)reg_ptr = val; + break; + case 2: + *(uint16_t *)reg_ptr = val; + break; + case 4: + *(uint64_t *)reg_ptr = (uint32_t)val; + break; + case 8: + *(uint64_t *)reg_ptr = val; + break; + default: + VM_PANIC("write_val: Unknown size\n"); + break; } } -static bool is_host_reg(struct CPUState* cpu, addr_t ptr) { +static bool is_host_reg(struct CPUState *cpu, addr_t ptr) +{ return (ptr > (addr_t)cpu && ptr < (addr_t)cpu + sizeof(struct CPUState)) || - (ptr > (addr_t)cpu->hvf_x86 && ptr < (addr_t)(cpu->hvf_x86 + sizeof(struct hvf_x86_state))); + (ptr > (addr_t)cpu->hvf_x86 && ptr < + (addr_t)(cpu->hvf_x86 + sizeof(struct hvf_x86_state))); } -void write_val_ext(struct CPUState* cpu, addr_t ptr, addr_t val, int size) +void write_val_ext(struct CPUState *cpu, addr_t ptr, addr_t val, int size) { if (is_host_reg(cpu, ptr)) { write_val_to_reg(ptr, val, size); @@ -223,68 +231,77 @@ void write_val_ext(struct CPUState* cpu, addr_t ptr, addr_t val, int size) vmx_write_mem(cpu, ptr, &val, size); } -uint8_t *read_mmio(struct CPUState* cpu, addr_t ptr, int bytes) +uint8_t *read_mmio(struct CPUState *cpu, addr_t ptr, int bytes) { vmx_read_mem(cpu, cpu->hvf_x86->mmio_buf, ptr, bytes); return cpu->hvf_x86->mmio_buf; } -addr_t read_val_ext(struct CPUState* cpu, addr_t ptr, int size) +addr_t read_val_ext(struct CPUState *cpu, addr_t ptr, int size) { addr_t val; uint8_t *mmio_ptr; - + if (is_host_reg(cpu, ptr)) { return read_val_from_reg(ptr, size); } - + mmio_ptr = read_mmio(cpu, ptr, size); switch (size) { - case 1: - val = *(uint8_t*)mmio_ptr; - break; - case 2: - val = *(uint16_t*)mmio_ptr; - break; - case 4: - val = *(uint32_t*)mmio_ptr; - break; - case 8: - val = *(uint64_t*)mmio_ptr; - break; - default: - VM_PANIC("bad size\n"); - break; + case 1: + val = *(uint8_t *)mmio_ptr; + break; + case 2: + val = *(uint16_t *)mmio_ptr; + break; + case 4: + val = *(uint32_t *)mmio_ptr; + break; + case 8: + val = *(uint64_t *)mmio_ptr; + break; + default: + VM_PANIC("bad size\n"); + break; } return val; } -static void fetch_operands(struct CPUState *cpu, struct x86_decode *decode, int n, bool val_op0, bool val_op1, bool val_op2) +static void fetch_operands(struct CPUState *cpu, struct x86_decode *decode, + int n, bool val_op0, bool val_op1, bool val_op2) { int i; bool calc_val[3] = {val_op0, val_op1, val_op2}; for (i = 0; i < n; i++) { switch (decode->op[i].type) { - case X86_VAR_IMMEDIATE: - break; - case X86_VAR_REG: - VM_PANIC_ON(!decode->op[i].ptr); - if (calc_val[i]) - decode->op[i].val = read_val_from_reg(decode->op[i].ptr, decode->operand_size); - break; - case X86_VAR_RM: - calc_modrm_operand(cpu, decode, &decode->op[i]); - if (calc_val[i]) - decode->op[i].val = read_val_ext(cpu, decode->op[i].ptr, decode->operand_size); - break; - case X86_VAR_OFFSET: - decode->op[i].ptr = decode_linear_addr(cpu, decode, decode->op[i].ptr, REG_SEG_DS); - if (calc_val[i]) - decode->op[i].val = read_val_ext(cpu, decode->op[i].ptr, decode->operand_size); - break; - default: - break; + case X86_VAR_IMMEDIATE: + break; + case X86_VAR_REG: + VM_PANIC_ON(!decode->op[i].ptr); + if (calc_val[i]) { + decode->op[i].val = read_val_from_reg(decode->op[i].ptr, + decode->operand_size); + } + break; + case X86_VAR_RM: + calc_modrm_operand(cpu, decode, &decode->op[i]); + if (calc_val[i]) { + decode->op[i].val = read_val_ext(cpu, decode->op[i].ptr, + decode->operand_size); + } + break; + case X86_VAR_OFFSET: + decode->op[i].ptr = decode_linear_addr(cpu, decode, + decode->op[i].ptr, + REG_SEG_DS); + if (calc_val[i]) { + decode->op[i].val = read_val_ext(cpu, decode->op[i].ptr, + decode->operand_size); + } + break; + default: + break; } } } @@ -292,7 +309,8 @@ static void fetch_operands(struct CPUState *cpu, struct x86_decode *decode, int static void exec_mov(struct CPUState *cpu, struct x86_decode *decode) { fetch_operands(cpu, decode, 2, false, true, false); - write_val_ext(cpu, decode->op[0].ptr, decode->op[1].val, decode->operand_size); + write_val_ext(cpu, decode->op[0].ptr, decode->op[1].val, + decode->operand_size); RIP(cpu) += decode->len; } @@ -341,7 +359,7 @@ static void exec_xor(struct CPUState *cpu, struct x86_decode *decode) static void exec_neg(struct CPUState *cpu, struct x86_decode *decode) { - //EXEC_2OP_ARITH_CMD(cpu, decode, -, SET_FLAGS_OSZAPC_SUB, false); + /*EXEC_2OP_ARITH_CMD(cpu, decode, -, SET_FLAGS_OSZAPC_SUB, false);*/ int32_t val; fetch_operands(cpu, decode, 2, true, true, false); @@ -350,17 +368,15 @@ static void exec_neg(struct CPUState *cpu, struct x86_decode *decode) if (4 == decode->operand_size) { SET_FLAGS_OSZAPC_SUB_32(0, 0 - val, val); - } - else if (2 == decode->operand_size) { + } else if (2 == decode->operand_size) { SET_FLAGS_OSZAPC_SUB_16(0, 0 - val, val); - } - else if (1 == decode->operand_size) { + } else if (1 == decode->operand_size) { SET_FLAGS_OSZAPC_SUB_8(0, 0 - val, val); } else { VM_PANIC("bad op size\n"); } - //lflags_to_rflags(cpu); + /*lflags_to_rflags(cpu);*/ RIP(cpu) += decode->len; } @@ -399,7 +415,8 @@ static void exec_not(struct CPUState *cpu, struct x86_decode *decode) { fetch_operands(cpu, decode, 1, true, false, false); - write_val_ext(cpu, decode->op[0].ptr, ~decode->op[0].val, decode->operand_size); + write_val_ext(cpu, decode->op[0].ptr, ~decode->op[0].val, + decode->operand_size); RIP(cpu) += decode->len; } @@ -410,10 +427,11 @@ void exec_movzx(struct CPUState *cpu, struct x86_decode *decode) fetch_operands(cpu, decode, 1, false, false, false); - if (0xb6 == decode->opcode[1]) + if (0xb6 == decode->opcode[1]) { src_op_size = 1; - else + } else { src_op_size = 2; + } decode->operand_size = src_op_size; calc_modrm_operand(cpu, decode, &decode->op[1]); decode->op[1].val = read_val_ext(cpu, decode->op[1].ptr, src_op_size); @@ -425,21 +443,22 @@ void exec_movzx(struct CPUState *cpu, struct x86_decode *decode) static void exec_out(struct CPUState *cpu, struct x86_decode *decode) { switch (decode->opcode[0]) { - case 0xe6: - hvf_handle_io(cpu, decode->op[0].val, &AL(cpu), 1, 1, 1); - break; - case 0xe7: - hvf_handle_io(cpu, decode->op[0].val, &RAX(cpu), 1, decode->operand_size, 1); - break; - case 0xee: - hvf_handle_io(cpu, DX(cpu), &AL(cpu), 1, 1, 1); - break; - case 0xef: - hvf_handle_io(cpu, DX(cpu), &RAX(cpu), 1, decode->operand_size, 1); - break; - default: - VM_PANIC("Bad out opcode\n"); - break; + case 0xe6: + hvf_handle_io(cpu, decode->op[0].val, &AL(cpu), 1, 1, 1); + break; + case 0xe7: + hvf_handle_io(cpu, decode->op[0].val, &RAX(cpu), 1, + decode->operand_size, 1); + break; + case 0xee: + hvf_handle_io(cpu, DX(cpu), &AL(cpu), 1, 1, 1); + break; + case 0xef: + hvf_handle_io(cpu, DX(cpu), &RAX(cpu), 1, decode->operand_size, 1); + break; + default: + VM_PANIC("Bad out opcode\n"); + break; } RIP(cpu) += decode->len; } @@ -448,63 +467,73 @@ static void exec_in(struct CPUState *cpu, struct x86_decode *decode) { addr_t val = 0; switch (decode->opcode[0]) { - case 0xe4: - hvf_handle_io(cpu, decode->op[0].val, &AL(cpu), 0, 1, 1); - break; - case 0xe5: - hvf_handle_io(cpu, decode->op[0].val, &val, 0, decode->operand_size, 1); - if (decode->operand_size == 2) - AX(cpu) = val; - else - RAX(cpu) = (uint32_t)val; - break; - case 0xec: - hvf_handle_io(cpu, DX(cpu), &AL(cpu), 0, 1, 1); - break; - case 0xed: - hvf_handle_io(cpu, DX(cpu), &val, 0, decode->operand_size, 1); - if (decode->operand_size == 2) - AX(cpu) = val; - else - RAX(cpu) = (uint32_t)val; + case 0xe4: + hvf_handle_io(cpu, decode->op[0].val, &AL(cpu), 0, 1, 1); + break; + case 0xe5: + hvf_handle_io(cpu, decode->op[0].val, &val, 0, decode->operand_size, 1); + if (decode->operand_size == 2) { + AX(cpu) = val; + } else { + RAX(cpu) = (uint32_t)val; + } + break; + case 0xec: + hvf_handle_io(cpu, DX(cpu), &AL(cpu), 0, 1, 1); + break; + case 0xed: + hvf_handle_io(cpu, DX(cpu), &val, 0, decode->operand_size, 1); + if (decode->operand_size == 2) { + AX(cpu) = val; + } else { + RAX(cpu) = (uint32_t)val; + } - break; - default: - VM_PANIC("Bad in opcode\n"); - break; + break; + default: + VM_PANIC("Bad in opcode\n"); + break; } RIP(cpu) += decode->len; } -static inline void string_increment_reg(struct CPUState * cpu, int reg, struct x86_decode *decode) +static inline void string_increment_reg(struct CPUState *cpu, int reg, + struct x86_decode *decode) { addr_t val = read_reg(cpu, reg, decode->addressing_size); - if (cpu->hvf_x86->rflags.df) + if (cpu->hvf_x86->rflags.df) { val -= decode->operand_size; - else + } else { val += decode->operand_size; + } write_reg(cpu, reg, val, decode->addressing_size); } -static inline void string_rep(struct CPUState * cpu, struct x86_decode *decode, void (*func)(struct CPUState *cpu, struct x86_decode *ins), int rep) +static inline void string_rep(struct CPUState *cpu, struct x86_decode *decode, + void (*func)(struct CPUState *cpu, + struct x86_decode *ins), int rep) { addr_t rcx = read_reg(cpu, REG_RCX, decode->addressing_size); while (rcx--) { func(cpu, decode); write_reg(cpu, REG_RCX, rcx, decode->addressing_size); - if ((PREFIX_REP == rep) && !get_ZF(cpu)) + if ((PREFIX_REP == rep) && !get_ZF(cpu)) { break; - if ((PREFIX_REPN == rep) && get_ZF(cpu)) + } + if ((PREFIX_REPN == rep) && get_ZF(cpu)) { break; + } } } static void exec_ins_single(struct CPUState *cpu, struct x86_decode *decode) { - addr_t addr = linear_addr_size(cpu, RDI(cpu), decode->addressing_size, REG_SEG_ES); + addr_t addr = linear_addr_size(cpu, RDI(cpu), decode->addressing_size, + REG_SEG_ES); - hvf_handle_io(cpu, DX(cpu), cpu->hvf_x86->mmio_buf, 0, decode->operand_size, 1); + hvf_handle_io(cpu, DX(cpu), cpu->hvf_x86->mmio_buf, 0, + decode->operand_size, 1); vmx_write_mem(cpu, addr, cpu->hvf_x86->mmio_buf, decode->operand_size); string_increment_reg(cpu, REG_RDI, decode); @@ -512,10 +541,11 @@ static void exec_ins_single(struct CPUState *cpu, struct x86_decode *decode) static void exec_ins(struct CPUState *cpu, struct x86_decode *decode) { - if (decode->rep) + if (decode->rep) { string_rep(cpu, decode, exec_ins_single, 0); - else + } else { exec_ins_single(cpu, decode); + } RIP(cpu) += decode->len; } @@ -525,18 +555,20 @@ static void exec_outs_single(struct CPUState *cpu, struct x86_decode *decode) addr_t addr = decode_linear_addr(cpu, decode, RSI(cpu), REG_SEG_DS); vmx_read_mem(cpu, cpu->hvf_x86->mmio_buf, addr, decode->operand_size); - hvf_handle_io(cpu, DX(cpu), cpu->hvf_x86->mmio_buf, 1, decode->operand_size, 1); + hvf_handle_io(cpu, DX(cpu), cpu->hvf_x86->mmio_buf, 1, + decode->operand_size, 1); string_increment_reg(cpu, REG_RSI, decode); } static void exec_outs(struct CPUState *cpu, struct x86_decode *decode) { - if (decode->rep) + if (decode->rep) { string_rep(cpu, decode, exec_outs_single, 0); - else + } else { exec_outs_single(cpu, decode); - + } + RIP(cpu) += decode->len; } @@ -545,10 +577,11 @@ static void exec_movs_single(struct CPUState *cpu, struct x86_decode *decode) addr_t src_addr; addr_t dst_addr; addr_t val; - + src_addr = decode_linear_addr(cpu, decode, RSI(cpu), REG_SEG_DS); - dst_addr = linear_addr_size(cpu, RDI(cpu), decode->addressing_size, REG_SEG_ES); - + dst_addr = linear_addr_size(cpu, RDI(cpu), decode->addressing_size, + REG_SEG_ES); + val = read_val_ext(cpu, src_addr, decode->operand_size); write_val_ext(cpu, dst_addr, val, decode->operand_size); @@ -560,9 +593,9 @@ static void exec_movs(struct CPUState *cpu, struct x86_decode *decode) { if (decode->rep) { string_rep(cpu, decode, exec_movs_single, 0); - } - else + } else { exec_movs_single(cpu, decode); + } RIP(cpu) += decode->len; } @@ -573,7 +606,8 @@ static void exec_cmps_single(struct CPUState *cpu, struct x86_decode *decode) addr_t dst_addr; src_addr = decode_linear_addr(cpu, decode, RSI(cpu), REG_SEG_DS); - dst_addr = linear_addr_size(cpu, RDI(cpu), decode->addressing_size, REG_SEG_ES); + dst_addr = linear_addr_size(cpu, RDI(cpu), decode->addressing_size, + REG_SEG_ES); decode->op[0].type = X86_VAR_IMMEDIATE; decode->op[0].val = read_val_ext(cpu, src_addr, decode->operand_size); @@ -590,9 +624,9 @@ static void exec_cmps(struct CPUState *cpu, struct x86_decode *decode) { if (decode->rep) { string_rep(cpu, decode, exec_cmps_single, decode->rep); - } - else + } else { exec_cmps_single(cpu, decode); + } RIP(cpu) += decode->len; } @@ -614,9 +648,9 @@ static void exec_stos(struct CPUState *cpu, struct x86_decode *decode) { if (decode->rep) { string_rep(cpu, decode, exec_stos_single, 0); - } - else + } else { exec_stos_single(cpu, decode); + } RIP(cpu) += decode->len; } @@ -624,7 +658,7 @@ static void exec_stos(struct CPUState *cpu, struct x86_decode *decode) static void exec_scas_single(struct CPUState *cpu, struct x86_decode *decode) { addr_t addr; - + addr = linear_addr_size(cpu, RDI(cpu), decode->addressing_size, REG_SEG_ES); decode->op[1].type = X86_VAR_IMMEDIATE; vmx_read_mem(cpu, &decode->op[1].val, addr, decode->operand_size); @@ -639,9 +673,9 @@ static void exec_scas(struct CPUState *cpu, struct x86_decode *decode) decode->op[0].reg = REG_RAX; if (decode->rep) { string_rep(cpu, decode, exec_scas_single, decode->rep); - } - else + } else { exec_scas_single(cpu, decode); + } RIP(cpu) += decode->len; } @@ -650,7 +684,7 @@ static void exec_lods_single(struct CPUState *cpu, struct x86_decode *decode) { addr_t addr; addr_t val = 0; - + addr = decode_linear_addr(cpu, decode, RSI(cpu), REG_SEG_DS); vmx_read_mem(cpu, &val, addr, decode->operand_size); write_reg(cpu, REG_RAX, val, decode->operand_size); @@ -662,14 +696,14 @@ static void exec_lods(struct CPUState *cpu, struct x86_decode *decode) { if (decode->rep) { string_rep(cpu, decode, exec_lods_single, 0); - } - else + } else { exec_lods_single(cpu, decode); + } RIP(cpu) += decode->len; } -#define MSR_IA32_UCODE_REV 0x00000017 +#define MSR_IA32_UCODE_REV 0x00000017 void simulate_rdmsr(struct CPUState *cpu) { @@ -679,83 +713,83 @@ void simulate_rdmsr(struct CPUState *cpu) uint64_t val = 0; switch (msr) { - case MSR_IA32_TSC: - val = rdtscp() + rvmcs(cpu->hvf_fd, VMCS_TSC_OFFSET); - break; - case MSR_IA32_APICBASE: - val = cpu_get_apic_base(X86_CPU(cpu)->apic_state); - break; - case MSR_IA32_UCODE_REV: - val = (0x100000000ULL << 32) | 0x100000000ULL; - break; - case MSR_EFER: - val = rvmcs(cpu->hvf_fd, VMCS_GUEST_IA32_EFER); - break; - case MSR_FSBASE: - val = rvmcs(cpu->hvf_fd, VMCS_GUEST_FS_BASE); - break; - case MSR_GSBASE: - val = rvmcs(cpu->hvf_fd, VMCS_GUEST_GS_BASE); - break; - case MSR_KERNELGSBASE: - val = rvmcs(cpu->hvf_fd, VMCS_HOST_FS_BASE); - break; - case MSR_STAR: - abort(); - break; - case MSR_LSTAR: - abort(); - break; - case MSR_CSTAR: - abort(); - break; - case MSR_IA32_MISC_ENABLE: - val = env->msr_ia32_misc_enable; - break; - case MSR_MTRRphysBase(0): - case MSR_MTRRphysBase(1): - case MSR_MTRRphysBase(2): - case MSR_MTRRphysBase(3): - case MSR_MTRRphysBase(4): - case MSR_MTRRphysBase(5): - case MSR_MTRRphysBase(6): - case MSR_MTRRphysBase(7): - val = env->mtrr_var[(ECX(cpu) - MSR_MTRRphysBase(0)) / 2].base; - break; - case MSR_MTRRphysMask(0): - case MSR_MTRRphysMask(1): - case MSR_MTRRphysMask(2): - case MSR_MTRRphysMask(3): - case MSR_MTRRphysMask(4): - case MSR_MTRRphysMask(5): - case MSR_MTRRphysMask(6): - case MSR_MTRRphysMask(7): - val = env->mtrr_var[(ECX(cpu) - MSR_MTRRphysMask(0)) / 2].mask; - break; - case MSR_MTRRfix64K_00000: - val = env->mtrr_fixed[0]; - break; - case MSR_MTRRfix16K_80000: - case MSR_MTRRfix16K_A0000: - val = env->mtrr_fixed[ECX(cpu) - MSR_MTRRfix16K_80000 + 1]; - break; - case MSR_MTRRfix4K_C0000: - case MSR_MTRRfix4K_C8000: - case MSR_MTRRfix4K_D0000: - case MSR_MTRRfix4K_D8000: - case MSR_MTRRfix4K_E0000: - case MSR_MTRRfix4K_E8000: - case MSR_MTRRfix4K_F0000: - case MSR_MTRRfix4K_F8000: - val = env->mtrr_fixed[ECX(cpu) - MSR_MTRRfix4K_C0000 + 3]; - break; - case MSR_MTRRdefType: - val = env->mtrr_deftype; - break; - default: - // fprintf(stderr, "%s: unknown msr 0x%x\n", __func__, msr); - val = 0; - break; + case MSR_IA32_TSC: + val = rdtscp() + rvmcs(cpu->hvf_fd, VMCS_TSC_OFFSET); + break; + case MSR_IA32_APICBASE: + val = cpu_get_apic_base(X86_CPU(cpu)->apic_state); + break; + case MSR_IA32_UCODE_REV: + val = (0x100000000ULL << 32) | 0x100000000ULL; + break; + case MSR_EFER: + val = rvmcs(cpu->hvf_fd, VMCS_GUEST_IA32_EFER); + break; + case MSR_FSBASE: + val = rvmcs(cpu->hvf_fd, VMCS_GUEST_FS_BASE); + break; + case MSR_GSBASE: + val = rvmcs(cpu->hvf_fd, VMCS_GUEST_GS_BASE); + break; + case MSR_KERNELGSBASE: + val = rvmcs(cpu->hvf_fd, VMCS_HOST_FS_BASE); + break; + case MSR_STAR: + abort(); + break; + case MSR_LSTAR: + abort(); + break; + case MSR_CSTAR: + abort(); + break; + case MSR_IA32_MISC_ENABLE: + val = env->msr_ia32_misc_enable; + break; + case MSR_MTRRphysBase(0): + case MSR_MTRRphysBase(1): + case MSR_MTRRphysBase(2): + case MSR_MTRRphysBase(3): + case MSR_MTRRphysBase(4): + case MSR_MTRRphysBase(5): + case MSR_MTRRphysBase(6): + case MSR_MTRRphysBase(7): + val = env->mtrr_var[(ECX(cpu) - MSR_MTRRphysBase(0)) / 2].base; + break; + case MSR_MTRRphysMask(0): + case MSR_MTRRphysMask(1): + case MSR_MTRRphysMask(2): + case MSR_MTRRphysMask(3): + case MSR_MTRRphysMask(4): + case MSR_MTRRphysMask(5): + case MSR_MTRRphysMask(6): + case MSR_MTRRphysMask(7): + val = env->mtrr_var[(ECX(cpu) - MSR_MTRRphysMask(0)) / 2].mask; + break; + case MSR_MTRRfix64K_00000: + val = env->mtrr_fixed[0]; + break; + case MSR_MTRRfix16K_80000: + case MSR_MTRRfix16K_A0000: + val = env->mtrr_fixed[ECX(cpu) - MSR_MTRRfix16K_80000 + 1]; + break; + case MSR_MTRRfix4K_C0000: + case MSR_MTRRfix4K_C8000: + case MSR_MTRRfix4K_D0000: + case MSR_MTRRfix4K_D8000: + case MSR_MTRRfix4K_E0000: + case MSR_MTRRfix4K_E8000: + case MSR_MTRRfix4K_F0000: + case MSR_MTRRfix4K_F8000: + val = env->mtrr_fixed[ECX(cpu) - MSR_MTRRfix4K_C0000 + 3]; + break; + case MSR_MTRRdefType: + val = env->mtrr_deftype; + break; + default: + /* fprintf(stderr, "%s: unknown msr 0x%x\n", __func__, msr); */ + val = 0; + break; } RAX(cpu) = (uint32_t)val; @@ -776,88 +810,89 @@ void simulate_wrmsr(struct CPUState *cpu) uint64_t data = ((uint64_t)EDX(cpu) << 32) | EAX(cpu); switch (msr) { - case MSR_IA32_TSC: - // if (!osx_is_sierra()) - // wvmcs(cpu->hvf_fd, VMCS_TSC_OFFSET, data - rdtscp()); - //hv_vm_sync_tsc(data); - break; - case MSR_IA32_APICBASE: - cpu_set_apic_base(X86_CPU(cpu)->apic_state, data); - break; - case MSR_FSBASE: - wvmcs(cpu->hvf_fd, VMCS_GUEST_FS_BASE, data); - break; - case MSR_GSBASE: - wvmcs(cpu->hvf_fd, VMCS_GUEST_GS_BASE, data); - break; - case MSR_KERNELGSBASE: - wvmcs(cpu->hvf_fd, VMCS_HOST_FS_BASE, data); - break; - case MSR_STAR: - abort(); - break; - case MSR_LSTAR: - abort(); - break; - case MSR_CSTAR: - abort(); - break; - case MSR_EFER: - cpu->hvf_x86->efer.efer = data; - //printf("new efer %llx\n", EFER(cpu)); - wvmcs(cpu->hvf_fd, VMCS_GUEST_IA32_EFER, data); - if (data & EFER_NXE) - hv_vcpu_invalidate_tlb(cpu->hvf_fd); - break; - case MSR_MTRRphysBase(0): - case MSR_MTRRphysBase(1): - case MSR_MTRRphysBase(2): - case MSR_MTRRphysBase(3): - case MSR_MTRRphysBase(4): - case MSR_MTRRphysBase(5): - case MSR_MTRRphysBase(6): - case MSR_MTRRphysBase(7): - env->mtrr_var[(ECX(cpu) - MSR_MTRRphysBase(0)) / 2].base = data; - break; - case MSR_MTRRphysMask(0): - case MSR_MTRRphysMask(1): - case MSR_MTRRphysMask(2): - case MSR_MTRRphysMask(3): - case MSR_MTRRphysMask(4): - case MSR_MTRRphysMask(5): - case MSR_MTRRphysMask(6): - case MSR_MTRRphysMask(7): - env->mtrr_var[(ECX(cpu) - MSR_MTRRphysMask(0)) / 2].mask = data; - break; - case MSR_MTRRfix64K_00000: - env->mtrr_fixed[ECX(cpu) - MSR_MTRRfix64K_00000] = data; - break; - case MSR_MTRRfix16K_80000: - case MSR_MTRRfix16K_A0000: - env->mtrr_fixed[ECX(cpu) - MSR_MTRRfix16K_80000 + 1] = data; - break; - case MSR_MTRRfix4K_C0000: - case MSR_MTRRfix4K_C8000: - case MSR_MTRRfix4K_D0000: - case MSR_MTRRfix4K_D8000: - case MSR_MTRRfix4K_E0000: - case MSR_MTRRfix4K_E8000: - case MSR_MTRRfix4K_F0000: - case MSR_MTRRfix4K_F8000: - env->mtrr_fixed[ECX(cpu) - MSR_MTRRfix4K_C0000 + 3] = data; - break; - case MSR_MTRRdefType: - env->mtrr_deftype = data; - break; - default: - break; + case MSR_IA32_TSC: + /* if (!osx_is_sierra()) + wvmcs(cpu->hvf_fd, VMCS_TSC_OFFSET, data - rdtscp()); + hv_vm_sync_tsc(data);*/ + break; + case MSR_IA32_APICBASE: + cpu_set_apic_base(X86_CPU(cpu)->apic_state, data); + break; + case MSR_FSBASE: + wvmcs(cpu->hvf_fd, VMCS_GUEST_FS_BASE, data); + break; + case MSR_GSBASE: + wvmcs(cpu->hvf_fd, VMCS_GUEST_GS_BASE, data); + break; + case MSR_KERNELGSBASE: + wvmcs(cpu->hvf_fd, VMCS_HOST_FS_BASE, data); + break; + case MSR_STAR: + abort(); + break; + case MSR_LSTAR: + abort(); + break; + case MSR_CSTAR: + abort(); + break; + case MSR_EFER: + cpu->hvf_x86->efer.efer = data; + /*printf("new efer %llx\n", EFER(cpu));*/ + wvmcs(cpu->hvf_fd, VMCS_GUEST_IA32_EFER, data); + if (data & EFER_NXE) { + hv_vcpu_invalidate_tlb(cpu->hvf_fd); + } + break; + case MSR_MTRRphysBase(0): + case MSR_MTRRphysBase(1): + case MSR_MTRRphysBase(2): + case MSR_MTRRphysBase(3): + case MSR_MTRRphysBase(4): + case MSR_MTRRphysBase(5): + case MSR_MTRRphysBase(6): + case MSR_MTRRphysBase(7): + env->mtrr_var[(ECX(cpu) - MSR_MTRRphysBase(0)) / 2].base = data; + break; + case MSR_MTRRphysMask(0): + case MSR_MTRRphysMask(1): + case MSR_MTRRphysMask(2): + case MSR_MTRRphysMask(3): + case MSR_MTRRphysMask(4): + case MSR_MTRRphysMask(5): + case MSR_MTRRphysMask(6): + case MSR_MTRRphysMask(7): + env->mtrr_var[(ECX(cpu) - MSR_MTRRphysMask(0)) / 2].mask = data; + break; + case MSR_MTRRfix64K_00000: + env->mtrr_fixed[ECX(cpu) - MSR_MTRRfix64K_00000] = data; + break; + case MSR_MTRRfix16K_80000: + case MSR_MTRRfix16K_A0000: + env->mtrr_fixed[ECX(cpu) - MSR_MTRRfix16K_80000 + 1] = data; + break; + case MSR_MTRRfix4K_C0000: + case MSR_MTRRfix4K_C8000: + case MSR_MTRRfix4K_D0000: + case MSR_MTRRfix4K_D8000: + case MSR_MTRRfix4K_E0000: + case MSR_MTRRfix4K_E8000: + case MSR_MTRRfix4K_F0000: + case MSR_MTRRfix4K_F8000: + env->mtrr_fixed[ECX(cpu) - MSR_MTRRfix4K_C0000 + 3] = data; + break; + case MSR_MTRRdefType: + env->mtrr_deftype = data; + break; + default: + break; } /* Related to support known hypervisor interface */ - // if (g_hypervisor_iface) - // g_hypervisor_iface->wrmsr_handler(cpu, msr, data); + /* if (g_hypervisor_iface) + g_hypervisor_iface->wrmsr_handler(cpu, msr, data); - //printf("write msr %llx\n", RCX(cpu)); + printf("write msr %llx\n", RCX(cpu));*/ } static void exec_wrmsr(struct CPUState *cpu, struct x86_decode *decode) @@ -893,24 +928,26 @@ static void do_bt(struct CPUState *cpu, struct x86_decode *decode, int flag) VM_PANIC("bt 64bit\n"); } } - decode->op[0].val = read_val_ext(cpu, decode->op[0].ptr, decode->operand_size); + decode->op[0].val = read_val_ext(cpu, decode->op[0].ptr, + decode->operand_size); cf = (decode->op[0].val >> index) & 0x01; switch (flag) { - case 0: - set_CF(cpu, cf); - return; - case 1: - decode->op[0].val ^= (1u << index); - break; - case 2: - decode->op[0].val |= (1u << index); - break; - case 3: - decode->op[0].val &= ~(1u << index); - break; + case 0: + set_CF(cpu, cf); + return; + case 1: + decode->op[0].val ^= (1u << index); + break; + case 2: + decode->op[0].val |= (1u << index); + break; + case 3: + decode->op[0].val &= ~(1u << index); + break; } - write_val_ext(cpu, decode->op[0].ptr, decode->op[0].val, decode->operand_size); + write_val_ext(cpu, decode->op[0].ptr, decode->op[0].val, + decode->operand_size); set_CF(cpu, cf); } @@ -946,58 +983,59 @@ void exec_shl(struct CPUState *cpu, struct x86_decode *decode) fetch_operands(cpu, decode, 2, true, true, false); count = decode->op[1].val; - count &= 0x1f; // count is masked to 5 bits - if (!count) + count &= 0x1f; /* count is masked to 5 bits*/ + if (!count) { goto exit; + } switch (decode->operand_size) { - case 1: - { - uint8_t res = 0; - if (count <= 8) { - res = (decode->op[0].val << count); - cf = (decode->op[0].val >> (8 - count)) & 0x1; - of = cf ^ (res >> 7); - } - - write_val_ext(cpu, decode->op[0].ptr, res, 1); - SET_FLAGS_OSZAPC_LOGIC_8(res); - SET_FLAGS_OxxxxC(cpu, of, cf); - break; + case 1: + { + uint8_t res = 0; + if (count <= 8) { + res = (decode->op[0].val << count); + cf = (decode->op[0].val >> (8 - count)) & 0x1; + of = cf ^ (res >> 7); } - case 2: - { - uint16_t res = 0; - - /* from bochs */ - if (count <= 16) { - res = (decode->op[0].val << count); - cf = (decode->op[0].val >> (16 - count)) & 0x1; - of = cf ^ (res >> 15); // of = cf ^ result15 - } - write_val_ext(cpu, decode->op[0].ptr, res, 2); - SET_FLAGS_OSZAPC_LOGIC_16(res); - SET_FLAGS_OxxxxC(cpu, of, cf); - break; - } - case 4: - { - uint32_t res = decode->op[0].val << count; - - write_val_ext(cpu, decode->op[0].ptr, res, 4); - SET_FLAGS_OSZAPC_LOGIC_32(res); - cf = (decode->op[0].val >> (32 - count)) & 0x1; - of = cf ^ (res >> 31); // of = cf ^ result31 - SET_FLAGS_OxxxxC(cpu, of, cf); - break; + write_val_ext(cpu, decode->op[0].ptr, res, 1); + SET_FLAGS_OSZAPC_LOGIC_8(res); + SET_FLAGS_OxxxxC(cpu, of, cf); + break; + } + case 2: + { + uint16_t res = 0; + + /* from bochs */ + if (count <= 16) { + res = (decode->op[0].val << count); + cf = (decode->op[0].val >> (16 - count)) & 0x1; + of = cf ^ (res >> 15); /* of = cf ^ result15 */ } - default: - abort(); + + write_val_ext(cpu, decode->op[0].ptr, res, 2); + SET_FLAGS_OSZAPC_LOGIC_16(res); + SET_FLAGS_OxxxxC(cpu, of, cf); + break; + } + case 4: + { + uint32_t res = decode->op[0].val << count; + + write_val_ext(cpu, decode->op[0].ptr, res, 4); + SET_FLAGS_OSZAPC_LOGIC_32(res); + cf = (decode->op[0].val >> (32 - count)) & 0x1; + of = cf ^ (res >> 31); /* of = cf ^ result31 */ + SET_FLAGS_OxxxxC(cpu, of, cf); + break; + } + default: + abort(); } exit: - //lflags_to_rflags(cpu); + /* lflags_to_rflags(cpu); */ RIP(cpu) += decode->len; } @@ -1008,14 +1046,16 @@ void exec_movsx(struct CPUState *cpu, struct x86_decode *decode) fetch_operands(cpu, decode, 2, false, false, false); - if (0xbe == decode->opcode[1]) + if (0xbe == decode->opcode[1]) { src_op_size = 1; - else + } else { src_op_size = 2; + } decode->operand_size = src_op_size; calc_modrm_operand(cpu, decode, &decode->op[1]); - decode->op[1].val = sign(read_val_ext(cpu, decode->op[1].ptr, src_op_size), src_op_size); + decode->op[1].val = sign(read_val_ext(cpu, decode->op[1].ptr, src_op_size), + src_op_size); write_val_ext(cpu, decode->op[0].ptr, decode->op[1].val, op_size); @@ -1030,68 +1070,71 @@ void exec_ror(struct CPUState *cpu, struct x86_decode *decode) count = decode->op[1].val; switch (decode->operand_size) { - case 1: - { - uint32_t bit6, bit7; - uint8_t res; - - if ((count & 0x07) == 0) { - if (count & 0x18) { - bit6 = ((uint8_t)decode->op[0].val >> 6) & 1; - bit7 = ((uint8_t)decode->op[0].val >> 7) & 1; - SET_FLAGS_OxxxxC(cpu, bit6 ^ bit7, bit7); - } - } else { - count &= 0x7; /* use only bottom 3 bits */ - res = ((uint8_t)decode->op[0].val >> count) | ((uint8_t)decode->op[0].val << (8 - count)); - write_val_ext(cpu, decode->op[0].ptr, res, 1); - bit6 = (res >> 6) & 1; - bit7 = (res >> 7) & 1; - /* set eflags: ROR count affects the following flags: C, O */ + case 1: + { + uint32_t bit6, bit7; + uint8_t res; + + if ((count & 0x07) == 0) { + if (count & 0x18) { + bit6 = ((uint8_t)decode->op[0].val >> 6) & 1; + bit7 = ((uint8_t)decode->op[0].val >> 7) & 1; SET_FLAGS_OxxxxC(cpu, bit6 ^ bit7, bit7); - } - break; + } + } else { + count &= 0x7; /* use only bottom 3 bits */ + res = ((uint8_t)decode->op[0].val >> count) | + ((uint8_t)decode->op[0].val << (8 - count)); + write_val_ext(cpu, decode->op[0].ptr, res, 1); + bit6 = (res >> 6) & 1; + bit7 = (res >> 7) & 1; + /* set eflags: ROR count affects the following flags: C, O */ + SET_FLAGS_OxxxxC(cpu, bit6 ^ bit7, bit7); } - case 2: - { - uint32_t bit14, bit15; - uint16_t res; - - if ((count & 0x0f) == 0) { - if (count & 0x10) { - bit14 = ((uint16_t)decode->op[0].val >> 14) & 1; - bit15 = ((uint16_t)decode->op[0].val >> 15) & 1; - // of = result14 ^ result15 - SET_FLAGS_OxxxxC(cpu, bit14 ^ bit15, bit15); - } - } else { - count &= 0x0f; // use only 4 LSB's - res = ((uint16_t)decode->op[0].val >> count) | ((uint16_t)decode->op[0].val << (16 - count)); - write_val_ext(cpu, decode->op[0].ptr, res, 2); - - bit14 = (res >> 14) & 1; - bit15 = (res >> 15) & 1; - // of = result14 ^ result15 + break; + } + case 2: + { + uint32_t bit14, bit15; + uint16_t res; + + if ((count & 0x0f) == 0) { + if (count & 0x10) { + bit14 = ((uint16_t)decode->op[0].val >> 14) & 1; + bit15 = ((uint16_t)decode->op[0].val >> 15) & 1; + /* of = result14 ^ result15 */ SET_FLAGS_OxxxxC(cpu, bit14 ^ bit15, bit15); } - break; + } else { + count &= 0x0f; /* use only 4 LSB's */ + res = ((uint16_t)decode->op[0].val >> count) | + ((uint16_t)decode->op[0].val << (16 - count)); + write_val_ext(cpu, decode->op[0].ptr, res, 2); + + bit14 = (res >> 14) & 1; + bit15 = (res >> 15) & 1; + /* of = result14 ^ result15 */ + SET_FLAGS_OxxxxC(cpu, bit14 ^ bit15, bit15); } - case 4: - { - uint32_t bit31, bit30; - uint32_t res; - - count &= 0x1f; - if (count) { - res = ((uint32_t)decode->op[0].val >> count) | ((uint32_t)decode->op[0].val << (32 - count)); - write_val_ext(cpu, decode->op[0].ptr, res, 4); - - bit31 = (res >> 31) & 1; - bit30 = (res >> 30) & 1; - // of = result30 ^ result31 - SET_FLAGS_OxxxxC(cpu, bit30 ^ bit31, bit31); - } - break; + break; + } + case 4: + { + uint32_t bit31, bit30; + uint32_t res; + + count &= 0x1f; + if (count) { + res = ((uint32_t)decode->op[0].val >> count) | + ((uint32_t)decode->op[0].val << (32 - count)); + write_val_ext(cpu, decode->op[0].ptr, res, 4); + + bit31 = (res >> 31) & 1; + bit30 = (res >> 30) & 1; + /* of = result30 ^ result31 */ + SET_FLAGS_OxxxxC(cpu, bit30 ^ bit31, bit31); + } + break; } } RIP(cpu) += decode->len; @@ -1105,71 +1148,74 @@ void exec_rol(struct CPUState *cpu, struct x86_decode *decode) count = decode->op[1].val; switch (decode->operand_size) { - case 1: - { - uint32_t bit0, bit7; - uint8_t res; - - if ((count & 0x07) == 0) { - if (count & 0x18) { - bit0 = ((uint8_t)decode->op[0].val & 1); - bit7 = ((uint8_t)decode->op[0].val >> 7); - SET_FLAGS_OxxxxC(cpu, bit0 ^ bit7, bit0); - } - } else { - count &= 0x7; // use only lowest 3 bits - res = ((uint8_t)decode->op[0].val << count) | ((uint8_t)decode->op[0].val >> (8 - count)); - - write_val_ext(cpu, decode->op[0].ptr, res, 1); - /* set eflags: - * ROL count affects the following flags: C, O - */ - bit0 = (res & 1); - bit7 = (res >> 7); + case 1: + { + uint32_t bit0, bit7; + uint8_t res; + + if ((count & 0x07) == 0) { + if (count & 0x18) { + bit0 = ((uint8_t)decode->op[0].val & 1); + bit7 = ((uint8_t)decode->op[0].val >> 7); SET_FLAGS_OxxxxC(cpu, bit0 ^ bit7, bit0); } - break; + } else { + count &= 0x7; /* use only lowest 3 bits */ + res = ((uint8_t)decode->op[0].val << count) | + ((uint8_t)decode->op[0].val >> (8 - count)); + + write_val_ext(cpu, decode->op[0].ptr, res, 1); + /* set eflags: + * ROL count affects the following flags: C, O + */ + bit0 = (res & 1); + bit7 = (res >> 7); + SET_FLAGS_OxxxxC(cpu, bit0 ^ bit7, bit0); } - case 2: - { - uint32_t bit0, bit15; - uint16_t res; - - if ((count & 0x0f) == 0) { - if (count & 0x10) { - bit0 = ((uint16_t)decode->op[0].val & 0x1); - bit15 = ((uint16_t)decode->op[0].val >> 15); - // of = cf ^ result15 - SET_FLAGS_OxxxxC(cpu, bit0 ^ bit15, bit0); - } - } else { - count &= 0x0f; // only use bottom 4 bits - res = ((uint16_t)decode->op[0].val << count) | ((uint16_t)decode->op[0].val >> (16 - count)); - - write_val_ext(cpu, decode->op[0].ptr, res, 2); - bit0 = (res & 0x1); - bit15 = (res >> 15); - // of = cf ^ result15 + break; + } + case 2: + { + uint32_t bit0, bit15; + uint16_t res; + + if ((count & 0x0f) == 0) { + if (count & 0x10) { + bit0 = ((uint16_t)decode->op[0].val & 0x1); + bit15 = ((uint16_t)decode->op[0].val >> 15); + /* of = cf ^ result15 */ SET_FLAGS_OxxxxC(cpu, bit0 ^ bit15, bit0); } - break; + } else { + count &= 0x0f; /* only use bottom 4 bits */ + res = ((uint16_t)decode->op[0].val << count) | + ((uint16_t)decode->op[0].val >> (16 - count)); + + write_val_ext(cpu, decode->op[0].ptr, res, 2); + bit0 = (res & 0x1); + bit15 = (res >> 15); + /* of = cf ^ result15 */ + SET_FLAGS_OxxxxC(cpu, bit0 ^ bit15, bit0); } - case 4: - { - uint32_t bit0, bit31; - uint32_t res; - - count &= 0x1f; - if (count) { - res = ((uint32_t)decode->op[0].val << count) | ((uint32_t)decode->op[0].val >> (32 - count)); - - write_val_ext(cpu, decode->op[0].ptr, res, 4); - bit0 = (res & 0x1); - bit31 = (res >> 31); - // of = cf ^ result31 - SET_FLAGS_OxxxxC(cpu, bit0 ^ bit31, bit0); - } - break; + break; + } + case 4: + { + uint32_t bit0, bit31; + uint32_t res; + + count &= 0x1f; + if (count) { + res = ((uint32_t)decode->op[0].val << count) | + ((uint32_t)decode->op[0].val >> (32 - count)); + + write_val_ext(cpu, decode->op[0].ptr, res, 4); + bit0 = (res & 0x1); + bit31 = (res >> 31); + /* of = cf ^ result31 */ + SET_FLAGS_OxxxxC(cpu, bit0 ^ bit31, bit0); + } + break; } } RIP(cpu) += decode->len; @@ -1184,70 +1230,79 @@ void exec_rcl(struct CPUState *cpu, struct x86_decode *decode) fetch_operands(cpu, decode, 2, true, true, false); count = decode->op[1].val & 0x1f; - switch(decode->operand_size) { - case 1: - { - uint8_t op1_8 = decode->op[0].val; - uint8_t res; - count %= 9; - if (!count) - break; + switch (decode->operand_size) { + case 1: + { + uint8_t op1_8 = decode->op[0].val; + uint8_t res; + count %= 9; + if (!count) { + break; + } + + if (1 == count) { + res = (op1_8 << 1) | get_CF(cpu); + } else { + res = (op1_8 << count) | (get_CF(cpu) << (count - 1)) | + (op1_8 >> (9 - count)); + } - if (1 == count) - res = (op1_8 << 1) | get_CF(cpu); - else - res = (op1_8 << count) | (get_CF(cpu) << (count - 1)) | (op1_8 >> (9 - count)); + write_val_ext(cpu, decode->op[0].ptr, res, 1); - write_val_ext(cpu, decode->op[0].ptr, res, 1); + cf = (op1_8 >> (8 - count)) & 0x01; + of = cf ^ (res >> 7); /* of = cf ^ result7 */ + SET_FLAGS_OxxxxC(cpu, of, cf); + break; + } + case 2: + { + uint16_t res; + uint16_t op1_16 = decode->op[0].val; - cf = (op1_8 >> (8 - count)) & 0x01; - of = cf ^ (res >> 7); // of = cf ^ result7 - SET_FLAGS_OxxxxC(cpu, of, cf); - break; - } - case 2: - { - uint16_t res; - uint16_t op1_16 = decode->op[0].val; - - count %= 17; - if (!count) - break; - - if (1 == count) - res = (op1_16 << 1) | get_CF(cpu); - else if (count == 16) - res = (get_CF(cpu) << 15) | (op1_16 >> 1); - else // 2..15 - res = (op1_16 << count) | (get_CF(cpu) << (count - 1)) | (op1_16 >> (17 - count)); - - write_val_ext(cpu, decode->op[0].ptr, res, 2); - - cf = (op1_16 >> (16 - count)) & 0x1; - of = cf ^ (res >> 15); // of = cf ^ result15 - SET_FLAGS_OxxxxC(cpu, of, cf); + count %= 17; + if (!count) { break; } - case 4: - { - uint32_t res; - uint32_t op1_32 = decode->op[0].val; - if (!count) - break; + if (1 == count) { + res = (op1_16 << 1) | get_CF(cpu); + } else if (count == 16) { + res = (get_CF(cpu) << 15) | (op1_16 >> 1); + } else { /* 2..15 */ + res = (op1_16 << count) | (get_CF(cpu) << (count - 1)) | + (op1_16 >> (17 - count)); + } - if (1 == count) - res = (op1_32 << 1) | get_CF(cpu); - else - res = (op1_32 << count) | (get_CF(cpu) << (count - 1)) | (op1_32 >> (33 - count)); + write_val_ext(cpu, decode->op[0].ptr, res, 2); - write_val_ext(cpu, decode->op[0].ptr, res, 4); + cf = (op1_16 >> (16 - count)) & 0x1; + of = cf ^ (res >> 15); /* of = cf ^ result15 */ + SET_FLAGS_OxxxxC(cpu, of, cf); + break; + } + case 4: + { + uint32_t res; + uint32_t op1_32 = decode->op[0].val; - cf = (op1_32 >> (32 - count)) & 0x1; - of = cf ^ (res >> 31); // of = cf ^ result31 - SET_FLAGS_OxxxxC(cpu, of, cf); + if (!count) { break; } + + if (1 == count) { + res = (op1_32 << 1) | get_CF(cpu); + } else { + res = (op1_32 << count) | (get_CF(cpu) << (count - 1)) | + (op1_32 >> (33 - count)); + } + + write_val_ext(cpu, decode->op[0].ptr, res, 4); + + cf = (op1_32 >> (32 - count)) & 0x1; + of = cf ^ (res >> 31); /* of = cf ^ result31 */ + SET_FLAGS_OxxxxC(cpu, of, cf); + break; + } } RIP(cpu) += decode->len; } @@ -1260,60 +1315,68 @@ void exec_rcr(struct CPUState *cpu, struct x86_decode *decode) fetch_operands(cpu, decode, 2, true, true, false); count = decode->op[1].val & 0x1f; - switch(decode->operand_size) { - case 1: - { - uint8_t op1_8 = decode->op[0].val; - uint8_t res; + switch (decode->operand_size) { + case 1: + { + uint8_t op1_8 = decode->op[0].val; + uint8_t res; - count %= 9; - if (!count) - break; - res = (op1_8 >> count) | (get_CF(cpu) << (8 - count)) | (op1_8 << (9 - count)); + count %= 9; + if (!count) { + break; + } + res = (op1_8 >> count) | (get_CF(cpu) << (8 - count)) | + (op1_8 << (9 - count)); - write_val_ext(cpu, decode->op[0].ptr, res, 1); + write_val_ext(cpu, decode->op[0].ptr, res, 1); + + cf = (op1_8 >> (count - 1)) & 0x1; + of = (((res << 1) ^ res) >> 7) & 0x1; /* of = result6 ^ result7 */ + SET_FLAGS_OxxxxC(cpu, of, cf); + break; + } + case 2: + { + uint16_t op1_16 = decode->op[0].val; + uint16_t res; - cf = (op1_8 >> (count - 1)) & 0x1; - of = (((res << 1) ^ res) >> 7) & 0x1; // of = result6 ^ result7 - SET_FLAGS_OxxxxC(cpu, of, cf); + count %= 17; + if (!count) { break; } - case 2: - { - uint16_t op1_16 = decode->op[0].val; - uint16_t res; + res = (op1_16 >> count) | (get_CF(cpu) << (16 - count)) | + (op1_16 << (17 - count)); - count %= 17; - if (!count) - break; - res = (op1_16 >> count) | (get_CF(cpu) << (16 - count)) | (op1_16 << (17 - count)); + write_val_ext(cpu, decode->op[0].ptr, res, 2); - write_val_ext(cpu, decode->op[0].ptr, res, 2); + cf = (op1_16 >> (count - 1)) & 0x1; + of = ((uint16_t)((res << 1) ^ res) >> 15) & 0x1; /* of = result15 ^ + result14 */ + SET_FLAGS_OxxxxC(cpu, of, cf); + break; + } + case 4: + { + uint32_t res; + uint32_t op1_32 = decode->op[0].val; - cf = (op1_16 >> (count - 1)) & 0x1; - of = ((uint16_t)((res << 1) ^ res) >> 15) & 0x1; // of = result15 ^ result14 - SET_FLAGS_OxxxxC(cpu, of, cf); + if (!count) { break; } - case 4: - { - uint32_t res; - uint32_t op1_32 = decode->op[0].val; - - if (!count) - break; - - if (1 == count) - res = (op1_32 >> 1) | (get_CF(cpu) << 31); - else - res = (op1_32 >> count) | (get_CF(cpu) << (32 - count)) | (op1_32 << (33 - count)); - write_val_ext(cpu, decode->op[0].ptr, res, 4); + if (1 == count) { + res = (op1_32 >> 1) | (get_CF(cpu) << 31); + } else { + res = (op1_32 >> count) | (get_CF(cpu) << (32 - count)) | + (op1_32 << (33 - count)); + } - cf = (op1_32 >> (count - 1)) & 0x1; - of = ((res << 1) ^ res) >> 31; // of = result30 ^ result31 - SET_FLAGS_OxxxxC(cpu, of, cf); - break; + write_val_ext(cpu, decode->op[0].ptr, res, 4); + + cf = (op1_32 >> (count - 1)) & 0x1; + of = ((res << 1) ^ res) >> 31; /* of = result30 ^ result31 */ + SET_FLAGS_OxxxxC(cpu, of, cf); + break; } } RIP(cpu) += decode->len; @@ -1323,8 +1386,10 @@ static void exec_xchg(struct CPUState *cpu, struct x86_decode *decode) { fetch_operands(cpu, decode, 2, true, true, false); - write_val_ext(cpu, decode->op[0].ptr, decode->op[1].val, decode->operand_size); - write_val_ext(cpu, decode->op[1].ptr, decode->op[0].val, decode->operand_size); + write_val_ext(cpu, decode->op[0].ptr, decode->op[1].val, + decode->operand_size); + write_val_ext(cpu, decode->op[1].ptr, decode->op[0].val, + decode->operand_size); RIP(cpu) += decode->len; } @@ -1332,7 +1397,8 @@ static void exec_xchg(struct CPUState *cpu, struct x86_decode *decode) static void exec_xadd(struct CPUState *cpu, struct x86_decode *decode) { EXEC_2OP_ARITH_CMD(cpu, decode, +, SET_FLAGS_OSZAPC_ADD, true); - write_val_ext(cpu, decode->op[1].ptr, decode->op[0].val, decode->operand_size); + write_val_ext(cpu, decode->op[1].ptr, decode->op[0].val, + decode->operand_size); RIP(cpu) += decode->len; } @@ -1388,13 +1454,9 @@ static struct cmd_handler _cmd_handler[X86_DECODE_CMD_LAST]; static void init_cmd_handler(CPUState *cpu) { int i; - for (i = 0; i < ARRAY_SIZE(handlers); i++) + for (i = 0; i < ARRAY_SIZE(handlers); i++) { _cmd_handler[handlers[i].cmd] = handlers[i]; -} - -static void print_debug(struct CPUState *cpu) -{ - printf("%llx: eax %llx ebx %llx ecx %llx edx %llx esi %llx edi %llx ebp %llx esp %llx flags %llx\n", RIP(cpu), RAX(cpu), RBX(cpu), RCX(cpu), RDX(cpu), RSI(cpu), RDI(cpu), RBP(cpu), RSP(cpu), EFLAGS(cpu)); + } } void load_regs(struct CPUState *cpu) @@ -1408,14 +1470,13 @@ void load_regs(struct CPUState *cpu) RRX(cpu, REG_RDI) = rreg(cpu->hvf_fd, HV_X86_RDI); RRX(cpu, REG_RSP) = rreg(cpu->hvf_fd, HV_X86_RSP); RRX(cpu, REG_RBP) = rreg(cpu->hvf_fd, HV_X86_RBP); - for (i = 8; i < 16; i++) + for (i = 8; i < 16; i++) { RRX(cpu, i) = rreg(cpu->hvf_fd, HV_X86_RAX + i); - + } + RFLAGS(cpu) = rreg(cpu->hvf_fd, HV_X86_RFLAGS); rflags_to_lflags(cpu); RIP(cpu) = rreg(cpu->hvf_fd, HV_X86_RIP); - - //print_debug(cpu); } void store_regs(struct CPUState *cpu) @@ -1429,32 +1490,36 @@ void store_regs(struct CPUState *cpu) wreg(cpu->hvf_fd, HV_X86_RDI, RDI(cpu)); wreg(cpu->hvf_fd, HV_X86_RBP, RBP(cpu)); wreg(cpu->hvf_fd, HV_X86_RSP, RSP(cpu)); - for (i = 8; i < 16; i++) + for (i = 8; i < 16; i++) { wreg(cpu->hvf_fd, HV_X86_RAX + i, RRX(cpu, i)); - + } + lflags_to_rflags(cpu); wreg(cpu->hvf_fd, HV_X86_RFLAGS, RFLAGS(cpu)); macvm_set_rip(cpu, RIP(cpu)); - - //print_debug(cpu); } bool exec_instruction(struct CPUState *cpu, struct x86_decode *ins) { - //if (hvf_vcpu_id(cpu)) - //printf("%d, %llx: exec_instruction %s\n", hvf_vcpu_id(cpu), RIP(cpu), decode_cmd_to_string(ins->cmd)); - + /*if (hvf_vcpu_id(cpu)) + printf("%d, %llx: exec_instruction %s\n", hvf_vcpu_id(cpu), RIP(cpu), + decode_cmd_to_string(ins->cmd));*/ + if (0 && ins->is_fpu) { VM_PANIC("emulate fpu\n"); } else { if (!_cmd_handler[ins->cmd].handler) { - printf("Unimplemented handler (%llx) for %d (%x %x) \n", RIP(cpu), ins->cmd, ins->opcode[0], - ins->opcode_len > 1 ? ins->opcode[1] : 0); + printf("Unimplemented handler (%llx) for %d (%x %x) \n", RIP(cpu), + ins->cmd, ins->opcode[0], + ins->opcode_len > 1 ? ins->opcode[1] : 0); RIP(cpu) += ins->len; return true; } - - VM_PANIC_ON_EX(!_cmd_handler[ins->cmd].handler, "Unimplemented handler (%llx) for %d (%x %x) \n", RIP(cpu), ins->cmd, ins->opcode[0], ins->opcode_len > 1 ? ins->opcode[1] : 0); + + VM_PANIC_ON_EX(!_cmd_handler[ins->cmd].handler, + "Unimplemented handler (%llx) for %d (%x %x) \n", RIP(cpu), + ins->cmd, ins->opcode[0], + ins->opcode_len > 1 ? ins->opcode[1] : 0); _cmd_handler[ins->cmd].handler(cpu, ins); } return true; diff --git a/target/i386/hvf-utils/x86_emu.h b/target/i386/hvf-utils/x86_emu.h index 42cc5e4296..78a66394b8 100644 --- a/target/i386/hvf-utils/x86_emu.h +++ b/target/i386/hvf-utils/x86_emu.h @@ -30,4 +30,19 @@ void store_regs(struct CPUState *cpu); void simulate_rdmsr(struct CPUState *cpu); void simulate_wrmsr(struct CPUState *cpu); +addr_t read_reg(struct CPUState *cpu, int reg, int size); +void write_reg(struct CPUState *cpu, int reg, addr_t val, int size); +addr_t read_val_from_reg(addr_t reg_ptr, int size); +void write_val_to_reg(addr_t reg_ptr, addr_t val, int size); +void write_val_ext(struct CPUState *cpu, addr_t ptr, addr_t val, int size); +uint8_t *read_mmio(struct CPUState *cpu, addr_t ptr, int bytes); +addr_t read_val_ext(struct CPUState *cpu, addr_t ptr, int size); + +void exec_movzx(struct CPUState *cpu, struct x86_decode *decode); +void exec_shl(struct CPUState *cpu, struct x86_decode *decode); +void exec_movsx(struct CPUState *cpu, struct x86_decode *decode); +void exec_ror(struct CPUState *cpu, struct x86_decode *decode); +void exec_rol(struct CPUState *cpu, struct x86_decode *decode); +void exec_rcl(struct CPUState *cpu, struct x86_decode *decode); +void exec_rcr(struct CPUState *cpu, struct x86_decode *decode); #endif diff --git a/target/i386/hvf-utils/x86_flags.c b/target/i386/hvf-utils/x86_flags.c index ca876d03dd..187ab9b56b 100644 --- a/target/i386/hvf-utils/x86_flags.c +++ b/target/i386/hvf-utils/x86_flags.c @@ -32,65 +32,78 @@ void SET_FLAGS_OxxxxC(struct CPUState *cpu, uint32_t new_of, uint32_t new_cf) { uint32_t temp_po = new_of ^ new_cf; cpu->hvf_x86->lflags.auxbits &= ~(LF_MASK_PO | LF_MASK_CF); - cpu->hvf_x86->lflags.auxbits |= (temp_po << LF_BIT_PO) | (new_cf << LF_BIT_CF); + cpu->hvf_x86->lflags.auxbits |= (temp_po << LF_BIT_PO) | + (new_cf << LF_BIT_CF); } -void SET_FLAGS_OSZAPC_SUB32(struct CPUState *cpu, uint32_t v1, uint32_t v2, uint32_t diff) +void SET_FLAGS_OSZAPC_SUB32(struct CPUState *cpu, uint32_t v1, uint32_t v2, + uint32_t diff) { SET_FLAGS_OSZAPC_SUB_32(v1, v2, diff); } -void SET_FLAGS_OSZAPC_SUB16(struct CPUState *cpu, uint16_t v1, uint16_t v2, uint16_t diff) +void SET_FLAGS_OSZAPC_SUB16(struct CPUState *cpu, uint16_t v1, uint16_t v2, + uint16_t diff) { SET_FLAGS_OSZAPC_SUB_16(v1, v2, diff); } -void SET_FLAGS_OSZAPC_SUB8(struct CPUState *cpu, uint8_t v1, uint8_t v2, uint8_t diff) +void SET_FLAGS_OSZAPC_SUB8(struct CPUState *cpu, uint8_t v1, uint8_t v2, + uint8_t diff) { SET_FLAGS_OSZAPC_SUB_8(v1, v2, diff); } -void SET_FLAGS_OSZAPC_ADD32(struct CPUState *cpu, uint32_t v1, uint32_t v2, uint32_t diff) +void SET_FLAGS_OSZAPC_ADD32(struct CPUState *cpu, uint32_t v1, uint32_t v2, + uint32_t diff) { SET_FLAGS_OSZAPC_ADD_32(v1, v2, diff); } -void SET_FLAGS_OSZAPC_ADD16(struct CPUState *cpu, uint16_t v1, uint16_t v2, uint16_t diff) +void SET_FLAGS_OSZAPC_ADD16(struct CPUState *cpu, uint16_t v1, uint16_t v2, + uint16_t diff) { SET_FLAGS_OSZAPC_ADD_16(v1, v2, diff); } -void SET_FLAGS_OSZAPC_ADD8(struct CPUState *cpu, uint8_t v1, uint8_t v2, uint8_t diff) +void SET_FLAGS_OSZAPC_ADD8(struct CPUState *cpu, uint8_t v1, uint8_t v2, + uint8_t diff) { SET_FLAGS_OSZAPC_ADD_8(v1, v2, diff); } -void SET_FLAGS_OSZAP_SUB32(struct CPUState *cpu, uint32_t v1, uint32_t v2, uint32_t diff) +void SET_FLAGS_OSZAP_SUB32(struct CPUState *cpu, uint32_t v1, uint32_t v2, + uint32_t diff) { SET_FLAGS_OSZAP_SUB_32(v1, v2, diff); } -void SET_FLAGS_OSZAP_SUB16(struct CPUState *cpu, uint16_t v1, uint16_t v2, uint16_t diff) +void SET_FLAGS_OSZAP_SUB16(struct CPUState *cpu, uint16_t v1, uint16_t v2, + uint16_t diff) { SET_FLAGS_OSZAP_SUB_16(v1, v2, diff); } -void SET_FLAGS_OSZAP_SUB8(struct CPUState *cpu, uint8_t v1, uint8_t v2, uint8_t diff) +void SET_FLAGS_OSZAP_SUB8(struct CPUState *cpu, uint8_t v1, uint8_t v2, + uint8_t diff) { SET_FLAGS_OSZAP_SUB_8(v1, v2, diff); } -void SET_FLAGS_OSZAP_ADD32(struct CPUState *cpu, uint32_t v1, uint32_t v2, uint32_t diff) +void SET_FLAGS_OSZAP_ADD32(struct CPUState *cpu, uint32_t v1, uint32_t v2, + uint32_t diff) { SET_FLAGS_OSZAP_ADD_32(v1, v2, diff); } -void SET_FLAGS_OSZAP_ADD16(struct CPUState *cpu, uint16_t v1, uint16_t v2, uint16_t diff) +void SET_FLAGS_OSZAP_ADD16(struct CPUState *cpu, uint16_t v1, uint16_t v2, + uint16_t diff) { SET_FLAGS_OSZAP_ADD_16(v1, v2, diff); } -void SET_FLAGS_OSZAP_ADD8(struct CPUState *cpu, uint8_t v1, uint8_t v2, uint8_t diff) +void SET_FLAGS_OSZAP_ADD8(struct CPUState *cpu, uint8_t v1, uint8_t v2, + uint8_t diff) { SET_FLAGS_OSZAP_ADD_8(v1, v2, diff); } @@ -264,19 +277,22 @@ bool get_ZF(struct CPUState *cpu) void set_ZF(struct CPUState *cpu, bool val) { if (val) { - cpu->hvf_x86->lflags.auxbits ^= (((cpu->hvf_x86->lflags.result >> LF_SIGN_BIT) & 1) << LF_BIT_SD); - // merge the parity bits into the Parity Delta Byte + cpu->hvf_x86->lflags.auxbits ^= + (((cpu->hvf_x86->lflags.result >> LF_SIGN_BIT) & 1) << LF_BIT_SD); + /* merge the parity bits into the Parity Delta Byte */ uint32_t temp_pdb = (255 & cpu->hvf_x86->lflags.result); cpu->hvf_x86->lflags.auxbits ^= (temp_pdb << LF_BIT_PDB); - // now zero the .result value + /* now zero the .result value */ cpu->hvf_x86->lflags.result = 0; - } else + } else { cpu->hvf_x86->lflags.result |= (1 << 8); + } } bool get_SF(struct CPUState *cpu) { - return ((cpu->hvf_x86->lflags.result >> LF_SIGN_BIT) ^ (cpu->hvf_x86->lflags.auxbits >> LF_BIT_SD)) & 1; + return ((cpu->hvf_x86->lflags.result >> LF_SIGN_BIT) ^ + (cpu->hvf_x86->lflags.auxbits >> LF_BIT_SD)) & 1; } void set_SF(struct CPUState *cpu, bool val) diff --git a/target/i386/hvf-utils/x86_flags.h b/target/i386/hvf-utils/x86_flags.h index f963f8ad1b..68a0c10b90 100644 --- a/target/i386/hvf-utils/x86_flags.h +++ b/target/i386/hvf-utils/x86_flags.h @@ -55,19 +55,24 @@ typedef struct lazy_flags { #define GET_ADD_OVERFLOW(op1, op2, result, mask) \ ((((op1) ^ (result)) & ((op2) ^ (result))) & (mask)) -// ******************* -// OSZAPC -// ******************* +/* ******************* */ +/* OSZAPC */ +/* ******************* */ /* size, carries, result */ #define SET_FLAGS_OSZAPC_SIZE(size, lf_carries, lf_result) { \ addr_t temp = ((lf_carries) & (LF_MASK_AF)) | \ (((lf_carries) >> (size - 2)) << LF_BIT_PO); \ cpu->hvf_x86->lflags.result = (addr_t)(int##size##_t)(lf_result); \ - if ((size) == 32) temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \ - else if ((size) == 16) temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \ - else if ((size) == 8) temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \ - else VM_PANIC("unimplemented"); \ + if ((size) == 32) { \ + temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \ + } else if ((size) == 16) { \ + temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \ + } else if ((size) == 8) { \ + temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \ + } else { \ + VM_PANIC("unimplemented"); \ + } \ cpu->hvf_x86->lflags.auxbits = (addr_t)(uint32_t)temp; \ } @@ -87,10 +92,15 @@ typedef struct lazy_flags { #define SET_FLAGS_OSZAPC_LOGIC_32(result_32) \ SET_FLAGS_OSZAPC_32(0, (result_32)) #define SET_FLAGS_OSZAPC_LOGIC_SIZE(size, result) { \ - if (32 == size) {SET_FLAGS_OSZAPC_LOGIC_32(result);} \ - else if (16 == size) {SET_FLAGS_OSZAPC_LOGIC_16(result);} \ - else if (8 == size) {SET_FLAGS_OSZAPC_LOGIC_8(result);} \ - else VM_PANIC("unimplemented"); \ + if (32 == size) { \ + SET_FLAGS_OSZAPC_LOGIC_32(result); \ + } else if (16 == size) { \ + SET_FLAGS_OSZAPC_LOGIC_16(result); \ + } else if (8 == size) { \ + SET_FLAGS_OSZAPC_LOGIC_8(result); \ + } else { \ + VM_PANIC("unimplemented"); \ + } \ } /* op1, op2, result */ @@ -109,17 +119,22 @@ typedef struct lazy_flags { #define SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32) \ SET_FLAGS_OSZAPC_32(SUB_COUT_VEC((op1_32), (op2_32), (diff_32)), (diff_32)) -// ******************* -// OSZAP -// ******************* +/* ******************* */ +/* OSZAP */ +/* ******************* */ /* size, carries, result */ #define SET_FLAGS_OSZAP_SIZE(size, lf_carries, lf_result) { \ addr_t temp = ((lf_carries) & (LF_MASK_AF)) | \ (((lf_carries) >> (size - 2)) << LF_BIT_PO); \ - if ((size) == 32) temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \ - else if ((size) == 16) temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \ - else if ((size) == 8) temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \ - else VM_PANIC("unimplemented"); \ + if ((size) == 32) { \ + temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \ + } else if ((size) == 16) { \ + temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \ + } else if ((size) == 8) { \ + temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \ + } else { \ + VM_PANIC("unimplemented"); \ + } \ cpu->hvf_x86->lflags.result = (addr_t)(int##size##_t)(lf_result); \ addr_t delta_c = (cpu->hvf_x86->lflags.auxbits ^ temp) & LF_MASK_CF; \ delta_c ^= (delta_c >> 1); \ @@ -150,9 +165,9 @@ typedef struct lazy_flags { #define SET_FLAGS_OSZAP_SUB_32(op1_32, op2_32, diff_32) \ SET_FLAGS_OSZAP_32(SUB_COUT_VEC((op1_32), (op2_32), (diff_32)), (diff_32)) -// ******************* -// OSZAxC -// ******************* +/* ******************* */ +/* OSZAxC */ +/* ******************* */ /* size, carries, result */ #define SET_FLAGS_OSZAxC_LOGIC_SIZE(size, lf_result) { \ bool saved_PF = getB_PF(); \ @@ -183,21 +198,33 @@ void set_OSZAPC(struct CPUState *cpu, uint32_t flags32); void SET_FLAGS_OxxxxC(struct CPUState *cpu, uint32_t new_of, uint32_t new_cf); -void SET_FLAGS_OSZAPC_SUB32(struct CPUState *cpu, uint32_t v1, uint32_t v2, uint32_t diff); -void SET_FLAGS_OSZAPC_SUB16(struct CPUState *cpu, uint16_t v1, uint16_t v2, uint16_t diff); -void SET_FLAGS_OSZAPC_SUB8(struct CPUState *cpu, uint8_t v1, uint8_t v2, uint8_t diff); - -void SET_FLAGS_OSZAPC_ADD32(struct CPUState *cpu, uint32_t v1, uint32_t v2, uint32_t diff); -void SET_FLAGS_OSZAPC_ADD16(struct CPUState *cpu, uint16_t v1, uint16_t v2, uint16_t diff); -void SET_FLAGS_OSZAPC_ADD8(struct CPUState *cpu, uint8_t v1, uint8_t v2, uint8_t diff); - -void SET_FLAGS_OSZAP_SUB32(struct CPUState *cpu, uint32_t v1, uint32_t v2, uint32_t diff); -void SET_FLAGS_OSZAP_SUB16(struct CPUState *cpu, uint16_t v1, uint16_t v2, uint16_t diff); -void SET_FLAGS_OSZAP_SUB8(struct CPUState *cpu, uint8_t v1, uint8_t v2, uint8_t diff); - -void SET_FLAGS_OSZAP_ADD32(struct CPUState *cpu, uint32_t v1, uint32_t v2, uint32_t diff); -void SET_FLAGS_OSZAP_ADD16(struct CPUState *cpu, uint16_t v1, uint16_t v2, uint16_t diff); -void SET_FLAGS_OSZAP_ADD8(struct CPUState *cpu, uint8_t v1, uint8_t v2, uint8_t diff); +void SET_FLAGS_OSZAPC_SUB32(struct CPUState *cpu, uint32_t v1, uint32_t v2, + uint32_t diff); +void SET_FLAGS_OSZAPC_SUB16(struct CPUState *cpu, uint16_t v1, uint16_t v2, + uint16_t diff); +void SET_FLAGS_OSZAPC_SUB8(struct CPUState *cpu, uint8_t v1, uint8_t v2, + uint8_t diff); + +void SET_FLAGS_OSZAPC_ADD32(struct CPUState *cpu, uint32_t v1, uint32_t v2, + uint32_t diff); +void SET_FLAGS_OSZAPC_ADD16(struct CPUState *cpu, uint16_t v1, uint16_t v2, + uint16_t diff); +void SET_FLAGS_OSZAPC_ADD8(struct CPUState *cpu, uint8_t v1, uint8_t v2, + uint8_t diff); + +void SET_FLAGS_OSZAP_SUB32(struct CPUState *cpu, uint32_t v1, uint32_t v2, + uint32_t diff); +void SET_FLAGS_OSZAP_SUB16(struct CPUState *cpu, uint16_t v1, uint16_t v2, + uint16_t diff); +void SET_FLAGS_OSZAP_SUB8(struct CPUState *cpu, uint8_t v1, uint8_t v2, + uint8_t diff); + +void SET_FLAGS_OSZAP_ADD32(struct CPUState *cpu, uint32_t v1, uint32_t v2, + uint32_t diff); +void SET_FLAGS_OSZAP_ADD16(struct CPUState *cpu, uint16_t v1, uint16_t v2, + uint16_t diff); +void SET_FLAGS_OSZAP_ADD8(struct CPUState *cpu, uint8_t v1, uint8_t v2, + uint8_t diff); void SET_FLAGS_OSZAPC_LOGIC32(struct CPUState *cpu, uint32_t diff); void SET_FLAGS_OSZAPC_LOGIC16(struct CPUState *cpu, uint16_t diff); @@ -215,4 +242,6 @@ void SET_FLAGS_SHL32(struct CPUState *cpu, uint32_t v, int count, uint32_t res); void SET_FLAGS_SHL16(struct CPUState *cpu, uint16_t v, int count, uint16_t res); void SET_FLAGS_SHL8(struct CPUState *cpu, uint8_t v, int count, uint8_t res); +bool _get_OF(struct CPUState *cpu); +bool _get_CF(struct CPUState *cpu); #endif /* __X86_FLAGS_H__ */ diff --git a/target/i386/hvf-utils/x86_mmu.c b/target/i386/hvf-utils/x86_mmu.c index 00fae735be..4c9958ef4c 100644 --- a/target/i386/hvf-utils/x86_mmu.c +++ b/target/i386/hvf-utils/x86_mmu.c @@ -54,10 +54,12 @@ struct gpt_translation { static int gpt_top_level(struct CPUState *cpu, bool pae) { - if (!pae) + if (!pae) { return 2; - if (x86_is_long_mode(cpu)) + } + if (x86_is_long_mode(cpu)) { return 4; + } return 3; } @@ -74,18 +76,21 @@ static inline int pte_size(bool pae) } -static bool get_pt_entry(struct CPUState *cpu, struct gpt_translation *pt, int level, bool pae) +static bool get_pt_entry(struct CPUState *cpu, struct gpt_translation *pt, + int level, bool pae) { int index; uint64_t pte = 0; addr_t page_mask = pae ? PAE_PTE_PAGE_MASK : LEGACY_PTE_PAGE_MASK; addr_t gpa = pt->pte[level] & page_mask; - if (level == 3 && !x86_is_long_mode(cpu)) + if (level == 3 && !x86_is_long_mode(cpu)) { gpa = pt->pte[level]; + } index = gpt_entry(pt->gva, level, pae); - address_space_rw(&address_space_memory, gpa + index * pte_size(pae), MEMTXATTRS_UNSPECIFIED, (uint8_t *)&pte, pte_size(pae), 0); + address_space_rw(&address_space_memory, gpa + index * pte_size(pae), + MEMTXATTRS_UNSPECIFIED, (uint8_t *)&pte, pte_size(pae), 0); pt->pte[level - 1] = pte; @@ -93,32 +98,38 @@ static bool get_pt_entry(struct CPUState *cpu, struct gpt_translation *pt, int l } /* test page table entry */ -static bool test_pt_entry(struct CPUState *cpu, struct gpt_translation *pt, int level, bool *is_large, bool pae) +static bool test_pt_entry(struct CPUState *cpu, struct gpt_translation *pt, + int level, bool *is_large, bool pae) { uint64_t pte = pt->pte[level]; - - if (pt->write_access) + + if (pt->write_access) { pt->err_code |= MMU_PAGE_WT; - if (pt->user_access) + } + if (pt->user_access) { pt->err_code |= MMU_PAGE_US; - if (pt->exec_access) + } + if (pt->exec_access) { pt->err_code |= MMU_PAGE_NX; + } if (!pte_present(pte)) { - addr_t page_mask = pae ? PAE_PTE_PAGE_MASK : LEGACY_PTE_PAGE_MASK; + /* addr_t page_mask = pae ? PAE_PTE_PAGE_MASK : LEGACY_PTE_PAGE_MASK; */ return false; } - - if (pae && !x86_is_long_mode(cpu) && 2 == level) + + if (pae && !x86_is_long_mode(cpu) && 2 == level) { goto exit; - + } + if (1 == level && pte_large_page(pte)) { pt->err_code |= MMU_PAGE_PT; *is_large = true; } - if (!level) + if (!level) { pt->err_code |= MMU_PAGE_PT; - + } + addr_t cr0 = rvmcs(cpu->hvf_fd, VMCS_GUEST_CR0); /* check protection */ if (cr0 & CR0_WP) { @@ -134,7 +145,7 @@ static bool test_pt_entry(struct CPUState *cpu, struct gpt_translation *pt, int if (pae && pt->exec_access && !pte_exec_access(pte)) { return false; } - + exit: /* TODO: check reserved bits */ return true; @@ -149,22 +160,24 @@ static inline uint64_t large_page_gpa(struct gpt_translation *pt, bool pae) { VM_PANIC_ON(!pte_large_page(pt->pte[1])) /* 2Mb large page */ - if (pae) + if (pae) { return (pt->pte[1] & PAE_PTE_LARGE_PAGE_MASK) | (pt->gva & 0x1fffff); - + } + /* 4Mb large page */ return pse_pte_to_page(pt->pte[1]) | (pt->gva & 0x3fffff); } -static bool walk_gpt(struct CPUState *cpu, addr_t addr, int err_code, struct gpt_translation* pt, bool pae) +static bool walk_gpt(struct CPUState *cpu, addr_t addr, int err_code, + struct gpt_translation *pt, bool pae) { int top_level, level; bool is_large = false; addr_t cr3 = rvmcs(cpu->hvf_fd, VMCS_GUEST_CR3); addr_t page_mask = pae ? PAE_PTE_PAGE_MASK : LEGACY_PTE_PAGE_MASK; - + memset(pt, 0, sizeof(*pt)); top_level = gpt_top_level(cpu, pae); @@ -173,7 +186,7 @@ static bool walk_gpt(struct CPUState *cpu, addr_t addr, int err_code, struct gpt pt->user_access = (err_code & MMU_PAGE_US); pt->write_access = (err_code & MMU_PAGE_WT); pt->exec_access = (err_code & MMU_PAGE_NX); - + for (level = top_level; level > 0; level--) { get_pt_entry(cpu, pt, level, pae); @@ -181,14 +194,16 @@ static bool walk_gpt(struct CPUState *cpu, addr_t addr, int err_code, struct gpt return false; } - if (is_large) + if (is_large) { break; + } } - if (!is_large) + if (!is_large) { pt->gpa = (pt->pte[0] & page_mask) | (pt->gva & 0xfff); - else + } else { pt->gpa = large_page_gpa(pt, pae); + } return true; } @@ -214,18 +229,20 @@ bool mmu_gva_to_gpa(struct CPUState *cpu, addr_t gva, addr_t *gpa) return false; } -void vmx_write_mem(struct CPUState* cpu, addr_t gva, void *data, int bytes) +void vmx_write_mem(struct CPUState *cpu, addr_t gva, void *data, int bytes) { addr_t gpa; while (bytes > 0) { - // copy page + /* copy page */ int copy = MIN(bytes, 0x1000 - (gva & 0xfff)); if (!mmu_gva_to_gpa(cpu, gva, &gpa)) { - VM_PANIC_ON_EX(1, "%s: mmu_gva_to_gpa %llx failed\n", __FUNCTION__, gva); + VM_PANIC_ON_EX(1, "%s: mmu_gva_to_gpa %llx failed\n", __func__, + gva); } else { - address_space_rw(&address_space_memory, gpa, MEMTXATTRS_UNSPECIFIED, data, copy, 1); + address_space_rw(&address_space_memory, gpa, MEMTXATTRS_UNSPECIFIED, + data, copy, 1); } bytes -= copy; @@ -234,18 +251,20 @@ void vmx_write_mem(struct CPUState* cpu, addr_t gva, void *data, int bytes) } } -void vmx_read_mem(struct CPUState* cpu, void *data, addr_t gva, int bytes) +void vmx_read_mem(struct CPUState *cpu, void *data, addr_t gva, int bytes) { addr_t gpa; while (bytes > 0) { - // copy page + /* copy page */ int copy = MIN(bytes, 0x1000 - (gva & 0xfff)); if (!mmu_gva_to_gpa(cpu, gva, &gpa)) { - VM_PANIC_ON_EX(1, "%s: mmu_gva_to_gpa %llx failed\n", __FUNCTION__, gva); + VM_PANIC_ON_EX(1, "%s: mmu_gva_to_gpa %llx failed\n", __func__, + gva); } - address_space_rw(&address_space_memory, gpa, MEMTXATTRS_UNSPECIFIED, data, copy, 0); + address_space_rw(&address_space_memory, gpa, MEMTXATTRS_UNSPECIFIED, + data, copy, 0); bytes -= copy; gva += copy; diff --git a/target/i386/hvf-utils/x86_mmu.h b/target/i386/hvf-utils/x86_mmu.h index f794d04b3d..4fce48c18f 100644 --- a/target/i386/hvf-utils/x86_mmu.h +++ b/target/i386/hvf-utils/x86_mmu.h @@ -31,7 +31,7 @@ #define PT_GLOBAL (1 << 8) #define PT_NX (1llu << 63) -// error codes +/* error codes */ #define MMU_PAGE_PT (1 << 0) #define MMU_PAGE_WT (1 << 1) #define MMU_PAGE_US (1 << 2) @@ -39,7 +39,7 @@ bool mmu_gva_to_gpa(struct CPUState *cpu, addr_t gva, addr_t *gpa); -void vmx_write_mem(struct CPUState* cpu, addr_t gva, void *data, int bytes); -void vmx_read_mem(struct CPUState* cpu, void *data, addr_t gva, int bytes); +void vmx_write_mem(struct CPUState *cpu, addr_t gva, void *data, int bytes); +void vmx_read_mem(struct CPUState *cpu, void *data, addr_t gva, int bytes); #endif /* __X86_MMU_H__ */ diff --git a/target/i386/hvf-utils/x86hvf.c b/target/i386/hvf-utils/x86hvf.c index d5668df37f..967be2e7fe 100644 --- a/target/i386/hvf-utils/x86hvf.c +++ b/target/i386/hvf-utils/x86hvf.c @@ -35,16 +35,16 @@ #include #include -void hvf_cpu_synchronize_state(struct CPUState* cpu_state); - -void hvf_set_segment(struct CPUState *cpu, struct vmx_segment *vmx_seg, SegmentCache *qseg, bool is_tr) +void hvf_set_segment(struct CPUState *cpu, struct vmx_segment *vmx_seg, + SegmentCache *qseg, bool is_tr) { vmx_seg->sel = qseg->selector; vmx_seg->base = qseg->base; vmx_seg->limit = qseg->limit; if (!qseg->selector && !x86_is_real(cpu) && !is_tr) { - // the TR register is usable after processor reset despite having a null selector + /* the TR register is usable after processor reset despite + * having a null selector */ vmx_seg->ar = 1 << 16; return; } @@ -110,19 +110,18 @@ void hvf_put_xsave(CPUState *cpu_state) } } -void vmx_update_tpr(CPUState *cpu); void hvf_put_segments(CPUState *cpu_state) { CPUX86State *env = &X86_CPU(cpu_state)->env; struct vmx_segment seg; - + wvmcs(cpu_state->hvf_fd, VMCS_GUEST_IDTR_LIMIT, env->idt.limit); wvmcs(cpu_state->hvf_fd, VMCS_GUEST_IDTR_BASE, env->idt.base); wvmcs(cpu_state->hvf_fd, VMCS_GUEST_GDTR_LIMIT, env->gdt.limit); wvmcs(cpu_state->hvf_fd, VMCS_GUEST_GDTR_BASE, env->gdt.base); - //wvmcs(cpu_state->hvf_fd, VMCS_GUEST_CR2, env->cr[2]); + /* wvmcs(cpu_state->hvf_fd, VMCS_GUEST_CR2, env->cr[2]); */ wvmcs(cpu_state->hvf_fd, VMCS_GUEST_CR3, env->cr[3]); vmx_update_tpr(cpu_state); wvmcs(cpu_state->hvf_fd, VMCS_GUEST_IA32_EFER, env->efer); @@ -132,7 +131,7 @@ void hvf_put_segments(CPUState *cpu_state) hvf_set_segment(cpu_state, &seg, &env->segs[R_CS], false); vmx_write_segment_descriptor(cpu_state, &seg, REG_SEG_CS); - + hvf_set_segment(cpu_state, &seg, &env->segs[R_DS], false); vmx_write_segment_descriptor(cpu_state, &seg, REG_SEG_DS); @@ -153,17 +152,20 @@ void hvf_put_segments(CPUState *cpu_state) hvf_set_segment(cpu_state, &seg, &env->ldt, false); vmx_write_segment_descriptor(cpu_state, &seg, REG_SEG_LDTR); - + hv_vcpu_flush(cpu_state->hvf_fd); } - + void hvf_put_msrs(CPUState *cpu_state) { CPUX86State *env = &X86_CPU(cpu_state)->env; - hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_IA32_SYSENTER_CS, env->sysenter_cs); - hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_IA32_SYSENTER_ESP, env->sysenter_esp); - hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_IA32_SYSENTER_EIP, env->sysenter_eip); + hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_IA32_SYSENTER_CS, + env->sysenter_cs); + hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_IA32_SYSENTER_ESP, + env->sysenter_esp); + hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_IA32_SYSENTER_EIP, + env->sysenter_eip); hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_STAR, env->star); @@ -177,8 +179,8 @@ void hvf_put_msrs(CPUState *cpu_state) hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_GSBASE, env->segs[R_GS].base); hv_vcpu_write_msr(cpu_state->hvf_fd, MSR_FSBASE, env->segs[R_FS].base); - // if (!osx_is_sierra()) - // wvmcs(cpu_state->hvf_fd, VMCS_TSC_OFFSET, env->tsc - rdtscp()); + /* if (!osx_is_sierra()) + wvmcs(cpu_state->hvf_fd, VMCS_TSC_OFFSET, env->tsc - rdtscp());*/ hv_vm_sync_tsc(env->tsc); } @@ -230,7 +232,7 @@ void hvf_get_segments(CPUState *cpu_state) vmx_read_segment_descriptor(cpu_state, &seg, REG_SEG_CS); hvf_get_segment(&env->segs[R_CS], &seg); - + vmx_read_segment_descriptor(cpu_state, &seg, REG_SEG_DS); hvf_get_segment(&env->segs[R_DS], &seg); @@ -261,7 +263,7 @@ void hvf_get_segments(CPUState *cpu_state) env->cr[2] = 0; env->cr[3] = rvmcs(cpu_state->hvf_fd, VMCS_GUEST_CR3); env->cr[4] = rvmcs(cpu_state->hvf_fd, VMCS_GUEST_CR4); - + env->efer = rvmcs(cpu_state->hvf_fd, VMCS_GUEST_IA32_EFER); } @@ -269,10 +271,10 @@ void hvf_get_msrs(CPUState *cpu_state) { CPUX86State *env = &X86_CPU(cpu_state)->env; uint64_t tmp; - + hv_vcpu_read_msr(cpu_state->hvf_fd, MSR_IA32_SYSENTER_CS, &tmp); env->sysenter_cs = tmp; - + hv_vcpu_read_msr(cpu_state->hvf_fd, MSR_IA32_SYSENTER_ESP, &tmp); env->sysenter_esp = tmp; @@ -289,7 +291,7 @@ void hvf_get_msrs(CPUState *cpu_state) #endif hv_vcpu_read_msr(cpu_state->hvf_fd, MSR_IA32_APICBASE, &tmp); - + env->tsc = rdtscp() + rvmcs(cpu_state->hvf_fd, VMCS_TSC_OFFSET); } @@ -316,15 +318,15 @@ int hvf_put_registers(CPUState *cpu_state) wreg(cpu_state->hvf_fd, HV_X86_R15, env->regs[15]); wreg(cpu_state->hvf_fd, HV_X86_RFLAGS, env->eflags); wreg(cpu_state->hvf_fd, HV_X86_RIP, env->eip); - + wreg(cpu_state->hvf_fd, HV_X86_XCR0, env->xcr0); - + hvf_put_xsave(cpu_state); - + hvf_put_segments(cpu_state); - + hvf_put_msrs(cpu_state); - + wreg(cpu_state->hvf_fd, HV_X86_DR0, env->dr[0]); wreg(cpu_state->hvf_fd, HV_X86_DR1, env->dr[1]); wreg(cpu_state->hvf_fd, HV_X86_DR2, env->dr[2]); @@ -333,7 +335,7 @@ int hvf_put_registers(CPUState *cpu_state) wreg(cpu_state->hvf_fd, HV_X86_DR5, env->dr[5]); wreg(cpu_state->hvf_fd, HV_X86_DR6, env->dr[6]); wreg(cpu_state->hvf_fd, HV_X86_DR7, env->dr[7]); - + return 0; } @@ -359,16 +361,16 @@ int hvf_get_registers(CPUState *cpu_state) env->regs[13] = rreg(cpu_state->hvf_fd, HV_X86_R13); env->regs[14] = rreg(cpu_state->hvf_fd, HV_X86_R14); env->regs[15] = rreg(cpu_state->hvf_fd, HV_X86_R15); - + env->eflags = rreg(cpu_state->hvf_fd, HV_X86_RFLAGS); env->eip = rreg(cpu_state->hvf_fd, HV_X86_RIP); - + hvf_get_xsave(cpu_state); env->xcr0 = rreg(cpu_state->hvf_fd, HV_X86_XCR0); - + hvf_get_segments(cpu_state); hvf_get_msrs(cpu_state); - + env->dr[0] = rreg(cpu_state->hvf_fd, HV_X86_DR0); env->dr[1] = rreg(cpu_state->hvf_fd, HV_X86_DR1); env->dr[2] = rreg(cpu_state->hvf_fd, HV_X86_DR2); @@ -377,7 +379,7 @@ int hvf_get_registers(CPUState *cpu_state) env->dr[5] = rreg(cpu_state->hvf_fd, HV_X86_DR5); env->dr[6] = rreg(cpu_state->hvf_fd, HV_X86_DR6); env->dr[7] = rreg(cpu_state->hvf_fd, HV_X86_DR7); - + return 0; } @@ -385,14 +387,16 @@ static void vmx_set_int_window_exiting(CPUState *cpu) { uint64_t val; val = rvmcs(cpu->hvf_fd, VMCS_PRI_PROC_BASED_CTLS); - wvmcs(cpu->hvf_fd, VMCS_PRI_PROC_BASED_CTLS, val | VMCS_PRI_PROC_BASED_CTLS_INT_WINDOW_EXITING); + wvmcs(cpu->hvf_fd, VMCS_PRI_PROC_BASED_CTLS, val | + VMCS_PRI_PROC_BASED_CTLS_INT_WINDOW_EXITING); } void vmx_clear_int_window_exiting(CPUState *cpu) { uint64_t val; val = rvmcs(cpu->hvf_fd, VMCS_PRI_PROC_BASED_CTLS); - wvmcs(cpu->hvf_fd, VMCS_PRI_PROC_BASED_CTLS, val & ~VMCS_PRI_PROC_BASED_CTLS_INT_WINDOW_EXITING); + wvmcs(cpu->hvf_fd, VMCS_PRI_PROC_BASED_CTLS, val & + ~VMCS_PRI_PROC_BASED_CTLS_INT_WINDOW_EXITING); } #define NMI_VEC 2 @@ -400,28 +404,30 @@ void vmx_clear_int_window_exiting(CPUState *cpu) void hvf_inject_interrupts(CPUState *cpu_state) { X86CPU *x86cpu = X86_CPU(cpu_state); - int allow_nmi = !(rvmcs(cpu_state->hvf_fd, VMCS_GUEST_INTERRUPTIBILITY) & VMCS_INTERRUPTIBILITY_NMI_BLOCKING); + int allow_nmi = !(rvmcs(cpu_state->hvf_fd, VMCS_GUEST_INTERRUPTIBILITY) & + VMCS_INTERRUPTIBILITY_NMI_BLOCKING); uint64_t idt_info = rvmcs(cpu_state->hvf_fd, VMCS_IDT_VECTORING_INFO); uint64_t info = 0; - + if (idt_info & VMCS_IDT_VEC_VALID) { uint8_t vector = idt_info & 0xff; uint64_t intr_type = idt_info & VMCS_INTR_T_MASK; info = idt_info; - + uint64_t reason = rvmcs(cpu_state->hvf_fd, VMCS_EXIT_REASON); if (intr_type == VMCS_INTR_T_NMI && reason != EXIT_REASON_TASK_SWITCH) { allow_nmi = 1; vmx_clear_nmi_blocking(cpu_state); } - + if ((allow_nmi || intr_type != VMCS_INTR_T_NMI)) { info &= ~(1 << 12); /* clear undefined bit */ if (intr_type == VMCS_INTR_T_SWINTR || intr_type == VMCS_INTR_T_PRIV_SWEXCEPTION || intr_type == VMCS_INTR_T_SWEXCEPTION) { - uint64_t ins_len = rvmcs(cpu_state->hvf_fd, VMCS_EXIT_INSTRUCTION_LENGTH); + uint64_t ins_len = rvmcs(cpu_state->hvf_fd, + VMCS_EXIT_INSTRUCTION_LENGTH); wvmcs(cpu_state->hvf_fd, VMCS_ENTRY_INST_LENGTH, ins_len); } if (vector == EXCEPTION_BP || vector == EXCEPTION_OF) { @@ -431,16 +437,17 @@ void hvf_inject_interrupts(CPUState *cpu_state) */ info &= ~VMCS_INTR_T_MASK; info |= VMCS_INTR_T_SWEXCEPTION; - uint64_t ins_len = rvmcs(cpu_state->hvf_fd, VMCS_EXIT_INSTRUCTION_LENGTH); + uint64_t ins_len = rvmcs(cpu_state->hvf_fd, + VMCS_EXIT_INSTRUCTION_LENGTH); wvmcs(cpu_state->hvf_fd, VMCS_ENTRY_INST_LENGTH, ins_len); } - + uint64_t err = 0; if (idt_info & VMCS_INTR_DEL_ERRCODE) { err = rvmcs(cpu_state->hvf_fd, VMCS_IDT_VECTORING_ERROR); wvmcs(cpu_state->hvf_fd, VMCS_ENTRY_EXCEPTION_ERROR, err); } - //printf("reinject %lx err %d\n", info, err); + /*printf("reinject %lx err %d\n", info, err);*/ wvmcs(cpu_state->hvf_fd, VMCS_ENTRY_INTR_INFO, info); }; } @@ -455,22 +462,26 @@ void hvf_inject_interrupts(CPUState *cpu_state) } } - if (cpu_state->hvf_x86->interruptable && (cpu_state->interrupt_request & CPU_INTERRUPT_HARD) && + if (cpu_state->hvf_x86->interruptable && + (cpu_state->interrupt_request & CPU_INTERRUPT_HARD) && (EFLAGS(cpu_state) & IF_MASK) && !(info & VMCS_INTR_VALID)) { int line = cpu_get_pic_interrupt(&x86cpu->env); cpu_state->interrupt_request &= ~CPU_INTERRUPT_HARD; - if (line >= 0) - wvmcs(cpu_state->hvf_fd, VMCS_ENTRY_INTR_INFO, line | VMCS_INTR_VALID | VMCS_INTR_T_HWINTR); + if (line >= 0) { + wvmcs(cpu_state->hvf_fd, VMCS_ENTRY_INTR_INFO, line | + VMCS_INTR_VALID | VMCS_INTR_T_HWINTR); + } } - if (cpu_state->interrupt_request & CPU_INTERRUPT_HARD) + if (cpu_state->interrupt_request & CPU_INTERRUPT_HARD) { vmx_set_int_window_exiting(cpu_state); + } } int hvf_process_events(CPUState *cpu_state) { X86CPU *cpu = X86_CPU(cpu_state); CPUX86State *env = &cpu->env; - + EFLAGS(cpu_state) = rreg(cpu_state->hvf_fd, HV_X86_RFLAGS); if (cpu_state->interrupt_request & CPU_INTERRUPT_INIT) { @@ -482,7 +493,8 @@ int hvf_process_events(CPUState *cpu_state) cpu_state->interrupt_request &= ~CPU_INTERRUPT_POLL; apic_poll_irq(cpu->apic_state); } - if (((cpu_state->interrupt_request & CPU_INTERRUPT_HARD) && (EFLAGS(cpu_state) & IF_MASK)) || + if (((cpu_state->interrupt_request & CPU_INTERRUPT_HARD) && + (EFLAGS(cpu_state) & IF_MASK)) || (cpu_state->interrupt_request & CPU_INTERRUPT_NMI)) { cpu_state->halted = 0; } diff --git a/target/i386/hvf-utils/x86hvf.h b/target/i386/hvf-utils/x86hvf.h index fbc2158a2b..4e0d723689 100644 --- a/target/i386/hvf-utils/x86hvf.h +++ b/target/i386/hvf-utils/x86hvf.h @@ -24,7 +24,8 @@ int hvf_process_events(CPUState *); int hvf_put_registers(CPUState *); int hvf_get_registers(CPUState *); void hvf_inject_interrupts(CPUState *); -void hvf_set_segment(struct CPUState *cpu, struct vmx_segment *vmx_seg, SegmentCache *qseg, bool is_tr); +void hvf_set_segment(struct CPUState *cpu, struct vmx_segment *vmx_seg, + SegmentCache *qseg, bool is_tr); void hvf_get_segment(SegmentCache *qseg, struct vmx_segment *vmx_seg); void hvf_put_xsave(CPUState *cpu_state); void hvf_put_segments(CPUState *cpu_state); @@ -33,4 +34,6 @@ void hvf_get_xsave(CPUState *cpu_state); void hvf_get_msrs(CPUState *cpu_state); void vmx_clear_int_window_exiting(CPUState *cpu); void hvf_get_segments(CPUState *cpu_state); +void vmx_update_tpr(CPUState *cpu); +void hvf_cpu_synchronize_state(CPUState *cpu_state); #endif