diff --git a/MAINTAINERS b/MAINTAINERS index 15503f41d8..3275cc6bbe 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1903,6 +1903,11 @@ S: Maintained F: include/qemu/iova-tree.h F: util/iova-tree.c +elf2dmp +M: Viktor Prutyanov +S: Maintained +F: contrib/elf2dmp/ + Usermode Emulation ------------------ Overall diff --git a/Makefile b/Makefile index 3730092817..1144d6e3ba 100644 --- a/Makefile +++ b/Makefile @@ -415,6 +415,7 @@ dummy := $(call unnest-vars,, \ chardev-obj-y \ util-obj-y \ qga-obj-y \ + elf2dmp-obj-y \ ivshmem-client-obj-y \ ivshmem-server-obj-y \ libvhost-user-obj-y \ @@ -710,6 +711,10 @@ ifneq ($(EXESUF),) qemu-ga: qemu-ga$(EXESUF) $(QGA_VSS_PROVIDER) $(QEMU_GA_MSI) endif +elf2dmp: LIBS = $(CURL_LIBS) +elf2dmp: $(elf2dmp-obj-y) + $(call LINK, $^) + ifdef CONFIG_IVSHMEM ivshmem-client$(EXESUF): $(ivshmem-client-obj-y) $(COMMON_LDADDS) $(call LINK, $^) diff --git a/Makefile.objs b/Makefile.objs index ce9c79235e..1e1ff387d7 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -186,6 +186,7 @@ qga-vss-dll-obj-y = qga/ ###################################################################### # contrib +elf2dmp-obj-y = contrib/elf2dmp/ ivshmem-client-obj-$(CONFIG_IVSHMEM) = contrib/ivshmem-client/ ivshmem-server-obj-$(CONFIG_IVSHMEM) = contrib/ivshmem-server/ libvhost-user-obj-y = contrib/libvhost-user/ diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 9ffbbc2fbd..ad5c758246 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -2009,15 +2009,6 @@ void tb_invalidate_phys_page_fast(struct page_collection *pages, { PageDesc *p; -#if 0 - if (1) { - qemu_log("modifying code at 0x%x size=%d EIP=%x PC=%08x\n", - cpu_single_env->mem_io_vaddr, len, - cpu_single_env->eip, - cpu_single_env->eip + - (intptr_t)cpu_single_env->segs[R_CS].base); - } -#endif assert_memory_lock(); p = page_find(start >> TARGET_PAGE_BITS); diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index 0f9dca9113..afd0a49ea6 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -34,6 +34,8 @@ void translator_loop_temp_check(DisasContextBase *db) void translator_loop(const TranslatorOps *ops, DisasContextBase *db, CPUState *cpu, TranslationBlock *tb) { + int bp_insn = 0; + /* Initialize DisasContext */ db->tb = tb; db->pc_first = tb->pc; @@ -71,11 +73,13 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */ /* Pass breakpoint hits to target for further processing */ - if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) { + if (!db->singlestep_enabled + && unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) { CPUBreakpoint *bp; QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { if (bp->pc == db->pc_next) { if (ops->breakpoint_check(db, cpu, bp)) { + bp_insn = 1; break; } } @@ -118,7 +122,7 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, /* Emit code to exit the TB, as indicated by db->is_jmp. */ ops->tb_stop(db, cpu); - gen_tb_end(db->tb, db->num_insns); + gen_tb_end(db->tb, db->num_insns - bp_insn); /* The disas_log hook may use these values rather than recompute. */ db->tb->size = db->pc_next - db->pc_first; diff --git a/backends/Makefile.objs b/backends/Makefile.objs index ad7c0325ed..717fcbdae4 100644 --- a/backends/Makefile.objs +++ b/backends/Makefile.objs @@ -4,7 +4,7 @@ common-obj-$(CONFIG_POSIX) += rng-random.o common-obj-$(CONFIG_TPM) += tpm.o common-obj-y += hostmem.o hostmem-ram.o -common-obj-$(CONFIG_LINUX) += hostmem-file.o +common-obj-$(CONFIG_POSIX) += hostmem-file.o common-obj-y += cryptodev.o common-obj-y += cryptodev-builtin.o diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c index 2476dcb435..e64074954f 100644 --- a/backends/hostmem-file.c +++ b/backends/hostmem-file.c @@ -51,7 +51,7 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp) error_setg(errp, "mem-path property not set"); return; } -#ifndef CONFIG_LINUX +#ifndef CONFIG_POSIX error_setg(errp, "-mem-path not supported on this host"); #else if (!host_memory_backend_mr_inited(backend)) { diff --git a/backends/hostmem-memfd.c b/backends/hostmem-memfd.c index 1e20fe0ba8..3800bd07b6 100644 --- a/backends/hostmem-memfd.c +++ b/backends/hostmem-memfd.c @@ -140,18 +140,22 @@ memfd_backend_class_init(ObjectClass *oc, void *data) bc->alloc = memfd_backend_memory_alloc; - object_class_property_add_bool(oc, "hugetlb", - memfd_backend_get_hugetlb, - memfd_backend_set_hugetlb, - &error_abort); - object_class_property_add(oc, "hugetlbsize", "int", - memfd_backend_get_hugetlbsize, - memfd_backend_set_hugetlbsize, - NULL, NULL, &error_abort); - object_class_property_add_bool(oc, "seal", - memfd_backend_get_seal, - memfd_backend_set_seal, - &error_abort); + if (qemu_memfd_check(MFD_HUGETLB)) { + object_class_property_add_bool(oc, "hugetlb", + memfd_backend_get_hugetlb, + memfd_backend_set_hugetlb, + &error_abort); + object_class_property_add(oc, "hugetlbsize", "int", + memfd_backend_get_hugetlbsize, + memfd_backend_set_hugetlbsize, + NULL, NULL, &error_abort); + } + if (qemu_memfd_check(MFD_ALLOW_SEALING)) { + object_class_property_add_bool(oc, "seal", + memfd_backend_get_seal, + memfd_backend_set_seal, + &error_abort); + } } static const TypeInfo memfd_backend_info = { @@ -164,7 +168,9 @@ static const TypeInfo memfd_backend_info = { static void register_types(void) { - type_register_static(&memfd_backend_info); + if (qemu_memfd_check(0)) { + type_register_static(&memfd_backend_info); + } } type_init(register_types); diff --git a/chardev/char-pty.c b/chardev/char-pty.c index 68fd4e20c3..e8d9a53476 100644 --- a/chardev/char-pty.c +++ b/chardev/char-pty.c @@ -31,10 +31,6 @@ #include "chardev/char-io.h" -#if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ - || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \ - || defined(__GLIBC__) - typedef struct { Chardev parent; QIOChannel *ioc; @@ -299,5 +295,3 @@ static void register_types(void) } type_init(register_types); - -#endif diff --git a/chardev/char-socket.c b/chardev/char-socket.c index efbad6ee7c..7cd0ae2824 100644 --- a/chardev/char-socket.c +++ b/chardev/char-socket.c @@ -32,7 +32,6 @@ #include "qapi/error.h" #include "qapi/clone-visitor.h" #include "qapi/qapi-visit-sockets.h" -#include "sysemu/sysemu.h" #include "chardev/char-io.h" @@ -354,6 +353,15 @@ static GSource *tcp_chr_add_watch(Chardev *chr, GIOCondition cond) return qio_channel_create_watch(s->ioc, cond); } +static void remove_hup_source(SocketChardev *s) +{ + if (s->hup_source != NULL) { + g_source_destroy(s->hup_source); + g_source_unref(s->hup_source); + s->hup_source = NULL; + } +} + static void tcp_chr_free_connection(Chardev *chr) { SocketChardev *s = SOCKET_CHARDEV(chr); @@ -368,11 +376,7 @@ static void tcp_chr_free_connection(Chardev *chr) s->read_msgfds_num = 0; } - if (s->hup_source != NULL) { - g_source_destroy(s->hup_source); - g_source_unref(s->hup_source); - s->hup_source = NULL; - } + remove_hup_source(s); tcp_set_msgfds(chr, NULL, 0); remove_fd_in_watch(chr); @@ -541,6 +545,27 @@ static char *sockaddr_to_str(struct sockaddr_storage *ss, socklen_t ss_len, } } +static void update_ioc_handlers(SocketChardev *s) +{ + Chardev *chr = CHARDEV(s); + + if (!s->connected) { + return; + } + + remove_fd_in_watch(chr); + chr->gsource = io_add_watch_poll(chr, s->ioc, + tcp_chr_read_poll, + tcp_chr_read, chr, + chr->gcontext); + + remove_hup_source(s); + s->hup_source = qio_channel_create_watch(s->ioc, G_IO_HUP); + g_source_set_callback(s->hup_source, (GSourceFunc)tcp_chr_hup, + chr, NULL); + g_source_attach(s->hup_source, chr->gcontext); +} + static void tcp_chr_connect(void *opaque) { Chardev *chr = CHARDEV(opaque); @@ -553,16 +578,7 @@ static void tcp_chr_connect(void *opaque) s->is_listen, s->is_telnet); s->connected = 1; - chr->gsource = io_add_watch_poll(chr, s->ioc, - tcp_chr_read_poll, - tcp_chr_read, - chr, chr->gcontext); - - s->hup_source = qio_channel_create_watch(s->ioc, G_IO_HUP); - g_source_set_callback(s->hup_source, (GSourceFunc)tcp_chr_hup, - chr, NULL); - g_source_attach(s->hup_source, chr->gcontext); - + update_ioc_handlers(s); qemu_chr_be_event(chr, CHR_EVENT_OPENED); } @@ -593,17 +609,7 @@ static void tcp_chr_update_read_handler(Chardev *chr) tcp_chr_telnet_init(CHARDEV(s)); } - if (!s->connected) { - return; - } - - remove_fd_in_watch(chr); - if (s->ioc) { - chr->gsource = io_add_watch_poll(chr, s->ioc, - tcp_chr_read_poll, - tcp_chr_read, chr, - chr->gcontext); - } + update_ioc_handlers(s); } static gboolean tcp_chr_telnet_init_io(QIOChannel *ioc, @@ -724,11 +730,6 @@ static void tcp_chr_tls_init(Chardev *chr) Error *err = NULL; gchar *name; - if (!machine_init_done) { - /* This will be postponed to machine_done notifier */ - return; - } - if (s->is_listen) { tioc = qio_channel_tls_new_server( s->ioc, s->tls_creds, @@ -1011,8 +1012,9 @@ static void qmp_chardev_open_socket(Chardev *chr, s->reconnect_time = reconnect; } - /* If reconnect_time is set, will do that in chr_machine_done. */ - if (!s->reconnect_time) { + if (s->reconnect_time) { + tcp_chr_connect_async(chr); + } else { if (s->is_listen) { char *name; s->listener = qio_net_listener_new(); @@ -1161,21 +1163,6 @@ char_socket_get_connected(Object *obj, Error **errp) return s->connected; } -static int tcp_chr_machine_done_hook(Chardev *chr) -{ - SocketChardev *s = SOCKET_CHARDEV(chr); - - if (s->reconnect_time) { - tcp_chr_connect_async(chr); - } - - if (s->ioc && s->tls_creds) { - tcp_chr_tls_init(chr); - } - - return 0; -} - static void char_socket_class_init(ObjectClass *oc, void *data) { ChardevClass *cc = CHARDEV_CLASS(oc); @@ -1191,7 +1178,6 @@ static void char_socket_class_init(ObjectClass *oc, void *data) cc->chr_add_client = tcp_chr_add_client; cc->chr_add_watch = tcp_chr_add_watch; cc->chr_update_read_handler = tcp_chr_update_read_handler; - cc->chr_machine_done = tcp_chr_machine_done_hook; object_class_property_add(oc, "addr", "SocketAddress", char_socket_get_addr, NULL, diff --git a/configure b/configure index 18006f0865..f3d4b799a5 100755 --- a/configure +++ b/configure @@ -5721,6 +5721,9 @@ if test "$want_tools" = "yes" ; then if [ "$ivshmem" = "yes" ]; then tools="ivshmem-client\$(EXESUF) ivshmem-server\$(EXESUF) $tools" fi + if [ "$posix" = "yes" ] && [ "$curl" = "yes" ]; then + tools="elf2dmp $tools" + fi fi if test "$softmmu" = yes ; then if test "$linux" = yes; then @@ -7024,12 +7027,14 @@ TARGET_ABI_DIR="" case "$target_name" in i386) + mttcg="yes" gdb_xml_files="i386-32bit.xml i386-32bit-core.xml i386-32bit-sse.xml" target_compiler=$cross_cc_i386 target_compiler_cflags=$cross_cc_ccflags_i386 ;; x86_64) TARGET_BASE_ARCH=i386 + mttcg="yes" gdb_xml_files="i386-64bit.xml i386-64bit-core.xml i386-64bit-sse.xml" target_compiler=$cross_cc_x86_64 ;; @@ -7527,6 +7532,46 @@ cat <config.status # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. EOD + +preserve_env() { + envname=$1 + + eval envval=\$$envname + + if test -n "$envval" + then + echo "$envname='$envval'" >> config.status + echo "export $envname" >> config.status + else + echo "unset $envname" >> config.status + fi +} + +# Preserve various env variables that influence what +# features/build target configure will detect +preserve_env AR +preserve_env AS +preserve_env CC +preserve_env CPP +preserve_env CXX +preserve_env INSTALL +preserve_env LD +preserve_env LD_LIBRARY_PATH +preserve_env LIBTOOL +preserve_env MAKE +preserve_env NM +preserve_env OBJCOPY +preserve_env PATH +preserve_env PKG_CONFIG +preserve_env PKG_CONFIG_LIBDIR +preserve_env PKG_CONFIG_PATH +preserve_env PYTHON +preserve_env SDL_CONFIG +preserve_env SDL2_CONFIG +preserve_env SMBD +preserve_env STRIP +preserve_env WINDRES + printf "exec" >>config.status printf " '%s'" "$0" "$@" >>config.status echo ' "$@"' >>config.status diff --git a/contrib/elf2dmp/Makefile.objs b/contrib/elf2dmp/Makefile.objs new file mode 100644 index 0000000000..e3140f58cf --- /dev/null +++ b/contrib/elf2dmp/Makefile.objs @@ -0,0 +1 @@ +elf2dmp-obj-y = main.o addrspace.o download.o pdb.o qemu_elf.o diff --git a/contrib/elf2dmp/addrspace.c b/contrib/elf2dmp/addrspace.c new file mode 100644 index 0000000000..8a76069cb5 --- /dev/null +++ b/contrib/elf2dmp/addrspace.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2018 Virtuozzo International GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * + */ + +#include "qemu/osdep.h" +#include "addrspace.h" + +static struct pa_block *pa_space_find_block(struct pa_space *ps, uint64_t pa) +{ + size_t i; + for (i = 0; i < ps->block_nr; i++) { + if (ps->block[i].paddr <= pa && + pa <= ps->block[i].paddr + ps->block[i].size) { + return ps->block + i; + } + } + + return NULL; +} + +static uint8_t *pa_space_resolve(struct pa_space *ps, uint64_t pa) +{ + struct pa_block *block = pa_space_find_block(ps, pa); + + if (!block) { + return NULL; + } + + return block->addr + (pa - block->paddr); +} + +int pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf) +{ + Elf64_Half phdr_nr = elf_getphdrnum(qemu_elf->map); + Elf64_Phdr *phdr = elf64_getphdr(qemu_elf->map); + size_t block_i = 0; + size_t i; + + ps->block_nr = 0; + + for (i = 0; i < phdr_nr; i++) { + if (phdr[i].p_type == PT_LOAD) { + ps->block_nr++; + } + } + + ps->block = malloc(sizeof(*ps->block) * ps->block_nr); + if (!ps->block) { + return 1; + } + + for (i = 0; i < phdr_nr; i++) { + if (phdr[i].p_type == PT_LOAD) { + ps->block[block_i] = (struct pa_block) { + .addr = (uint8_t *)qemu_elf->map + phdr[i].p_offset, + .paddr = phdr[i].p_paddr, + .size = phdr[i].p_filesz, + }; + block_i++; + } + } + + return 0; +} + +void pa_space_destroy(struct pa_space *ps) +{ + ps->block_nr = 0; + free(ps->block); +} + +void va_space_set_dtb(struct va_space *vs, uint64_t dtb) +{ + vs->dtb = dtb & 0x00ffffffffff000; +} + +void va_space_create(struct va_space *vs, struct pa_space *ps, uint64_t dtb) +{ + vs->ps = ps; + va_space_set_dtb(vs, dtb); +} + +static uint64_t get_pml4e(struct va_space *vs, uint64_t va) +{ + uint64_t pa = (vs->dtb & 0xffffffffff000) | ((va & 0xff8000000000) >> 36); + + return *(uint64_t *)pa_space_resolve(vs->ps, pa); +} + +static uint64_t get_pdpi(struct va_space *vs, uint64_t va, uint64_t pml4e) +{ + uint64_t pdpte_paddr = (pml4e & 0xffffffffff000) | + ((va & 0x7FC0000000) >> 27); + + return *(uint64_t *)pa_space_resolve(vs->ps, pdpte_paddr); +} + +static uint64_t pde_index(uint64_t va) +{ + return (va >> 21) & 0x1FF; +} + +static uint64_t pdba_base(uint64_t pdpe) +{ + return pdpe & 0xFFFFFFFFFF000; +} + +static uint64_t get_pgd(struct va_space *vs, uint64_t va, uint64_t pdpe) +{ + uint64_t pgd_entry = pdba_base(pdpe) + pde_index(va) * 8; + + return *(uint64_t *)pa_space_resolve(vs->ps, pgd_entry); +} + +static uint64_t pte_index(uint64_t va) +{ + return (va >> 12) & 0x1FF; +} + +static uint64_t ptba_base(uint64_t pde) +{ + return pde & 0xFFFFFFFFFF000; +} + +static uint64_t get_pte(struct va_space *vs, uint64_t va, uint64_t pgd) +{ + uint64_t pgd_val = ptba_base(pgd) + pte_index(va) * 8; + + return *(uint64_t *)pa_space_resolve(vs->ps, pgd_val); +} + +static uint64_t get_paddr(uint64_t va, uint64_t pte) +{ + return (pte & 0xFFFFFFFFFF000) | (va & 0xFFF); +} + +static bool is_present(uint64_t entry) +{ + return entry & 0x1; +} + +static bool page_size_flag(uint64_t entry) +{ + return entry & (1 << 7); +} + +static uint64_t get_1GB_paddr(uint64_t va, uint64_t pdpte) +{ + return (pdpte & 0xfffffc0000000) | (va & 0x3fffffff); +} + +static uint64_t get_2MB_paddr(uint64_t va, uint64_t pgd_entry) +{ + return (pgd_entry & 0xfffffffe00000) | (va & 0x00000001fffff); +} + +static uint64_t va_space_va2pa(struct va_space *vs, uint64_t va) +{ + uint64_t pml4e, pdpe, pgd, pte; + + pml4e = get_pml4e(vs, va); + if (!is_present(pml4e)) { + return INVALID_PA; + } + + pdpe = get_pdpi(vs, va, pml4e); + if (!is_present(pdpe)) { + return INVALID_PA; + } + + if (page_size_flag(pdpe)) { + return get_1GB_paddr(va, pdpe); + } + + pgd = get_pgd(vs, va, pdpe); + if (!is_present(pgd)) { + return INVALID_PA; + } + + if (page_size_flag(pgd)) { + return get_2MB_paddr(va, pgd); + } + + pte = get_pte(vs, va, pgd); + if (!is_present(pte)) { + return INVALID_PA; + } + + return get_paddr(va, pte); +} + +void *va_space_resolve(struct va_space *vs, uint64_t va) +{ + uint64_t pa = va_space_va2pa(vs, va); + + if (pa == INVALID_PA) { + return NULL; + } + + return pa_space_resolve(vs->ps, pa); +} + +int va_space_rw(struct va_space *vs, uint64_t addr, + void *buf, size_t size, int is_write) +{ + while (size) { + uint64_t page = addr & PFN_MASK; + size_t s = (page + PAGE_SIZE) - addr; + void *ptr; + + s = (s > size) ? size : s; + + ptr = va_space_resolve(vs, addr); + if (!ptr) { + return 1; + } + + if (is_write) { + memcpy(ptr, buf, s); + } else { + memcpy(buf, ptr, s); + } + + size -= s; + buf = (uint8_t *)buf + s; + addr += s; + } + + return 0; +} diff --git a/contrib/elf2dmp/addrspace.h b/contrib/elf2dmp/addrspace.h new file mode 100644 index 0000000000..d87f6a18c6 --- /dev/null +++ b/contrib/elf2dmp/addrspace.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018 Virtuozzo International GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * + */ + +#ifndef ADDRSPACE_H +#define ADDRSPACE_H + +#include "qemu_elf.h" + +#define PAGE_BITS 12 +#define PAGE_SIZE (1ULL << PAGE_BITS) +#define PFN_MASK (~(PAGE_SIZE - 1)) + +#define INVALID_PA UINT64_MAX + +struct pa_block { + uint8_t *addr; + uint64_t paddr; + uint64_t size; +}; + +struct pa_space { + size_t block_nr; + struct pa_block *block; +}; + +struct va_space { + uint64_t dtb; + struct pa_space *ps; +}; + +int pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf); +void pa_space_destroy(struct pa_space *ps); + +void va_space_create(struct va_space *vs, struct pa_space *ps, uint64_t dtb); +void va_space_set_dtb(struct va_space *vs, uint64_t dtb); +void *va_space_resolve(struct va_space *vs, uint64_t va); +int va_space_rw(struct va_space *vs, uint64_t addr, + void *buf, size_t size, int is_write); + +#endif /* ADDRSPACE_H */ diff --git a/contrib/elf2dmp/download.c b/contrib/elf2dmp/download.c new file mode 100644 index 0000000000..d09e607431 --- /dev/null +++ b/contrib/elf2dmp/download.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018 Virtuozzo International GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * + */ + +#include "qemu/osdep.h" +#include +#include "download.h" + +int download_url(const char *name, const char *url) +{ + int err = 0; + FILE *file; + CURL *curl = curl_easy_init(); + + if (!curl) { + return 1; + } + + file = fopen(name, "wb"); + if (!file) { + err = 1; + goto out_curl; + } + + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, file); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); + + if (curl_easy_perform(curl) != CURLE_OK) { + err = 1; + fclose(file); + unlink(name); + goto out_curl; + } + + err = fclose(file); + +out_curl: + curl_easy_cleanup(curl); + + return err; +} diff --git a/contrib/elf2dmp/download.h b/contrib/elf2dmp/download.h new file mode 100644 index 0000000000..5c274925f7 --- /dev/null +++ b/contrib/elf2dmp/download.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2018 Virtuozzo International GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * + */ + +#ifndef DOWNLOAD_H +#define DOWNLOAD_H + +int download_url(const char *name, const char *url); + +#endif /* DOWNLOAD_H */ diff --git a/contrib/elf2dmp/err.h b/contrib/elf2dmp/err.h new file mode 100644 index 0000000000..5456bd5a30 --- /dev/null +++ b/contrib/elf2dmp/err.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2018 Virtuozzo International GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * + */ + +#ifndef ERR_H +#define ERR_H + +#define eprintf(...) fprintf(stderr, __VA_ARGS__) + +#endif /* ERR_H */ diff --git a/contrib/elf2dmp/kdbg.h b/contrib/elf2dmp/kdbg.h new file mode 100644 index 0000000000..851b57c321 --- /dev/null +++ b/contrib/elf2dmp/kdbg.h @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2018 Virtuozzo International GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * + */ + +#ifndef KDBG_H +#define KDBG_H + +typedef struct DBGKD_GET_VERSION64 { + uint16_t MajorVersion; + uint16_t MinorVersion; + uint8_t ProtocolVersion; + uint8_t KdSecondaryVersion; + uint16_t Flags; + uint16_t MachineType; + uint8_t MaxPacketType; + uint8_t MaxStateChange; + uint8_t MaxManipulate; + uint8_t Simulation; + uint16_t Unused[1]; + uint64_t KernBase; + uint64_t PsLoadedModuleList; + uint64_t DebuggerDataList; +} DBGKD_GET_VERSION64; + +typedef struct DBGKD_DEBUG_DATA_HEADER64 { + struct LIST_ENTRY64 { + struct LIST_ENTRY64 *Flink; + struct LIST_ENTRY64 *Blink; + } List; + uint32_t OwnerTag; + uint32_t Size; +} DBGKD_DEBUG_DATA_HEADER64; + +typedef struct KDDEBUGGER_DATA64 { + DBGKD_DEBUG_DATA_HEADER64 Header; + + uint64_t KernBase; + uint64_t BreakpointWithStatus; + uint64_t SavedContext; + uint16_t ThCallbackStack; + uint16_t NextCallback; + uint16_t FramePointer; + uint16_t PaeEnabled:1; + uint64_t KiCallUserMode; + uint64_t KeUserCallbackDispatcher; + uint64_t PsLoadedModuleList; + uint64_t PsActiveProcessHead; + uint64_t PspCidTable; + uint64_t ExpSystemResourcesList; + uint64_t ExpPagedPoolDescriptor; + uint64_t ExpNumberOfPagedPools; + uint64_t KeTimeIncrement; + uint64_t KeBugCheckCallbackListHead; + uint64_t KiBugcheckData; + uint64_t IopErrorLogListHead; + uint64_t ObpRootDirectoryObject; + uint64_t ObpTypeObjectType; + uint64_t MmSystemCacheStart; + uint64_t MmSystemCacheEnd; + uint64_t MmSystemCacheWs; + uint64_t MmPfnDatabase; + uint64_t MmSystemPtesStart; + uint64_t MmSystemPtesEnd; + uint64_t MmSubsectionBase; + uint64_t MmNumberOfPagingFiles; + uint64_t MmLowestPhysicalPage; + uint64_t MmHighestPhysicalPage; + uint64_t MmNumberOfPhysicalPages; + uint64_t MmMaximumNonPagedPoolInBytes; + uint64_t MmNonPagedSystemStart; + uint64_t MmNonPagedPoolStart; + uint64_t MmNonPagedPoolEnd; + uint64_t MmPagedPoolStart; + uint64_t MmPagedPoolEnd; + uint64_t MmPagedPoolInformation; + uint64_t MmPageSize; + uint64_t MmSizeOfPagedPoolInBytes; + uint64_t MmTotalCommitLimit; + uint64_t MmTotalCommittedPages; + uint64_t MmSharedCommit; + uint64_t MmDriverCommit; + uint64_t MmProcessCommit; + uint64_t MmPagedPoolCommit; + uint64_t MmExtendedCommit; + uint64_t MmZeroedPageListHead; + uint64_t MmFreePageListHead; + uint64_t MmStandbyPageListHead; + uint64_t MmModifiedPageListHead; + uint64_t MmModifiedNoWritePageListHead; + uint64_t MmAvailablePages; + uint64_t MmResidentAvailablePages; + uint64_t PoolTrackTable; + uint64_t NonPagedPoolDescriptor; + uint64_t MmHighestUserAddress; + uint64_t MmSystemRangeStart; + uint64_t MmUserProbeAddress; + uint64_t KdPrintCircularBuffer; + uint64_t KdPrintCircularBufferEnd; + uint64_t KdPrintWritePointer; + uint64_t KdPrintRolloverCount; + uint64_t MmLoadedUserImageList; + + /* NT 5.1 Addition */ + + uint64_t NtBuildLab; + uint64_t KiNormalSystemCall; + + /* NT 5.0 hotfix addition */ + + uint64_t KiProcessorBlock; + uint64_t MmUnloadedDrivers; + uint64_t MmLastUnloadedDriver; + uint64_t MmTriageActionTaken; + uint64_t MmSpecialPoolTag; + uint64_t KernelVerifier; + uint64_t MmVerifierData; + uint64_t MmAllocatedNonPagedPool; + uint64_t MmPeakCommitment; + uint64_t MmTotalCommitLimitMaximum; + uint64_t CmNtCSDVersion; + + /* NT 5.1 Addition */ + + uint64_t MmPhysicalMemoryBlock; + uint64_t MmSessionBase; + uint64_t MmSessionSize; + uint64_t MmSystemParentTablePage; + + /* Server 2003 addition */ + + uint64_t MmVirtualTranslationBase; + uint16_t OffsetKThreadNextProcessor; + uint16_t OffsetKThreadTeb; + uint16_t OffsetKThreadKernelStack; + uint16_t OffsetKThreadInitialStack; + uint16_t OffsetKThreadApcProcess; + uint16_t OffsetKThreadState; + uint16_t OffsetKThreadBStore; + uint16_t OffsetKThreadBStoreLimit; + uint16_t SizeEProcess; + uint16_t OffsetEprocessPeb; + uint16_t OffsetEprocessParentCID; + uint16_t OffsetEprocessDirectoryTableBase; + uint16_t SizePrcb; + uint16_t OffsetPrcbDpcRoutine; + uint16_t OffsetPrcbCurrentThread; + uint16_t OffsetPrcbMhz; + uint16_t OffsetPrcbCpuType; + uint16_t OffsetPrcbVendorString; + uint16_t OffsetPrcbProcStateContext; + uint16_t OffsetPrcbNumber; + uint16_t SizeEThread; + uint64_t KdPrintCircularBufferPtr; + uint64_t KdPrintBufferSize; + uint64_t KeLoaderBlock; + uint16_t SizePcr; + uint16_t OffsetPcrSelfPcr; + uint16_t OffsetPcrCurrentPrcb; + uint16_t OffsetPcrContainedPrcb; + uint16_t OffsetPcrInitialBStore; + uint16_t OffsetPcrBStoreLimit; + uint16_t OffsetPcrInitialStack; + uint16_t OffsetPcrStackLimit; + uint16_t OffsetPrcbPcrPage; + uint16_t OffsetPrcbProcStateSpecialReg; + uint16_t GdtR0Code; + uint16_t GdtR0Data; + uint16_t GdtR0Pcr; + uint16_t GdtR3Code; + uint16_t GdtR3Data; + uint16_t GdtR3Teb; + uint16_t GdtLdt; + uint16_t GdtTss; + uint16_t Gdt64R3CmCode; + uint16_t Gdt64R3CmTeb; + uint64_t IopNumTriageDumpDataBlocks; + uint64_t IopTriageDumpDataBlocks; + + /* Longhorn addition */ + + uint64_t VfCrashDataBlock; + uint64_t MmBadPagesDetected; + uint64_t MmZeroedPageSingleBitErrorsDetected; + + /* Windows 7 addition */ + + uint64_t EtwpDebuggerData; + uint16_t OffsetPrcbContext; +} KDDEBUGGER_DATA64; + +#endif /* KDBG_H */ diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c new file mode 100644 index 0000000000..9b93dab662 --- /dev/null +++ b/contrib/elf2dmp/main.c @@ -0,0 +1,589 @@ +/* + * Copyright (c) 2018 Virtuozzo International GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * + */ + +#include "qemu/osdep.h" +#include "err.h" +#include "addrspace.h" +#include "pe.h" +#include "pdb.h" +#include "kdbg.h" +#include "download.h" +#include "qemu/win_dump_defs.h" + +#define SYM_URL_BASE "https://msdl.microsoft.com/download/symbols/" +#define PDB_NAME "ntkrnlmp.pdb" + +#define INITIAL_MXCSR 0x1f80 + +typedef struct idt_desc { + uint16_t offset1; /* offset bits 0..15 */ + uint16_t selector; + uint8_t ist; + uint8_t type_attr; + uint16_t offset2; /* offset bits 16..31 */ + uint32_t offset3; /* offset bits 32..63 */ + uint32_t rsrvd; +} __attribute__ ((packed)) idt_desc_t; + +static uint64_t idt_desc_addr(idt_desc_t desc) +{ + return (uint64_t)desc.offset1 | ((uint64_t)desc.offset2 << 16) | + ((uint64_t)desc.offset3 << 32); +} + +static const uint64_t SharedUserData = 0xfffff78000000000; + +#define KUSD_OFFSET_SUITE_MASK 0x2d0 +#define KUSD_OFFSET_PRODUCT_TYPE 0x264 + +#define SYM_RESOLVE(base, r, s) ((s = pdb_resolve(base, r, #s)),\ + s ? printf(#s" = 0x%016lx\n", s) : eprintf("Failed to resolve "#s"\n"), s) + +static uint64_t rol(uint64_t x, uint64_t y) +{ + return (x << y) | (x >> (64 - y)); +} + +/* + * Decoding algorithm can be found in Volatility project + */ +static void kdbg_decode(uint64_t *dst, uint64_t *src, size_t size, + uint64_t kwn, uint64_t kwa, uint64_t kdbe) +{ + size_t i; + assert(size % sizeof(uint64_t) == 0); + for (i = 0; i < size / sizeof(uint64_t); i++) { + uint64_t block; + + block = src[i]; + block = rol(block ^ kwn, (uint8_t)kwn); + block = __builtin_bswap64(block ^ kdbe) ^ kwa; + dst[i] = block; + } +} + +static KDDEBUGGER_DATA64 *get_kdbg(uint64_t KernBase, struct pdb_reader *pdb, + struct va_space *vs, uint64_t KdDebuggerDataBlock) +{ + const char OwnerTag[4] = "KDBG"; + KDDEBUGGER_DATA64 *kdbg = NULL; + DBGKD_DEBUG_DATA_HEADER64 kdbg_hdr; + bool decode = false; + uint64_t kwn, kwa, KdpDataBlockEncoded; + + if (va_space_rw(vs, + KdDebuggerDataBlock + offsetof(KDDEBUGGER_DATA64, Header), + &kdbg_hdr, sizeof(kdbg_hdr), 0)) { + eprintf("Failed to extract KDBG header\n"); + return NULL; + } + + if (memcmp(&kdbg_hdr.OwnerTag, OwnerTag, sizeof(OwnerTag))) { + uint64_t KiWaitNever, KiWaitAlways; + + decode = true; + + if (!SYM_RESOLVE(KernBase, pdb, KiWaitNever) || + !SYM_RESOLVE(KernBase, pdb, KiWaitAlways) || + !SYM_RESOLVE(KernBase, pdb, KdpDataBlockEncoded)) { + return NULL; + } + + if (va_space_rw(vs, KiWaitNever, &kwn, sizeof(kwn), 0) || + va_space_rw(vs, KiWaitAlways, &kwa, sizeof(kwa), 0)) { + return NULL; + } + + printf("[KiWaitNever] = 0x%016lx\n", kwn); + printf("[KiWaitAlways] = 0x%016lx\n", kwa); + + /* + * If KDBG header can be decoded, KDBG size is available + * and entire KDBG can be decoded. + */ + printf("Decoding KDBG header...\n"); + kdbg_decode((uint64_t *)&kdbg_hdr, (uint64_t *)&kdbg_hdr, + sizeof(kdbg_hdr), kwn, kwa, KdpDataBlockEncoded); + + printf("Owner tag is \'%.4s\'\n", (char *)&kdbg_hdr.OwnerTag); + if (memcmp(&kdbg_hdr.OwnerTag, OwnerTag, sizeof(OwnerTag))) { + eprintf("Failed to decode KDBG header\n"); + return NULL; + } + } + + kdbg = malloc(kdbg_hdr.Size); + if (!kdbg) { + return NULL; + } + + if (va_space_rw(vs, KdDebuggerDataBlock, kdbg, kdbg_hdr.Size, 0)) { + eprintf("Failed to extract entire KDBG\n"); + return NULL; + } + + if (!decode) { + return kdbg; + } + + printf("Decoding KdDebuggerDataBlock...\n"); + kdbg_decode((uint64_t *)kdbg, (uint64_t *)kdbg, kdbg_hdr.Size, + kwn, kwa, KdpDataBlockEncoded); + + va_space_rw(vs, KdDebuggerDataBlock, kdbg, kdbg_hdr.Size, 1); + + return kdbg; +} + +static void win_context_init_from_qemu_cpu_state(WinContext *ctx, + QEMUCPUState *s) +{ + WinContext win_ctx = (WinContext){ + .ContextFlags = WIN_CTX_X64 | WIN_CTX_INT | WIN_CTX_SEG | WIN_CTX_CTL, + .MxCsr = INITIAL_MXCSR, + + .SegCs = s->cs.selector, + .SegSs = s->ss.selector, + .SegDs = s->ds.selector, + .SegEs = s->es.selector, + .SegFs = s->fs.selector, + .SegGs = s->gs.selector, + .EFlags = (uint32_t)s->rflags, + + .Rax = s->rax, + .Rbx = s->rbx, + .Rcx = s->rcx, + .Rdx = s->rdx, + .Rsp = s->rsp, + .Rbp = s->rbp, + .Rsi = s->rsi, + .Rdi = s->rdi, + .R8 = s->r8, + .R9 = s->r9, + .R10 = s->r10, + .R11 = s->r11, + .R12 = s->r12, + .R13 = s->r13, + .R14 = s->r14, + .R15 = s->r15, + + .Rip = s->rip, + .FltSave = { + .MxCsr = INITIAL_MXCSR, + }, + }; + + *ctx = win_ctx; +} + +/* + * Finds paging-structure hierarchy base, + * if previously set doesn't give access to kernel structures + */ +static int fix_dtb(struct va_space *vs, QEMU_Elf *qe) +{ + /* + * Firstly, test previously set DTB. + */ + if (va_space_resolve(vs, SharedUserData)) { + return 0; + } + + /* + * Secondly, find CPU which run system task. + */ + size_t i; + for (i = 0; i < qe->state_nr; i++) { + QEMUCPUState *s = qe->state[i]; + + if (is_system(s)) { + va_space_set_dtb(vs, s->cr[3]); + printf("DTB 0x%016lx has been found from CPU #%zu" + " as system task CR3\n", vs->dtb, i); + return !(va_space_resolve(vs, SharedUserData)); + } + } + + /* + * Thirdly, use KERNEL_GS_BASE from CPU #0 as PRCB address and + * CR3 as [Prcb+0x7000] + */ + if (qe->has_kernel_gs_base) { + QEMUCPUState *s = qe->state[0]; + uint64_t Prcb = s->kernel_gs_base; + uint64_t *cr3 = va_space_resolve(vs, Prcb + 0x7000); + + if (!cr3) { + return 1; + } + + va_space_set_dtb(vs, *cr3); + printf("DirectoryTableBase = 0x%016lx has been found from CPU #0" + " as interrupt handling CR3\n", vs->dtb); + return !(va_space_resolve(vs, SharedUserData)); + } + + return 1; +} + +static int fill_header(WinDumpHeader64 *hdr, struct pa_space *ps, + struct va_space *vs, uint64_t KdDebuggerDataBlock, + KDDEBUGGER_DATA64 *kdbg, uint64_t KdVersionBlock, int nr_cpus) +{ + uint32_t *suite_mask = va_space_resolve(vs, SharedUserData + + KUSD_OFFSET_SUITE_MASK); + int32_t *product_type = va_space_resolve(vs, SharedUserData + + KUSD_OFFSET_PRODUCT_TYPE); + DBGKD_GET_VERSION64 kvb; + WinDumpHeader64 h; + size_t i; + + QEMU_BUILD_BUG_ON(KUSD_OFFSET_SUITE_MASK >= PAGE_SIZE); + QEMU_BUILD_BUG_ON(KUSD_OFFSET_PRODUCT_TYPE >= PAGE_SIZE); + + if (!suite_mask || !product_type) { + return 1; + } + + if (va_space_rw(vs, KdVersionBlock, &kvb, sizeof(kvb), 0)) { + eprintf("Failed to extract KdVersionBlock\n"); + return 1; + } + + h = (WinDumpHeader64) { + .Signature = "PAGE", + .ValidDump = "DU64", + .MajorVersion = kvb.MajorVersion, + .MinorVersion = kvb.MinorVersion, + .DirectoryTableBase = vs->dtb, + .PfnDatabase = kdbg->MmPfnDatabase, + .PsLoadedModuleList = kdbg->PsLoadedModuleList, + .PsActiveProcessHead = kdbg->PsActiveProcessHead, + .MachineImageType = kvb.MachineType, + .NumberProcessors = nr_cpus, + .BugcheckCode = LIVE_SYSTEM_DUMP, + .KdDebuggerDataBlock = KdDebuggerDataBlock, + .DumpType = 1, + .Comment = "Hello from elf2dmp!", + .SuiteMask = *suite_mask, + .ProductType = *product_type, + .SecondaryDataState = kvb.KdSecondaryVersion, + .PhysicalMemoryBlock = (WinDumpPhyMemDesc64) { + .NumberOfRuns = ps->block_nr, + }, + .RequiredDumpSpace = sizeof(h), + }; + + for (i = 0; i < ps->block_nr; i++) { + h.PhysicalMemoryBlock.NumberOfPages += ps->block[i].size / PAGE_SIZE; + h.PhysicalMemoryBlock.Run[i] = (WinDumpPhyMemRun64) { + .BasePage = ps->block[i].paddr / PAGE_SIZE, + .PageCount = ps->block[i].size / PAGE_SIZE, + }; + } + + h.RequiredDumpSpace += h.PhysicalMemoryBlock.NumberOfPages << PAGE_BITS; + + *hdr = h; + + return 0; +} + +static int fill_context(KDDEBUGGER_DATA64 *kdbg, + struct va_space *vs, QEMU_Elf *qe) +{ + int i; + for (i = 0; i < qe->state_nr; i++) { + uint64_t Prcb; + uint64_t Context; + WinContext ctx; + QEMUCPUState *s = qe->state[i]; + + if (va_space_rw(vs, kdbg->KiProcessorBlock + sizeof(Prcb) * i, + &Prcb, sizeof(Prcb), 0)) { + eprintf("Failed to read CPU #%d PRCB location\n", i); + return 1; + } + + if (va_space_rw(vs, Prcb + kdbg->OffsetPrcbContext, + &Context, sizeof(Context), 0)) { + eprintf("Failed to read CPU #%d ContextFrame location\n", i); + return 1; + } + + printf("Filling context for CPU #%d...\n", i); + win_context_init_from_qemu_cpu_state(&ctx, s); + + if (va_space_rw(vs, Context, &ctx, sizeof(ctx), 1)) { + eprintf("Failed to fill CPU #%d context\n", i); + return 1; + } + } + + return 0; +} + +static int write_dump(struct pa_space *ps, + WinDumpHeader64 *hdr, const char *name) +{ + FILE *dmp_file = fopen(name, "wb"); + size_t i; + + if (!dmp_file) { + eprintf("Failed to open output file \'%s\'\n", name); + return 1; + } + + printf("Writing header to file...\n"); + + if (fwrite(hdr, sizeof(*hdr), 1, dmp_file) != 1) { + eprintf("Failed to write dump header\n"); + fclose(dmp_file); + return 1; + } + + for (i = 0; i < ps->block_nr; i++) { + struct pa_block *b = &ps->block[i]; + + printf("Writing block #%zu/%zu to file...\n", i, ps->block_nr); + if (fwrite(b->addr, b->size, 1, dmp_file) != 1) { + eprintf("Failed to write dump header\n"); + fclose(dmp_file); + return 1; + } + } + + return fclose(dmp_file); +} + +static int pe_get_pdb_symstore_hash(uint64_t base, void *start_addr, + char *hash, struct va_space *vs) +{ + const char e_magic[2] = "MZ"; + const char Signature[4] = "PE\0\0"; + const char sign_rsds[4] = "RSDS"; + IMAGE_DOS_HEADER *dos_hdr = start_addr; + IMAGE_NT_HEADERS64 nt_hdrs; + IMAGE_FILE_HEADER *file_hdr = &nt_hdrs.FileHeader; + IMAGE_OPTIONAL_HEADER64 *opt_hdr = &nt_hdrs.OptionalHeader; + IMAGE_DATA_DIRECTORY *data_dir = nt_hdrs.OptionalHeader.DataDirectory; + IMAGE_DEBUG_DIRECTORY debug_dir; + OMFSignatureRSDS rsds; + char *pdb_name; + size_t pdb_name_sz; + size_t i; + + QEMU_BUILD_BUG_ON(sizeof(*dos_hdr) >= PAGE_SIZE); + + if (memcmp(&dos_hdr->e_magic, e_magic, sizeof(e_magic))) { + return 1; + } + + if (va_space_rw(vs, base + dos_hdr->e_lfanew, + &nt_hdrs, sizeof(nt_hdrs), 0)) { + return 1; + } + + if (memcmp(&nt_hdrs.Signature, Signature, sizeof(Signature)) || + file_hdr->Machine != 0x8664 || opt_hdr->Magic != 0x020b) { + return 1; + } + + printf("Debug Directory RVA = 0x%016x\n", + data_dir[IMAGE_FILE_DEBUG_DIRECTORY].VirtualAddress); + + if (va_space_rw(vs, + base + data_dir[IMAGE_FILE_DEBUG_DIRECTORY].VirtualAddress, + &debug_dir, sizeof(debug_dir), 0)) { + return 1; + } + + if (debug_dir.Type != IMAGE_DEBUG_TYPE_CODEVIEW) { + return 1; + } + + if (va_space_rw(vs, + base + debug_dir.AddressOfRawData, + &rsds, sizeof(rsds), 0)) { + return 1; + } + + printf("CodeView signature is \'%.4s\'\n", rsds.Signature); + + if (memcmp(&rsds.Signature, sign_rsds, sizeof(sign_rsds))) { + return 1; + } + + pdb_name_sz = debug_dir.SizeOfData - sizeof(rsds); + pdb_name = malloc(pdb_name_sz); + if (!pdb_name) { + return 1; + } + + if (va_space_rw(vs, base + debug_dir.AddressOfRawData + + offsetof(OMFSignatureRSDS, name), pdb_name, pdb_name_sz, 0)) { + free(pdb_name); + return 1; + } + + printf("PDB name is \'%s\', \'%s\' expected\n", pdb_name, PDB_NAME); + + if (strcmp(pdb_name, PDB_NAME)) { + eprintf("Unexpected PDB name, it seems the kernel isn't found\n"); + free(pdb_name); + return 1; + } + + free(pdb_name); + + sprintf(hash, "%.08x%.04x%.04x%.02x%.02x", rsds.guid.a, rsds.guid.b, + rsds.guid.c, rsds.guid.d[0], rsds.guid.d[1]); + hash += 20; + for (i = 0; i < 6; i++, hash += 2) { + sprintf(hash, "%.02x", rsds.guid.e[i]); + } + + sprintf(hash, "%.01x", rsds.age); + + return 0; +} + +int main(int argc, char *argv[]) +{ + int err = 0; + QEMU_Elf qemu_elf; + struct pa_space ps; + struct va_space vs; + QEMUCPUState *state; + idt_desc_t first_idt_desc; + uint64_t KernBase; + void *nt_start_addr = NULL; + WinDumpHeader64 header; + char pdb_hash[34]; + char pdb_url[] = SYM_URL_BASE PDB_NAME + "/0123456789ABCDEF0123456789ABCDEFx/" PDB_NAME; + struct pdb_reader pdb; + uint64_t KdDebuggerDataBlock; + KDDEBUGGER_DATA64 *kdbg; + uint64_t KdVersionBlock; + + if (argc != 3) { + eprintf("usage:\n\t%s elf_file dmp_file\n", argv[0]); + return 1; + } + + if (QEMU_Elf_init(&qemu_elf, argv[1])) { + eprintf("Failed to initialize QEMU ELF dump\n"); + return 1; + } + + if (pa_space_create(&ps, &qemu_elf)) { + eprintf("Failed to initialize physical address space\n"); + err = 1; + goto out_elf; + } + + state = qemu_elf.state[0]; + printf("CPU #0 CR3 is 0x%016lx\n", state->cr[3]); + + va_space_create(&vs, &ps, state->cr[3]); + if (fix_dtb(&vs, &qemu_elf)) { + eprintf("Failed to find paging base\n"); + err = 1; + goto out_elf; + } + + printf("CPU #0 IDT is at 0x%016lx\n", state->idt.base); + + if (va_space_rw(&vs, state->idt.base, + &first_idt_desc, sizeof(first_idt_desc), 0)) { + eprintf("Failed to get CPU #0 IDT[0]\n"); + err = 1; + goto out_ps; + } + printf("CPU #0 IDT[0] -> 0x%016lx\n", idt_desc_addr(first_idt_desc)); + + KernBase = idt_desc_addr(first_idt_desc) & ~(PAGE_SIZE - 1); + printf("Searching kernel downwards from 0x%16lx...\n", KernBase); + + for (; KernBase >= 0xfffff78000000000; KernBase -= PAGE_SIZE) { + nt_start_addr = va_space_resolve(&vs, KernBase); + if (!nt_start_addr) { + continue; + } + + if (*(uint16_t *)nt_start_addr == 0x5a4d) { /* MZ */ + break; + } + } + + printf("KernBase = 0x%16lx, signature is \'%.2s\'\n", KernBase, + (char *)nt_start_addr); + + if (pe_get_pdb_symstore_hash(KernBase, nt_start_addr, pdb_hash, &vs)) { + eprintf("Failed to get PDB symbol store hash\n"); + err = 1; + goto out_ps; + } + + sprintf(pdb_url, "%s%s/%s/%s", SYM_URL_BASE, PDB_NAME, pdb_hash, PDB_NAME); + printf("PDB URL is %s\n", pdb_url); + + if (download_url(PDB_NAME, pdb_url)) { + eprintf("Failed to download PDB file\n"); + err = 1; + goto out_ps; + } + + if (pdb_init_from_file(PDB_NAME, &pdb)) { + eprintf("Failed to initialize PDB reader\n"); + err = 1; + goto out_pdb_file; + } + + if (!SYM_RESOLVE(KernBase, &pdb, KdDebuggerDataBlock) || + !SYM_RESOLVE(KernBase, &pdb, KdVersionBlock)) { + err = 1; + goto out_pdb; + } + + kdbg = get_kdbg(KernBase, &pdb, &vs, KdDebuggerDataBlock); + if (!kdbg) { + err = 1; + goto out_pdb; + } + + if (fill_header(&header, &ps, &vs, KdDebuggerDataBlock, kdbg, + KdVersionBlock, qemu_elf.state_nr)) { + err = 1; + goto out_pdb; + } + + if (fill_context(kdbg, &vs, &qemu_elf)) { + err = 1; + goto out_pdb; + } + + if (write_dump(&ps, &header, argv[2])) { + eprintf("Failed to save dump\n"); + err = 1; + goto out_kdbg; + } + +out_kdbg: + free(kdbg); +out_pdb: + pdb_exit(&pdb); +out_pdb_file: + unlink(PDB_NAME); +out_ps: + pa_space_destroy(&ps); +out_elf: + QEMU_Elf_exit(&qemu_elf); + + return err; +} diff --git a/contrib/elf2dmp/pdb.c b/contrib/elf2dmp/pdb.c new file mode 100644 index 0000000000..bcb01b414f --- /dev/null +++ b/contrib/elf2dmp/pdb.c @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2018 Virtuozzo International GmbH + * + * Based on source of Wine project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "qemu/osdep.h" +#include "pdb.h" +#include "err.h" + +static uint32_t pdb_get_file_size(const struct pdb_reader *r, unsigned idx) +{ + return r->ds.toc->file_size[idx]; +} + +static pdb_seg *get_seg_by_num(struct pdb_reader *r, size_t n) +{ + size_t i = 0; + char *ptr; + + for (ptr = r->segs; (ptr < r->segs + r->segs_size); ) { + i++; + ptr += 8; + if (i == n) { + break; + } + ptr += sizeof(pdb_seg); + } + + return (pdb_seg *)ptr; +} + +uint64_t pdb_find_public_v3_symbol(struct pdb_reader *r, const char *name) +{ + size_t size = pdb_get_file_size(r, r->symbols->gsym_file); + int length; + const union codeview_symbol *sym; + const uint8_t *root = r->modimage; + size_t i; + + for (i = 0; i < size; i += length) { + sym = (const void *)(root + i); + length = sym->generic.len + 2; + + if (!sym->generic.id || length < 4) { + break; + } + + if (sym->generic.id == S_PUB_V3 && + !strcmp(name, sym->public_v3.name)) { + pdb_seg *segment = get_seg_by_num(r, sym->public_v3.segment); + uint32_t sect_rva = segment->dword[1]; + uint64_t rva = sect_rva + sym->public_v3.offset; + + printf("%s: 0x%016x(%d:\'%.8s\') + 0x%08x = 0x%09lx\n", name, + sect_rva, sym->public_v3.segment, + ((char *)segment - 8), sym->public_v3.offset, rva); + return rva; + } + } + + return 0; +} + +uint64_t pdb_resolve(uint64_t img_base, struct pdb_reader *r, const char *name) +{ + uint64_t rva = pdb_find_public_v3_symbol(r, name); + + if (!rva) { + return 0; + } + + return img_base + rva; +} + +static void pdb_reader_ds_exit(struct pdb_reader *r) +{ + free(r->ds.toc); +} + +static void pdb_exit_symbols(struct pdb_reader *r) +{ + free(r->modimage); + free(r->symbols); +} + +static void pdb_exit_segments(struct pdb_reader *r) +{ + free(r->segs); +} + +static void *pdb_ds_read(const PDB_DS_HEADER *header, + const uint32_t *block_list, int size) +{ + int i, nBlocks; + uint8_t *buffer; + + if (!size) { + return NULL; + } + + nBlocks = (size + header->block_size - 1) / header->block_size; + + buffer = malloc(nBlocks * header->block_size); + if (!buffer) { + return NULL; + } + + for (i = 0; i < nBlocks; i++) { + memcpy(buffer + i * header->block_size, (const char *)header + + block_list[i] * header->block_size, header->block_size); + } + + return buffer; +} + +static void *pdb_ds_read_file(struct pdb_reader* r, uint32_t file_number) +{ + const uint32_t *block_list; + uint32_t block_size; + const uint32_t *file_size; + size_t i; + + if (!r->ds.toc || file_number >= r->ds.toc->num_files) { + return NULL; + } + + file_size = r->ds.toc->file_size; + r->file_used[file_number / 32] |= 1 << (file_number % 32); + + if (file_size[file_number] == 0 || file_size[file_number] == 0xFFFFFFFF) { + return NULL; + } + + block_list = file_size + r->ds.toc->num_files; + block_size = r->ds.header->block_size; + + for (i = 0; i < file_number; i++) { + block_list += (file_size[i] + block_size - 1) / block_size; + } + + return pdb_ds_read(r->ds.header, block_list, file_size[file_number]); +} + +static int pdb_init_segments(struct pdb_reader *r) +{ + char *segs; + unsigned stream_idx = r->sidx.segments; + + segs = pdb_ds_read_file(r, stream_idx); + if (!segs) { + return 1; + } + + r->segs = segs; + r->segs_size = pdb_get_file_size(r, stream_idx); + + return 0; +} + +static int pdb_init_symbols(struct pdb_reader *r) +{ + int err = 0; + PDB_SYMBOLS *symbols; + PDB_STREAM_INDEXES *sidx = &r->sidx; + + memset(sidx, -1, sizeof(*sidx)); + + symbols = pdb_ds_read_file(r, 3); + if (!symbols) { + return 1; + } + + r->symbols = symbols; + + if (symbols->stream_index_size != sizeof(PDB_STREAM_INDEXES)) { + err = 1; + goto out_symbols; + } + + memcpy(sidx, (const char *)symbols + sizeof(PDB_SYMBOLS) + + symbols->module_size + symbols->offset_size + + symbols->hash_size + symbols->srcmodule_size + + symbols->pdbimport_size + symbols->unknown2_size, sizeof(*sidx)); + + /* Read global symbol table */ + r->modimage = pdb_ds_read_file(r, symbols->gsym_file); + if (!r->modimage) { + err = 1; + goto out_symbols; + } + + return 0; + +out_symbols: + free(symbols); + + return err; +} + +static int pdb_reader_ds_init(struct pdb_reader *r, PDB_DS_HEADER *hdr) +{ + memset(r->file_used, 0, sizeof(r->file_used)); + r->ds.header = hdr; + r->ds.toc = pdb_ds_read(hdr, (uint32_t *)((uint8_t *)hdr + + hdr->toc_page * hdr->block_size), hdr->toc_size); + + if (!r->ds.toc) { + return 1; + } + + return 0; +} + +static int pdb_reader_init(struct pdb_reader *r, void *data) +{ + int err = 0; + const char pdb7[] = "Microsoft C/C++ MSF 7.00"; + + if (memcmp(data, pdb7, sizeof(pdb7) - 1)) { + return 1; + } + + if (pdb_reader_ds_init(r, data)) { + return 1; + } + + r->ds.root = pdb_ds_read_file(r, 1); + if (!r->ds.root) { + err = 1; + goto out_ds; + } + + if (pdb_init_symbols(r)) { + err = 1; + goto out_root; + } + + if (pdb_init_segments(r)) { + err = 1; + goto out_sym; + } + + return 0; + +out_sym: + pdb_exit_symbols(r); +out_root: + free(r->ds.root); +out_ds: + pdb_reader_ds_exit(r); + + return err; +} + +static void pdb_reader_exit(struct pdb_reader *r) +{ + pdb_exit_segments(r); + pdb_exit_symbols(r); + free(r->ds.root); + pdb_reader_ds_exit(r); +} + +int pdb_init_from_file(const char *name, struct pdb_reader *reader) +{ + int err = 0; + int fd; + void *map; + struct stat st; + + fd = open(name, O_RDONLY, 0); + if (fd == -1) { + eprintf("Failed to open PDB file \'%s\'\n", name); + return 1; + } + reader->fd = fd; + + fstat(fd, &st); + reader->file_size = st.st_size; + + map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (map == MAP_FAILED) { + eprintf("Failed to map PDB file\n"); + err = 1; + goto out_fd; + } + + if (pdb_reader_init(reader, map)) { + err = 1; + goto out_unmap; + } + + return 0; + +out_unmap: + munmap(map, st.st_size); +out_fd: + close(fd); + + return err; +} + +void pdb_exit(struct pdb_reader *reader) +{ + munmap(reader->ds.header, reader->file_size); + close(reader->fd); + pdb_reader_exit(reader); +} diff --git a/contrib/elf2dmp/pdb.h b/contrib/elf2dmp/pdb.h new file mode 100644 index 0000000000..4351a2dd61 --- /dev/null +++ b/contrib/elf2dmp/pdb.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2018 Virtuozzo International GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * + */ + +#ifndef PDB_H +#define PDB_H + +#include +#include + +typedef struct GUID { + unsigned int Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +} GUID; + +struct PDB_FILE { + uint32_t size; + uint32_t unknown; +}; + +typedef struct PDB_DS_HEADER { + char signature[32]; + uint32_t block_size; + uint32_t unknown1; + uint32_t num_pages; + uint32_t toc_size; + uint32_t unknown2; + uint32_t toc_page; +} PDB_DS_HEADER; + +typedef struct PDB_DS_TOC { + uint32_t num_files; + uint32_t file_size[1]; +} PDB_DS_TOC; + +typedef struct PDB_DS_ROOT { + uint32_t Version; + uint32_t TimeDateStamp; + uint32_t Age; + GUID guid; + uint32_t cbNames; + char names[1]; +} PDB_DS_ROOT; + +typedef struct PDB_TYPES_OLD { + uint32_t version; + uint16_t first_index; + uint16_t last_index; + uint32_t type_size; + uint16_t file; + uint16_t pad; +} PDB_TYPES_OLD; + +typedef struct PDB_TYPES { + uint32_t version; + uint32_t type_offset; + uint32_t first_index; + uint32_t last_index; + uint32_t type_size; + uint16_t file; + uint16_t pad; + uint32_t hash_size; + uint32_t hash_base; + uint32_t hash_offset; + uint32_t hash_len; + uint32_t search_offset; + uint32_t search_len; + uint32_t unknown_offset; + uint32_t unknown_len; +} PDB_TYPES; + +typedef struct PDB_SYMBOL_RANGE { + uint16_t segment; + uint16_t pad1; + uint32_t offset; + uint32_t size; + uint32_t characteristics; + uint16_t index; + uint16_t pad2; +} PDB_SYMBOL_RANGE; + +typedef struct PDB_SYMBOL_RANGE_EX { + uint16_t segment; + uint16_t pad1; + uint32_t offset; + uint32_t size; + uint32_t characteristics; + uint16_t index; + uint16_t pad2; + uint32_t timestamp; + uint32_t unknown; +} PDB_SYMBOL_RANGE_EX; + +typedef struct PDB_SYMBOL_FILE { + uint32_t unknown1; + PDB_SYMBOL_RANGE range; + uint16_t flag; + uint16_t file; + uint32_t symbol_size; + uint32_t lineno_size; + uint32_t unknown2; + uint32_t nSrcFiles; + uint32_t attribute; + char filename[1]; +} PDB_SYMBOL_FILE; + +typedef struct PDB_SYMBOL_FILE_EX { + uint32_t unknown1; + PDB_SYMBOL_RANGE_EX range; + uint16_t flag; + uint16_t file; + uint32_t symbol_size; + uint32_t lineno_size; + uint32_t unknown2; + uint32_t nSrcFiles; + uint32_t attribute; + uint32_t reserved[2]; + char filename[1]; +} PDB_SYMBOL_FILE_EX; + +typedef struct PDB_SYMBOL_SOURCE { + uint16_t nModules; + uint16_t nSrcFiles; + uint16_t table[1]; +} PDB_SYMBOL_SOURCE; + +typedef struct PDB_SYMBOL_IMPORT { + uint32_t unknown1; + uint32_t unknown2; + uint32_t TimeDateStamp; + uint32_t Age; + char filename[1]; +} PDB_SYMBOL_IMPORT; + +typedef struct PDB_SYMBOLS_OLD { + uint16_t hash1_file; + uint16_t hash2_file; + uint16_t gsym_file; + uint16_t pad; + uint32_t module_size; + uint32_t offset_size; + uint32_t hash_size; + uint32_t srcmodule_size; +} PDB_SYMBOLS_OLD; + +typedef struct PDB_SYMBOLS { + uint32_t signature; + uint32_t version; + uint32_t unknown; + uint32_t hash1_file; + uint32_t hash2_file; + uint16_t gsym_file; + uint16_t unknown1; + uint32_t module_size; + uint32_t offset_size; + uint32_t hash_size; + uint32_t srcmodule_size; + uint32_t pdbimport_size; + uint32_t resvd0; + uint32_t stream_index_size; + uint32_t unknown2_size; + uint16_t resvd3; + uint16_t machine; + uint32_t resvd4; +} PDB_SYMBOLS; + +typedef struct { + uint16_t FPO; + uint16_t unk0; + uint16_t unk1; + uint16_t unk2; + uint16_t unk3; + uint16_t segments; +} PDB_STREAM_INDEXES_OLD; + +typedef struct { + uint16_t FPO; + uint16_t unk0; + uint16_t unk1; + uint16_t unk2; + uint16_t unk3; + uint16_t segments; + uint16_t unk4; + uint16_t unk5; + uint16_t unk6; + uint16_t FPO_EXT; + uint16_t unk7; +} PDB_STREAM_INDEXES; + +union codeview_symbol { + struct { + int16_t len; + int16_t id; + } generic; + + struct { + int16_t len; + int16_t id; + uint32_t symtype; + uint32_t offset; + uint16_t segment; + char name[1]; + } public_v3; +}; + +#define S_PUB_V3 0x110E + +typedef struct pdb_seg { + uint32_t dword[8]; +} __attribute__ ((packed)) pdb_seg; + +#define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_AMD64 0x8664 + +struct pdb_reader { + int fd; + size_t file_size; + struct { + PDB_DS_HEADER *header; + PDB_DS_TOC *toc; + PDB_DS_ROOT *root; + } ds; + uint32_t file_used[1024]; + PDB_SYMBOLS *symbols; + PDB_STREAM_INDEXES sidx; + uint8_t *modimage; + char *segs; + size_t segs_size; +}; + +int pdb_init_from_file(const char *name, struct pdb_reader *reader); +void pdb_exit(struct pdb_reader *reader); +uint64_t pdb_resolve(uint64_t img_base, struct pdb_reader *r, const char *name); +uint64_t pdb_find_public_v3_symbol(struct pdb_reader *reader, const char *name); + +#endif /* PDB_H */ diff --git a/contrib/elf2dmp/pe.h b/contrib/elf2dmp/pe.h new file mode 100644 index 0000000000..374e06a9c5 --- /dev/null +++ b/contrib/elf2dmp/pe.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2018 Virtuozzo International GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * + */ + +#ifndef PE_H +#define PE_H + +#include + +typedef struct IMAGE_DOS_HEADER { + uint16_t e_magic; /* 0x00: MZ Header signature */ + uint16_t e_cblp; /* 0x02: Bytes on last page of file */ + uint16_t e_cp; /* 0x04: Pages in file */ + uint16_t e_crlc; /* 0x06: Relocations */ + uint16_t e_cparhdr; /* 0x08: Size of header in paragraphs */ + uint16_t e_minalloc; /* 0x0a: Minimum extra paragraphs needed */ + uint16_t e_maxalloc; /* 0x0c: Maximum extra paragraphs needed */ + uint16_t e_ss; /* 0x0e: Initial (relative) SS value */ + uint16_t e_sp; /* 0x10: Initial SP value */ + uint16_t e_csum; /* 0x12: Checksum */ + uint16_t e_ip; /* 0x14: Initial IP value */ + uint16_t e_cs; /* 0x16: Initial (relative) CS value */ + uint16_t e_lfarlc; /* 0x18: File address of relocation table */ + uint16_t e_ovno; /* 0x1a: Overlay number */ + uint16_t e_res[4]; /* 0x1c: Reserved words */ + uint16_t e_oemid; /* 0x24: OEM identifier (for e_oeminfo) */ + uint16_t e_oeminfo; /* 0x26: OEM information; e_oemid specific */ + uint16_t e_res2[10]; /* 0x28: Reserved words */ + uint32_t e_lfanew; /* 0x3c: Offset to extended header */ +} __attribute__ ((packed)) IMAGE_DOS_HEADER; + +typedef struct IMAGE_FILE_HEADER { + uint16_t Machine; + uint16_t NumberOfSections; + uint32_t TimeDateStamp; + uint32_t PointerToSymbolTable; + uint32_t NumberOfSymbols; + uint16_t SizeOfOptionalHeader; + uint16_t Characteristics; +} __attribute__ ((packed)) IMAGE_FILE_HEADER; + +typedef struct IMAGE_DATA_DIRECTORY { + uint32_t VirtualAddress; + uint32_t Size; +} __attribute__ ((packed)) IMAGE_DATA_DIRECTORY; + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 + +typedef struct IMAGE_OPTIONAL_HEADER64 { + uint16_t Magic; /* 0x20b */ + uint8_t MajorLinkerVersion; + uint8_t MinorLinkerVersion; + uint32_t SizeOfCode; + uint32_t SizeOfInitializedData; + uint32_t SizeOfUninitializedData; + uint32_t AddressOfEntryPoint; + uint32_t BaseOfCode; + uint64_t ImageBase; + uint32_t SectionAlignment; + uint32_t FileAlignment; + uint16_t MajorOperatingSystemVersion; + uint16_t MinorOperatingSystemVersion; + uint16_t MajorImageVersion; + uint16_t MinorImageVersion; + uint16_t MajorSubsystemVersion; + uint16_t MinorSubsystemVersion; + uint32_t Win32VersionValue; + uint32_t SizeOfImage; + uint32_t SizeOfHeaders; + uint32_t CheckSum; + uint16_t Subsystem; + uint16_t DllCharacteristics; + uint64_t SizeOfStackReserve; + uint64_t SizeOfStackCommit; + uint64_t SizeOfHeapReserve; + uint64_t SizeOfHeapCommit; + uint32_t LoaderFlags; + uint32_t NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} __attribute__ ((packed)) IMAGE_OPTIONAL_HEADER64; + +typedef struct IMAGE_NT_HEADERS64 { + uint32_t Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER64 OptionalHeader; +} __attribute__ ((packed)) IMAGE_NT_HEADERS64; + +#define IMAGE_FILE_DEBUG_DIRECTORY 6 + +typedef struct IMAGE_DEBUG_DIRECTORY { + uint32_t Characteristics; + uint32_t TimeDateStamp; + uint16_t MajorVersion; + uint16_t MinorVersion; + uint32_t Type; + uint32_t SizeOfData; + uint32_t AddressOfRawData; + uint32_t PointerToRawData; +} __attribute__ ((packed)) IMAGE_DEBUG_DIRECTORY; + +#define IMAGE_DEBUG_TYPE_CODEVIEW 2 + +typedef struct guid_t { + uint32_t a; + uint16_t b; + uint16_t c; + uint8_t d[2]; + uint8_t e[6]; +} __attribute__ ((packed)) guid_t; + +typedef struct OMFSignatureRSDS { + char Signature[4]; + guid_t guid; + uint32_t age; + char name[]; +} __attribute__ ((packed)) OMFSignatureRSDS; + +#endif /* PE_H */ diff --git a/contrib/elf2dmp/qemu_elf.c b/contrib/elf2dmp/qemu_elf.c new file mode 100644 index 0000000000..e9c0d2534a --- /dev/null +++ b/contrib/elf2dmp/qemu_elf.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2018 Virtuozzo International GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * + */ + +#include "qemu/osdep.h" +#include "err.h" +#include "qemu_elf.h" + +#define QEMU_NOTE_NAME "QEMU" + +#ifndef ROUND_UP +#define ROUND_UP(n, d) (((n) + (d) - 1) & -(0 ? (n) : (d))) +#endif + +#ifndef DIV_ROUND_UP +#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) +#endif + +#define ELF_NOTE_SIZE(hdr_size, name_size, desc_size) \ + ((DIV_ROUND_UP((hdr_size), 4) + \ + DIV_ROUND_UP((name_size), 4) + \ + DIV_ROUND_UP((desc_size), 4)) * 4) + +int is_system(QEMUCPUState *s) +{ + return s->gs.base >> 63; +} + +static char *nhdr_get_name(Elf64_Nhdr *nhdr) +{ + return (char *)nhdr + ROUND_UP(sizeof(*nhdr), 4); +} + +static void *nhdr_get_desc(Elf64_Nhdr *nhdr) +{ + return nhdr_get_name(nhdr) + ROUND_UP(nhdr->n_namesz, 4); +} + +static Elf64_Nhdr *nhdr_get_next(Elf64_Nhdr *nhdr) +{ + return (void *)((uint8_t *)nhdr + ELF_NOTE_SIZE(sizeof(*nhdr), + nhdr->n_namesz, nhdr->n_descsz)); +} + +Elf64_Phdr *elf64_getphdr(void *map) +{ + Elf64_Ehdr *ehdr = map; + Elf64_Phdr *phdr = (void *)((uint8_t *)map + ehdr->e_phoff); + + return phdr; +} + +Elf64_Half elf_getphdrnum(void *map) +{ + Elf64_Ehdr *ehdr = map; + + return ehdr->e_phnum; +} + +static int init_states(QEMU_Elf *qe) +{ + Elf64_Phdr *phdr = elf64_getphdr(qe->map); + Elf64_Nhdr *start = (void *)((uint8_t *)qe->map + phdr[0].p_offset); + Elf64_Nhdr *end = (void *)((uint8_t *)start + phdr[0].p_memsz); + Elf64_Nhdr *nhdr; + size_t cpu_nr = 0; + + if (phdr[0].p_type != PT_NOTE) { + eprintf("Failed to find PT_NOTE\n"); + return 1; + } + + qe->has_kernel_gs_base = 1; + + for (nhdr = start; nhdr < end; nhdr = nhdr_get_next(nhdr)) { + if (!strcmp(nhdr_get_name(nhdr), QEMU_NOTE_NAME)) { + QEMUCPUState *state = nhdr_get_desc(nhdr); + + if (state->size < sizeof(*state)) { + eprintf("CPU #%zu: QEMU CPU state size %u doesn't match\n", + cpu_nr, state->size); + /* + * We assume either every QEMU CPU state has KERNEL_GS_BASE or + * no one has. + */ + qe->has_kernel_gs_base = 0; + } + cpu_nr++; + } + } + + printf("%zu CPU states has been found\n", cpu_nr); + + qe->state = malloc(sizeof(*qe->state) * cpu_nr); + if (!qe->state) { + return 1; + } + + cpu_nr = 0; + + for (nhdr = start; nhdr < end; nhdr = nhdr_get_next(nhdr)) { + if (!strcmp(nhdr_get_name(nhdr), QEMU_NOTE_NAME)) { + qe->state[cpu_nr] = nhdr_get_desc(nhdr); + cpu_nr++; + } + } + + qe->state_nr = cpu_nr; + + return 0; +} + +static void exit_states(QEMU_Elf *qe) +{ + free(qe->state); +} + +int QEMU_Elf_init(QEMU_Elf *qe, const char *filename) +{ + int err = 0; + struct stat st; + + qe->fd = open(filename, O_RDONLY, 0); + if (qe->fd == -1) { + eprintf("Failed to open ELF dump file \'%s\'\n", filename); + return 1; + } + + fstat(qe->fd, &st); + qe->size = st.st_size; + + qe->map = mmap(NULL, qe->size, PROT_READ | PROT_WRITE, + MAP_PRIVATE, qe->fd, 0); + if (qe->map == MAP_FAILED) { + eprintf("Failed to map ELF file\n"); + err = 1; + goto out_fd; + } + + if (init_states(qe)) { + eprintf("Failed to extract QEMU CPU states\n"); + err = 1; + goto out_unmap; + } + + return 0; + +out_unmap: + munmap(qe->map, qe->size); +out_fd: + close(qe->fd); + + return err; +} + +void QEMU_Elf_exit(QEMU_Elf *qe) +{ + exit_states(qe); + munmap(qe->map, qe->size); + close(qe->fd); +} diff --git a/contrib/elf2dmp/qemu_elf.h b/contrib/elf2dmp/qemu_elf.h new file mode 100644 index 0000000000..d85d6558fa --- /dev/null +++ b/contrib/elf2dmp/qemu_elf.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2018 Virtuozzo International GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * + */ + +#ifndef QEMU_ELF_H +#define QEMU_ELF_H + +#include +#include + +typedef struct QEMUCPUSegment { + uint32_t selector; + uint32_t limit; + uint32_t flags; + uint32_t pad; + uint64_t base; +} QEMUCPUSegment; + +typedef struct QEMUCPUState { + uint32_t version; + uint32_t size; + uint64_t rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp; + uint64_t r8, r9, r10, r11, r12, r13, r14, r15; + uint64_t rip, rflags; + QEMUCPUSegment cs, ds, es, fs, gs, ss; + QEMUCPUSegment ldt, tr, gdt, idt; + uint64_t cr[5]; + uint64_t kernel_gs_base; +} QEMUCPUState; + +int is_system(QEMUCPUState *s); + +typedef struct QEMU_Elf { + int fd; + size_t size; + void *map; + QEMUCPUState **state; + size_t state_nr; + int has_kernel_gs_base; +} QEMU_Elf; + +int QEMU_Elf_init(QEMU_Elf *qe, const char *filename); +void QEMU_Elf_exit(QEMU_Elf *qe); + +Elf64_Phdr *elf64_getphdr(void *map); +Elf64_Half elf_getphdrnum(void *map); + +#endif /* QEMU_ELF_H */ diff --git a/cpus.c b/cpus.c index 719788320f..361678e459 100644 --- a/cpus.c +++ b/cpus.c @@ -245,21 +245,27 @@ static int64_t cpu_get_icount_executed(CPUState *cpu) * account executed instructions. This is done by the TCG vCPU * thread so the main-loop can see time has moved forward. */ -void cpu_update_icount(CPUState *cpu) +static void cpu_update_icount_locked(CPUState *cpu) { int64_t executed = cpu_get_icount_executed(cpu); cpu->icount_budget -= executed; -#ifndef CONFIG_ATOMIC64 + atomic_set_i64(&timers_state.qemu_icount, + timers_state.qemu_icount + executed); +} + +/* + * Update the global shared timer_state.qemu_icount to take into + * account executed instructions. This is done by the TCG vCPU + * thread so the main-loop can see time has moved forward. + */ +void cpu_update_icount(CPUState *cpu) +{ seqlock_write_lock(&timers_state.vm_clock_seqlock, &timers_state.vm_clock_lock); -#endif - atomic_set__nocheck(&timers_state.qemu_icount, - timers_state.qemu_icount + executed); -#ifndef CONFIG_ATOMIC64 + cpu_update_icount_locked(cpu); seqlock_write_unlock(&timers_state.vm_clock_seqlock, &timers_state.vm_clock_lock); -#endif } static int64_t cpu_get_icount_raw_locked(void) @@ -272,16 +278,17 @@ static int64_t cpu_get_icount_raw_locked(void) exit(1); } /* Take into account what has run */ - cpu_update_icount(cpu); + cpu_update_icount_locked(cpu); } - /* The read is protected by the seqlock, so __nocheck is okay. */ - return atomic_read__nocheck(&timers_state.qemu_icount); + /* The read is protected by the seqlock, but needs atomic64 to avoid UB */ + return atomic_read_i64(&timers_state.qemu_icount); } static int64_t cpu_get_icount_locked(void) { int64_t icount = cpu_get_icount_raw_locked(); - return atomic_read__nocheck(&timers_state.qemu_icount_bias) + cpu_icount_to_ns(icount); + return atomic_read_i64(&timers_state.qemu_icount_bias) + + cpu_icount_to_ns(icount); } int64_t cpu_get_icount_raw(void) @@ -454,9 +461,9 @@ static void icount_adjust(void) timers_state.icount_time_shift + 1); } last_delta = delta; - atomic_set__nocheck(&timers_state.qemu_icount_bias, - cur_icount - (timers_state.qemu_icount - << timers_state.icount_time_shift)); + atomic_set_i64(&timers_state.qemu_icount_bias, + cur_icount - (timers_state.qemu_icount + << timers_state.icount_time_shift)); seqlock_write_unlock(&timers_state.vm_clock_seqlock, &timers_state.vm_clock_lock); } @@ -516,8 +523,8 @@ static void icount_warp_rt(void) int64_t delta = clock - cur_icount; warp_delta = MIN(warp_delta, delta); } - atomic_set__nocheck(&timers_state.qemu_icount_bias, - timers_state.qemu_icount_bias + warp_delta); + atomic_set_i64(&timers_state.qemu_icount_bias, + timers_state.qemu_icount_bias + warp_delta); } timers_state.vm_clock_warp_start = -1; seqlock_write_unlock(&timers_state.vm_clock_seqlock, @@ -548,8 +555,8 @@ void qtest_clock_warp(int64_t dest) seqlock_write_lock(&timers_state.vm_clock_seqlock, &timers_state.vm_clock_lock); - atomic_set__nocheck(&timers_state.qemu_icount_bias, - timers_state.qemu_icount_bias + warp); + atomic_set_i64(&timers_state.qemu_icount_bias, + timers_state.qemu_icount_bias + warp); seqlock_write_unlock(&timers_state.vm_clock_seqlock, &timers_state.vm_clock_lock); @@ -576,18 +583,29 @@ void qemu_start_warp_timer(void) return; } - /* warp clock deterministically in record/replay mode */ - if (!replay_checkpoint(CHECKPOINT_CLOCK_WARP_START)) { - return; - } + if (replay_mode != REPLAY_MODE_PLAY) { + if (!all_cpu_threads_idle()) { + return; + } - if (!all_cpu_threads_idle()) { - return; - } + if (qtest_enabled()) { + /* When testing, qtest commands advance icount. */ + return; + } - if (qtest_enabled()) { - /* When testing, qtest commands advance icount. */ - return; + replay_checkpoint(CHECKPOINT_CLOCK_WARP_START); + } else { + /* warp clock deterministically in record/replay mode */ + if (!replay_checkpoint(CHECKPOINT_CLOCK_WARP_START)) { + /* vCPU is sleeping and warp can't be started. + It is probably a race condition: notification sent + to vCPU was processed in advance and vCPU went to sleep. + Therefore we have to wake it up for doing someting. */ + if (replay_has_checkpoint()) { + qemu_clock_notify(QEMU_CLOCK_VIRTUAL); + } + return; + } } /* We want to use the earliest deadline from ALL vm_clocks */ @@ -620,8 +638,8 @@ void qemu_start_warp_timer(void) */ seqlock_write_lock(&timers_state.vm_clock_seqlock, &timers_state.vm_clock_lock); - atomic_set__nocheck(&timers_state.qemu_icount_bias, - timers_state.qemu_icount_bias + deadline); + atomic_set_i64(&timers_state.qemu_icount_bias, + timers_state.qemu_icount_bias + deadline); seqlock_write_unlock(&timers_state.vm_clock_seqlock, &timers_state.vm_clock_lock); qemu_clock_notify(QEMU_CLOCK_VIRTUAL); @@ -823,6 +841,7 @@ int cpu_throttle_get_percentage(void) void cpu_ticks_init(void) { seqlock_init(&timers_state.vm_clock_seqlock); + qemu_spin_init(&timers_state.vm_clock_lock); vmstate_register(NULL, 0, &vmstate_timers, &timers_state); throttle_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT, cpu_throttle_timer_tick, NULL); @@ -964,6 +983,8 @@ static void start_tcg_kick_timer(void) if (!tcg_kick_vcpu_timer && CPU_NEXT(first_cpu)) { tcg_kick_vcpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, kick_tcg_thread, NULL); + } + if (tcg_kick_vcpu_timer && !timer_pending(tcg_kick_vcpu_timer)) { timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick()); } } @@ -971,9 +992,8 @@ static void start_tcg_kick_timer(void) static void stop_tcg_kick_timer(void) { assert(!mttcg_enabled); - if (tcg_kick_vcpu_timer) { + if (tcg_kick_vcpu_timer && timer_pending(tcg_kick_vcpu_timer)) { timer_del(tcg_kick_vcpu_timer); - tcg_kick_vcpu_timer = NULL; } } diff --git a/docs/devel/memory.txt b/docs/devel/memory.txt index c1dee1252c..42577e1d86 100644 --- a/docs/devel/memory.txt +++ b/docs/devel/memory.txt @@ -326,8 +326,15 @@ visible as the pci-hole alias clips it to a 0.5GB range. MMIO Operations --------------- -MMIO regions are provided with ->read() and ->write() callbacks; in addition -various constraints can be supplied to control how these callbacks are called: +MMIO regions are provided with ->read() and ->write() callbacks, +which are sufficient for most devices. Some devices change behaviour +based on the attributes used for the memory transaction, or need +to be able to respond that the access should provoke a bus error +rather than completing successfully; those devices can use the +->read_with_attrs() and ->write_with_attrs() callbacks instead. + +In addition various constraints can be supplied to control how these +callbacks are called: - .valid.min_access_size, .valid.max_access_size define the access sizes (in bytes) which the device accepts; accesses outside this range will @@ -342,5 +349,3 @@ various constraints can be supplied to control how these callbacks are called: - .impl.unaligned specifies that the *implementation* supports unaligned accesses; if false, unaligned accesses will be emulated by two aligned accesses. - - .old_mmio eases the porting of code that was formerly using - cpu_register_io_memory(). It should not be used in new code. diff --git a/exec.c b/exec.c index 6826c8337d..d0821e69aa 100644 --- a/exec.c +++ b/exec.c @@ -1734,7 +1734,7 @@ long qemu_getrampagesize(void) } #endif -#ifdef __linux__ +#ifdef CONFIG_POSIX static int64_t get_file_size(int fd) { int64_t size = lseek(fd, 0, SEEK_END); @@ -2230,7 +2230,7 @@ static void ram_block_add(RAMBlock *new_block, Error **errp, bool shared) } } -#ifdef __linux__ +#ifdef CONFIG_POSIX RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr, uint32_t ram_flags, int fd, Error **errp) diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c index 80b987f7fb..dd62f2a405 100644 --- a/hw/alpha/dp264.c +++ b/hw/alpha/dp264.c @@ -150,7 +150,8 @@ static void clipper_init(MachineState *machine) } if (initrd_filename) { - long initrd_base, initrd_size; + long initrd_base; + int64_t initrd_size; initrd_size = get_image_size(initrd_filename); if (initrd_size < 0) { diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c index dd75c9e8f5..4f980a598b 100644 --- a/hw/audio/es1370.c +++ b/hw/audio/es1370.c @@ -506,10 +506,13 @@ static void es1370_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) d - &s->chan[0], val >> 16, (val & 0xffff)); break; + case ES1370_REG_ADC_FRAMEADR: + d += 2; + goto frameadr; case ES1370_REG_DAC1_FRAMEADR: case ES1370_REG_DAC2_FRAMEADR: - case ES1370_REG_ADC_FRAMEADR: d += (addr - ES1370_REG_DAC1_FRAMEADR) >> 3; + frameadr: d->frame_addr = val; ldebug ("chan %td frame address %#x\n", d - &s->chan[0], val); break; @@ -521,10 +524,13 @@ static void es1370_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) lwarn ("writing to phantom frame address %#x\n", val); break; + case ES1370_REG_ADC_FRAMECNT: + d += 2; + goto framecnt; case ES1370_REG_DAC1_FRAMECNT: case ES1370_REG_DAC2_FRAMECNT: - case ES1370_REG_ADC_FRAMECNT: d += (addr - ES1370_REG_DAC1_FRAMECNT) >> 3; + framecnt: d->frame_cnt = val; d->leftover = 0; ldebug ("chan %td frame count %d, buffer size %d\n", diff --git a/hw/char/serial.c b/hw/char/serial.c index 251f40fdac..02463e3388 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -345,9 +345,9 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, default: case 0: if (s->lcr & UART_LCR_DLAB) { - if (size == 2) { + if (size == 1) { s->divider = (s->divider & 0xff00) | val; - } else if (size == 4) { + } else { s->divider = val; } serial_update_parameters(s); diff --git a/hw/char/sh_serial.c b/hw/char/sh_serial.c index 373a40595f..12831561a6 100644 --- a/hw/char/sh_serial.c +++ b/hw/char/sh_serial.c @@ -29,6 +29,7 @@ #include "hw/sh4/sh.h" #include "chardev/char-fe.h" #include "qapi/error.h" +#include "qemu/timer.h" //#define DEBUG_SERIAL @@ -63,6 +64,8 @@ typedef struct { int rtrg; CharBackend chr; + QEMUTimer *fifo_timeout_timer; + uint64_t etu; /* Elementary Time Unit (ns) */ qemu_irq eri; qemu_irq rxi; @@ -314,6 +317,16 @@ static int sh_serial_can_receive1(void *opaque) return sh_serial_can_receive(s); } +static void sh_serial_timeout_int(void *opaque) +{ + sh_serial_state *s = opaque; + + s->flags |= SH_SERIAL_FLAG_RDF; + if (s->scr & (1 << 6) && s->rxi) { + qemu_set_irq(s->rxi, 1); + } +} + static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size) { sh_serial_state *s = opaque; @@ -330,8 +343,12 @@ static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size) if (s->rx_cnt >= s->rtrg) { s->flags |= SH_SERIAL_FLAG_RDF; if (s->scr & (1 << 6) && s->rxi) { + timer_del(s->fifo_timeout_timer); qemu_set_irq(s->rxi, 1); } + } else { + timer_mod(s->fifo_timeout_timer, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 15 * s->etu); } } } @@ -402,6 +419,9 @@ void sh_serial_init(MemoryRegion *sysmem, sh_serial_event, NULL, s, NULL, true); } + s->fifo_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, + sh_serial_timeout_int, s); + s->etu = NANOSECONDS_PER_SECOND / 9600; s->eri = eri_source; s->rxi = rxi_source; s->txi = txi_source; diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index d2dd8ab502..04e3ebe352 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -667,9 +667,9 @@ static void virtio_serial_save_device(VirtIODevice *vdev, QEMUFile *f) /* The config space (ignored on the far end in current versions) */ get_config(vdev, (uint8_t *)&config); - qemu_put_be16s(f, &config.cols); - qemu_put_be16s(f, &config.rows); - qemu_put_be32s(f, &config.max_nr_ports); + qemu_put_be16(f, config.cols); + qemu_put_be16(f, config.rows); + qemu_put_be32(f, config.max_nr_ports); /* The ports map */ max_nr_ports = s->serial.max_virtserial_ports; diff --git a/hw/core/loader.c b/hw/core/loader.c index 390987a05c..aa0b3fc867 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -61,9 +61,10 @@ static int roms_loaded; /* return the size or -1 if error */ -int get_image_size(const char *filename) +int64_t get_image_size(const char *filename) { - int fd, size; + int fd; + int64_t size; fd = open(filename, O_RDONLY | O_BINARY); if (fd < 0) return -1; diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index 0fb8fb877e..ac6dd7f6ab 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -191,7 +191,7 @@ static void machine_hppa_init(MachineState *machine) if (initrd_filename) { ram_addr_t initrd_base; - long initrd_size; + int64_t initrd_size; initrd_size = get_image_size(initrd_filename); if (initrd_size < 0) { diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c index 0bf1c60a06..25ea783bec 100644 --- a/hw/i386/kvm/clock.c +++ b/hw/i386/kvm/clock.c @@ -147,6 +147,15 @@ static void kvm_update_clock(KVMClockState *s) s->clock_is_reliable = kvm_has_adjust_clock_stable(); } +static void do_kvmclock_ctrl(CPUState *cpu, run_on_cpu_data data) +{ + int ret = kvm_vcpu_ioctl(cpu, KVM_KVMCLOCK_CTRL, 0); + + if (ret && ret != -EINVAL) { + fprintf(stderr, "%s: %s\n", __func__, strerror(-ret)); + } +} + static void kvmclock_vm_state_change(void *opaque, int running, RunState state) { @@ -183,13 +192,7 @@ static void kvmclock_vm_state_change(void *opaque, int running, return; } CPU_FOREACH(cpu) { - ret = kvm_vcpu_ioctl(cpu, KVM_KVMCLOCK_CTRL, 0); - if (ret) { - if (ret != -EINVAL) { - fprintf(stderr, "%s: %s\n", __func__, strerror(-ret)); - } - return; - } + run_on_cpu(cpu, do_kvmclock_ctrl, RUN_ON_CPU_NULL); } } else { diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 03148450c8..cd5029c149 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -838,7 +838,8 @@ static void load_linux(PCMachineState *pcms, FWCfgState *fw_cfg) { uint16_t protocol; - int setup_size, kernel_size, initrd_size = 0, cmdline_size; + int setup_size, kernel_size, cmdline_size; + int64_t initrd_size = 0; int dtb_size, setup_data_offset; uint32_t initrd_max; uint8_t header[8192], *setup, *kernel, *initrd_data; @@ -974,6 +975,10 @@ static void load_linux(PCMachineState *pcms, fprintf(stderr, "qemu: error reading initrd %s: %s\n", initrd_filename, strerror(errno)); exit(1); + } else if (initrd_size >= initrd_max) { + fprintf(stderr, "qemu: initrd is too large, cannot support." + "(max: %"PRIu32", need %"PRId64")\n", initrd_max, initrd_size); + exit(1); } initrd_addr = (initrd_max-initrd_size) & ~4095; diff --git a/hw/ide/core.c b/hw/ide/core.c index 2c62efc536..04e22e751d 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -35,6 +35,7 @@ #include "sysemu/block-backend.h" #include "qapi/error.h" #include "qemu/cutils.h" +#include "sysemu/replay.h" #include "hw/ide/internal.h" #include "trace.h" @@ -479,7 +480,7 @@ static void ide_issue_trim_cb(void *opaque, int ret) done: iocb->aiocb = NULL; if (iocb->bh) { - qemu_bh_schedule(iocb->bh); + replay_bh_schedule_event(iocb->bh); } } diff --git a/hw/input/ps2.c b/hw/input/ps2.c index fdfcadf9a1..6c43fc2912 100644 --- a/hw/input/ps2.c +++ b/hw/input/ps2.c @@ -914,7 +914,12 @@ static void ps2_common_post_load(PS2State *s) uint8_t tmp_data[PS2_QUEUE_SIZE]; /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */ - size = (q->count < 0 || q->count > PS2_QUEUE_SIZE) ? 0 : q->count; + size = q->count; + if (q->count < 0) { + size = 0; + } else if (q->count > PS2_QUEUE_SIZE) { + size = PS2_QUEUE_SIZE; + } /* move the queue elements to the start of data array */ for (i = 0; i < size; i++) { @@ -929,7 +934,6 @@ static void ps2_common_post_load(PS2State *s) q->rptr = 0; q->wptr = (size == PS2_QUEUE_SIZE) ? 0 : size; q->count = size; - s->update_irq(s->update_arg, q->count != 0); } static void ps2_kbd_reset(void *opaque) diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c index c1694c8254..2fbba32c48 100644 --- a/hw/mips/mips_fulong2e.c +++ b/hw/mips/mips_fulong2e.c @@ -104,9 +104,9 @@ static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t* prom_buf, int index, static int64_t load_kernel (CPUMIPSState *env) { - int64_t kernel_entry, kernel_low, kernel_high; + int64_t kernel_entry, kernel_low, kernel_high, initrd_size; int index = 0; - long kernel_size, initrd_size; + long kernel_size; ram_addr_t initrd_offset; uint32_t *prom_buf; long prom_size; @@ -150,7 +150,7 @@ static int64_t load_kernel (CPUMIPSState *env) prom_set(prom_buf, index++, "%s", loaderparams.kernel_filename); if (initrd_size > 0) { - prom_set(prom_buf, index++, "rd_start=0x%" PRIx64 " rd_size=%li %s", + prom_set(prom_buf, index++, "rd_start=0x%" PRIx64 " rd_size=%" PRId64 " %s", cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size, loaderparams.kernel_cmdline); } else { diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 40041d5ec0..29b90bacf3 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -995,8 +995,8 @@ static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t* prom_buf, int index, /* Kernel */ static int64_t load_kernel (void) { - int64_t kernel_entry, kernel_high; - long kernel_size, initrd_size; + int64_t kernel_entry, kernel_high, initrd_size; + long kernel_size; ram_addr_t initrd_offset; int big_endian; uint32_t *prom_buf; @@ -1070,7 +1070,7 @@ static int64_t load_kernel (void) prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_filename); if (initrd_size > 0) { - prom_set(prom_buf, prom_index++, "rd_start=0x%" PRIx64 " rd_size=%li %s", + prom_set(prom_buf, prom_index++, "rd_start=0x%" PRIx64 " rd_size=%" PRId64 " %s", xlate_to_kseg0(NULL, initrd_offset), initrd_size, loaderparams.kernel_cmdline); } else { diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mips_mipssim.c index 241faa1d0f..f665752a2f 100644 --- a/hw/mips/mips_mipssim.c +++ b/hw/mips/mips_mipssim.c @@ -58,9 +58,8 @@ typedef struct ResetData { static int64_t load_kernel(void) { - int64_t entry, kernel_high; + int64_t entry, kernel_high, initrd_size; long kernel_size; - long initrd_size; ram_addr_t initrd_offset; int big_endian; diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c index d5725d0555..3e852e98cf 100644 --- a/hw/mips/mips_r4k.c +++ b/hw/mips/mips_r4k.c @@ -81,8 +81,8 @@ typedef struct ResetData { static int64_t load_kernel(void) { const size_t params_size = 264; - int64_t entry, kernel_high; - long kernel_size, initrd_size; + int64_t entry, kernel_high, initrd_size; + long kernel_size; ram_addr_t initrd_offset; uint32_t *params_buf; int big_endian; @@ -136,7 +136,7 @@ static int64_t load_kernel(void) params_buf[1] = tswap32(0x12345678); if (initrd_size > 0) { - snprintf((char *)params_buf + 8, 256, "rd_start=0x%" PRIx64 " rd_size=%li %s", + snprintf((char *)params_buf + 8, 256, "rd_start=0x%" PRIx64 " rd_size=%" PRId64 " %s", cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size, loaderparams.kernel_cmdline); } else { diff --git a/hw/misc/debugexit.c b/hw/misc/debugexit.c index 84fa1a5b9d..bed293247e 100644 --- a/hw/misc/debugexit.c +++ b/hw/misc/debugexit.c @@ -23,6 +23,11 @@ typedef struct ISADebugExitState { MemoryRegion io; } ISADebugExitState; +static uint64_t debug_exit_read(void *opaque, hwaddr addr, unsigned size) +{ + return 0; +} + static void debug_exit_write(void *opaque, hwaddr addr, uint64_t val, unsigned width) { @@ -30,6 +35,7 @@ static void debug_exit_write(void *opaque, hwaddr addr, uint64_t val, } static const MemoryRegionOps debug_exit_ops = { + .read = debug_exit_read, .write = debug_exit_write, .valid.min_access_size = 1, .valid.max_access_size = 4, diff --git a/hw/misc/edu.c b/hw/misc/edu.c index df26a4d046..0687ffd343 100644 --- a/hw/misc/edu.c +++ b/hw/misc/edu.c @@ -30,7 +30,8 @@ #include "qemu/main-loop.h" /* iothread mutex */ #include "qapi/visitor.h" -#define EDU(obj) OBJECT_CHECK(EduState, obj, "edu") +#define TYPE_PCI_EDU_DEVICE "edu" +#define EDU(obj) OBJECT_CHECK(EduState, obj, TYPE_PCI_EDU_DEVICE) #define FACT_IRQ 0x00000001 #define DMA_IRQ 0x00000100 @@ -414,7 +415,7 @@ static void pci_edu_register_types(void) { }, }; static const TypeInfo edu_info = { - .name = "edu", + .name = TYPE_PCI_EDU_DEVICE, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(EduState), .instance_init = edu_instance_init, diff --git a/hw/misc/hyperv_testdev.c b/hw/misc/hyperv_testdev.c index bf6bbfa8cf..7549f470b1 100644 --- a/hw/misc/hyperv_testdev.c +++ b/hw/misc/hyperv_testdev.c @@ -105,7 +105,12 @@ static void hv_synic_test_dev_control(HypervTestDev *dev, uint32_t ctl, } } -static void hv_test_dev_control(void *opaque, hwaddr addr, uint64_t data, +static uint64_t hv_test_dev_read(void *opaque, hwaddr addr, unsigned size) +{ + return 0; +} + +static void hv_test_dev_write(void *opaque, hwaddr addr, uint64_t data, uint32_t len) { HypervTestDev *dev = HYPERV_TEST_DEV(opaque); @@ -127,7 +132,8 @@ static void hv_test_dev_control(void *opaque, hwaddr addr, uint64_t data, } static const MemoryRegionOps synic_test_sint_ops = { - .write = hv_test_dev_control, + .read = hv_test_dev_read, + .write = hv_test_dev_write, .valid.min_access_size = 4, .valid.max_access_size = 4, .endianness = DEVICE_LITTLE_ENDIAN, diff --git a/hw/misc/pc-testdev.c b/hw/misc/pc-testdev.c index b81d820084..697eb88c97 100644 --- a/hw/misc/pc-testdev.c +++ b/hw/misc/pc-testdev.c @@ -58,7 +58,12 @@ typedef struct PCTestdev { #define TESTDEV(obj) \ OBJECT_CHECK(PCTestdev, (obj), TYPE_TESTDEV) -static void test_irq_line(void *opaque, hwaddr addr, uint64_t data, +static uint64_t test_irq_line_read(void *opaque, hwaddr addr, unsigned size) +{ + return 0; +} + +static void test_irq_line_write(void *opaque, hwaddr addr, uint64_t data, unsigned len) { PCTestdev *dev = opaque; @@ -68,7 +73,8 @@ static void test_irq_line(void *opaque, hwaddr addr, uint64_t data, } static const MemoryRegionOps test_irq_ops = { - .write = test_irq_line, + .read = test_irq_line_read, + .write = test_irq_line_write, .valid.min_access_size = 1, .valid.max_access_size = 1, .endianness = DEVICE_LITTLE_ENDIAN, @@ -110,7 +116,12 @@ static const MemoryRegionOps test_ioport_byte_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static void test_flush_page(void *opaque, hwaddr addr, uint64_t data, +static uint64_t test_flush_page_read(void *opaque, hwaddr addr, unsigned size) +{ + return 0; +} + +static void test_flush_page_write(void *opaque, hwaddr addr, uint64_t data, unsigned len) { hwaddr page = 4096; @@ -126,7 +137,8 @@ static void test_flush_page(void *opaque, hwaddr addr, uint64_t data, } static const MemoryRegionOps test_flush_ops = { - .write = test_flush_page, + .read = test_flush_page_read, + .write = test_flush_page_write, .valid.min_access_size = 4, .valid.max_access_size = 4, .endianness = DEVICE_LITTLE_ENDIAN, diff --git a/hw/moxie/moxiesim.c b/hw/moxie/moxiesim.c index d41247dbdc..4b0ce09c5e 100644 --- a/hw/moxie/moxiesim.c +++ b/hw/moxie/moxiesim.c @@ -54,8 +54,8 @@ typedef struct { static void load_kernel(MoxieCPU *cpu, LoaderParams *loader_params) { uint64_t entry, kernel_low, kernel_high; + int64_t initrd_size; long kernel_size; - long initrd_size; ram_addr_t initrd_offset; kernel_size = load_elf(loader_params->kernel_filename, NULL, NULL, diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index d79a568f54..946f765f7f 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -434,6 +434,11 @@ static bool fw_cfg_data_mem_valid(void *opaque, hwaddr addr, return addr == 0; } +static uint64_t fw_cfg_ctl_mem_read(void *opaque, hwaddr addr, unsigned size) +{ + return 0; +} + static void fw_cfg_ctl_mem_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { @@ -468,6 +473,7 @@ static bool fw_cfg_comb_valid(void *opaque, hwaddr addr, } static const MemoryRegionOps fw_cfg_ctl_mem_ops = { + .read = fw_cfg_ctl_mem_read, .write = fw_cfg_ctl_mem_write, .endianness = DEVICE_BIG_ENDIAN, .valid.accepts = fw_cfg_ctl_mem_valid, @@ -1109,12 +1115,7 @@ static void fw_cfg_mem_realize(DeviceState *dev, Error **errp) sysbus_init_mmio(sbd, &s->ctl_iomem); if (s->data_width > data_ops->valid.max_access_size) { - /* memberwise copy because the "old_mmio" member is const */ - s->wide_data_ops.read = data_ops->read; - s->wide_data_ops.write = data_ops->write; - s->wide_data_ops.endianness = data_ops->endianness; - s->wide_data_ops.valid = data_ops->valid; - s->wide_data_ops.impl = data_ops->impl; + s->wide_data_ops = *data_ops; s->wide_data_ops.valid.max_access_size = s->data_width; s->wide_data_ops.impl.max_access_size = s->data_width; diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index 996b40650d..d1e6534311 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -20,20 +20,7 @@ #include "hw/scsi/scsi.h" #include "sysemu/dma.h" #include "qemu/log.h" - -//#define DEBUG_LSI -//#define DEBUG_LSI_REG - -#ifdef DEBUG_LSI -#define DPRINTF(fmt, ...) \ -do { printf("lsi_scsi: " fmt , ## __VA_ARGS__); } while (0) -#define BADF(fmt, ...) \ -do { fprintf(stderr, "lsi_scsi: error: " fmt , ## __VA_ARGS__); exit(1);} while (0) -#else -#define DPRINTF(fmt, ...) do {} while(0) -#define BADF(fmt, ...) \ -do { fprintf(stderr, "lsi_scsi: error: " fmt , ## __VA_ARGS__);} while (0) -#endif +#include "trace.h" static const char *names[] = { "SCNTL0", "SCNTL1", "SCNTL2", "SCNTL3", "SCID", "SXFER", "SDID", "GPREG", @@ -313,7 +300,7 @@ static inline int lsi_irq_on_rsl(LSIState *s) static void lsi_soft_reset(LSIState *s) { - DPRINTF("Reset\n"); + trace_lsi_reset(); s->carry = 0; s->msg_action = 0; @@ -484,15 +471,13 @@ static void lsi_update_irq(LSIState *s) level = 1; if (level != last_level) { - DPRINTF("Update IRQ level %d dstat %02x sist %02x%02x\n", - level, s->dstat, s->sist1, s->sist0); + trace_lsi_update_irq(level, s->dstat, s->sist1, s->sist0); last_level = level; } lsi_set_irq(s, level); if (!level && lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON)) { - DPRINTF("Handled IRQs & disconnected, looking for pending " - "processes\n"); + trace_lsi_update_irq_disconnected(); QTAILQ_FOREACH(p, &s->queue, next) { if (p->pending) { lsi_reselect(s, p); @@ -508,8 +493,7 @@ static void lsi_script_scsi_interrupt(LSIState *s, int stat0, int stat1) uint32_t mask0; uint32_t mask1; - DPRINTF("SCSI Interrupt 0x%02x%02x prev 0x%02x%02x\n", - stat1, stat0, s->sist1, s->sist0); + trace_lsi_script_scsi_interrupt(stat1, stat0, s->sist1, s->sist0); s->sist0 |= stat0; s->sist1 |= stat1; /* Stop processor on fatal or unmasked interrupt. As a special hack @@ -527,7 +511,7 @@ static void lsi_script_scsi_interrupt(LSIState *s, int stat0, int stat1) /* Stop SCRIPTS execution and raise a DMA interrupt. */ static void lsi_script_dma_interrupt(LSIState *s, int stat) { - DPRINTF("DMA Interrupt 0x%x prev 0x%x\n", stat, s->dstat); + trace_lsi_script_dma_interrupt(stat, s->dstat); s->dstat |= stat; lsi_update_irq(s); lsi_stop_script(s); @@ -547,9 +531,9 @@ static void lsi_bad_phase(LSIState *s, int out, int new_phase) } else { s->dsp = (s->scntl2 & LSI_SCNTL2_WSR ? s->pmjad2 : s->pmjad1); } - DPRINTF("Data phase mismatch jump to %08x\n", s->dsp); + trace_lsi_bad_phase_jump(s->dsp); } else { - DPRINTF("Phase mismatch interrupt\n"); + trace_lsi_bad_phase_interrupt(); lsi_script_scsi_interrupt(s, LSI_SIST0_MA, 0); lsi_stop_script(s); } @@ -576,7 +560,7 @@ static void lsi_disconnect(LSIState *s) static void lsi_bad_selection(LSIState *s, uint32_t id) { - DPRINTF("Selected absent target %d\n", id); + trace_lsi_bad_selection(id); lsi_script_scsi_interrupt(s, 0, LSI_SIST1_STO); lsi_disconnect(s); } @@ -591,7 +575,7 @@ static void lsi_do_dma(LSIState *s, int out) assert(s->current); if (!s->current->dma_len) { /* Wait until data is available. */ - DPRINTF("DMA no data available\n"); + trace_lsi_do_dma_unavailable(); return; } @@ -611,7 +595,7 @@ static void lsi_do_dma(LSIState *s, int out) else if (s->sbms) addr |= ((uint64_t)s->sbms << 32); - DPRINTF("DMA addr=0x" DMA_ADDR_FMT " len=%d\n", addr, count); + trace_lsi_do_dma(addr, count); s->csbc += count; s->dnad += count; s->dbc -= count; @@ -640,7 +624,7 @@ static void lsi_queue_command(LSIState *s) { lsi_request *p = s->current; - DPRINTF("Queueing tag=0x%x\n", p->tag); + trace_lsi_queue_command(p->tag); assert(s->current != NULL); assert(s->current->dma_len == 0); QTAILQ_INSERT_TAIL(&s->queue, s->current, next); @@ -654,9 +638,9 @@ static void lsi_queue_command(LSIState *s) static void lsi_add_msg_byte(LSIState *s, uint8_t data) { if (s->msg_len >= LSI_MAX_MSGIN_LEN) { - BADF("MSG IN data too long\n"); + trace_lsi_add_msg_byte_error(); } else { - DPRINTF("MSG IN 0x%02x\n", data); + trace_lsi_add_msg_byte(data); s->msg[s->msg_len++] = data; } } @@ -676,7 +660,7 @@ static void lsi_reselect(LSIState *s, lsi_request *p) if (!(s->dcntl & LSI_DCNTL_COM)) { s->sfbr = 1 << (id & 0x7); } - DPRINTF("Reselected target %d\n", id); + trace_lsi_reselect(id); s->scntl1 |= LSI_SCNTL1_CON; lsi_set_phase(s, PHASE_MI); s->msg_action = p->out ? 2 : 3; @@ -732,7 +716,7 @@ static int lsi_queue_req(LSIState *s, SCSIRequest *req, uint32_t len) lsi_request *p = req->hba_private; if (p->pending) { - BADF("Multiple IO pending for request %p\n", p); + trace_lsi_queue_req_error(p); } p->pending = len; /* Reselect if waiting for it, or if reselection triggers an IRQ @@ -747,7 +731,7 @@ static int lsi_queue_req(LSIState *s, SCSIRequest *req, uint32_t len) lsi_reselect(s, p); return 0; } else { - DPRINTF("Queueing IO tag=0x%x\n", p->tag); + trace_lsi_queue_req(p->tag); p->pending = len; return 1; } @@ -760,7 +744,7 @@ static void lsi_command_complete(SCSIRequest *req, uint32_t status, size_t resid int out; out = (s->sstat1 & PHASE_MASK) == PHASE_DO; - DPRINTF("Command complete status=%d\n", (int)status); + trace_lsi_command_complete(status); s->status = status; s->command_complete = 2; if (s->waiting && s->dbc != 0) { @@ -795,7 +779,7 @@ static void lsi_transfer_data(SCSIRequest *req, uint32_t len) out = (s->sstat1 & PHASE_MASK) == PHASE_DO; /* host adapter (re)connected */ - DPRINTF("Data ready tag=0x%x len=%d\n", req->tag, len); + trace_lsi_transfer_data(req->tag, len); s->current->dma_len = len; s->command_complete = 1; if (s->waiting) { @@ -814,7 +798,7 @@ static void lsi_do_command(LSIState *s) uint32_t id; int n; - DPRINTF("Send command len=%d\n", s->dbc); + trace_lsi_do_command(s->dbc); if (s->dbc > 16) s->dbc = 16; pci_dma_read(PCI_DEVICE(s), s->dnad, buf, s->dbc); @@ -862,9 +846,10 @@ static void lsi_do_command(LSIState *s) static void lsi_do_status(LSIState *s) { uint8_t status; - DPRINTF("Get status len=%d status=%d\n", s->dbc, s->status); - if (s->dbc != 1) - BADF("Bad Status move\n"); + trace_lsi_do_status(s->dbc, s->status); + if (s->dbc != 1) { + trace_lsi_do_status_error(); + } s->dbc = 1; status = s->status; s->sfbr = status; @@ -877,7 +862,7 @@ static void lsi_do_status(LSIState *s) static void lsi_do_msgin(LSIState *s) { int len; - DPRINTF("Message in len=%d/%d\n", s->dbc, s->msg_len); + trace_lsi_do_msgin(s->dbc, s->msg_len); s->sfbr = s->msg[0]; len = s->msg_len; if (len > s->dbc) @@ -942,36 +927,36 @@ static void lsi_do_msgout(LSIState *s) current_req = lsi_find_by_tag(s, current_tag); } - DPRINTF("MSG out len=%d\n", s->dbc); + trace_lsi_do_msgout(s->dbc); while (s->dbc) { msg = lsi_get_msgbyte(s); s->sfbr = msg; switch (msg) { case 0x04: - DPRINTF("MSG: Disconnect\n"); + trace_lsi_do_msgout_disconnect(); lsi_disconnect(s); break; case 0x08: - DPRINTF("MSG: No Operation\n"); + trace_lsi_do_msgout_noop(); lsi_set_phase(s, PHASE_CMD); break; case 0x01: len = lsi_get_msgbyte(s); msg = lsi_get_msgbyte(s); (void)len; /* avoid a warning about unused variable*/ - DPRINTF("Extended message 0x%x (len %d)\n", msg, len); + trace_lsi_do_msgout_extended(msg, len); switch (msg) { case 1: - DPRINTF("SDTR (ignored)\n"); + trace_lsi_do_msgout_ignored("SDTR"); lsi_skip_msgbytes(s, 2); break; case 3: - DPRINTF("WDTR (ignored)\n"); + trace_lsi_do_msgout_ignored("WDTR"); lsi_skip_msgbytes(s, 1); break; case 4: - DPRINTF("PPR (ignored)\n"); + trace_lsi_do_msgout_ignored("PPR"); lsi_skip_msgbytes(s, 5); break; default: @@ -980,19 +965,20 @@ static void lsi_do_msgout(LSIState *s) break; case 0x20: /* SIMPLE queue */ s->select_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID; - DPRINTF("SIMPLE queue tag=0x%x\n", s->select_tag & 0xff); + trace_lsi_do_msgout_simplequeue(s->select_tag & 0xff); break; case 0x21: /* HEAD of queue */ - BADF("HEAD queue not implemented\n"); + qemu_log_mask(LOG_UNIMP, "lsi_scsi: HEAD queue not implemented\n"); s->select_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID; break; case 0x22: /* ORDERED queue */ - BADF("ORDERED queue not implemented\n"); + qemu_log_mask(LOG_UNIMP, + "lsi_scsi: ORDERED queue not implemented\n"); s->select_tag |= lsi_get_msgbyte(s) | LSI_TAG_VALID; break; case 0x0d: /* The ABORT TAG message clears the current I/O process only. */ - DPRINTF("MSG: ABORT TAG tag=0x%x\n", current_tag); + trace_lsi_do_msgout_abort(current_tag); if (current_req) { scsi_req_cancel(current_req->req); } @@ -1004,17 +990,17 @@ static void lsi_do_msgout(LSIState *s) /* The ABORT message clears all I/O processes for the selecting initiator on the specified logical unit of the target. */ if (msg == 0x06) { - DPRINTF("MSG: ABORT tag=0x%x\n", current_tag); + trace_lsi_do_msgout_abort(current_tag); } /* The CLEAR QUEUE message clears all I/O processes for all initiators on the specified logical unit of the target. */ if (msg == 0x0e) { - DPRINTF("MSG: CLEAR QUEUE tag=0x%x\n", current_tag); + trace_lsi_do_msgout_clearqueue(current_tag); } /* The BUS DEVICE RESET message clears all I/O processes for all initiators on all logical units of the target. */ if (msg == 0x0c) { - DPRINTF("MSG: BUS DEVICE RESET tag=0x%x\n", current_tag); + trace_lsi_do_msgout_busdevicereset(current_tag); } /* clear the current I/O process */ @@ -1042,14 +1028,14 @@ static void lsi_do_msgout(LSIState *s) goto bad; } s->current_lun = msg & 7; - DPRINTF("Select LUN %d\n", s->current_lun); + trace_lsi_do_msgout_select(s->current_lun); lsi_set_phase(s, PHASE_CMD); break; } } return; bad: - BADF("Unimplemented message 0x%02x\n", msg); + qemu_log_mask(LOG_UNIMP, "Unimplemented message 0x%02x\n", msg); lsi_set_phase(s, PHASE_MI); lsi_add_msg_byte(s, 7); /* MESSAGE REJECT */ s->msg_action = 0; @@ -1061,7 +1047,7 @@ static void lsi_memcpy(LSIState *s, uint32_t dest, uint32_t src, int count) int n; uint8_t buf[LSI_BUF_SIZE]; - DPRINTF("memcpy dest 0x%08x src 0x%08x count %d\n", dest, src, count); + trace_lsi_memcpy(dest, src, count); while (count) { n = (count > LSI_BUF_SIZE) ? LSI_BUF_SIZE : count; lsi_mem_read(s, src, buf, n); @@ -1076,7 +1062,7 @@ static void lsi_wait_reselect(LSIState *s) { lsi_request *p; - DPRINTF("Wait Reselect\n"); + trace_lsi_wait_reselect(); QTAILQ_FOREACH(p, &s->queue, next) { if (p->pending) { @@ -1109,14 +1095,14 @@ again: } addr = read_dword(s, s->dsp + 4); addr_high = 0; - DPRINTF("SCRIPTS dsp=%08x opcode %08x arg %08x\n", s->dsp, insn, addr); + trace_lsi_execute_script(s->dsp, insn, addr); s->dsps = addr; s->dcmd = insn >> 24; s->dsp += 8; switch (insn >> 30) { case 0: /* Block move. */ if (s->sist1 & LSI_SIST1_STO) { - DPRINTF("Delayed select timeout\n"); + trace_lsi_execute_script_blockmove_delayed(); lsi_stop_script(s); break; } @@ -1171,8 +1157,9 @@ again: addr_high = s->dbms; break; default: - BADF("Illegal selector specified (0x%x > 0x15)" - " for 64-bit DMA block move", selector); + qemu_log_mask(LOG_GUEST_ERROR, + "lsi_scsi: Illegal selector specified (0x%x > 0x15) " + "for 64-bit DMA block move", selector); break; } } @@ -1184,8 +1171,8 @@ again: s->ia = s->dsp - 12; } if ((s->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) { - DPRINTF("Wrong phase got %d expected %d\n", - s->sstat1 & PHASE_MASK, (insn >> 24) & 7); + trace_lsi_execute_script_blockmove_badphase(s->sstat1 & PHASE_MASK, + (insn >> 24) & 7); lsi_script_scsi_interrupt(s, LSI_SIST0_MA, 0); break; } @@ -1217,8 +1204,8 @@ again: lsi_do_msgin(s); break; default: - BADF("Unimplemented phase %d\n", s->sstat1 & PHASE_MASK); - exit(1); + qemu_log_mask(LOG_UNIMP, "lsi_scsi: Unimplemented phase %d\n", + s->sstat1 & PHASE_MASK); } s->dfifo = s->dbc & 0xff; s->ctest5 = (s->ctest5 & 0xfc) | ((s->dbc >> 8) & 3); @@ -1246,7 +1233,7 @@ again: case 0: /* Select */ s->sdid = id; if (s->scntl1 & LSI_SCNTL1_CON) { - DPRINTF("Already reselected, jumping to alternative address\n"); + trace_lsi_execute_script_io_alreadyreselected(); s->dsp = s->dnad; break; } @@ -1256,8 +1243,8 @@ again: lsi_bad_selection(s, id); break; } - DPRINTF("Selected target %d%s\n", - id, insn & (1 << 3) ? " ATN" : ""); + trace_lsi_execute_script_io_selected(id, + insn & (1 << 3) ? " ATN" : ""); /* ??? Linux drivers compain when this is set. Maybe it only applies in low-level mode (unimplemented). lsi_script_scsi_interrupt(s, LSI_SIST0_CMP, 0); */ @@ -1269,7 +1256,7 @@ again: lsi_set_phase(s, PHASE_MO); break; case 1: /* Disconnect */ - DPRINTF("Wait Disconnect\n"); + trace_lsi_execute_script_io_disconnect(); s->scntl1 &= ~LSI_SCNTL1_CON; break; case 2: /* Wait Reselect */ @@ -1278,7 +1265,7 @@ again: } break; case 3: /* Set */ - DPRINTF("Set%s%s%s%s\n", + trace_lsi_execute_script_io_set( insn & (1 << 3) ? " ATN" : "", insn & (1 << 6) ? " ACK" : "", insn & (1 << 9) ? " TM" : "", @@ -1288,14 +1275,14 @@ again: lsi_set_phase(s, PHASE_MO); } if (insn & (1 << 9)) { - BADF("Target mode not implemented\n"); - exit(1); + qemu_log_mask(LOG_UNIMP, + "lsi_scsi: Target mode not implemented\n"); } if (insn & (1 << 10)) s->carry = 1; break; case 4: /* Clear */ - DPRINTF("Clear%s%s%s%s\n", + trace_lsi_execute_script_io_clear( insn & (1 << 3) ? " ATN" : "", insn & (1 << 6) ? " ACK" : "", insn & (1 << 9) ? " TM" : "", @@ -1313,18 +1300,17 @@ again: uint8_t data8; int reg; int operator; -#ifdef DEBUG_LSI + static const char *opcode_names[3] = {"Write", "Read", "Read-Modify-Write"}; static const char *operator_names[8] = {"MOV", "SHL", "OR", "XOR", "AND", "SHR", "ADD", "ADC"}; -#endif reg = ((insn >> 16) & 0x7f) | (insn & 0x80); data8 = (insn >> 8) & 0xff; opcode = (insn >> 27) & 7; operator = (insn >> 24) & 7; - DPRINTF("%s reg 0x%x %s data8=0x%02x sfbr=0x%02x%s\n", + trace_lsi_execute_script_io_opcode( opcode_names[opcode - 5], reg, operator_names[operator], data8, s->sfbr, (insn & (1 << 23)) ? " SFBR" : ""); @@ -1404,21 +1390,21 @@ again: int jmp; if ((insn & 0x002e0000) == 0) { - DPRINTF("NOP\n"); + trace_lsi_execute_script_tc_nop(); break; } if (s->sist1 & LSI_SIST1_STO) { - DPRINTF("Delayed select timeout\n"); + trace_lsi_execute_script_tc_delayedselect_timeout(); lsi_stop_script(s); break; } cond = jmp = (insn & (1 << 19)) != 0; if (cond == jmp && (insn & (1 << 21))) { - DPRINTF("Compare carry %d\n", s->carry == jmp); + trace_lsi_execute_script_tc_compc(s->carry == jmp); cond = s->carry != 0; } if (cond == jmp && (insn & (1 << 17))) { - DPRINTF("Compare phase %d %c= %d\n", + trace_lsi_execute_script_tc_compp( (s->sstat1 & PHASE_MASK), jmp ? '=' : '!', ((insn >> 24) & 7)); @@ -1428,7 +1414,7 @@ again: uint8_t mask; mask = (~insn >> 8) & 0xff; - DPRINTF("Compare data 0x%x & 0x%x %c= 0x%x\n", + trace_lsi_execute_script_tc_compd( s->sfbr, mask, jmp ? '=' : '!', insn & mask); cond = (s->sfbr & mask) == (insn & mask); } @@ -1439,21 +1425,21 @@ again: } switch ((insn >> 27) & 7) { case 0: /* Jump */ - DPRINTF("Jump to 0x%08x\n", addr); + trace_lsi_execute_script_tc_jump(addr); s->adder = addr; s->dsp = addr; break; case 1: /* Call */ - DPRINTF("Call 0x%08x\n", addr); + trace_lsi_execute_script_tc_call(addr); s->temp = s->dsp; s->dsp = addr; break; case 2: /* Return */ - DPRINTF("Return to 0x%08x\n", s->temp); + trace_lsi_execute_script_tc_return(s->temp); s->dsp = s->temp; break; case 3: /* Interrupt */ - DPRINTF("Interrupt 0x%08x\n", s->dsps); + trace_lsi_execute_script_tc_interrupt(s->dsps); if ((insn & (1 << 20)) != 0) { s->istat0 |= LSI_ISTAT0_INTF; lsi_update_irq(s); @@ -1462,12 +1448,12 @@ again: } break; default: - DPRINTF("Illegal transfer control\n"); + trace_lsi_execute_script_tc_illegal(); lsi_script_dma_interrupt(s, LSI_DSTAT_IID); break; } } else { - DPRINTF("Control condition failed\n"); + trace_lsi_execute_script_tc_cc_failed(); } } break; @@ -1495,13 +1481,12 @@ again: reg = (insn >> 16) & 0xff; if (insn & (1 << 24)) { pci_dma_read(pci_dev, addr, data, n); - DPRINTF("Load reg 0x%x size %d addr 0x%08x = %08x\n", reg, n, - addr, *(int *)data); + trace_lsi_execute_script_mm_load(reg, n, addr, *(int *)data); for (i = 0; i < n; i++) { lsi_reg_writeb(s, reg + i, data[i]); } } else { - DPRINTF("Store reg 0x%x size %d addr 0x%08x\n", reg, n, addr); + trace_lsi_execute_script_mm_store(reg, n, addr); for (i = 0; i < n; i++) { data[i] = lsi_reg_readb(s, reg + i); } @@ -1515,8 +1500,10 @@ again: assume this is the case and force an unexpected device disconnect. This is apparently sufficient to beat the drivers into submission. */ - if (!(s->sien0 & LSI_SIST0_UDC)) - fprintf(stderr, "inf. loop with UDC masked\n"); + if (!(s->sien0 & LSI_SIST0_UDC)) { + qemu_log_mask(LOG_GUEST_ERROR, + "lsi_scsi: inf. loop with UDC masked"); + } lsi_script_scsi_interrupt(s, LSI_SIST0_UDC, 0); lsi_disconnect(s); } else if (s->istat1 & LSI_ISTAT1_SRUN && !s->waiting) { @@ -1526,7 +1513,7 @@ again: goto again; } } - DPRINTF("SCRIPTS execution stopped\n"); + trace_lsi_execute_script_stop(); } static uint8_t lsi_reg_readb(LSIState *s, int offset) @@ -1761,10 +1748,8 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset) #undef CASE_GET_REG24 #undef CASE_GET_REG32 -#ifdef DEBUG_LSI_REG - DPRINTF("Read reg %s %x = %02x\n", - offset < ARRAY_SIZE(names) ? names[offset] : "???", offset, ret); -#endif + trace_lsi_reg_read(offset < ARRAY_SIZE(names) ? names[offset] : "???", + offset, ret); return ret; } @@ -1782,21 +1767,22 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val) case addr + 2: s->name &= 0xff00ffff; s->name |= val << 16; break; \ case addr + 3: s->name &= 0x00ffffff; s->name |= val << 24; break; -#ifdef DEBUG_LSI_REG - DPRINTF("Write reg %s %x = %02x\n", - offset < ARRAY_SIZE(names) ? names[offset] : "???", offset, val); -#endif + trace_lsi_reg_write(offset < ARRAY_SIZE(names) ? names[offset] : "???", + offset, val); + switch (offset) { case 0x00: /* SCNTL0 */ s->scntl0 = val; if (val & LSI_SCNTL0_START) { - BADF("Start sequence not implemented\n"); + qemu_log_mask(LOG_UNIMP, + "lsi_scsi: Start sequence not implemented\n"); } break; case 0x01: /* SCNTL1 */ s->scntl1 = val & ~LSI_SCNTL1_SST; if (val & LSI_SCNTL1_IARB) { - BADF("Immediate Arbritration not implemented\n"); + qemu_log_mask(LOG_UNIMP, + "lsi_scsi: Immediate Arbritration not implemented\n"); } if (val & LSI_SCNTL1_RST) { if (!(s->sstat0 & LSI_SSTAT0_RST)) { @@ -1823,7 +1809,8 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val) break; case 0x06: /* SDID */ if ((s->ssid & 0x80) && (val & 0xf) != (s->ssid & 0xf)) { - BADF("Destination ID does not match SSID\n"); + qemu_log_mask(LOG_GUEST_ERROR, + "lsi_scsi: Destination ID does not match SSID\n"); } s->sdid = val & 0xf; break; @@ -1851,7 +1838,7 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val) lsi_update_irq(s); } if (s->waiting == 1 && val & LSI_ISTAT0_SIGP) { - DPRINTF("Woken by SIGP\n"); + trace_lsi_awoken(); s->waiting = 0; s->dsp = s->dnad; lsi_execute_script(s); @@ -1878,13 +1865,15 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val) CASE_SET_REG32(temp, 0x1c) case 0x21: /* CTEST4 */ if (val & 7) { - BADF("Unimplemented CTEST4-FBL 0x%x\n", val); + qemu_log_mask(LOG_UNIMP, + "lsi_scsi: Unimplemented CTEST4-FBL 0x%x\n", val); } s->ctest4 = val; break; case 0x22: /* CTEST5 */ if (val & (LSI_CTEST5_ADCK | LSI_CTEST5_BBCK)) { - BADF("CTEST5 DMA increment not implemented\n"); + qemu_log_mask(LOG_UNIMP, + "lsi_scsi: CTEST5 DMA increment not implemented\n"); } s->ctest5 = val; break; @@ -1941,7 +1930,8 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val) break; case 0x49: /* STIME1 */ if (val & 0xf) { - DPRINTF("General purpose timer not implemented\n"); + qemu_log_mask(LOG_UNIMP, + "lsi_scsi: General purpose timer not implemented\n"); /* ??? Raising the interrupt immediately seems to be sufficient to keep the FreeBSD driver happy. */ lsi_script_scsi_interrupt(s, 0, LSI_SIST1_GEN); @@ -1958,13 +1948,15 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val) break; case 0x4e: /* STEST2 */ if (val & 1) { - BADF("Low level mode not implemented\n"); + qemu_log_mask(LOG_UNIMP, + "lsi_scsi: Low level mode not implemented\n"); } s->stest2 = val; break; case 0x4f: /* STEST3 */ if (val & 0x41) { - BADF("SCSI FIFO test mode not implemented\n"); + qemu_log_mask(LOG_UNIMP, + "lsi_scsi: SCSI FIFO test mode not implemented\n"); } s->stest3 = val; break; diff --git a/hw/scsi/mptendian.c b/hw/scsi/mptendian.c index 8ae39a76f4..79f99734d2 100644 --- a/hw/scsi/mptendian.c +++ b/hw/scsi/mptendian.c @@ -35,152 +35,155 @@ static void mptsas_fix_sgentry_endianness(MPISGEntry *sge) { - le32_to_cpus(&sge->FlagsLength); + sge->FlagsLength = le32_to_cpu(sge->FlagsLength); if (sge->FlagsLength & MPI_SGE_FLAGS_64_BIT_ADDRESSING) { - le64_to_cpus(&sge->u.Address64); + sge->u.Address64 = le64_to_cpu(sge->u.Address64); } else { - le32_to_cpus(&sge->u.Address32); + sge->u.Address32 = le32_to_cpu(sge->u.Address32); } } static void mptsas_fix_sgentry_endianness_reply(MPISGEntry *sge) { if (sge->FlagsLength & MPI_SGE_FLAGS_64_BIT_ADDRESSING) { - cpu_to_le64s(&sge->u.Address64); + sge->u.Address64 = cpu_to_le64(sge->u.Address64); } else { - cpu_to_le32s(&sge->u.Address32); + sge->u.Address32 = cpu_to_le32(sge->u.Address32); } - cpu_to_le32s(&sge->FlagsLength); + sge->FlagsLength = cpu_to_le32(sge->FlagsLength); } void mptsas_fix_scsi_io_endianness(MPIMsgSCSIIORequest *req) { - le32_to_cpus(&req->MsgContext); - le32_to_cpus(&req->Control); - le32_to_cpus(&req->DataLength); - le32_to_cpus(&req->SenseBufferLowAddr); + req->MsgContext = le32_to_cpu(req->MsgContext); + req->Control = le32_to_cpu(req->Control); + req->DataLength = le32_to_cpu(req->DataLength); + req->SenseBufferLowAddr = le32_to_cpu(req->SenseBufferLowAddr); } void mptsas_fix_scsi_io_reply_endianness(MPIMsgSCSIIOReply *reply) { - cpu_to_le32s(&reply->MsgContext); - cpu_to_le16s(&reply->IOCStatus); - cpu_to_le32s(&reply->IOCLogInfo); - cpu_to_le32s(&reply->TransferCount); - cpu_to_le32s(&reply->SenseCount); - cpu_to_le32s(&reply->ResponseInfo); - cpu_to_le16s(&reply->TaskTag); + reply->MsgContext = cpu_to_le32(reply->MsgContext); + reply->IOCStatus = cpu_to_le16(reply->IOCStatus); + reply->IOCLogInfo = cpu_to_le32(reply->IOCLogInfo); + reply->TransferCount = cpu_to_le32(reply->TransferCount); + reply->SenseCount = cpu_to_le32(reply->SenseCount); + reply->ResponseInfo = cpu_to_le32(reply->ResponseInfo); + reply->TaskTag = cpu_to_le16(reply->TaskTag); } void mptsas_fix_scsi_task_mgmt_endianness(MPIMsgSCSITaskMgmt *req) { - le32_to_cpus(&req->MsgContext); - le32_to_cpus(&req->TaskMsgContext); + req->MsgContext = le32_to_cpu(req->MsgContext); + req->TaskMsgContext = le32_to_cpu(req->TaskMsgContext); } void mptsas_fix_scsi_task_mgmt_reply_endianness(MPIMsgSCSITaskMgmtReply *reply) { - cpu_to_le32s(&reply->MsgContext); - cpu_to_le16s(&reply->IOCStatus); - cpu_to_le32s(&reply->IOCLogInfo); - cpu_to_le32s(&reply->TerminationCount); + reply->MsgContext = cpu_to_le32(reply->MsgContext); + reply->IOCStatus = cpu_to_le16(reply->IOCStatus); + reply->IOCLogInfo = cpu_to_le32(reply->IOCLogInfo); + reply->TerminationCount = cpu_to_le32(reply->TerminationCount); } void mptsas_fix_ioc_init_endianness(MPIMsgIOCInit *req) { - le32_to_cpus(&req->MsgContext); - le16_to_cpus(&req->ReplyFrameSize); - le32_to_cpus(&req->HostMfaHighAddr); - le32_to_cpus(&req->SenseBufferHighAddr); - le32_to_cpus(&req->ReplyFifoHostSignalingAddr); + req->MsgContext = le32_to_cpu(req->MsgContext); + req->ReplyFrameSize = le16_to_cpu(req->ReplyFrameSize); + req->HostMfaHighAddr = le32_to_cpu(req->HostMfaHighAddr); + req->SenseBufferHighAddr = le32_to_cpu(req->SenseBufferHighAddr); + req->ReplyFifoHostSignalingAddr = + le32_to_cpu(req->ReplyFifoHostSignalingAddr); mptsas_fix_sgentry_endianness(&req->HostPageBufferSGE); - le16_to_cpus(&req->MsgVersion); - le16_to_cpus(&req->HeaderVersion); + req->MsgVersion = le16_to_cpu(req->MsgVersion); + req->HeaderVersion = le16_to_cpu(req->HeaderVersion); } void mptsas_fix_ioc_init_reply_endianness(MPIMsgIOCInitReply *reply) { - cpu_to_le32s(&reply->MsgContext); - cpu_to_le16s(&reply->IOCStatus); - cpu_to_le32s(&reply->IOCLogInfo); + reply->MsgContext = cpu_to_le32(reply->MsgContext); + reply->IOCStatus = cpu_to_le16(reply->IOCStatus); + reply->IOCLogInfo = cpu_to_le32(reply->IOCLogInfo); } void mptsas_fix_ioc_facts_endianness(MPIMsgIOCFacts *req) { - le32_to_cpus(&req->MsgContext); + req->MsgContext = le32_to_cpu(req->MsgContext); } void mptsas_fix_ioc_facts_reply_endianness(MPIMsgIOCFactsReply *reply) { - cpu_to_le16s(&reply->MsgVersion); - cpu_to_le16s(&reply->HeaderVersion); - cpu_to_le32s(&reply->MsgContext); - cpu_to_le16s(&reply->IOCExceptions); - cpu_to_le16s(&reply->IOCStatus); - cpu_to_le32s(&reply->IOCLogInfo); - cpu_to_le16s(&reply->ReplyQueueDepth); - cpu_to_le16s(&reply->RequestFrameSize); - cpu_to_le16s(&reply->ProductID); - cpu_to_le32s(&reply->CurrentHostMfaHighAddr); - cpu_to_le16s(&reply->GlobalCredits); - cpu_to_le32s(&reply->CurrentSenseBufferHighAddr); - cpu_to_le16s(&reply->CurReplyFrameSize); - cpu_to_le32s(&reply->FWImageSize); - cpu_to_le32s(&reply->IOCCapabilities); - cpu_to_le16s(&reply->HighPriorityQueueDepth); + reply->MsgVersion = cpu_to_le16(reply->MsgVersion); + reply->HeaderVersion = cpu_to_le16(reply->HeaderVersion); + reply->MsgContext = cpu_to_le32(reply->MsgContext); + reply->IOCExceptions = cpu_to_le16(reply->IOCExceptions); + reply->IOCStatus = cpu_to_le16(reply->IOCStatus); + reply->IOCLogInfo = cpu_to_le32(reply->IOCLogInfo); + reply->ReplyQueueDepth = cpu_to_le16(reply->ReplyQueueDepth); + reply->RequestFrameSize = cpu_to_le16(reply->RequestFrameSize); + reply->ProductID = cpu_to_le16(reply->ProductID); + reply->CurrentHostMfaHighAddr = cpu_to_le32(reply->CurrentHostMfaHighAddr); + reply->GlobalCredits = cpu_to_le16(reply->GlobalCredits); + reply->CurrentSenseBufferHighAddr = + cpu_to_le32(reply->CurrentSenseBufferHighAddr); + reply->CurReplyFrameSize = cpu_to_le16(reply->CurReplyFrameSize); + reply->FWImageSize = cpu_to_le32(reply->FWImageSize); + reply->IOCCapabilities = cpu_to_le32(reply->IOCCapabilities); + reply->HighPriorityQueueDepth = cpu_to_le16(reply->HighPriorityQueueDepth); mptsas_fix_sgentry_endianness_reply(&reply->HostPageBufferSGE); - cpu_to_le32s(&reply->ReplyFifoHostSignalingAddr); + reply->ReplyFifoHostSignalingAddr = + cpu_to_le32(reply->ReplyFifoHostSignalingAddr); } void mptsas_fix_config_endianness(MPIMsgConfig *req) { - le16_to_cpus(&req->ExtPageLength); - le32_to_cpus(&req->MsgContext); - le32_to_cpus(&req->PageAddress); + req->ExtPageLength = le16_to_cpu(req->ExtPageLength); + req->MsgContext = le32_to_cpu(req->MsgContext); + req->PageAddress = le32_to_cpu(req->PageAddress); mptsas_fix_sgentry_endianness(&req->PageBufferSGE); } void mptsas_fix_config_reply_endianness(MPIMsgConfigReply *reply) { - cpu_to_le16s(&reply->ExtPageLength); - cpu_to_le32s(&reply->MsgContext); - cpu_to_le16s(&reply->IOCStatus); - cpu_to_le32s(&reply->IOCLogInfo); + reply->ExtPageLength = cpu_to_le16(reply->ExtPageLength); + reply->MsgContext = cpu_to_le32(reply->MsgContext); + reply->IOCStatus = cpu_to_le16(reply->IOCStatus); + reply->IOCLogInfo = cpu_to_le32(reply->IOCLogInfo); } void mptsas_fix_port_facts_endianness(MPIMsgPortFacts *req) { - le32_to_cpus(&req->MsgContext); + req->MsgContext = le32_to_cpu(req->MsgContext); } void mptsas_fix_port_facts_reply_endianness(MPIMsgPortFactsReply *reply) { - cpu_to_le32s(&reply->MsgContext); - cpu_to_le16s(&reply->IOCStatus); - cpu_to_le32s(&reply->IOCLogInfo); - cpu_to_le16s(&reply->MaxDevices); - cpu_to_le16s(&reply->PortSCSIID); - cpu_to_le16s(&reply->ProtocolFlags); - cpu_to_le16s(&reply->MaxPostedCmdBuffers); - cpu_to_le16s(&reply->MaxPersistentIDs); - cpu_to_le16s(&reply->MaxLanBuckets); + reply->MsgContext = cpu_to_le32(reply->MsgContext); + reply->IOCStatus = cpu_to_le16(reply->IOCStatus); + reply->IOCLogInfo = cpu_to_le32(reply->IOCLogInfo); + reply->MaxDevices = cpu_to_le16(reply->MaxDevices); + reply->PortSCSIID = cpu_to_le16(reply->PortSCSIID); + reply->ProtocolFlags = cpu_to_le16(reply->ProtocolFlags); + reply->MaxPostedCmdBuffers = cpu_to_le16(reply->MaxPostedCmdBuffers); + reply->MaxPersistentIDs = cpu_to_le16(reply->MaxPersistentIDs); + reply->MaxLanBuckets = cpu_to_le16(reply->MaxLanBuckets); } void mptsas_fix_port_enable_endianness(MPIMsgPortEnable *req) { - le32_to_cpus(&req->MsgContext); + req->MsgContext = le32_to_cpu(req->MsgContext); } void mptsas_fix_port_enable_reply_endianness(MPIMsgPortEnableReply *reply) { - cpu_to_le32s(&reply->MsgContext); - cpu_to_le16s(&reply->IOCStatus); - cpu_to_le32s(&reply->IOCLogInfo); + reply->MsgContext = cpu_to_le32(reply->MsgContext); + reply->IOCStatus = cpu_to_le16(reply->IOCStatus); + reply->IOCLogInfo = cpu_to_le32(reply->IOCLogInfo); } void mptsas_fix_event_notification_endianness(MPIMsgEventNotify *req) { - le32_to_cpus(&req->MsgContext); + req->MsgContext = le32_to_cpu(req->MsgContext); } void mptsas_fix_event_notification_reply_endianness(MPIMsgEventNotifyReply *reply) @@ -188,16 +191,16 @@ void mptsas_fix_event_notification_reply_endianness(MPIMsgEventNotifyReply *repl int length = reply->EventDataLength; int i; - cpu_to_le16s(&reply->EventDataLength); - cpu_to_le32s(&reply->MsgContext); - cpu_to_le16s(&reply->IOCStatus); - cpu_to_le32s(&reply->IOCLogInfo); - cpu_to_le32s(&reply->Event); - cpu_to_le32s(&reply->EventContext); + reply->EventDataLength = cpu_to_le16(reply->EventDataLength); + reply->MsgContext = cpu_to_le32(reply->MsgContext); + reply->IOCStatus = cpu_to_le16(reply->IOCStatus); + reply->IOCLogInfo = cpu_to_le32(reply->IOCLogInfo); + reply->Event = cpu_to_le32(reply->Event); + reply->EventContext = cpu_to_le32(reply->EventContext); /* Really depends on the event kind. This will do for now. */ for (i = 0; i < length; i++) { - cpu_to_le32s(&reply->Data[i]); + reply->Data[i] = cpu_to_le32(reply->Data[i]); } } diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 5ae7baa082..c43163cef4 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -2610,6 +2610,12 @@ static void scsi_block_realize(SCSIDevice *dev, Error **errp) return; } + if (s->rotation_rate) { + error_report_once("rotation_rate is specified for scsi-block but is " + "not implemented. This option is deprecated and will " + "be removed in a future version"); + } + /* check we are using a driver managing SG_IO (version 3 and after) */ rc = blk_ioctl(s->qdev.conf.blk, SG_GET_VERSION_NUM, &sg_version); if (rc < 0) { diff --git a/hw/scsi/trace-events b/hw/scsi/trace-events index 6e299d0338..0fb6a99616 100644 --- a/hw/scsi/trace-events +++ b/hw/scsi/trace-events @@ -229,3 +229,65 @@ spapr_vscsi_process_login(void) "Got login, sending response !" spapr_vscsi_queue_cmd_no_drive(uint64_t lun) "Command for lun 0x%08" PRIx64 " with no drive" spapr_vscsi_queue_cmd(uint32_t qtag, unsigned cdb, const char *cmd, int lun, int ret) "Queued command tag 0x%"PRIx32" CMD 0x%x=%s LUN %d ret: %d" spapr_vscsi_do_crq(unsigned c0, unsigned c1) "crq: %02x %02x ..." + +# hw/scsi/lsi53c895a.c +lsi_reset(void) "Reset" +lsi_update_irq(int level, uint8_t dstat, uint8_t sist1, uint8_t sist0) "Update IRQ level %d dstat 0x%02x sist 0x%02x0x%02x" +lsi_update_irq_disconnected(void) "Handled IRQs & disconnected, looking for pending processes" +lsi_script_scsi_interrupt(uint8_t stat1, uint8_t stat0, uint8_t sist1, uint8_t sist0) "SCSI Interrupt 0x%02x0x%02x prev 0x%02x0x%02x" +lsi_script_dma_interrupt(uint8_t stat, uint8_t dstat) "DMA Interrupt 0x%x prev 0x%x" +lsi_bad_phase_jump(uint32_t dsp) "Data phase mismatch jump to 0x%"PRIX32 +lsi_bad_phase_interrupt(void) "Phase mismatch interrupt" +lsi_bad_selection(uint32_t id) "Selected absent target %"PRIu32 +lsi_do_dma_unavailable(void) "DMA no data available" +lsi_do_dma(uint64_t addr, int len) "DMA addr=0x%"PRIx64" len=%d" +lsi_queue_command(uint32_t tag) "Queueing tag=0x%"PRId32 +lsi_add_msg_byte_error(void) "MSG IN data too long" +lsi_add_msg_byte(uint8_t data) "MSG IN 0x%02x" +lsi_reselect(int id) "Reselected target %d" +lsi_queue_req_error(void *p) "Multiple IO pending for request %p" +lsi_queue_req(uint32_t tag) "Queueing IO tag=0x%"PRIx32 +lsi_command_complete(uint32_t status) "Command complete status=%"PRId32 +lsi_transfer_data(uint32_t tag, uint32_t len) "Data ready tag=0x%"PRIx32" len=%"PRId32 +lsi_do_command(uint32_t dbc) "Send command len=%"PRId32 +lsi_do_status(uint32_t dbc, uint8_t status) "Get status len=%"PRId32" status=%d" +lsi_do_status_error(void) "Bad Status move" +lsi_do_msgin(uint32_t dbc, int len) "Message in len=%"PRId32" %d" +lsi_do_msgout(uint32_t dbc) "MSG out len=%"PRId32 +lsi_do_msgout_disconnect(void) "MSG: Disconnect" +lsi_do_msgout_noop(void) "MSG: No Operation" +lsi_do_msgout_extended(uint8_t msg, uint8_t len) "Extended message 0x%x (len %d)" +lsi_do_msgout_ignored(const char *msg) "%s (ignored)" +lsi_do_msgout_simplequeue(uint8_t select_tag) "SIMPLE queue tag=0x%x" +lsi_do_msgout_abort(uint32_t tag) "MSG: ABORT TAG tag=0x%"PRId32 +lsi_do_msgout_clearqueue(uint32_t tag) "MSG: CLEAR QUEUE tag=0x%"PRIx32 +lsi_do_msgout_busdevicereset(uint32_t tag) "MSG: BUS DEVICE RESET tag=0x%"PRIx32 +lsi_do_msgout_select(int id) "Select LUN %d" +lsi_memcpy(uint32_t dest, uint32_t src, int count) "memcpy dest 0x%"PRIx32" src 0x%"PRIx32" count %d" +lsi_wait_reselect(void) "Wait Reselect" +lsi_execute_script(uint32_t dsp, uint32_t insn, uint32_t addr) "SCRIPTS dsp=0x%"PRIx32" opcode 0x%"PRIx32" arg 0x%"PRIx32 +lsi_execute_script_blockmove_delayed(void) "Delayed select timeout" +lsi_execute_script_blockmove_badphase(uint8_t phase, uint8_t expected) "Wrong phase got %d expected %d" +lsi_execute_script_io_alreadyreselected(void) "Already reselected, jumping to alternative address" +lsi_execute_script_io_selected(uint8_t id, const char *atn) "Selected target %d%s" +lsi_execute_script_io_disconnect(void) "Wait Disconnect" +lsi_execute_script_io_set(const char *atn, const char *ack, const char *tm, const char *cc) "Set%s%s%s%s" +lsi_execute_script_io_clear(const char *atn, const char *ack, const char *tm, const char *cc) "Clear%s%s%s%s" +lsi_execute_script_io_opcode(const char *opcode, int reg, const char *opname, uint8_t data8, uint32_t sfbr, const char *ssfbr) "%s reg 0x%x %s data8=0x%02x sfbr=0x%02x%s" +lsi_execute_script_tc_nop(void) "NOP" +lsi_execute_script_tc_delayedselect_timeout(void) "Delayed select timeout" +lsi_execute_script_tc_compc(int result) "Compare carry %d" +lsi_execute_script_tc_compp(uint8_t phase, int op, uint8_t insn_phase) "Compare phase %d %c= %d" +lsi_execute_script_tc_compd(uint32_t sfbr, uint8_t mask, int op, int result) "Compare data 0x%"PRIx32" & 0x%x %c= 0x%x" +lsi_execute_script_tc_jump(uint32_t addr) "Jump to 0x%"PRIx32 +lsi_execute_script_tc_call(uint32_t addr) "Call 0x%"PRIx32 +lsi_execute_script_tc_return(uint32_t addr) "Return to 0x%"PRIx32 +lsi_execute_script_tc_interrupt(uint32_t addr) "Interrupt 0x%"PRIx32 +lsi_execute_script_tc_illegal(void) "Illegal transfer control" +lsi_execute_script_tc_cc_failed(void) "Control condition failed" +lsi_execute_script_mm_load(int reg, int n, uint32_t addr, int data) "Load reg 0x%x size %d addr 0x%"PRIx32" = 0x%08x" +lsi_execute_script_mm_store(int reg, int n, uint32_t addr) "Store reg 0x%x size %d addr 0x%"PRIx32 +lsi_execute_script_stop(void) "SCRIPTS execution stopped" +lsi_awoken(void) "Woken by SIGP" +lsi_reg_read(const char *name, int offset, uint8_t ret) "Read reg %s 0x%x = 0x%02x" +lsi_reg_write(const char *name, int offset, uint8_t val) "Write reg %s 0x%x = 0x%02x" diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index f6a588ab57..94f5c8e52a 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -358,6 +358,10 @@ int virtio_queue_ready(VirtQueue *vq) * Called within rcu_read_lock(). */ static int virtio_queue_empty_rcu(VirtQueue *vq) { + if (unlikely(vq->vdev->broken)) { + return 1; + } + if (unlikely(!vq->vring.avail)) { return 1; } @@ -373,6 +377,10 @@ int virtio_queue_empty(VirtQueue *vq) { bool empty; + if (unlikely(vq->vdev->broken)) { + return 1; + } + if (unlikely(!vq->vring.avail)) { return 1; } diff --git a/include/exec/memory.h b/include/exec/memory.h index eb4f2fb249..3a427aacf1 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -201,11 +201,6 @@ struct MemoryRegionOps { */ bool unaligned; } impl; - - /* If .read and .write are not present, old_mmio may be used for - * backwards compatibility with old mmio registration - */ - const MemoryRegionMmio old_mmio; }; enum IOMMUMemoryRegionAttr { @@ -633,7 +628,7 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr, uint64_t length, void *host), Error **errp); -#ifdef __linux__ +#ifdef CONFIG_POSIX /** * memory_region_init_ram_from_file: Initialize RAM memory region with a diff --git a/include/hw/loader.h b/include/hw/loader.h index 3c112975f4..67a0af84ac 100644 --- a/include/hw/loader.h +++ b/include/hw/loader.h @@ -10,7 +10,7 @@ * Returns the size of the image file on success, -1 otherwise. * On error, errno is also set as appropriate. */ -int get_image_size(const char *filename); +int64_t get_image_size(const char *filename); int load_image(const char *filename, uint8_t *addr); /* deprecated */ ssize_t load_image_size(const char *filename, void *addr, size_t size); diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h index 9ed39effd3..f6993a8fb1 100644 --- a/include/qemu/atomic.h +++ b/include/qemu/atomic.h @@ -98,7 +98,7 @@ * We'd prefer not want to pull in everything else TCG related, so handle * those few cases by hand. * - * Note that x32 is fully detected with __x64_64__ + _ILP32, and that for + * Note that x32 is fully detected with __x86_64__ + _ILP32, and that for * Sparc we always force the use of sparcv9 in configure. */ #if defined(__x86_64__) || defined(__sparc__) @@ -450,4 +450,38 @@ _oldn; \ }) +/* Abstractions to access atomically (i.e. "once") i64/u64 variables */ +#ifdef CONFIG_ATOMIC64 +static inline int64_t atomic_read_i64(const int64_t *ptr) +{ + /* use __nocheck because sizeof(void *) might be < sizeof(u64) */ + return atomic_read__nocheck(ptr); +} + +static inline uint64_t atomic_read_u64(const uint64_t *ptr) +{ + return atomic_read__nocheck(ptr); +} + +static inline void atomic_set_i64(int64_t *ptr, int64_t val) +{ + atomic_set__nocheck(ptr, val); +} + +static inline void atomic_set_u64(uint64_t *ptr, uint64_t val) +{ + atomic_set__nocheck(ptr, val); +} + +static inline void atomic64_init(void) +{ +} +#else /* !CONFIG_ATOMIC64 */ +int64_t atomic_read_i64(const int64_t *ptr); +uint64_t atomic_read_u64(const uint64_t *ptr); +void atomic_set_i64(int64_t *ptr, int64_t val); +void atomic_set_u64(uint64_t *ptr, uint64_t val); +void atomic64_init(void); +#endif /* !CONFIG_ATOMIC64 */ + #endif /* QEMU_ATOMIC_H */ diff --git a/include/qemu/memfd.h b/include/qemu/memfd.h index 49e79634da..d551c28b68 100644 --- a/include/qemu/memfd.h +++ b/include/qemu/memfd.h @@ -16,12 +16,28 @@ #define F_SEAL_WRITE 0x0008 /* prevent writes */ #endif +#ifndef MFD_CLOEXEC +#define MFD_CLOEXEC 0x0001U +#endif + +#ifndef MFD_ALLOW_SEALING +#define MFD_ALLOW_SEALING 0x0002U +#endif + +#ifndef MFD_HUGETLB +#define MFD_HUGETLB 0x0004U +#endif + +#ifndef MFD_HUGE_SHIFT +#define MFD_HUGE_SHIFT 26 +#endif + int qemu_memfd_create(const char *name, size_t size, bool hugetlb, uint64_t hugetlbsize, unsigned int seals, Error **errp); bool qemu_memfd_alloc_check(void); void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals, int *fd, Error **errp); void qemu_memfd_free(void *ptr, size_t size, int fd); -bool qemu_memfd_check(void); +bool qemu_memfd_check(unsigned int flags); #endif /* QEMU_MEMFD_H */ diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index a91068df0e..4f8559e550 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -448,7 +448,8 @@ bool qemu_has_ofd_lock(void); #define FMT_pid "%d" #endif -int qemu_create_pidfile(const char *filename); +bool qemu_write_pidfile(const char *pidfile, Error **errp); + int qemu_get_thread_id(void); #ifndef CONFIG_IOVEC @@ -570,6 +571,8 @@ extern uintptr_t qemu_real_host_page_size; extern intptr_t qemu_real_host_page_mask; extern int qemu_icache_linesize; +extern int qemu_icache_linesize_log; extern int qemu_dcache_linesize; +extern int qemu_dcache_linesize_log; #endif diff --git a/include/qemu/thread.h b/include/qemu/thread.h index dacebcfff0..b2661b6672 100644 --- a/include/qemu/thread.h +++ b/include/qemu/thread.h @@ -48,6 +48,22 @@ extern QemuCondWaitFunc qemu_cond_wait_func; #define qemu_mutex_trylock__raw(m) \ qemu_mutex_trylock_impl(m, __FILE__, __LINE__) +#ifdef __COVERITY__ +/* + * Coverity is severely confused by the indirect function calls, + * hide them. + */ +#define qemu_mutex_lock(m) \ + qemu_mutex_lock_impl(m, __FILE__, __LINE__); +#define qemu_mutex_trylock(m) \ + qemu_mutex_trylock_impl(m, __FILE__, __LINE__); +#define qemu_rec_mutex_lock(m) \ + qemu_rec_mutex_lock_impl(m, __FILE__, __LINE__); +#define qemu_rec_mutex_trylock(m) \ + qemu_rec_mutex_trylock_impl(m, __FILE__, __LINE__); +#define qemu_cond_wait(c, m) \ + qemu_cond_wait_impl(c, m, __FILE__, __LINE__); +#else #define qemu_mutex_lock(m) ({ \ QemuMutexLockFunc _f = atomic_read(&qemu_mutex_lock_func); \ _f(m, __FILE__, __LINE__); \ @@ -73,6 +89,7 @@ extern QemuCondWaitFunc qemu_cond_wait_func; QemuCondWaitFunc _f = atomic_read(&qemu_cond_wait_func); \ _f(c, m, __FILE__, __LINE__); \ }) +#endif #define qemu_mutex_unlock(mutex) \ qemu_mutex_unlock_impl(mutex, __FILE__, __LINE__) diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 39ea907e65..a005ed2692 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -42,6 +42,14 @@ * In icount mode, this clock counts nanoseconds while the virtual * machine is running. It is used to increase @QEMU_CLOCK_VIRTUAL * while the CPUs are sleeping and thus not executing instructions. + * + * @QEMU_CLOCK_VIRTUAL_EXT: virtual clock for external subsystems + * + * The virtual clock only runs during the emulation. It stops + * when the virtual machine is stopped. The timers for this clock + * do not recorded in rr mode, therefore this clock could be used + * for the subsystems that operate outside the guest core. + * */ typedef enum { @@ -49,6 +57,7 @@ typedef enum { QEMU_CLOCK_VIRTUAL = 1, QEMU_CLOCK_HOST = 2, QEMU_CLOCK_VIRTUAL_RT = 3, + QEMU_CLOCK_VIRTUAL_EXT = 4, QEMU_CLOCK_MAX } QEMUClockType; diff --git a/include/qemu/win_dump_defs.h b/include/qemu/win_dump_defs.h new file mode 100644 index 0000000000..145096e8ee --- /dev/null +++ b/include/qemu/win_dump_defs.h @@ -0,0 +1,179 @@ +/* + * Windows crashdump definitions + * + * Copyright (c) 2018 Virtuozzo International GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef QEMU_WIN_DUMP_DEFS_H +#define QEMU_WIN_DUMP_DEFS_H + +typedef struct WinDumpPhyMemRun64 { + uint64_t BasePage; + uint64_t PageCount; +} QEMU_PACKED WinDumpPhyMemRun64; + +typedef struct WinDumpPhyMemDesc64 { + uint32_t NumberOfRuns; + uint32_t unused; + uint64_t NumberOfPages; + WinDumpPhyMemRun64 Run[43]; +} QEMU_PACKED WinDumpPhyMemDesc64; + +typedef struct WinDumpExceptionRecord { + uint32_t ExceptionCode; + uint32_t ExceptionFlags; + uint64_t ExceptionRecord; + uint64_t ExceptionAddress; + uint32_t NumberParameters; + uint32_t unused; + uint64_t ExceptionInformation[15]; +} QEMU_PACKED WinDumpExceptionRecord; + +typedef struct WinDumpHeader64 { + char Signature[4]; + char ValidDump[4]; + uint32_t MajorVersion; + uint32_t MinorVersion; + uint64_t DirectoryTableBase; + uint64_t PfnDatabase; + uint64_t PsLoadedModuleList; + uint64_t PsActiveProcessHead; + uint32_t MachineImageType; + uint32_t NumberProcessors; + union { + struct { + uint32_t BugcheckCode; + uint32_t unused0; + uint64_t BugcheckParameter1; + uint64_t BugcheckParameter2; + uint64_t BugcheckParameter3; + uint64_t BugcheckParameter4; + }; + uint8_t BugcheckData[40]; + }; + uint8_t VersionUser[32]; + uint64_t KdDebuggerDataBlock; + union { + WinDumpPhyMemDesc64 PhysicalMemoryBlock; + uint8_t PhysicalMemoryBlockBuffer[704]; + }; + union { + uint8_t ContextBuffer[3000]; + }; + WinDumpExceptionRecord Exception; + uint32_t DumpType; + uint32_t unused1; + uint64_t RequiredDumpSpace; + uint64_t SystemTime; + char Comment[128]; + uint64_t SystemUpTime; + uint32_t MiniDumpFields; + uint32_t SecondaryDataState; + uint32_t ProductType; + uint32_t SuiteMask; + uint32_t WriterStatus; + uint8_t unused2; + uint8_t KdSecondaryVersion; + uint8_t reserved[4018]; +} QEMU_PACKED WinDumpHeader64; + +#define KDBG_OWNER_TAG_OFFSET64 0x10 +#define KDBG_MM_PFN_DATABASE_OFFSET64 0xC0 +#define KDBG_KI_BUGCHECK_DATA_OFFSET64 0x88 +#define KDBG_KI_PROCESSOR_BLOCK_OFFSET64 0x218 +#define KDBG_OFFSET_PRCB_CONTEXT_OFFSET64 0x338 + +#define VMCOREINFO_ELF_NOTE_HDR_SIZE 24 + +#define WIN_CTX_X64 0x00100000L + +#define WIN_CTX_CTL 0x00000001L +#define WIN_CTX_INT 0x00000002L +#define WIN_CTX_SEG 0x00000004L +#define WIN_CTX_FP 0x00000008L +#define WIN_CTX_DBG 0x00000010L + +#define WIN_CTX_FULL (WIN_CTX_X64 | WIN_CTX_CTL | WIN_CTX_INT | WIN_CTX_FP) +#define WIN_CTX_ALL (WIN_CTX_FULL | WIN_CTX_SEG | WIN_CTX_DBG) + +#define LIVE_SYSTEM_DUMP 0x00000161 + +typedef struct WinM128A { + uint64_t low; + int64_t high; +} QEMU_ALIGNED(16) WinM128A; + +typedef struct WinContext { + uint64_t PHome[6]; + + uint32_t ContextFlags; + uint32_t MxCsr; + + uint16_t SegCs; + uint16_t SegDs; + uint16_t SegEs; + uint16_t SegFs; + uint16_t SegGs; + uint16_t SegSs; + uint32_t EFlags; + + uint64_t Dr0; + uint64_t Dr1; + uint64_t Dr2; + uint64_t Dr3; + uint64_t Dr6; + uint64_t Dr7; + + uint64_t Rax; + uint64_t Rcx; + uint64_t Rdx; + uint64_t Rbx; + uint64_t Rsp; + uint64_t Rbp; + uint64_t Rsi; + uint64_t Rdi; + uint64_t R8; + uint64_t R9; + uint64_t R10; + uint64_t R11; + uint64_t R12; + uint64_t R13; + uint64_t R14; + uint64_t R15; + + uint64_t Rip; + + struct { + uint16_t ControlWord; + uint16_t StatusWord; + uint8_t TagWord; + uint8_t Reserved1; + uint16_t ErrorOpcode; + uint32_t ErrorOffset; + uint16_t ErrorSelector; + uint16_t Reserved2; + uint32_t DataOffset; + uint16_t DataSelector; + uint16_t Reserved3; + uint32_t MxCsr; + uint32_t MxCsr_Mask; + WinM128A FloatRegisters[8]; + WinM128A XmmRegisters[16]; + uint8_t Reserved4[96]; + } FltSave; + + WinM128A VectorRegister[26]; + uint64_t VectorControl; + + uint64_t DebugControl; + uint64_t LastBranchToRip; + uint64_t LastBranchFromRip; + uint64_t LastExceptionToRip; + uint64_t LastExceptionFromRip; +} QEMU_ALIGNED(16) WinContext; + +#endif /* QEMU_WIN_DUMP_DEFS_H */ diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h index 3ced6bc231..7f7a594eca 100644 --- a/include/sysemu/replay.h +++ b/include/sysemu/replay.h @@ -120,6 +120,9 @@ void replay_shutdown_request(ShutdownCause cause); Returns 0 in PLAY mode if checkpoint was not found. Returns 1 in all other cases. */ bool replay_checkpoint(ReplayCheckpoint checkpoint); +/*! Used to determine that checkpoint is pending. + Does not proceed to the next event in the log. */ +bool replay_has_checkpoint(void); /* Asynchronous events queue */ diff --git a/memory.c b/memory.c index 9b73892768..d852f1143d 100644 --- a/memory.c +++ b/memory.c @@ -374,6 +374,33 @@ static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size) } } +static inline void memory_region_shift_read_access(uint64_t *value, + signed shift, + uint64_t mask, + uint64_t tmp) +{ + if (shift >= 0) { + *value |= (tmp & mask) << shift; + } else { + *value |= (tmp & mask) >> -shift; + } +} + +static inline uint64_t memory_region_shift_write_access(uint64_t *value, + signed shift, + uint64_t mask) +{ + uint64_t tmp; + + if (shift >= 0) { + tmp = (*value >> shift) & mask; + } else { + tmp = (*value << -shift) & mask; + } + + return tmp; +} + static hwaddr memory_region_to_absolute_addr(MemoryRegion *mr, hwaddr offset) { MemoryRegion *root; @@ -396,37 +423,11 @@ static int get_cpu_index(void) return -1; } -static MemTxResult memory_region_oldmmio_read_accessor(MemoryRegion *mr, - hwaddr addr, - uint64_t *value, - unsigned size, - unsigned shift, - uint64_t mask, - MemTxAttrs attrs) -{ - uint64_t tmp; - - tmp = mr->ops->old_mmio.read[ctz32(size)](mr->opaque, addr); - if (mr->subpage) { - trace_memory_region_subpage_read(get_cpu_index(), mr, addr, tmp, size); - } else if (mr == &io_mem_notdirty) { - /* Accesses to code which has previously been translated into a TB show - * up in the MMIO path, as accesses to the io_mem_notdirty - * MemoryRegion. */ - trace_memory_region_tb_read(get_cpu_index(), addr, tmp, size); - } else if (TRACE_MEMORY_REGION_OPS_READ_ENABLED) { - hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr); - trace_memory_region_ops_read(get_cpu_index(), mr, abs_addr, tmp, size); - } - *value |= (tmp & mask) << shift; - return MEMTX_OK; -} - static MemTxResult memory_region_read_accessor(MemoryRegion *mr, hwaddr addr, uint64_t *value, unsigned size, - unsigned shift, + signed shift, uint64_t mask, MemTxAttrs attrs) { @@ -444,7 +445,7 @@ static MemTxResult memory_region_read_accessor(MemoryRegion *mr, hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr); trace_memory_region_ops_read(get_cpu_index(), mr, abs_addr, tmp, size); } - *value |= (tmp & mask) << shift; + memory_region_shift_read_access(value, shift, mask, tmp); return MEMTX_OK; } @@ -452,7 +453,7 @@ static MemTxResult memory_region_read_with_attrs_accessor(MemoryRegion *mr, hwaddr addr, uint64_t *value, unsigned size, - unsigned shift, + signed shift, uint64_t mask, MemTxAttrs attrs) { @@ -471,47 +472,20 @@ static MemTxResult memory_region_read_with_attrs_accessor(MemoryRegion *mr, hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr); trace_memory_region_ops_read(get_cpu_index(), mr, abs_addr, tmp, size); } - *value |= (tmp & mask) << shift; + memory_region_shift_read_access(value, shift, mask, tmp); return r; } -static MemTxResult memory_region_oldmmio_write_accessor(MemoryRegion *mr, - hwaddr addr, - uint64_t *value, - unsigned size, - unsigned shift, - uint64_t mask, - MemTxAttrs attrs) -{ - uint64_t tmp; - - tmp = (*value >> shift) & mask; - if (mr->subpage) { - trace_memory_region_subpage_write(get_cpu_index(), mr, addr, tmp, size); - } else if (mr == &io_mem_notdirty) { - /* Accesses to code which has previously been translated into a TB show - * up in the MMIO path, as accesses to the io_mem_notdirty - * MemoryRegion. */ - trace_memory_region_tb_write(get_cpu_index(), addr, tmp, size); - } else if (TRACE_MEMORY_REGION_OPS_WRITE_ENABLED) { - hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr); - trace_memory_region_ops_write(get_cpu_index(), mr, abs_addr, tmp, size); - } - mr->ops->old_mmio.write[ctz32(size)](mr->opaque, addr, tmp); - return MEMTX_OK; -} - static MemTxResult memory_region_write_accessor(MemoryRegion *mr, hwaddr addr, uint64_t *value, unsigned size, - unsigned shift, + signed shift, uint64_t mask, MemTxAttrs attrs) { - uint64_t tmp; + uint64_t tmp = memory_region_shift_write_access(value, shift, mask); - tmp = (*value >> shift) & mask; if (mr->subpage) { trace_memory_region_subpage_write(get_cpu_index(), mr, addr, tmp, size); } else if (mr == &io_mem_notdirty) { @@ -531,13 +505,12 @@ static MemTxResult memory_region_write_with_attrs_accessor(MemoryRegion *mr, hwaddr addr, uint64_t *value, unsigned size, - unsigned shift, + signed shift, uint64_t mask, MemTxAttrs attrs) { - uint64_t tmp; + uint64_t tmp = memory_region_shift_write_access(value, shift, mask); - tmp = (*value >> shift) & mask; if (mr->subpage) { trace_memory_region_subpage_write(get_cpu_index(), mr, addr, tmp, size); } else if (mr == &io_mem_notdirty) { @@ -562,7 +535,7 @@ static MemTxResult access_with_adjusted_size(hwaddr addr, hwaddr addr, uint64_t *value, unsigned size, - unsigned shift, + signed shift, uint64_t mask, MemTxAttrs attrs), MemoryRegion *mr, @@ -582,7 +555,7 @@ static MemTxResult access_with_adjusted_size(hwaddr addr, /* FIXME: support unaligned access? */ access_size = MAX(MIN(size, access_size_max), access_size_min); - access_mask = -1ULL >> (64 - access_size * 8); + access_mask = MAKE_64BIT_MASK(0, access_size * 8); if (memory_region_big_endian(mr)) { for (i = 0; i < size; i += access_size) { r |= access_fn(mr, addr + i, value, access_size, @@ -1394,16 +1367,12 @@ static MemTxResult memory_region_dispatch_read1(MemoryRegion *mr, mr->ops->impl.max_access_size, memory_region_read_accessor, mr, attrs); - } else if (mr->ops->read_with_attrs) { + } else { return access_with_adjusted_size(addr, pval, size, mr->ops->impl.min_access_size, mr->ops->impl.max_access_size, memory_region_read_with_attrs_accessor, mr, attrs); - } else { - return access_with_adjusted_size(addr, pval, size, 1, 4, - memory_region_oldmmio_read_accessor, - mr, attrs); } } @@ -1475,17 +1444,13 @@ MemTxResult memory_region_dispatch_write(MemoryRegion *mr, mr->ops->impl.max_access_size, memory_region_write_accessor, mr, attrs); - } else if (mr->ops->write_with_attrs) { + } else { return access_with_adjusted_size(addr, &data, size, mr->ops->impl.min_access_size, mr->ops->impl.max_access_size, memory_region_write_with_attrs_accessor, mr, attrs); - } else { - return access_with_adjusted_size(addr, &data, size, 1, 4, - memory_region_oldmmio_write_accessor, - mr, attrs); } } @@ -1518,12 +1483,18 @@ void memory_region_init_ram_shared_nomigrate(MemoryRegion *mr, bool share, Error **errp) { + Error *err = NULL; memory_region_init(mr, owner, name, size); mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; - mr->ram_block = qemu_ram_alloc(size, share, mr, errp); + mr->ram_block = qemu_ram_alloc(size, share, mr, &err); mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; + if (err) { + mr->size = int128_zero(); + object_unparent(OBJECT(mr)); + error_propagate(errp, err); + } } void memory_region_init_resizeable_ram(MemoryRegion *mr, @@ -1536,16 +1507,22 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr, void *host), Error **errp) { + Error *err = NULL; memory_region_init(mr, owner, name, size); mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; mr->ram_block = qemu_ram_alloc_resizeable(size, max_size, resized, - mr, errp); + mr, &err); mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; + if (err) { + mr->size = int128_zero(); + object_unparent(OBJECT(mr)); + error_propagate(errp, err); + } } -#ifdef __linux__ +#ifdef CONFIG_POSIX void memory_region_init_ram_from_file(MemoryRegion *mr, struct Object *owner, const char *name, @@ -1555,13 +1532,19 @@ void memory_region_init_ram_from_file(MemoryRegion *mr, const char *path, Error **errp) { + Error *err = NULL; memory_region_init(mr, owner, name, size); mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; mr->align = align; - mr->ram_block = qemu_ram_alloc_from_file(size, mr, ram_flags, path, errp); + mr->ram_block = qemu_ram_alloc_from_file(size, mr, ram_flags, path, &err); mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; + if (err) { + mr->size = int128_zero(); + object_unparent(OBJECT(mr)); + error_propagate(errp, err); + } } void memory_region_init_ram_from_fd(MemoryRegion *mr, @@ -1572,14 +1555,20 @@ void memory_region_init_ram_from_fd(MemoryRegion *mr, int fd, Error **errp) { + Error *err = NULL; memory_region_init(mr, owner, name, size); mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; mr->ram_block = qemu_ram_alloc_from_fd(size, mr, share ? RAM_SHARED : 0, - fd, errp); + fd, &err); mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; + if (err) { + mr->size = int128_zero(); + object_unparent(OBJECT(mr)); + error_propagate(errp, err); + } } #endif @@ -1630,13 +1619,19 @@ void memory_region_init_rom_nomigrate(MemoryRegion *mr, uint64_t size, Error **errp) { + Error *err = NULL; memory_region_init(mr, owner, name, size); mr->ram = true; mr->readonly = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; - mr->ram_block = qemu_ram_alloc(size, false, mr, errp); + mr->ram_block = qemu_ram_alloc(size, false, mr, &err); mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; + if (err) { + mr->size = int128_zero(); + object_unparent(OBJECT(mr)); + error_propagate(errp, err); + } } void memory_region_init_rom_device_nomigrate(MemoryRegion *mr, @@ -1647,6 +1642,7 @@ void memory_region_init_rom_device_nomigrate(MemoryRegion *mr, uint64_t size, Error **errp) { + Error *err = NULL; assert(ops); memory_region_init(mr, owner, name, size); mr->ops = ops; @@ -1654,7 +1650,12 @@ void memory_region_init_rom_device_nomigrate(MemoryRegion *mr, mr->terminates = true; mr->rom_device = true; mr->destructor = memory_region_destructor_ram; - mr->ram_block = qemu_ram_alloc(size, false, mr, errp); + mr->ram_block = qemu_ram_alloc(size, false, mr, &err); + if (err) { + mr->size = int128_zero(); + object_unparent(OBJECT(mr)); + error_propagate(errp, err); + } } void memory_region_init_iommu(void *_iommu_mr, diff --git a/os-posix.c b/os-posix.c index 8f39447dd4..4bd80e44e6 100644 --- a/os-posix.c +++ b/os-posix.c @@ -344,30 +344,6 @@ void os_set_line_buffering(void) setvbuf(stdout, NULL, _IOLBF, 0); } -int qemu_create_pidfile(const char *filename) -{ - char buffer[128]; - int len; - int fd; - - fd = qemu_open(filename, O_RDWR | O_CREAT, 0600); - if (fd == -1) { - return -1; - } - if (lockf(fd, F_TLOCK, 0) == -1) { - close(fd); - return -1; - } - len = snprintf(buffer, sizeof(buffer), FMT_pid "\n", getpid()); - if (write(fd, buffer, len) != len) { - close(fd); - return -1; - } - - /* keep pidfile open & locked forever */ - return 0; -} - bool is_daemonized(void) { return daemonize; diff --git a/os-win32.c b/os-win32.c index 0674f94b57..0e0d7f50f3 100644 --- a/os-win32.c +++ b/os-win32.c @@ -97,28 +97,3 @@ int os_parse_cmd_args(int index, const char *optarg) { return -1; } - -int qemu_create_pidfile(const char *filename) -{ - char buffer[128]; - int len; - HANDLE file; - OVERLAPPED overlap; - BOOL ret; - memset(&overlap, 0, sizeof(overlap)); - - file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, - OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - if (file == INVALID_HANDLE_VALUE) { - return -1; - } - len = snprintf(buffer, sizeof(buffer), "%d\n", getpid()); - ret = WriteFile(file, (LPCVOID)buffer, (DWORD)len, - NULL, &overlap); - CloseHandle(file); - if (ret == 0) { - return -1; - } - return 0; -} diff --git a/qga/main.c b/qga/main.c index 6d70242d05..c399320d3c 100644 --- a/qga/main.c +++ b/qga/main.c @@ -340,46 +340,6 @@ static FILE *ga_open_logfile(const char *logfile) return f; } -#ifndef _WIN32 -static bool ga_open_pidfile(const char *pidfile) -{ - int pidfd; - char pidstr[32]; - - pidfd = qemu_open(pidfile, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR); - if (pidfd == -1 || lockf(pidfd, F_TLOCK, 0)) { - g_critical("Cannot lock pid file, %s", strerror(errno)); - if (pidfd != -1) { - close(pidfd); - } - return false; - } - - if (ftruncate(pidfd, 0)) { - g_critical("Failed to truncate pid file"); - goto fail; - } - snprintf(pidstr, sizeof(pidstr), "%d\n", getpid()); - if (write(pidfd, pidstr, strlen(pidstr)) != strlen(pidstr)) { - g_critical("Failed to write pid file"); - goto fail; - } - - /* keep pidfile open & locked forever */ - return true; - -fail: - unlink(pidfile); - close(pidfd); - return false; -} -#else /* _WIN32 */ -static bool ga_open_pidfile(const char *pidfile) -{ - return true; -} -#endif - static gint ga_strcmp(gconstpointer str1, gconstpointer str2) { return strcmp(str1, str2); @@ -479,8 +439,11 @@ void ga_unset_frozen(GAState *s) ga_enable_logging(s); g_warning("logging re-enabled due to filesystem unfreeze"); if (s->deferred_options.pid_filepath) { - if (!ga_open_pidfile(s->deferred_options.pid_filepath)) { - g_warning("failed to create/open pid file"); + Error *err = NULL; + + if (!qemu_write_pidfile(s->deferred_options.pid_filepath, &err)) { + g_warning("%s", error_get_pretty(err)); + error_free(err); } s->deferred_options.pid_filepath = NULL; } @@ -515,8 +478,11 @@ static void become_daemon(const char *pidfile) } if (pidfile) { - if (!ga_open_pidfile(pidfile)) { - g_critical("failed to create pidfile"); + Error *err = NULL; + + if (!qemu_write_pidfile(pidfile, &err)) { + g_critical("%s", error_get_pretty(err)); + error_free(err); exit(EXIT_FAILURE); } } diff --git a/qom/object.c b/qom/object.c index 75d1d48944..9222b23172 100644 --- a/qom/object.c +++ b/qom/object.c @@ -286,7 +286,14 @@ static void type_initialize(TypeImpl *ti) if (ti->instance_size == 0) { ti->abstract = true; } - + if (type_is_ancestor(ti, type_interface)) { + assert(ti->instance_size == 0); + assert(ti->abstract); + assert(!ti->instance_init); + assert(!ti->instance_post_init); + assert(!ti->instance_finalize); + assert(!ti->num_interfaces); + } ti->class = g_malloc0(ti->class_size); parent = type_get_parent(ti); diff --git a/replay/replay-events.c b/replay/replay-events.c index 707de3867b..0964a82838 100644 --- a/replay/replay-events.c +++ b/replay/replay-events.c @@ -94,18 +94,6 @@ void replay_disable_events(void) } } -void replay_clear_events(void) -{ - g_assert(replay_mutex_locked()); - - while (!QTAILQ_EMPTY(&events_list)) { - Event *event = QTAILQ_FIRST(&events_list); - QTAILQ_REMOVE(&events_list, event, events); - - g_free(event); - } -} - /*! Adds specified async event to the queue */ void replay_add_event(ReplayAsyncEventKind event_kind, void *opaque, @@ -308,7 +296,7 @@ void replay_init_events(void) void replay_finish_events(void) { events_enabled = false; - replay_clear_events(); + replay_flush_events(); } bool replay_events_enabled(void) diff --git a/replay/replay-internal.h b/replay/replay-internal.h index ac4b27b674..9b0fd916a3 100644 --- a/replay/replay-internal.h +++ b/replay/replay-internal.h @@ -142,8 +142,6 @@ void replay_init_events(void); void replay_finish_events(void); /*! Flushes events queue */ void replay_flush_events(void); -/*! Clears events list before loading new VM state */ -void replay_clear_events(void); /*! Returns true if there are any unsaved events in the queue */ bool replay_has_events(void); /*! Saves events from queue into the file */ diff --git a/replay/replay-snapshot.c b/replay/replay-snapshot.c index 2ab85cfc60..16bacc98bc 100644 --- a/replay/replay-snapshot.c +++ b/replay/replay-snapshot.c @@ -33,11 +33,18 @@ static int replay_pre_save(void *opaque) static int replay_post_load(void *opaque, int version_id) { ReplayState *state = opaque; - fseek(replay_file, state->file_offset, SEEK_SET); - qemu_clock_set_last(QEMU_CLOCK_HOST, state->host_clock_last); - /* If this was a vmstate, saved in recording mode, - we need to initialize replay data fields. */ - replay_fetch_data_kind(); + if (replay_mode == REPLAY_MODE_PLAY) { + fseek(replay_file, state->file_offset, SEEK_SET); + qemu_clock_set_last(QEMU_CLOCK_HOST, state->host_clock_last); + /* If this was a vmstate, saved in recording mode, + we need to initialize replay data fields. */ + replay_fetch_data_kind(); + } else if (replay_mode == REPLAY_MODE_RECORD) { + /* This is only useful for loading the initial state. + Therefore reset all the counters. */ + state->instructions_count = 0; + state->block_request_id = 0; + } return 0; } diff --git a/replay/replay.c b/replay/replay.c index 8228261401..379b51ab46 100644 --- a/replay/replay.c +++ b/replay/replay.c @@ -224,6 +224,18 @@ out: return res; } +bool replay_has_checkpoint(void) +{ + bool res = false; + if (replay_mode == REPLAY_MODE_PLAY) { + g_assert(replay_mutex_locked()); + replay_account_executed_instructions(); + res = EVENT_CHECKPOINT <= replay_state.data_kind + && replay_state.data_kind <= EVENT_CHECKPOINT_LAST; + } + return res; +} + static void replay_enable(const char *fname, int mode) { const char *fmode = NULL; diff --git a/scsi/qemu-pr-helper.c b/scsi/qemu-pr-helper.c index ed037aabee..ce40008bfc 100644 --- a/scsi/qemu-pr-helper.c +++ b/scsi/qemu-pr-helper.c @@ -117,39 +117,6 @@ QEMU_COPYRIGHT "\n" , name); } -static void write_pidfile(void) -{ - int pidfd; - char pidstr[32]; - - pidfd = qemu_open(pidfile, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR); - if (pidfd == -1) { - error_report("Cannot open pid file, %s", strerror(errno)); - exit(EXIT_FAILURE); - } - - if (lockf(pidfd, F_TLOCK, 0)) { - error_report("Cannot lock pid file, %s", strerror(errno)); - goto fail; - } - if (ftruncate(pidfd, 0)) { - error_report("Failed to truncate pid file"); - goto fail; - } - - snprintf(pidstr, sizeof(pidstr), "%d\n", getpid()); - if (write(pidfd, pidstr, strlen(pidstr)) != strlen(pidstr)) { - error_report("Failed to write pid file"); - goto fail; - } - return; - -fail: - unlink(pidfile); - close(pidfd); - exit(EXIT_FAILURE); -} - /* SG_IO support */ typedef struct PRHelperSGIOData { @@ -1080,8 +1047,11 @@ int main(int argc, char **argv) } } - if (daemonize || pidfile_specified) - write_pidfile(); + if ((daemonize || pidfile_specified) && + !qemu_write_pidfile(pidfile, &local_err)) { + error_report_err(local_err); + exit(EXIT_FAILURE); + } #ifdef CONFIG_LIBCAP if (drop_privileges() < 0) { diff --git a/slirp/ip6_icmp.c b/slirp/ip6_icmp.c index ee333d05a2..3f41187cfe 100644 --- a/slirp/ip6_icmp.c +++ b/slirp/ip6_icmp.c @@ -17,7 +17,7 @@ static void ra_timer_handler(void *opaque) { Slirp *slirp = opaque; timer_mod(slirp->ra_timer, - qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + NDP_Interval); + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_EXT) + NDP_Interval); ndp_send_ra(slirp); } @@ -27,9 +27,10 @@ void icmp6_init(Slirp *slirp) return; } - slirp->ra_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, ra_timer_handler, slirp); + slirp->ra_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL_EXT, + ra_timer_handler, slirp); timer_mod(slirp->ra_timer, - qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + NDP_Interval); + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_EXT) + NDP_Interval); } void icmp6_cleanup(Slirp *slirp) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index f24295e6e4..c88876dfe3 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -5429,20 +5429,51 @@ static void x86_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb) cpu->env.eip = tb->pc - tb->cs_base; } -static bool x86_cpu_has_work(CPUState *cs) +int x86_cpu_pending_interrupt(CPUState *cs, int interrupt_request) { X86CPU *cpu = X86_CPU(cs); CPUX86State *env = &cpu->env; - return ((cs->interrupt_request & (CPU_INTERRUPT_HARD | - CPU_INTERRUPT_POLL)) && - (env->eflags & IF_MASK)) || - (cs->interrupt_request & (CPU_INTERRUPT_NMI | - CPU_INTERRUPT_INIT | - CPU_INTERRUPT_SIPI | - CPU_INTERRUPT_MCE)) || - ((cs->interrupt_request & CPU_INTERRUPT_SMI) && - !(env->hflags & HF_SMM_MASK)); +#if !defined(CONFIG_USER_ONLY) + if (interrupt_request & CPU_INTERRUPT_POLL) { + return CPU_INTERRUPT_POLL; + } +#endif + if (interrupt_request & CPU_INTERRUPT_SIPI) { + return CPU_INTERRUPT_SIPI; + } + + if (env->hflags2 & HF2_GIF_MASK) { + if ((interrupt_request & CPU_INTERRUPT_SMI) && + !(env->hflags & HF_SMM_MASK)) { + return CPU_INTERRUPT_SMI; + } else if ((interrupt_request & CPU_INTERRUPT_NMI) && + !(env->hflags2 & HF2_NMI_MASK)) { + return CPU_INTERRUPT_NMI; + } else if (interrupt_request & CPU_INTERRUPT_MCE) { + return CPU_INTERRUPT_MCE; + } else if ((interrupt_request & CPU_INTERRUPT_HARD) && + (((env->hflags2 & HF2_VINTR_MASK) && + (env->hflags2 & HF2_HIF_MASK)) || + (!(env->hflags2 & HF2_VINTR_MASK) && + (env->eflags & IF_MASK && + !(env->hflags & HF_INHIBIT_IRQ_MASK))))) { + return CPU_INTERRUPT_HARD; +#if !defined(CONFIG_USER_ONLY) + } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) && + (env->eflags & IF_MASK) && + !(env->hflags & HF_INHIBIT_IRQ_MASK)) { + return CPU_INTERRUPT_VIRQ; +#endif + } + } + + return 0; +} + +static bool x86_cpu_has_work(CPUState *cs) +{ + return x86_cpu_pending_interrupt(cs, cs->interrupt_request) != 0; } static void x86_disas_set_info(CPUState *cs, disassemble_info *info) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index b572a8e4aa..730c06f80a 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -171,7 +171,7 @@ typedef enum X86Seg { #define HF_AC_SHIFT 18 /* must be same as eflags */ #define HF_SMM_SHIFT 19 /* CPU in SMM mode */ #define HF_SVME_SHIFT 20 /* SVME enabled (copy of EFER.SVME) */ -#define HF_SVMI_SHIFT 21 /* SVM intercepts are active */ +#define HF_GUEST_SHIFT 21 /* SVM intercepts are active */ #define HF_OSFXSR_SHIFT 22 /* CR4.OSFXSR */ #define HF_SMAP_SHIFT 23 /* CR4.SMAP */ #define HF_IOBPT_SHIFT 24 /* an io breakpoint enabled */ @@ -196,7 +196,7 @@ typedef enum X86Seg { #define HF_AC_MASK (1 << HF_AC_SHIFT) #define HF_SMM_MASK (1 << HF_SMM_SHIFT) #define HF_SVME_MASK (1 << HF_SVME_SHIFT) -#define HF_SVMI_MASK (1 << HF_SVMI_SHIFT) +#define HF_GUEST_MASK (1 << HF_GUEST_SHIFT) #define HF_OSFXSR_MASK (1 << HF_OSFXSR_SHIFT) #define HF_SMAP_MASK (1 << HF_SMAP_SHIFT) #define HF_IOBPT_MASK (1 << HF_IOBPT_SHIFT) @@ -1327,7 +1327,9 @@ typedef struct CPUX86State { bool tsc_valid; int64_t tsc_khz; int64_t user_tsc_khz; /* for sanity check only */ - void *kvm_xsave_buf; +#if defined(CONFIG_KVM) || defined(CONFIG_HVF) + void *xsave_buf; +#endif #if defined(CONFIG_HVF) HVFX86EmulatorState *hvf_emul; #endif @@ -1485,6 +1487,7 @@ extern struct VMStateDescription vmstate_x86_cpu; */ void x86_cpu_do_interrupt(CPUState *cpu); bool x86_cpu_exec_interrupt(CPUState *cpu, int int_req); +int x86_cpu_pending_interrupt(CPUState *cs, int interrupt_request); int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu, int cpuid, void *opaque); diff --git a/target/i386/excp_helper.c b/target/i386/excp_helper.c index 37a33d5ae0..49231f6b69 100644 --- a/target/i386/excp_helper.c +++ b/target/i386/excp_helper.c @@ -53,7 +53,7 @@ static int check_exception(CPUX86State *env, int intno, int *error_code, #if !defined(CONFIG_USER_ONLY) if (env->old_exception == EXCP08_DBLE) { - if (env->hflags & HF_SVMI_MASK) { + if (env->hflags & HF_GUEST_MASK) { cpu_vmexit(env, SVM_EXIT_SHUTDOWN, 0, retaddr); /* does not return */ } diff --git a/target/i386/hvf/README.md b/target/i386/hvf/README.md index 0d27a0d52b..2d33477aca 100644 --- a/target/i386/hvf/README.md +++ b/target/i386/hvf/README.md @@ -2,6 +2,6 @@ These sources (and ../hvf-all.c) are adapted from Veertu Inc's vdhh (Veertu Desktop Hosted Hypervisor) (last known location: https://github.com/veertuinc/vdhh) with some minor changes, the most significant of which were: -1. Adapt to our current QEMU's `CPUState` structure and `address_space_rw` API; many struct members have been moved around (emulated x86 state, kvm_xsave_buf) due to historical differences + QEMU needing to handle more emulation targets. +1. Adapt to our current QEMU's `CPUState` structure and `address_space_rw` API; many struct members have been moved around (emulated x86 state, xsave_buf) due to historical differences + QEMU needing to handle more emulation targets. 2. Removal of `apic_page` and hyperv-related functionality. 3. More relaxed use of `qemu_mutex_lock_iothread`. diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index df69e6d0a7..9f52bc413a 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -72,7 +72,6 @@ #include "sysemu/sysemu.h" #include "target/i386/cpu.h" -pthread_rwlock_t mem_lock = PTHREAD_RWLOCK_INITIALIZER; HVFState *hvf_state; int hvf_disabled = 1; @@ -587,7 +586,7 @@ int hvf_init_vcpu(CPUState *cpu) hvf_reset_vcpu(cpu); x86cpu = X86_CPU(cpu); - x86cpu->env.kvm_xsave_buf = qemu_memalign(4096, 4096); + x86cpu->env.xsave_buf = qemu_memalign(4096, 4096); hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_STAR, 1); hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_LSTAR, 1); diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c index 6c88939b96..df8e946fbc 100644 --- a/target/i386/hvf/x86hvf.c +++ b/target/i386/hvf/x86hvf.c @@ -75,7 +75,7 @@ void hvf_put_xsave(CPUState *cpu_state) struct X86XSaveArea *xsave; - xsave = X86_CPU(cpu_state)->env.kvm_xsave_buf; + xsave = X86_CPU(cpu_state)->env.xsave_buf; x86_cpu_xsave_all_areas(X86_CPU(cpu_state), xsave); @@ -163,7 +163,7 @@ void hvf_get_xsave(CPUState *cpu_state) { struct X86XSaveArea *xsave; - xsave = X86_CPU(cpu_state)->env.kvm_xsave_buf; + xsave = X86_CPU(cpu_state)->env.xsave_buf; if (hv_vcpu_read_fpstate(cpu_state->hvf_fd, (void*)xsave, 4096)) { abort(); diff --git a/target/i386/kvm.c b/target/i386/kvm.c index 0b2a07d3a4..dc4047b02f 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -1189,7 +1189,7 @@ int kvm_arch_init_vcpu(CPUState *cs) } if (has_xsave) { - env->kvm_xsave_buf = qemu_memalign(4096, sizeof(struct kvm_xsave)); + env->xsave_buf = qemu_memalign(4096, sizeof(struct kvm_xsave)); } cpu->kvm_msr_buf = g_malloc0(MSR_BUF_SIZE); @@ -1639,7 +1639,7 @@ ASSERT_OFFSET(XSAVE_PKRU, pkru_state); static int kvm_put_xsave(X86CPU *cpu) { CPUX86State *env = &cpu->env; - X86XSaveArea *xsave = env->kvm_xsave_buf; + X86XSaveArea *xsave = env->xsave_buf; if (!has_xsave) { return kvm_put_fpu(cpu); @@ -2081,7 +2081,7 @@ static int kvm_get_fpu(X86CPU *cpu) static int kvm_get_xsave(X86CPU *cpu) { CPUX86State *env = &cpu->env; - X86XSaveArea *xsave = env->kvm_xsave_buf; + X86XSaveArea *xsave = env->xsave_buf; int ret; if (!has_xsave) { @@ -3669,6 +3669,10 @@ int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, MSIMessage src, dst; X86IOMMUClass *class = X86_IOMMU_GET_CLASS(iommu); + if (!class->int_remap) { + return 0; + } + src.address = route->u.msi.address_hi; src.address <<= VTD_MSI_ADDR_HI_SHIFT; src.address |= route->u.msi.address_lo; diff --git a/target/i386/seg_helper.c b/target/i386/seg_helper.c index d1cbc6ebf0..33714bc6e1 100644 --- a/target/i386/seg_helper.c +++ b/target/i386/seg_helper.c @@ -1244,7 +1244,7 @@ static void do_interrupt_all(X86CPU *cpu, int intno, int is_int, } if (env->cr[0] & CR0_PE_MASK) { #if !defined(CONFIG_USER_ONLY) - if (env->hflags & HF_SVMI_MASK) { + if (env->hflags & HF_GUEST_MASK) { handle_even_inj(env, intno, is_int, error_code, is_hw, 0); } #endif @@ -1259,7 +1259,7 @@ static void do_interrupt_all(X86CPU *cpu, int intno, int is_int, } } else { #if !defined(CONFIG_USER_ONLY) - if (env->hflags & HF_SVMI_MASK) { + if (env->hflags & HF_GUEST_MASK) { handle_even_inj(env, intno, is_int, error_code, is_hw, 1); } #endif @@ -1267,7 +1267,7 @@ static void do_interrupt_all(X86CPU *cpu, int intno, int is_int, } #if !defined(CONFIG_USER_ONLY) - if (env->hflags & HF_SVMI_MASK) { + if (env->hflags & HF_GUEST_MASK) { CPUState *cs = CPU(cpu); uint32_t event_inj = x86_ldl_phys(cs, env->vm_vmcb + offsetof(struct vmcb, @@ -1319,74 +1319,66 @@ bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request) { X86CPU *cpu = X86_CPU(cs); CPUX86State *env = &cpu->env; - bool ret = false; + int intno; + interrupt_request = x86_cpu_pending_interrupt(cs, interrupt_request); + if (!interrupt_request) { + return false; + } + + /* Don't process multiple interrupt requests in a single call. + * This is required to make icount-driven execution deterministic. + */ + switch (interrupt_request) { #if !defined(CONFIG_USER_ONLY) - if (interrupt_request & CPU_INTERRUPT_POLL) { + case CPU_INTERRUPT_POLL: cs->interrupt_request &= ~CPU_INTERRUPT_POLL; apic_poll_irq(cpu->apic_state); - /* Don't process multiple interrupt requests in a single call. - This is required to make icount-driven execution deterministic. */ - return true; - } + break; #endif - if (interrupt_request & CPU_INTERRUPT_SIPI) { + case CPU_INTERRUPT_SIPI: do_cpu_sipi(cpu); - ret = true; - } else if (env->hflags2 & HF2_GIF_MASK) { - if ((interrupt_request & CPU_INTERRUPT_SMI) && - !(env->hflags & HF_SMM_MASK)) { - cpu_svm_check_intercept_param(env, SVM_EXIT_SMI, 0, 0); - cs->interrupt_request &= ~CPU_INTERRUPT_SMI; - do_smm_enter(cpu); - ret = true; - } else if ((interrupt_request & CPU_INTERRUPT_NMI) && - !(env->hflags2 & HF2_NMI_MASK)) { - cpu_svm_check_intercept_param(env, SVM_EXIT_NMI, 0, 0); - cs->interrupt_request &= ~CPU_INTERRUPT_NMI; - env->hflags2 |= HF2_NMI_MASK; - do_interrupt_x86_hardirq(env, EXCP02_NMI, 1); - ret = true; - } else if (interrupt_request & CPU_INTERRUPT_MCE) { - cs->interrupt_request &= ~CPU_INTERRUPT_MCE; - do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0); - ret = true; - } else if ((interrupt_request & CPU_INTERRUPT_HARD) && - (((env->hflags2 & HF2_VINTR_MASK) && - (env->hflags2 & HF2_HIF_MASK)) || - (!(env->hflags2 & HF2_VINTR_MASK) && - (env->eflags & IF_MASK && - !(env->hflags & HF_INHIBIT_IRQ_MASK))))) { - int intno; - cpu_svm_check_intercept_param(env, SVM_EXIT_INTR, 0, 0); - cs->interrupt_request &= ~(CPU_INTERRUPT_HARD | - CPU_INTERRUPT_VIRQ); - intno = cpu_get_pic_interrupt(env); - qemu_log_mask(CPU_LOG_TB_IN_ASM, - "Servicing hardware INT=0x%02x\n", intno); - do_interrupt_x86_hardirq(env, intno, 1); - /* ensure that no TB jump will be modified as - the program flow was changed */ - ret = true; + break; + case CPU_INTERRUPT_SMI: + cpu_svm_check_intercept_param(env, SVM_EXIT_SMI, 0, 0); + cs->interrupt_request &= ~CPU_INTERRUPT_SMI; + do_smm_enter(cpu); + break; + case CPU_INTERRUPT_NMI: + cpu_svm_check_intercept_param(env, SVM_EXIT_NMI, 0, 0); + cs->interrupt_request &= ~CPU_INTERRUPT_NMI; + env->hflags2 |= HF2_NMI_MASK; + do_interrupt_x86_hardirq(env, EXCP02_NMI, 1); + break; + case CPU_INTERRUPT_MCE: + cs->interrupt_request &= ~CPU_INTERRUPT_MCE; + do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0); + break; + case CPU_INTERRUPT_HARD: + cpu_svm_check_intercept_param(env, SVM_EXIT_INTR, 0, 0); + cs->interrupt_request &= ~(CPU_INTERRUPT_HARD | + CPU_INTERRUPT_VIRQ); + intno = cpu_get_pic_interrupt(env); + qemu_log_mask(CPU_LOG_TB_IN_ASM, + "Servicing hardware INT=0x%02x\n", intno); + do_interrupt_x86_hardirq(env, intno, 1); + break; #if !defined(CONFIG_USER_ONLY) - } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) && - (env->eflags & IF_MASK) && - !(env->hflags & HF_INHIBIT_IRQ_MASK)) { - int intno; - /* FIXME: this should respect TPR */ - cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR, 0, 0); - intno = x86_ldl_phys(cs, env->vm_vmcb + case CPU_INTERRUPT_VIRQ: + /* FIXME: this should respect TPR */ + cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR, 0, 0); + intno = x86_ldl_phys(cs, env->vm_vmcb + offsetof(struct vmcb, control.int_vector)); - qemu_log_mask(CPU_LOG_TB_IN_ASM, - "Servicing virtual hardware INT=0x%02x\n", intno); - do_interrupt_x86_hardirq(env, intno, 1); - cs->interrupt_request &= ~CPU_INTERRUPT_VIRQ; - ret = true; + qemu_log_mask(CPU_LOG_TB_IN_ASM, + "Servicing virtual hardware INT=0x%02x\n", intno); + do_interrupt_x86_hardirq(env, intno, 1); + cs->interrupt_request &= ~CPU_INTERRUPT_VIRQ; + break; #endif - } } - return ret; + /* Ensure that no TB jump will be modified as the program flow was changed. */ + return true; } void helper_lldt(CPUX86State *env, int selector) diff --git a/target/i386/svm_helper.c b/target/i386/svm_helper.c index 342ece082f..9fd22a883b 100644 --- a/target/i386/svm_helper.c +++ b/target/i386/svm_helper.c @@ -228,7 +228,7 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend) } /* enable intercepts */ - env->hflags |= HF_SVMI_MASK; + env->hflags |= HF_GUEST_MASK; env->tsc_offset = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, control.tsc_offset)); @@ -503,7 +503,7 @@ void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type, { CPUState *cs = CPU(x86_env_get_cpu(env)); - if (likely(!(env->hflags & HF_SVMI_MASK))) { + if (likely(!(env->hflags & HF_GUEST_MASK))) { return; } switch (type) { @@ -697,7 +697,7 @@ void do_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1) /* Reload the host state from vm_hsave */ env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK); - env->hflags &= ~HF_SVMI_MASK; + env->hflags &= ~HF_GUEST_MASK; env->intercept = 0; env->intercept_exceptions = 0; cs->interrupt_request &= ~CPU_INTERRUPT_VIRQ; diff --git a/target/i386/translate.c b/target/i386/translate.c index 1f9d1d9b24..83c1ebe491 100644 --- a/target/i386/translate.c +++ b/target/i386/translate.c @@ -72,27 +72,15 @@ //#define MACRO_TEST 1 /* global register indexes */ -static TCGv cpu_A0; -static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2, cpu_cc_srcT; +static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2; static TCGv_i32 cpu_cc_op; static TCGv cpu_regs[CPU_NB_REGS]; static TCGv cpu_seg_base[6]; static TCGv_i64 cpu_bndl[4]; static TCGv_i64 cpu_bndu[4]; -/* local temps */ -static TCGv cpu_T0, cpu_T1; -/* local register indexes (only used inside old micro ops) */ -static TCGv cpu_tmp0, cpu_tmp4; -static TCGv_ptr cpu_ptr0, cpu_ptr1; -static TCGv_i32 cpu_tmp2_i32, cpu_tmp3_i32; -static TCGv_i64 cpu_tmp1_i64; #include "exec/gen-icount.h" -#ifdef TARGET_X86_64 -static int x86_64_hregs; -#endif - typedef struct DisasContext { DisasContextBase base; @@ -117,6 +105,9 @@ typedef struct DisasContext { int ss32; /* 32 bit stack segment */ CCOp cc_op; /* current CC operation */ bool cc_op_dirty; +#ifdef TARGET_X86_64 + bool x86_64_hregs; +#endif int addseg; /* non zero if either DS/ES/SS have a non zero base */ int f_st; /* currently unused */ int vm86; /* vm86 mode */ @@ -135,6 +126,22 @@ typedef struct DisasContext { int cpuid_ext3_features; int cpuid_7_0_ebx_features; int cpuid_xsave_features; + + /* TCG local temps */ + TCGv cc_srcT; + TCGv A0; + TCGv T0; + TCGv T1; + + /* TCG local register indexes (only used inside old micro ops) */ + TCGv tmp0; + TCGv tmp4; + TCGv_ptr ptr0; + TCGv_ptr ptr1; + TCGv_i32 tmp2_i32; + TCGv_i32 tmp3_i32; + TCGv_i64 tmp1_i64; + sigjmp_buf jmpbuf; } DisasContext; @@ -244,7 +251,7 @@ static void set_cc_op(DisasContext *s, CCOp op) tcg_gen_discard_tl(cpu_cc_src2); } if (dead & USES_CC_SRCT) { - tcg_gen_discard_tl(cpu_cc_srcT); + tcg_gen_discard_tl(s->cc_srcT); } if (op == CC_OP_DYNAMIC) { @@ -299,13 +306,13 @@ static void gen_update_cc_op(DisasContext *s) * [AH, CH, DH, BH], ie "bits 15..8 of register N-4". Return * true for this special case, false otherwise. */ -static inline bool byte_reg_is_xH(int reg) +static inline bool byte_reg_is_xH(DisasContext *s, int reg) { if (reg < 4) { return false; } #ifdef TARGET_X86_64 - if (reg >= 8 || x86_64_hregs) { + if (reg >= 8 || s->x86_64_hregs) { return false; } #endif @@ -352,11 +359,11 @@ static inline TCGMemOp mo_b_d32(int b, TCGMemOp ot) return b & 1 ? (ot == MO_16 ? MO_16 : MO_32) : MO_8; } -static void gen_op_mov_reg_v(TCGMemOp ot, int reg, TCGv t0) +static void gen_op_mov_reg_v(DisasContext *s, TCGMemOp ot, int reg, TCGv t0) { switch(ot) { case MO_8: - if (!byte_reg_is_xH(reg)) { + if (!byte_reg_is_xH(s, reg)) { tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8); } else { tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8); @@ -380,9 +387,10 @@ static void gen_op_mov_reg_v(TCGMemOp ot, int reg, TCGv t0) } } -static inline void gen_op_mov_v_reg(TCGMemOp ot, TCGv t0, int reg) +static inline +void gen_op_mov_v_reg(DisasContext *s, TCGMemOp ot, TCGv t0, int reg) { - if (ot == MO_8 && byte_reg_is_xH(reg)) { + if (ot == MO_8 && byte_reg_is_xH(s, reg)) { tcg_gen_extract_tl(t0, cpu_regs[reg - 4], 8, 8); } else { tcg_gen_mov_tl(t0, cpu_regs[reg]); @@ -391,9 +399,9 @@ static inline void gen_op_mov_v_reg(TCGMemOp ot, TCGv t0, int reg) static void gen_add_A0_im(DisasContext *s, int val) { - tcg_gen_addi_tl(cpu_A0, cpu_A0, val); + tcg_gen_addi_tl(s->A0, s->A0, val); if (!CODE64(s)) { - tcg_gen_ext32u_tl(cpu_A0, cpu_A0); + tcg_gen_ext32u_tl(s->A0, s->A0); } } @@ -402,16 +410,17 @@ static inline void gen_op_jmp_v(TCGv dest) tcg_gen_st_tl(dest, cpu_env, offsetof(CPUX86State, eip)); } -static inline void gen_op_add_reg_im(TCGMemOp size, int reg, int32_t val) +static inline +void gen_op_add_reg_im(DisasContext *s, TCGMemOp size, int reg, int32_t val) { - tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val); - gen_op_mov_reg_v(size, reg, cpu_tmp0); + tcg_gen_addi_tl(s->tmp0, cpu_regs[reg], val); + gen_op_mov_reg_v(s, size, reg, s->tmp0); } -static inline void gen_op_add_reg_T0(TCGMemOp size, int reg) +static inline void gen_op_add_reg_T0(DisasContext *s, TCGMemOp size, int reg) { - tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T0); - gen_op_mov_reg_v(size, reg, cpu_tmp0); + tcg_gen_add_tl(s->tmp0, cpu_regs[reg], s->T0); + gen_op_mov_reg_v(s, size, reg, s->tmp0); } static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0) @@ -427,16 +436,16 @@ static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0) static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d) { if (d == OR_TMP0) { - gen_op_st_v(s, idx, cpu_T0, cpu_A0); + gen_op_st_v(s, idx, s->T0, s->A0); } else { - gen_op_mov_reg_v(idx, d, cpu_T0); + gen_op_mov_reg_v(s, idx, d, s->T0); } } -static inline void gen_jmp_im(target_ulong pc) +static inline void gen_jmp_im(DisasContext *s, target_ulong pc) { - tcg_gen_movi_tl(cpu_tmp0, pc); - gen_op_jmp_v(cpu_tmp0); + tcg_gen_movi_tl(s->tmp0, pc); + gen_op_jmp_v(s->tmp0); } /* Compute SEG:REG into A0. SEG is selected from the override segment @@ -449,7 +458,7 @@ static void gen_lea_v_seg(DisasContext *s, TCGMemOp aflag, TCGv a0, #ifdef TARGET_X86_64 case MO_64: if (ovr_seg < 0) { - tcg_gen_mov_tl(cpu_A0, a0); + tcg_gen_mov_tl(s->A0, a0); return; } break; @@ -460,14 +469,14 @@ static void gen_lea_v_seg(DisasContext *s, TCGMemOp aflag, TCGv a0, ovr_seg = def_seg; } if (ovr_seg < 0) { - tcg_gen_ext32u_tl(cpu_A0, a0); + tcg_gen_ext32u_tl(s->A0, a0); return; } break; case MO_16: /* 16 bit address */ - tcg_gen_ext16u_tl(cpu_A0, a0); - a0 = cpu_A0; + tcg_gen_ext16u_tl(s->A0, a0); + a0 = s->A0; if (ovr_seg < 0) { if (s->addseg) { ovr_seg = def_seg; @@ -484,13 +493,13 @@ static void gen_lea_v_seg(DisasContext *s, TCGMemOp aflag, TCGv a0, TCGv seg = cpu_seg_base[ovr_seg]; if (aflag == MO_64) { - tcg_gen_add_tl(cpu_A0, a0, seg); + tcg_gen_add_tl(s->A0, a0, seg); } else if (CODE64(s)) { - tcg_gen_ext32u_tl(cpu_A0, a0); - tcg_gen_add_tl(cpu_A0, cpu_A0, seg); + tcg_gen_ext32u_tl(s->A0, a0); + tcg_gen_add_tl(s->A0, s->A0, seg); } else { - tcg_gen_add_tl(cpu_A0, a0, seg); - tcg_gen_ext32u_tl(cpu_A0, cpu_A0); + tcg_gen_add_tl(s->A0, a0, seg); + tcg_gen_ext32u_tl(s->A0, s->A0); } } } @@ -505,10 +514,10 @@ static inline void gen_string_movl_A0_EDI(DisasContext *s) gen_lea_v_seg(s, s->aflag, cpu_regs[R_EDI], R_ES, -1); } -static inline void gen_op_movl_T0_Dshift(TCGMemOp ot) +static inline void gen_op_movl_T0_Dshift(DisasContext *s, TCGMemOp ot) { - tcg_gen_ld32s_tl(cpu_T0, cpu_env, offsetof(CPUX86State, df)); - tcg_gen_shli_tl(cpu_T0, cpu_T0, ot); + tcg_gen_ld32s_tl(s->T0, cpu_env, offsetof(CPUX86State, df)); + tcg_gen_shli_tl(s->T0, s->T0, ot); }; static TCGv gen_ext_tl(TCGv dst, TCGv src, TCGMemOp size, bool sign) @@ -552,18 +561,20 @@ static void gen_exts(TCGMemOp ot, TCGv reg) gen_ext_tl(reg, reg, ot, true); } -static inline void gen_op_jnz_ecx(TCGMemOp size, TCGLabel *label1) +static inline +void gen_op_jnz_ecx(DisasContext *s, TCGMemOp size, TCGLabel *label1) { - tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]); - gen_extu(size, cpu_tmp0); - tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1); + tcg_gen_mov_tl(s->tmp0, cpu_regs[R_ECX]); + gen_extu(size, s->tmp0); + tcg_gen_brcondi_tl(TCG_COND_NE, s->tmp0, 0, label1); } -static inline void gen_op_jz_ecx(TCGMemOp size, TCGLabel *label1) +static inline +void gen_op_jz_ecx(DisasContext *s, TCGMemOp size, TCGLabel *label1) { - tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]); - gen_extu(size, cpu_tmp0); - tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1); + tcg_gen_mov_tl(s->tmp0, cpu_regs[R_ECX]); + gen_extu(size, s->tmp0); + tcg_gen_brcondi_tl(TCG_COND_EQ, s->tmp0, 0, label1); } static void gen_helper_in_func(TCGMemOp ot, TCGv v, TCGv_i32 n) @@ -606,28 +617,28 @@ static void gen_check_io(DisasContext *s, TCGMemOp ot, target_ulong cur_eip, target_ulong next_eip; if (s->pe && (s->cpl > s->iopl || s->vm86)) { - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); switch (ot) { case MO_8: - gen_helper_check_iob(cpu_env, cpu_tmp2_i32); + gen_helper_check_iob(cpu_env, s->tmp2_i32); break; case MO_16: - gen_helper_check_iow(cpu_env, cpu_tmp2_i32); + gen_helper_check_iow(cpu_env, s->tmp2_i32); break; case MO_32: - gen_helper_check_iol(cpu_env, cpu_tmp2_i32); + gen_helper_check_iol(cpu_env, s->tmp2_i32); break; default: tcg_abort(); } } - if(s->flags & HF_SVMI_MASK) { + if(s->flags & HF_GUEST_MASK) { gen_update_cc_op(s); - gen_jmp_im(cur_eip); + gen_jmp_im(s, cur_eip); svm_flags |= (1 << (4 + ot)); next_eip = s->pc - s->cs_base; - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); - gen_helper_svm_check_io(cpu_env, cpu_tmp2_i32, + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); + gen_helper_svm_check_io(cpu_env, s->tmp2_i32, tcg_const_i32(svm_flags), tcg_const_i32(next_eip - cur_eip)); } @@ -636,42 +647,42 @@ static void gen_check_io(DisasContext *s, TCGMemOp ot, target_ulong cur_eip, static inline void gen_movs(DisasContext *s, TCGMemOp ot) { gen_string_movl_A0_ESI(s); - gen_op_ld_v(s, ot, cpu_T0, cpu_A0); + gen_op_ld_v(s, ot, s->T0, s->A0); gen_string_movl_A0_EDI(s); - gen_op_st_v(s, ot, cpu_T0, cpu_A0); - gen_op_movl_T0_Dshift(ot); - gen_op_add_reg_T0(s->aflag, R_ESI); - gen_op_add_reg_T0(s->aflag, R_EDI); + gen_op_st_v(s, ot, s->T0, s->A0); + gen_op_movl_T0_Dshift(s, ot); + gen_op_add_reg_T0(s, s->aflag, R_ESI); + gen_op_add_reg_T0(s, s->aflag, R_EDI); } -static void gen_op_update1_cc(void) +static void gen_op_update1_cc(DisasContext *s) { - tcg_gen_mov_tl(cpu_cc_dst, cpu_T0); + tcg_gen_mov_tl(cpu_cc_dst, s->T0); } -static void gen_op_update2_cc(void) +static void gen_op_update2_cc(DisasContext *s) { - tcg_gen_mov_tl(cpu_cc_src, cpu_T1); - tcg_gen_mov_tl(cpu_cc_dst, cpu_T0); + tcg_gen_mov_tl(cpu_cc_src, s->T1); + tcg_gen_mov_tl(cpu_cc_dst, s->T0); } -static void gen_op_update3_cc(TCGv reg) +static void gen_op_update3_cc(DisasContext *s, TCGv reg) { tcg_gen_mov_tl(cpu_cc_src2, reg); - tcg_gen_mov_tl(cpu_cc_src, cpu_T1); - tcg_gen_mov_tl(cpu_cc_dst, cpu_T0); + tcg_gen_mov_tl(cpu_cc_src, s->T1); + tcg_gen_mov_tl(cpu_cc_dst, s->T0); } -static inline void gen_op_testl_T0_T1_cc(void) +static inline void gen_op_testl_T0_T1_cc(DisasContext *s) { - tcg_gen_and_tl(cpu_cc_dst, cpu_T0, cpu_T1); + tcg_gen_and_tl(cpu_cc_dst, s->T0, s->T1); } -static void gen_op_update_neg_cc(void) +static void gen_op_update_neg_cc(DisasContext *s) { - tcg_gen_mov_tl(cpu_cc_dst, cpu_T0); - tcg_gen_neg_tl(cpu_cc_src, cpu_T0); - tcg_gen_movi_tl(cpu_cc_srcT, 0); + tcg_gen_mov_tl(cpu_cc_dst, s->T0); + tcg_gen_neg_tl(cpu_cc_src, s->T0); + tcg_gen_movi_tl(s->cc_srcT, 0); } /* compute all eflags to cc_src */ @@ -739,17 +750,17 @@ static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg) case CC_OP_SUBB ... CC_OP_SUBQ: /* (DATA_TYPE)CC_SRCT < (DATA_TYPE)CC_SRC */ size = s->cc_op - CC_OP_SUBB; - t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false); + t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false); /* If no temporary was used, be careful not to alias t1 and t0. */ - t0 = t1 == cpu_cc_src ? cpu_tmp0 : reg; - tcg_gen_mov_tl(t0, cpu_cc_srcT); + t0 = t1 == cpu_cc_src ? s->tmp0 : reg; + tcg_gen_mov_tl(t0, s->cc_srcT); gen_extu(size, t0); goto add_sub; case CC_OP_ADDB ... CC_OP_ADDQ: /* (DATA_TYPE)CC_DST < (DATA_TYPE)CC_SRC */ size = s->cc_op - CC_OP_ADDB; - t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false); + t1 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false); t0 = gen_ext_tl(reg, cpu_cc_dst, size, false); add_sub: return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0, @@ -899,10 +910,10 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg) size = s->cc_op - CC_OP_SUBB; switch (jcc_op) { case JCC_BE: - tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT); - gen_extu(size, cpu_tmp4); - t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false); - cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = cpu_tmp4, + tcg_gen_mov_tl(s->tmp4, s->cc_srcT); + gen_extu(size, s->tmp4); + t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, false); + cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = s->tmp4, .reg2 = t0, .mask = -1, .use_reg2 = true }; break; @@ -912,10 +923,10 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg) case JCC_LE: cond = TCG_COND_LE; fast_jcc_l: - tcg_gen_mov_tl(cpu_tmp4, cpu_cc_srcT); - gen_exts(size, cpu_tmp4); - t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, true); - cc = (CCPrepare) { .cond = cond, .reg = cpu_tmp4, + tcg_gen_mov_tl(s->tmp4, s->cc_srcT); + gen_exts(size, s->tmp4); + t0 = gen_ext_tl(s->tmp0, cpu_cc_src, size, true); + cc = (CCPrepare) { .cond = cond, .reg = s->tmp4, .reg2 = t0, .mask = -1, .use_reg2 = true }; break; @@ -951,7 +962,7 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg) case JCC_L: gen_compute_eflags(s); if (reg == cpu_cc_src) { - reg = cpu_tmp0; + reg = s->tmp0; } tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */ tcg_gen_xor_tl(reg, reg, cpu_cc_src); @@ -962,7 +973,7 @@ static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg) case JCC_LE: gen_compute_eflags(s); if (reg == cpu_cc_src) { - reg = cpu_tmp0; + reg = s->tmp0; } tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */ tcg_gen_xor_tl(reg, reg, cpu_cc_src); @@ -1018,11 +1029,11 @@ static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg) value 'b'. In the fast case, T0 is guaranted not to be used. */ static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1) { - CCPrepare cc = gen_prepare_cc(s, b, cpu_T0); + CCPrepare cc = gen_prepare_cc(s, b, s->T0); if (cc.mask != -1) { - tcg_gen_andi_tl(cpu_T0, cc.reg, cc.mask); - cc.reg = cpu_T0; + tcg_gen_andi_tl(s->T0, cc.reg, cc.mask); + cc.reg = s->T0; } if (cc.use_reg2) { tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1); @@ -1036,12 +1047,12 @@ static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1) A translation block must end soon. */ static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1) { - CCPrepare cc = gen_prepare_cc(s, b, cpu_T0); + CCPrepare cc = gen_prepare_cc(s, b, s->T0); gen_update_cc_op(s); if (cc.mask != -1) { - tcg_gen_andi_tl(cpu_T0, cc.reg, cc.mask); - cc.reg = cpu_T0; + tcg_gen_andi_tl(s->T0, cc.reg, cc.mask); + cc.reg = s->T0; } set_cc_op(s, CC_OP_DYNAMIC); if (cc.use_reg2) { @@ -1057,7 +1068,7 @@ static TCGLabel *gen_jz_ecx_string(DisasContext *s, target_ulong next_eip) { TCGLabel *l1 = gen_new_label(); TCGLabel *l2 = gen_new_label(); - gen_op_jnz_ecx(s->aflag, l1); + gen_op_jnz_ecx(s, s->aflag, l1); gen_set_label(l2); gen_jmp_tb(s, next_eip, 1); gen_set_label(l1); @@ -1066,40 +1077,40 @@ static TCGLabel *gen_jz_ecx_string(DisasContext *s, target_ulong next_eip) static inline void gen_stos(DisasContext *s, TCGMemOp ot) { - gen_op_mov_v_reg(MO_32, cpu_T0, R_EAX); + gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX); gen_string_movl_A0_EDI(s); - gen_op_st_v(s, ot, cpu_T0, cpu_A0); - gen_op_movl_T0_Dshift(ot); - gen_op_add_reg_T0(s->aflag, R_EDI); + gen_op_st_v(s, ot, s->T0, s->A0); + gen_op_movl_T0_Dshift(s, ot); + gen_op_add_reg_T0(s, s->aflag, R_EDI); } static inline void gen_lods(DisasContext *s, TCGMemOp ot) { gen_string_movl_A0_ESI(s); - gen_op_ld_v(s, ot, cpu_T0, cpu_A0); - gen_op_mov_reg_v(ot, R_EAX, cpu_T0); - gen_op_movl_T0_Dshift(ot); - gen_op_add_reg_T0(s->aflag, R_ESI); + gen_op_ld_v(s, ot, s->T0, s->A0); + gen_op_mov_reg_v(s, ot, R_EAX, s->T0); + gen_op_movl_T0_Dshift(s, ot); + gen_op_add_reg_T0(s, s->aflag, R_ESI); } static inline void gen_scas(DisasContext *s, TCGMemOp ot) { gen_string_movl_A0_EDI(s); - gen_op_ld_v(s, ot, cpu_T1, cpu_A0); + gen_op_ld_v(s, ot, s->T1, s->A0); gen_op(s, OP_CMPL, ot, R_EAX); - gen_op_movl_T0_Dshift(ot); - gen_op_add_reg_T0(s->aflag, R_EDI); + gen_op_movl_T0_Dshift(s, ot); + gen_op_add_reg_T0(s, s->aflag, R_EDI); } static inline void gen_cmps(DisasContext *s, TCGMemOp ot) { gen_string_movl_A0_EDI(s); - gen_op_ld_v(s, ot, cpu_T1, cpu_A0); + gen_op_ld_v(s, ot, s->T1, s->A0); gen_string_movl_A0_ESI(s); gen_op(s, OP_CMPL, ot, OR_TMP0); - gen_op_movl_T0_Dshift(ot); - gen_op_add_reg_T0(s->aflag, R_ESI); - gen_op_add_reg_T0(s->aflag, R_EDI); + gen_op_movl_T0_Dshift(s, ot); + gen_op_add_reg_T0(s, s->aflag, R_ESI); + gen_op_add_reg_T0(s, s->aflag, R_EDI); } static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot) @@ -1123,15 +1134,15 @@ static inline void gen_ins(DisasContext *s, TCGMemOp ot) gen_string_movl_A0_EDI(s); /* Note: we must do this dummy write first to be restartable in case of page fault. */ - tcg_gen_movi_tl(cpu_T0, 0); - gen_op_st_v(s, ot, cpu_T0, cpu_A0); - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]); - tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff); - gen_helper_in_func(ot, cpu_T0, cpu_tmp2_i32); - gen_op_st_v(s, ot, cpu_T0, cpu_A0); - gen_op_movl_T0_Dshift(ot); - gen_op_add_reg_T0(s->aflag, R_EDI); - gen_bpt_io(s, cpu_tmp2_i32, ot); + tcg_gen_movi_tl(s->T0, 0); + gen_op_st_v(s, ot, s->T0, s->A0); + tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]); + tcg_gen_andi_i32(s->tmp2_i32, s->tmp2_i32, 0xffff); + gen_helper_in_func(ot, s->T0, s->tmp2_i32); + gen_op_st_v(s, ot, s->T0, s->A0); + gen_op_movl_T0_Dshift(s, ot); + gen_op_add_reg_T0(s, s->aflag, R_EDI); + gen_bpt_io(s, s->tmp2_i32, ot); if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { gen_io_end(); } @@ -1143,15 +1154,15 @@ static inline void gen_outs(DisasContext *s, TCGMemOp ot) gen_io_start(); } gen_string_movl_A0_ESI(s); - gen_op_ld_v(s, ot, cpu_T0, cpu_A0); + gen_op_ld_v(s, ot, s->T0, s->A0); - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]); - tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff); - tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T0); - gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32); - gen_op_movl_T0_Dshift(ot); - gen_op_add_reg_T0(s->aflag, R_ESI); - gen_bpt_io(s, cpu_tmp2_i32, ot); + tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_EDX]); + tcg_gen_andi_i32(s->tmp2_i32, s->tmp2_i32, 0xffff); + tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T0); + gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32); + gen_op_movl_T0_Dshift(s, ot); + gen_op_add_reg_T0(s, s->aflag, R_ESI); + gen_bpt_io(s, s->tmp2_i32, ot); if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { gen_io_end(); } @@ -1167,11 +1178,11 @@ static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \ gen_update_cc_op(s); \ l2 = gen_jz_ecx_string(s, next_eip); \ gen_ ## op(s, ot); \ - gen_op_add_reg_im(s->aflag, R_ECX, -1); \ + gen_op_add_reg_im(s, s->aflag, R_ECX, -1); \ /* a loop would cause two single step exceptions if ECX = 1 \ before rep string_insn */ \ if (s->repz_opt) \ - gen_op_jz_ecx(s->aflag, l2); \ + gen_op_jz_ecx(s, s->aflag, l2); \ gen_jmp(s, cur_eip); \ } @@ -1185,11 +1196,11 @@ static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \ gen_update_cc_op(s); \ l2 = gen_jz_ecx_string(s, next_eip); \ gen_ ## op(s, ot); \ - gen_op_add_reg_im(s->aflag, R_ECX, -1); \ + gen_op_add_reg_im(s, s->aflag, R_ECX, -1); \ gen_update_cc_op(s); \ gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \ if (s->repz_opt) \ - gen_op_jz_ecx(s->aflag, l2); \ + gen_op_jz_ecx(s, s->aflag, l2); \ gen_jmp(s, cur_eip); \ } @@ -1261,103 +1272,103 @@ static void gen_helper_fp_arith_STN_ST0(int op, int opreg) static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d) { if (d != OR_TMP0) { - gen_op_mov_v_reg(ot, cpu_T0, d); + gen_op_mov_v_reg(s1, ot, s1->T0, d); } else if (!(s1->prefix & PREFIX_LOCK)) { - gen_op_ld_v(s1, ot, cpu_T0, cpu_A0); + gen_op_ld_v(s1, ot, s1->T0, s1->A0); } switch(op) { case OP_ADCL: - gen_compute_eflags_c(s1, cpu_tmp4); + gen_compute_eflags_c(s1, s1->tmp4); if (s1->prefix & PREFIX_LOCK) { - tcg_gen_add_tl(cpu_T0, cpu_tmp4, cpu_T1); - tcg_gen_atomic_add_fetch_tl(cpu_T0, cpu_A0, cpu_T0, + tcg_gen_add_tl(s1->T0, s1->tmp4, s1->T1); + tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0, s1->mem_index, ot | MO_LE); } else { - tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1); - tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_tmp4); + tcg_gen_add_tl(s1->T0, s1->T0, s1->T1); + tcg_gen_add_tl(s1->T0, s1->T0, s1->tmp4); gen_op_st_rm_T0_A0(s1, ot, d); } - gen_op_update3_cc(cpu_tmp4); + gen_op_update3_cc(s1, s1->tmp4); set_cc_op(s1, CC_OP_ADCB + ot); break; case OP_SBBL: - gen_compute_eflags_c(s1, cpu_tmp4); + gen_compute_eflags_c(s1, s1->tmp4); if (s1->prefix & PREFIX_LOCK) { - tcg_gen_add_tl(cpu_T0, cpu_T1, cpu_tmp4); - tcg_gen_neg_tl(cpu_T0, cpu_T0); - tcg_gen_atomic_add_fetch_tl(cpu_T0, cpu_A0, cpu_T0, + tcg_gen_add_tl(s1->T0, s1->T1, s1->tmp4); + tcg_gen_neg_tl(s1->T0, s1->T0); + tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0, s1->mem_index, ot | MO_LE); } else { - tcg_gen_sub_tl(cpu_T0, cpu_T0, cpu_T1); - tcg_gen_sub_tl(cpu_T0, cpu_T0, cpu_tmp4); + tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1); + tcg_gen_sub_tl(s1->T0, s1->T0, s1->tmp4); gen_op_st_rm_T0_A0(s1, ot, d); } - gen_op_update3_cc(cpu_tmp4); + gen_op_update3_cc(s1, s1->tmp4); set_cc_op(s1, CC_OP_SBBB + ot); break; case OP_ADDL: if (s1->prefix & PREFIX_LOCK) { - tcg_gen_atomic_add_fetch_tl(cpu_T0, cpu_A0, cpu_T1, + tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T1, s1->mem_index, ot | MO_LE); } else { - tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1); + tcg_gen_add_tl(s1->T0, s1->T0, s1->T1); gen_op_st_rm_T0_A0(s1, ot, d); } - gen_op_update2_cc(); + gen_op_update2_cc(s1); set_cc_op(s1, CC_OP_ADDB + ot); break; case OP_SUBL: if (s1->prefix & PREFIX_LOCK) { - tcg_gen_neg_tl(cpu_T0, cpu_T1); - tcg_gen_atomic_fetch_add_tl(cpu_cc_srcT, cpu_A0, cpu_T0, + tcg_gen_neg_tl(s1->T0, s1->T1); + tcg_gen_atomic_fetch_add_tl(s1->cc_srcT, s1->A0, s1->T0, s1->mem_index, ot | MO_LE); - tcg_gen_sub_tl(cpu_T0, cpu_cc_srcT, cpu_T1); + tcg_gen_sub_tl(s1->T0, s1->cc_srcT, s1->T1); } else { - tcg_gen_mov_tl(cpu_cc_srcT, cpu_T0); - tcg_gen_sub_tl(cpu_T0, cpu_T0, cpu_T1); + tcg_gen_mov_tl(s1->cc_srcT, s1->T0); + tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1); gen_op_st_rm_T0_A0(s1, ot, d); } - gen_op_update2_cc(); + gen_op_update2_cc(s1); set_cc_op(s1, CC_OP_SUBB + ot); break; default: case OP_ANDL: if (s1->prefix & PREFIX_LOCK) { - tcg_gen_atomic_and_fetch_tl(cpu_T0, cpu_A0, cpu_T1, + tcg_gen_atomic_and_fetch_tl(s1->T0, s1->A0, s1->T1, s1->mem_index, ot | MO_LE); } else { - tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_T1); + tcg_gen_and_tl(s1->T0, s1->T0, s1->T1); gen_op_st_rm_T0_A0(s1, ot, d); } - gen_op_update1_cc(); + gen_op_update1_cc(s1); set_cc_op(s1, CC_OP_LOGICB + ot); break; case OP_ORL: if (s1->prefix & PREFIX_LOCK) { - tcg_gen_atomic_or_fetch_tl(cpu_T0, cpu_A0, cpu_T1, + tcg_gen_atomic_or_fetch_tl(s1->T0, s1->A0, s1->T1, s1->mem_index, ot | MO_LE); } else { - tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_T1); + tcg_gen_or_tl(s1->T0, s1->T0, s1->T1); gen_op_st_rm_T0_A0(s1, ot, d); } - gen_op_update1_cc(); + gen_op_update1_cc(s1); set_cc_op(s1, CC_OP_LOGICB + ot); break; case OP_XORL: if (s1->prefix & PREFIX_LOCK) { - tcg_gen_atomic_xor_fetch_tl(cpu_T0, cpu_A0, cpu_T1, + tcg_gen_atomic_xor_fetch_tl(s1->T0, s1->A0, s1->T1, s1->mem_index, ot | MO_LE); } else { - tcg_gen_xor_tl(cpu_T0, cpu_T0, cpu_T1); + tcg_gen_xor_tl(s1->T0, s1->T0, s1->T1); gen_op_st_rm_T0_A0(s1, ot, d); } - gen_op_update1_cc(); + gen_op_update1_cc(s1); set_cc_op(s1, CC_OP_LOGICB + ot); break; case OP_CMPL: - tcg_gen_mov_tl(cpu_cc_src, cpu_T1); - tcg_gen_mov_tl(cpu_cc_srcT, cpu_T0); - tcg_gen_sub_tl(cpu_cc_dst, cpu_T0, cpu_T1); + tcg_gen_mov_tl(cpu_cc_src, s1->T1); + tcg_gen_mov_tl(s1->cc_srcT, s1->T0); + tcg_gen_sub_tl(cpu_cc_dst, s1->T0, s1->T1); set_cc_op(s1, CC_OP_SUBB + ot); break; } @@ -1367,21 +1378,21 @@ static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d) static void gen_inc(DisasContext *s1, TCGMemOp ot, int d, int c) { if (s1->prefix & PREFIX_LOCK) { - tcg_gen_movi_tl(cpu_T0, c > 0 ? 1 : -1); - tcg_gen_atomic_add_fetch_tl(cpu_T0, cpu_A0, cpu_T0, + tcg_gen_movi_tl(s1->T0, c > 0 ? 1 : -1); + tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0, s1->mem_index, ot | MO_LE); } else { if (d != OR_TMP0) { - gen_op_mov_v_reg(ot, cpu_T0, d); + gen_op_mov_v_reg(s1, ot, s1->T0, d); } else { - gen_op_ld_v(s1, ot, cpu_T0, cpu_A0); + gen_op_ld_v(s1, ot, s1->T0, s1->A0); } - tcg_gen_addi_tl(cpu_T0, cpu_T0, (c > 0 ? 1 : -1)); + tcg_gen_addi_tl(s1->T0, s1->T0, (c > 0 ? 1 : -1)); gen_op_st_rm_T0_A0(s1, ot, d); } gen_compute_eflags_c(s1, cpu_cc_src); - tcg_gen_mov_tl(cpu_cc_dst, cpu_T0); + tcg_gen_mov_tl(cpu_cc_dst, s1->T0); set_cc_op(s1, (c > 0 ? CC_OP_INCB : CC_OP_DECB) + ot); } @@ -1410,19 +1421,19 @@ static void gen_shift_flags(DisasContext *s, TCGMemOp ot, TCGv result, tcg_temp_free(z_tl); /* Get the two potential CC_OP values into temporaries. */ - tcg_gen_movi_i32(cpu_tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot); + tcg_gen_movi_i32(s->tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot); if (s->cc_op == CC_OP_DYNAMIC) { oldop = cpu_cc_op; } else { - tcg_gen_movi_i32(cpu_tmp3_i32, s->cc_op); - oldop = cpu_tmp3_i32; + tcg_gen_movi_i32(s->tmp3_i32, s->cc_op); + oldop = s->tmp3_i32; } /* Conditionally store the CC_OP value. */ z32 = tcg_const_i32(0); s32 = tcg_temp_new_i32(); tcg_gen_trunc_tl_i32(s32, count); - tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, cpu_tmp2_i32, oldop); + tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, s->tmp2_i32, oldop); tcg_temp_free_i32(z32); tcg_temp_free_i32(s32); @@ -1437,33 +1448,33 @@ static void gen_shift_rm_T1(DisasContext *s, TCGMemOp ot, int op1, /* load */ if (op1 == OR_TMP0) { - gen_op_ld_v(s, ot, cpu_T0, cpu_A0); + gen_op_ld_v(s, ot, s->T0, s->A0); } else { - gen_op_mov_v_reg(ot, cpu_T0, op1); + gen_op_mov_v_reg(s, ot, s->T0, op1); } - tcg_gen_andi_tl(cpu_T1, cpu_T1, mask); - tcg_gen_subi_tl(cpu_tmp0, cpu_T1, 1); + tcg_gen_andi_tl(s->T1, s->T1, mask); + tcg_gen_subi_tl(s->tmp0, s->T1, 1); if (is_right) { if (is_arith) { - gen_exts(ot, cpu_T0); - tcg_gen_sar_tl(cpu_tmp0, cpu_T0, cpu_tmp0); - tcg_gen_sar_tl(cpu_T0, cpu_T0, cpu_T1); + gen_exts(ot, s->T0); + tcg_gen_sar_tl(s->tmp0, s->T0, s->tmp0); + tcg_gen_sar_tl(s->T0, s->T0, s->T1); } else { - gen_extu(ot, cpu_T0); - tcg_gen_shr_tl(cpu_tmp0, cpu_T0, cpu_tmp0); - tcg_gen_shr_tl(cpu_T0, cpu_T0, cpu_T1); + gen_extu(ot, s->T0); + tcg_gen_shr_tl(s->tmp0, s->T0, s->tmp0); + tcg_gen_shr_tl(s->T0, s->T0, s->T1); } } else { - tcg_gen_shl_tl(cpu_tmp0, cpu_T0, cpu_tmp0); - tcg_gen_shl_tl(cpu_T0, cpu_T0, cpu_T1); + tcg_gen_shl_tl(s->tmp0, s->T0, s->tmp0); + tcg_gen_shl_tl(s->T0, s->T0, s->T1); } /* store */ gen_op_st_rm_T0_A0(s, ot, op1); - gen_shift_flags(s, ot, cpu_T0, cpu_tmp0, cpu_T1, is_right); + gen_shift_flags(s, ot, s->T0, s->tmp0, s->T1, is_right); } static void gen_shift_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2, @@ -1473,25 +1484,25 @@ static void gen_shift_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2, /* load */ if (op1 == OR_TMP0) - gen_op_ld_v(s, ot, cpu_T0, cpu_A0); + gen_op_ld_v(s, ot, s->T0, s->A0); else - gen_op_mov_v_reg(ot, cpu_T0, op1); + gen_op_mov_v_reg(s, ot, s->T0, op1); op2 &= mask; if (op2 != 0) { if (is_right) { if (is_arith) { - gen_exts(ot, cpu_T0); - tcg_gen_sari_tl(cpu_tmp4, cpu_T0, op2 - 1); - tcg_gen_sari_tl(cpu_T0, cpu_T0, op2); + gen_exts(ot, s->T0); + tcg_gen_sari_tl(s->tmp4, s->T0, op2 - 1); + tcg_gen_sari_tl(s->T0, s->T0, op2); } else { - gen_extu(ot, cpu_T0); - tcg_gen_shri_tl(cpu_tmp4, cpu_T0, op2 - 1); - tcg_gen_shri_tl(cpu_T0, cpu_T0, op2); + gen_extu(ot, s->T0); + tcg_gen_shri_tl(s->tmp4, s->T0, op2 - 1); + tcg_gen_shri_tl(s->T0, s->T0, op2); } } else { - tcg_gen_shli_tl(cpu_tmp4, cpu_T0, op2 - 1); - tcg_gen_shli_tl(cpu_T0, cpu_T0, op2); + tcg_gen_shli_tl(s->tmp4, s->T0, op2 - 1); + tcg_gen_shli_tl(s->T0, s->T0, op2); } } @@ -1500,8 +1511,8 @@ static void gen_shift_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2, /* update eflags if non zero shift */ if (op2 != 0) { - tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4); - tcg_gen_mov_tl(cpu_cc_dst, cpu_T0); + tcg_gen_mov_tl(cpu_cc_src, s->tmp4); + tcg_gen_mov_tl(cpu_cc_dst, s->T0); set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot); } } @@ -1513,41 +1524,41 @@ static void gen_rot_rm_T1(DisasContext *s, TCGMemOp ot, int op1, int is_right) /* load */ if (op1 == OR_TMP0) { - gen_op_ld_v(s, ot, cpu_T0, cpu_A0); + gen_op_ld_v(s, ot, s->T0, s->A0); } else { - gen_op_mov_v_reg(ot, cpu_T0, op1); + gen_op_mov_v_reg(s, ot, s->T0, op1); } - tcg_gen_andi_tl(cpu_T1, cpu_T1, mask); + tcg_gen_andi_tl(s->T1, s->T1, mask); switch (ot) { case MO_8: /* Replicate the 8-bit input so that a 32-bit rotate works. */ - tcg_gen_ext8u_tl(cpu_T0, cpu_T0); - tcg_gen_muli_tl(cpu_T0, cpu_T0, 0x01010101); + tcg_gen_ext8u_tl(s->T0, s->T0); + tcg_gen_muli_tl(s->T0, s->T0, 0x01010101); goto do_long; case MO_16: /* Replicate the 16-bit input so that a 32-bit rotate works. */ - tcg_gen_deposit_tl(cpu_T0, cpu_T0, cpu_T0, 16, 16); + tcg_gen_deposit_tl(s->T0, s->T0, s->T0, 16, 16); goto do_long; do_long: #ifdef TARGET_X86_64 case MO_32: - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); - tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1); + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); + tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1); if (is_right) { - tcg_gen_rotr_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32); + tcg_gen_rotr_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32); } else { - tcg_gen_rotl_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32); + tcg_gen_rotl_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32); } - tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32); + tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32); break; #endif default: if (is_right) { - tcg_gen_rotr_tl(cpu_T0, cpu_T0, cpu_T1); + tcg_gen_rotr_tl(s->T0, s->T0, s->T1); } else { - tcg_gen_rotl_tl(cpu_T0, cpu_T0, cpu_T1); + tcg_gen_rotl_tl(s->T0, s->T0, s->T1); } break; } @@ -1563,12 +1574,12 @@ static void gen_rot_rm_T1(DisasContext *s, TCGMemOp ot, int op1, int is_right) since we've computed the flags into CC_SRC, these variables are currently dead. */ if (is_right) { - tcg_gen_shri_tl(cpu_cc_src2, cpu_T0, mask - 1); - tcg_gen_shri_tl(cpu_cc_dst, cpu_T0, mask); + tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask - 1); + tcg_gen_shri_tl(cpu_cc_dst, s->T0, mask); tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1); } else { - tcg_gen_shri_tl(cpu_cc_src2, cpu_T0, mask); - tcg_gen_andi_tl(cpu_cc_dst, cpu_T0, 1); + tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask); + tcg_gen_andi_tl(cpu_cc_dst, s->T0, 1); } tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1); tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst); @@ -1579,11 +1590,11 @@ static void gen_rot_rm_T1(DisasContext *s, TCGMemOp ot, int op1, int is_right) exactly as we computed above. */ t0 = tcg_const_i32(0); t1 = tcg_temp_new_i32(); - tcg_gen_trunc_tl_i32(t1, cpu_T1); - tcg_gen_movi_i32(cpu_tmp2_i32, CC_OP_ADCOX); - tcg_gen_movi_i32(cpu_tmp3_i32, CC_OP_EFLAGS); + tcg_gen_trunc_tl_i32(t1, s->T1); + tcg_gen_movi_i32(s->tmp2_i32, CC_OP_ADCOX); + tcg_gen_movi_i32(s->tmp3_i32, CC_OP_EFLAGS); tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0, - cpu_tmp2_i32, cpu_tmp3_i32); + s->tmp2_i32, s->tmp3_i32); tcg_temp_free_i32(t0); tcg_temp_free_i32(t1); @@ -1599,9 +1610,9 @@ static void gen_rot_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2, /* load */ if (op1 == OR_TMP0) { - gen_op_ld_v(s, ot, cpu_T0, cpu_A0); + gen_op_ld_v(s, ot, s->T0, s->A0); } else { - gen_op_mov_v_reg(ot, cpu_T0, op1); + gen_op_mov_v_reg(s, ot, s->T0, op1); } op2 &= mask; @@ -1609,20 +1620,20 @@ static void gen_rot_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2, switch (ot) { #ifdef TARGET_X86_64 case MO_32: - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); if (is_right) { - tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2); + tcg_gen_rotri_i32(s->tmp2_i32, s->tmp2_i32, op2); } else { - tcg_gen_rotli_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2); + tcg_gen_rotli_i32(s->tmp2_i32, s->tmp2_i32, op2); } - tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32); + tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32); break; #endif default: if (is_right) { - tcg_gen_rotri_tl(cpu_T0, cpu_T0, op2); + tcg_gen_rotri_tl(s->T0, s->T0, op2); } else { - tcg_gen_rotli_tl(cpu_T0, cpu_T0, op2); + tcg_gen_rotli_tl(s->T0, s->T0, op2); } break; case MO_8: @@ -1635,10 +1646,10 @@ static void gen_rot_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2, if (is_right) { shift = mask + 1 - shift; } - gen_extu(ot, cpu_T0); - tcg_gen_shli_tl(cpu_tmp0, cpu_T0, shift); - tcg_gen_shri_tl(cpu_T0, cpu_T0, mask + 1 - shift); - tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_tmp0); + gen_extu(ot, s->T0); + tcg_gen_shli_tl(s->tmp0, s->T0, shift); + tcg_gen_shri_tl(s->T0, s->T0, mask + 1 - shift); + tcg_gen_or_tl(s->T0, s->T0, s->tmp0); break; } } @@ -1655,12 +1666,12 @@ static void gen_rot_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2, since we've computed the flags into CC_SRC, these variables are currently dead. */ if (is_right) { - tcg_gen_shri_tl(cpu_cc_src2, cpu_T0, mask - 1); - tcg_gen_shri_tl(cpu_cc_dst, cpu_T0, mask); + tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask - 1); + tcg_gen_shri_tl(cpu_cc_dst, s->T0, mask); tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1); } else { - tcg_gen_shri_tl(cpu_cc_src2, cpu_T0, mask); - tcg_gen_andi_tl(cpu_cc_dst, cpu_T0, 1); + tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask); + tcg_gen_andi_tl(cpu_cc_dst, s->T0, 1); } tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1); tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst); @@ -1677,24 +1688,24 @@ static void gen_rotc_rm_T1(DisasContext *s, TCGMemOp ot, int op1, /* load */ if (op1 == OR_TMP0) - gen_op_ld_v(s, ot, cpu_T0, cpu_A0); + gen_op_ld_v(s, ot, s->T0, s->A0); else - gen_op_mov_v_reg(ot, cpu_T0, op1); + gen_op_mov_v_reg(s, ot, s->T0, op1); if (is_right) { switch (ot) { case MO_8: - gen_helper_rcrb(cpu_T0, cpu_env, cpu_T0, cpu_T1); + gen_helper_rcrb(s->T0, cpu_env, s->T0, s->T1); break; case MO_16: - gen_helper_rcrw(cpu_T0, cpu_env, cpu_T0, cpu_T1); + gen_helper_rcrw(s->T0, cpu_env, s->T0, s->T1); break; case MO_32: - gen_helper_rcrl(cpu_T0, cpu_env, cpu_T0, cpu_T1); + gen_helper_rcrl(s->T0, cpu_env, s->T0, s->T1); break; #ifdef TARGET_X86_64 case MO_64: - gen_helper_rcrq(cpu_T0, cpu_env, cpu_T0, cpu_T1); + gen_helper_rcrq(s->T0, cpu_env, s->T0, s->T1); break; #endif default: @@ -1703,17 +1714,17 @@ static void gen_rotc_rm_T1(DisasContext *s, TCGMemOp ot, int op1, } else { switch (ot) { case MO_8: - gen_helper_rclb(cpu_T0, cpu_env, cpu_T0, cpu_T1); + gen_helper_rclb(s->T0, cpu_env, s->T0, s->T1); break; case MO_16: - gen_helper_rclw(cpu_T0, cpu_env, cpu_T0, cpu_T1); + gen_helper_rclw(s->T0, cpu_env, s->T0, s->T1); break; case MO_32: - gen_helper_rcll(cpu_T0, cpu_env, cpu_T0, cpu_T1); + gen_helper_rcll(s->T0, cpu_env, s->T0, s->T1); break; #ifdef TARGET_X86_64 case MO_64: - gen_helper_rclq(cpu_T0, cpu_env, cpu_T0, cpu_T1); + gen_helper_rclq(s->T0, cpu_env, s->T0, s->T1); break; #endif default: @@ -1733,9 +1744,9 @@ static void gen_shiftd_rm_T1(DisasContext *s, TCGMemOp ot, int op1, /* load */ if (op1 == OR_TMP0) { - gen_op_ld_v(s, ot, cpu_T0, cpu_A0); + gen_op_ld_v(s, ot, s->T0, s->A0); } else { - gen_op_mov_v_reg(ot, cpu_T0, op1); + gen_op_mov_v_reg(s, ot, s->T0, op1); } count = tcg_temp_new(); @@ -1747,69 +1758,69 @@ static void gen_shiftd_rm_T1(DisasContext *s, TCGMemOp ot, int op1, This means "shrdw C, B, A" shifts A:B:A >> C. Build the B:A portion by constructing it as a 32-bit value. */ if (is_right) { - tcg_gen_deposit_tl(cpu_tmp0, cpu_T0, cpu_T1, 16, 16); - tcg_gen_mov_tl(cpu_T1, cpu_T0); - tcg_gen_mov_tl(cpu_T0, cpu_tmp0); + tcg_gen_deposit_tl(s->tmp0, s->T0, s->T1, 16, 16); + tcg_gen_mov_tl(s->T1, s->T0); + tcg_gen_mov_tl(s->T0, s->tmp0); } else { - tcg_gen_deposit_tl(cpu_T1, cpu_T0, cpu_T1, 16, 16); + tcg_gen_deposit_tl(s->T1, s->T0, s->T1, 16, 16); } /* FALLTHRU */ #ifdef TARGET_X86_64 case MO_32: /* Concatenate the two 32-bit values and use a 64-bit shift. */ - tcg_gen_subi_tl(cpu_tmp0, count, 1); + tcg_gen_subi_tl(s->tmp0, count, 1); if (is_right) { - tcg_gen_concat_tl_i64(cpu_T0, cpu_T0, cpu_T1); - tcg_gen_shr_i64(cpu_tmp0, cpu_T0, cpu_tmp0); - tcg_gen_shr_i64(cpu_T0, cpu_T0, count); + tcg_gen_concat_tl_i64(s->T0, s->T0, s->T1); + tcg_gen_shr_i64(s->tmp0, s->T0, s->tmp0); + tcg_gen_shr_i64(s->T0, s->T0, count); } else { - tcg_gen_concat_tl_i64(cpu_T0, cpu_T1, cpu_T0); - tcg_gen_shl_i64(cpu_tmp0, cpu_T0, cpu_tmp0); - tcg_gen_shl_i64(cpu_T0, cpu_T0, count); - tcg_gen_shri_i64(cpu_tmp0, cpu_tmp0, 32); - tcg_gen_shri_i64(cpu_T0, cpu_T0, 32); + tcg_gen_concat_tl_i64(s->T0, s->T1, s->T0); + tcg_gen_shl_i64(s->tmp0, s->T0, s->tmp0); + tcg_gen_shl_i64(s->T0, s->T0, count); + tcg_gen_shri_i64(s->tmp0, s->tmp0, 32); + tcg_gen_shri_i64(s->T0, s->T0, 32); } break; #endif default: - tcg_gen_subi_tl(cpu_tmp0, count, 1); + tcg_gen_subi_tl(s->tmp0, count, 1); if (is_right) { - tcg_gen_shr_tl(cpu_tmp0, cpu_T0, cpu_tmp0); + tcg_gen_shr_tl(s->tmp0, s->T0, s->tmp0); - tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count); - tcg_gen_shr_tl(cpu_T0, cpu_T0, count); - tcg_gen_shl_tl(cpu_T1, cpu_T1, cpu_tmp4); + tcg_gen_subfi_tl(s->tmp4, mask + 1, count); + tcg_gen_shr_tl(s->T0, s->T0, count); + tcg_gen_shl_tl(s->T1, s->T1, s->tmp4); } else { - tcg_gen_shl_tl(cpu_tmp0, cpu_T0, cpu_tmp0); + tcg_gen_shl_tl(s->tmp0, s->T0, s->tmp0); if (ot == MO_16) { /* Only needed if count > 16, for Intel behaviour. */ - tcg_gen_subfi_tl(cpu_tmp4, 33, count); - tcg_gen_shr_tl(cpu_tmp4, cpu_T1, cpu_tmp4); - tcg_gen_or_tl(cpu_tmp0, cpu_tmp0, cpu_tmp4); + tcg_gen_subfi_tl(s->tmp4, 33, count); + tcg_gen_shr_tl(s->tmp4, s->T1, s->tmp4); + tcg_gen_or_tl(s->tmp0, s->tmp0, s->tmp4); } - tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count); - tcg_gen_shl_tl(cpu_T0, cpu_T0, count); - tcg_gen_shr_tl(cpu_T1, cpu_T1, cpu_tmp4); + tcg_gen_subfi_tl(s->tmp4, mask + 1, count); + tcg_gen_shl_tl(s->T0, s->T0, count); + tcg_gen_shr_tl(s->T1, s->T1, s->tmp4); } - tcg_gen_movi_tl(cpu_tmp4, 0); - tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T1, count, cpu_tmp4, - cpu_tmp4, cpu_T1); - tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_T1); + tcg_gen_movi_tl(s->tmp4, 0); + tcg_gen_movcond_tl(TCG_COND_EQ, s->T1, count, s->tmp4, + s->tmp4, s->T1); + tcg_gen_or_tl(s->T0, s->T0, s->T1); break; } /* store */ gen_op_st_rm_T0_A0(s, ot, op1); - gen_shift_flags(s, ot, cpu_T0, cpu_tmp0, count, is_right); + gen_shift_flags(s, ot, s->T0, s->tmp0, count, is_right); tcg_temp_free(count); } static void gen_shift(DisasContext *s1, int op, TCGMemOp ot, int d, int s) { if (s != OR_TMP1) - gen_op_mov_v_reg(ot, cpu_T1, s); + gen_op_mov_v_reg(s1, ot, s1->T1, s); switch(op) { case OP_ROL: gen_rot_rm_T1(s1, ot, d, 0); @@ -1857,7 +1868,7 @@ static void gen_shifti(DisasContext *s1, int op, TCGMemOp ot, int d, int c) break; default: /* currently not optimized */ - tcg_gen_movi_tl(cpu_T1, c); + tcg_gen_movi_tl(s1->T1, c); gen_shift(s1, op, ot, d, OR_TMP1); break; } @@ -2048,7 +2059,7 @@ static AddressParts gen_lea_modrm_0(CPUX86State *env, DisasContext *s, } /* Compute the address, with a minimum number of TCG ops. */ -static TCGv gen_lea_modrm_1(AddressParts a) +static TCGv gen_lea_modrm_1(DisasContext *s, AddressParts a) { TCGv ea = NULL; @@ -2056,22 +2067,22 @@ static TCGv gen_lea_modrm_1(AddressParts a) if (a.scale == 0) { ea = cpu_regs[a.index]; } else { - tcg_gen_shli_tl(cpu_A0, cpu_regs[a.index], a.scale); - ea = cpu_A0; + tcg_gen_shli_tl(s->A0, cpu_regs[a.index], a.scale); + ea = s->A0; } if (a.base >= 0) { - tcg_gen_add_tl(cpu_A0, ea, cpu_regs[a.base]); - ea = cpu_A0; + tcg_gen_add_tl(s->A0, ea, cpu_regs[a.base]); + ea = s->A0; } } else if (a.base >= 0) { ea = cpu_regs[a.base]; } if (!ea) { - tcg_gen_movi_tl(cpu_A0, a.disp); - ea = cpu_A0; + tcg_gen_movi_tl(s->A0, a.disp); + ea = s->A0; } else if (a.disp != 0) { - tcg_gen_addi_tl(cpu_A0, ea, a.disp); - ea = cpu_A0; + tcg_gen_addi_tl(s->A0, ea, a.disp); + ea = s->A0; } return ea; @@ -2080,7 +2091,7 @@ static TCGv gen_lea_modrm_1(AddressParts a) static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm) { AddressParts a = gen_lea_modrm_0(env, s, modrm); - TCGv ea = gen_lea_modrm_1(a); + TCGv ea = gen_lea_modrm_1(s, a); gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override); } @@ -2093,21 +2104,21 @@ static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm) static void gen_bndck(CPUX86State *env, DisasContext *s, int modrm, TCGCond cond, TCGv_i64 bndv) { - TCGv ea = gen_lea_modrm_1(gen_lea_modrm_0(env, s, modrm)); + TCGv ea = gen_lea_modrm_1(s, gen_lea_modrm_0(env, s, modrm)); - tcg_gen_extu_tl_i64(cpu_tmp1_i64, ea); + tcg_gen_extu_tl_i64(s->tmp1_i64, ea); if (!CODE64(s)) { - tcg_gen_ext32u_i64(cpu_tmp1_i64, cpu_tmp1_i64); + tcg_gen_ext32u_i64(s->tmp1_i64, s->tmp1_i64); } - tcg_gen_setcond_i64(cond, cpu_tmp1_i64, cpu_tmp1_i64, bndv); - tcg_gen_extrl_i64_i32(cpu_tmp2_i32, cpu_tmp1_i64); - gen_helper_bndck(cpu_env, cpu_tmp2_i32); + tcg_gen_setcond_i64(cond, s->tmp1_i64, s->tmp1_i64, bndv); + tcg_gen_extrl_i64_i32(s->tmp2_i32, s->tmp1_i64); + gen_helper_bndck(cpu_env, s->tmp2_i32); } /* used for LEA and MOV AX, mem */ static void gen_add_A0_ds_seg(DisasContext *s) { - gen_lea_v_seg(s, s->aflag, cpu_A0, R_DS, s->override); + gen_lea_v_seg(s, s->aflag, s->A0, R_DS, s->override); } /* generate modrm memory load or store of 'reg'. TMP0 is used if reg == @@ -2122,23 +2133,23 @@ static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm, if (mod == 3) { if (is_store) { if (reg != OR_TMP0) - gen_op_mov_v_reg(ot, cpu_T0, reg); - gen_op_mov_reg_v(ot, rm, cpu_T0); + gen_op_mov_v_reg(s, ot, s->T0, reg); + gen_op_mov_reg_v(s, ot, rm, s->T0); } else { - gen_op_mov_v_reg(ot, cpu_T0, rm); + gen_op_mov_v_reg(s, ot, s->T0, rm); if (reg != OR_TMP0) - gen_op_mov_reg_v(ot, reg, cpu_T0); + gen_op_mov_reg_v(s, ot, reg, s->T0); } } else { gen_lea_modrm(env, s, modrm); if (is_store) { if (reg != OR_TMP0) - gen_op_mov_v_reg(ot, cpu_T0, reg); - gen_op_st_v(s, ot, cpu_T0, cpu_A0); + gen_op_mov_v_reg(s, ot, s->T0, reg); + gen_op_st_v(s, ot, s->T0, s->A0); } else { - gen_op_ld_v(s, ot, cpu_T0, cpu_A0); + gen_op_ld_v(s, ot, s->T0, s->A0); if (reg != OR_TMP0) - gen_op_mov_reg_v(ot, reg, cpu_T0); + gen_op_mov_reg_v(s, ot, reg, s->T0); } } } @@ -2192,13 +2203,13 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip) if (use_goto_tb(s, pc)) { /* jump to same page: we can use a direct jump */ tcg_gen_goto_tb(tb_num); - gen_jmp_im(eip); + gen_jmp_im(s, eip); tcg_gen_exit_tb(s->base.tb, tb_num); s->base.is_jmp = DISAS_NORETURN; } else { /* jump to another page */ - gen_jmp_im(eip); - gen_jr(s, cpu_tmp0); + gen_jmp_im(s, eip); + gen_jr(s, s->tmp0); } } @@ -2220,11 +2231,11 @@ static inline void gen_jcc(DisasContext *s, int b, l2 = gen_new_label(); gen_jcc1(s, b, l1); - gen_jmp_im(next_eip); + gen_jmp_im(s, next_eip); tcg_gen_br(l2); gen_set_label(l1); - gen_jmp_im(val); + gen_jmp_im(s, val); gen_set_label(l2); gen_eob(s); } @@ -2237,7 +2248,7 @@ static void gen_cmovcc1(CPUX86State *env, DisasContext *s, TCGMemOp ot, int b, gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - cc = gen_prepare_cc(s, b, cpu_T1); + cc = gen_prepare_cc(s, b, s->T1); if (cc.mask != -1) { TCGv t0 = tcg_temp_new(); tcg_gen_andi_tl(t0, cc.reg, cc.mask); @@ -2247,9 +2258,9 @@ static void gen_cmovcc1(CPUX86State *env, DisasContext *s, TCGMemOp ot, int b, cc.reg2 = tcg_const_tl(cc.imm); } - tcg_gen_movcond_tl(cc.cond, cpu_T0, cc.reg, cc.reg2, - cpu_T0, cpu_regs[reg]); - gen_op_mov_reg_v(ot, reg, cpu_T0); + tcg_gen_movcond_tl(cc.cond, s->T0, cc.reg, cc.reg2, + s->T0, cpu_regs[reg]); + gen_op_mov_reg_v(s, ot, reg, s->T0); if (cc.mask != -1) { tcg_temp_free(cc.reg); @@ -2259,18 +2270,18 @@ static void gen_cmovcc1(CPUX86State *env, DisasContext *s, TCGMemOp ot, int b, } } -static inline void gen_op_movl_T0_seg(int seg_reg) +static inline void gen_op_movl_T0_seg(DisasContext *s, int seg_reg) { - tcg_gen_ld32u_tl(cpu_T0, cpu_env, + tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State,segs[seg_reg].selector)); } -static inline void gen_op_movl_seg_T0_vm(int seg_reg) +static inline void gen_op_movl_seg_T0_vm(DisasContext *s, int seg_reg) { - tcg_gen_ext16u_tl(cpu_T0, cpu_T0); - tcg_gen_st32_tl(cpu_T0, cpu_env, + tcg_gen_ext16u_tl(s->T0, s->T0); + tcg_gen_st32_tl(s->T0, cpu_env, offsetof(CPUX86State,segs[seg_reg].selector)); - tcg_gen_shli_tl(cpu_seg_base[seg_reg], cpu_T0, 4); + tcg_gen_shli_tl(cpu_seg_base[seg_reg], s->T0, 4); } /* move T0 to seg_reg and compute if the CPU state may change. Never @@ -2278,8 +2289,8 @@ static inline void gen_op_movl_seg_T0_vm(int seg_reg) static void gen_movl_seg_T0(DisasContext *s, int seg_reg) { if (s->pe && !s->vm86) { - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); - gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), cpu_tmp2_i32); + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); + gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), s->tmp2_i32); /* abort translation because the addseg value may change or because ss32 may change. For R_SS, translation must always stop as a special handling must be done to disable hardware @@ -2288,7 +2299,7 @@ static void gen_movl_seg_T0(DisasContext *s, int seg_reg) s->base.is_jmp = DISAS_TOO_MANY; } } else { - gen_op_movl_seg_T0_vm(seg_reg); + gen_op_movl_seg_T0_vm(s, seg_reg); if (seg_reg == R_SS) { s->base.is_jmp = DISAS_TOO_MANY; } @@ -2305,10 +2316,10 @@ gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start, uint32_t type, uint64_t param) { /* no SVM activated; fast case */ - if (likely(!(s->flags & HF_SVMI_MASK))) + if (likely(!(s->flags & HF_GUEST_MASK))) return; gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); gen_helper_svm_check_intercept_param(cpu_env, tcg_const_i32(type), tcg_const_i64(param)); } @@ -2321,7 +2332,7 @@ gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type) static inline void gen_stack_update(DisasContext *s, int addend) { - gen_op_add_reg_im(mo_stacksize(s), R_ESP, addend); + gen_op_add_reg_im(s, mo_stacksize(s), R_ESP, addend); } /* Generate a push. It depends on ss32, addseg and dflag. */ @@ -2330,20 +2341,20 @@ static void gen_push_v(DisasContext *s, TCGv val) TCGMemOp d_ot = mo_pushpop(s, s->dflag); TCGMemOp a_ot = mo_stacksize(s); int size = 1 << d_ot; - TCGv new_esp = cpu_A0; + TCGv new_esp = s->A0; - tcg_gen_subi_tl(cpu_A0, cpu_regs[R_ESP], size); + tcg_gen_subi_tl(s->A0, cpu_regs[R_ESP], size); if (!CODE64(s)) { if (s->addseg) { - new_esp = cpu_tmp4; - tcg_gen_mov_tl(new_esp, cpu_A0); + new_esp = s->tmp4; + tcg_gen_mov_tl(new_esp, s->A0); } - gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1); + gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1); } - gen_op_st_v(s, d_ot, val, cpu_A0); - gen_op_mov_reg_v(a_ot, R_ESP, new_esp); + gen_op_st_v(s, d_ot, val, s->A0); + gen_op_mov_reg_v(s, a_ot, R_ESP, new_esp); } /* two step pop is necessary for precise exceptions */ @@ -2352,7 +2363,7 @@ static TCGMemOp gen_pop_T0(DisasContext *s) TCGMemOp d_ot = mo_pushpop(s, s->dflag); gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1); - gen_op_ld_v(s, d_ot, cpu_T0, cpu_A0); + gen_op_ld_v(s, d_ot, s->T0, s->A0); return d_ot; } @@ -2375,9 +2386,9 @@ static void gen_pusha(DisasContext *s) int i; for (i = 0; i < 8; i++) { - tcg_gen_addi_tl(cpu_A0, cpu_regs[R_ESP], (i - 8) * size); - gen_lea_v_seg(s, s_ot, cpu_A0, R_SS, -1); - gen_op_st_v(s, d_ot, cpu_regs[7 - i], cpu_A0); + tcg_gen_addi_tl(s->A0, cpu_regs[R_ESP], (i - 8) * size); + gen_lea_v_seg(s, s_ot, s->A0, R_SS, -1); + gen_op_st_v(s, d_ot, cpu_regs[7 - i], s->A0); } gen_stack_update(s, -8 * size); @@ -2395,10 +2406,10 @@ static void gen_popa(DisasContext *s) if (7 - i == R_ESP) { continue; } - tcg_gen_addi_tl(cpu_A0, cpu_regs[R_ESP], i * size); - gen_lea_v_seg(s, s_ot, cpu_A0, R_SS, -1); - gen_op_ld_v(s, d_ot, cpu_T0, cpu_A0); - gen_op_mov_reg_v(d_ot, 7 - i, cpu_T0); + tcg_gen_addi_tl(s->A0, cpu_regs[R_ESP], i * size); + gen_lea_v_seg(s, s_ot, s->A0, R_SS, -1); + gen_op_ld_v(s, d_ot, s->T0, s->A0); + gen_op_mov_reg_v(s, d_ot, 7 - i, s->T0); } gen_stack_update(s, 8 * size); @@ -2411,9 +2422,9 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) int size = 1 << d_ot; /* Push BP; compute FrameTemp into T1. */ - tcg_gen_subi_tl(cpu_T1, cpu_regs[R_ESP], size); - gen_lea_v_seg(s, a_ot, cpu_T1, R_SS, -1); - gen_op_st_v(s, d_ot, cpu_regs[R_EBP], cpu_A0); + tcg_gen_subi_tl(s->T1, cpu_regs[R_ESP], size); + gen_lea_v_seg(s, a_ot, s->T1, R_SS, -1); + gen_op_st_v(s, d_ot, cpu_regs[R_EBP], s->A0); level &= 31; if (level != 0) { @@ -2421,27 +2432,27 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) /* Copy level-1 pointers from the previous frame. */ for (i = 1; i < level; ++i) { - tcg_gen_subi_tl(cpu_A0, cpu_regs[R_EBP], size * i); - gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1); - gen_op_ld_v(s, d_ot, cpu_tmp0, cpu_A0); + tcg_gen_subi_tl(s->A0, cpu_regs[R_EBP], size * i); + gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1); + gen_op_ld_v(s, d_ot, s->tmp0, s->A0); - tcg_gen_subi_tl(cpu_A0, cpu_T1, size * i); - gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1); - gen_op_st_v(s, d_ot, cpu_tmp0, cpu_A0); + tcg_gen_subi_tl(s->A0, s->T1, size * i); + gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1); + gen_op_st_v(s, d_ot, s->tmp0, s->A0); } /* Push the current FrameTemp as the last level. */ - tcg_gen_subi_tl(cpu_A0, cpu_T1, size * level); - gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1); - gen_op_st_v(s, d_ot, cpu_T1, cpu_A0); + tcg_gen_subi_tl(s->A0, s->T1, size * level); + gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1); + gen_op_st_v(s, d_ot, s->T1, s->A0); } /* Copy the FrameTemp value to EBP. */ - gen_op_mov_reg_v(a_ot, R_EBP, cpu_T1); + gen_op_mov_reg_v(s, a_ot, R_EBP, s->T1); /* Compute the final value of ESP. */ - tcg_gen_subi_tl(cpu_T1, cpu_T1, esp_addend + size * level); - gen_op_mov_reg_v(a_ot, R_ESP, cpu_T1); + tcg_gen_subi_tl(s->T1, s->T1, esp_addend + size * level); + gen_op_mov_reg_v(s, a_ot, R_ESP, s->T1); } static void gen_leave(DisasContext *s) @@ -2450,18 +2461,18 @@ static void gen_leave(DisasContext *s) TCGMemOp a_ot = mo_stacksize(s); gen_lea_v_seg(s, a_ot, cpu_regs[R_EBP], R_SS, -1); - gen_op_ld_v(s, d_ot, cpu_T0, cpu_A0); + gen_op_ld_v(s, d_ot, s->T0, s->A0); - tcg_gen_addi_tl(cpu_T1, cpu_regs[R_EBP], 1 << d_ot); + tcg_gen_addi_tl(s->T1, cpu_regs[R_EBP], 1 << d_ot); - gen_op_mov_reg_v(d_ot, R_EBP, cpu_T0); - gen_op_mov_reg_v(a_ot, R_ESP, cpu_T1); + gen_op_mov_reg_v(s, d_ot, R_EBP, s->T0); + gen_op_mov_reg_v(s, a_ot, R_ESP, s->T1); } static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip) { gen_update_cc_op(s); - gen_jmp_im(cur_eip); + gen_jmp_im(s, cur_eip); gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno)); s->base.is_jmp = DISAS_NORETURN; } @@ -2498,7 +2509,7 @@ static void gen_interrupt(DisasContext *s, int intno, target_ulong cur_eip, target_ulong next_eip) { gen_update_cc_op(s); - gen_jmp_im(cur_eip); + gen_jmp_im(s, cur_eip); gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno), tcg_const_i32(next_eip - cur_eip)); s->base.is_jmp = DISAS_NORETURN; @@ -2507,7 +2518,7 @@ static void gen_interrupt(DisasContext *s, int intno, static void gen_debug(DisasContext *s, target_ulong cur_eip) { gen_update_cc_op(s); - gen_jmp_im(cur_eip); + gen_jmp_im(s, cur_eip); gen_helper_debug(cpu_env); s->base.is_jmp = DISAS_NORETURN; } @@ -2617,7 +2628,7 @@ static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num) if (s->jmp_opt) { gen_goto_tb(s, tb_num, eip); } else { - gen_jmp_im(eip); + gen_jmp_im(s, eip); gen_eob(s); } } @@ -2629,60 +2640,60 @@ static void gen_jmp(DisasContext *s, target_ulong eip) static inline void gen_ldq_env_A0(DisasContext *s, int offset) { - tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ); - tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset); + tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ); + tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset); } static inline void gen_stq_env_A0(DisasContext *s, int offset) { - tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset); - tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ); + tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset); + tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ); } static inline void gen_ldo_env_A0(DisasContext *s, int offset) { int mem_index = s->mem_index; - tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, mem_index, MO_LEQ); - tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0))); - tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8); - tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_tmp0, mem_index, MO_LEQ); - tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1))); + tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index, MO_LEQ); + tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0))); + tcg_gen_addi_tl(s->tmp0, s->A0, 8); + tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEQ); + tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1))); } static inline void gen_sto_env_A0(DisasContext *s, int offset) { int mem_index = s->mem_index; - tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0))); - tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, mem_index, MO_LEQ); - tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8); - tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1))); - tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_tmp0, mem_index, MO_LEQ); + tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0))); + tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, mem_index, MO_LEQ); + tcg_gen_addi_tl(s->tmp0, s->A0, 8); + tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1))); + tcg_gen_qemu_st_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEQ); } -static inline void gen_op_movo(int d_offset, int s_offset) +static inline void gen_op_movo(DisasContext *s, int d_offset, int s_offset) { - tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(0))); - tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(0))); - tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(1))); - tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(1))); + tcg_gen_ld_i64(s->tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(0))); + tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(0))); + tcg_gen_ld_i64(s->tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(1))); + tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(1))); } -static inline void gen_op_movq(int d_offset, int s_offset) +static inline void gen_op_movq(DisasContext *s, int d_offset, int s_offset) { - tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset); - tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset); + tcg_gen_ld_i64(s->tmp1_i64, cpu_env, s_offset); + tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset); } -static inline void gen_op_movl(int d_offset, int s_offset) +static inline void gen_op_movl(DisasContext *s, int d_offset, int s_offset) { - tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, s_offset); - tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, d_offset); + tcg_gen_ld_i32(s->tmp2_i32, cpu_env, s_offset); + tcg_gen_st_i32(s->tmp2_i32, cpu_env, d_offset); } -static inline void gen_op_movq_env_0(int d_offset) +static inline void gen_op_movq_env_0(DisasContext *s, int d_offset) { - tcg_gen_movi_i64(cpu_tmp1_i64, 0); - tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset); + tcg_gen_movi_i64(s->tmp1_i64, 0); + tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset); } typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg); @@ -3122,41 +3133,42 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_stq_env_A0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0))); } else { - tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State, + tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0))); - gen_op_st_v(s, MO_32, cpu_T0, cpu_A0); + gen_op_st_v(s, MO_32, s->T0, s->A0); } break; case 0x6e: /* movd mm, ea */ #ifdef TARGET_X86_64 if (s->dflag == MO_64) { gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0); - tcg_gen_st_tl(cpu_T0, cpu_env, offsetof(CPUX86State,fpregs[reg].mmx)); + tcg_gen_st_tl(s->T0, cpu_env, + offsetof(CPUX86State, fpregs[reg].mmx)); } else #endif { gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0); - tcg_gen_addi_ptr(cpu_ptr0, cpu_env, + tcg_gen_addi_ptr(s->ptr0, cpu_env, offsetof(CPUX86State,fpregs[reg].mmx)); - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); - gen_helper_movl_mm_T0_mmx(cpu_ptr0, cpu_tmp2_i32); + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); + gen_helper_movl_mm_T0_mmx(s->ptr0, s->tmp2_i32); } break; case 0x16e: /* movd xmm, ea */ #ifdef TARGET_X86_64 if (s->dflag == MO_64) { gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0); - tcg_gen_addi_ptr(cpu_ptr0, cpu_env, + tcg_gen_addi_ptr(s->ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[reg])); - gen_helper_movq_mm_T0_xmm(cpu_ptr0, cpu_T0); + gen_helper_movq_mm_T0_xmm(s->ptr0, s->T0); } else #endif { gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0); - tcg_gen_addi_ptr(cpu_ptr0, cpu_env, + tcg_gen_addi_ptr(s->ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[reg])); - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); - gen_helper_movl_mm_T0_xmm(cpu_ptr0, cpu_tmp2_i32); + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); + gen_helper_movl_mm_T0_xmm(s->ptr0, s->tmp2_i32); } break; case 0x6f: /* movq mm, ea */ @@ -3165,9 +3177,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx)); } else { rm = (modrm & 7); - tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, + tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx)); - tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, + tcg_gen_st_i64(s->tmp1_i64, cpu_env, offsetof(CPUX86State,fpregs[reg].mmx)); } break; @@ -3182,22 +3194,26 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg])); } else { rm = (modrm & 7) | REX_B(s); - gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]), + gen_op_movo(s, offsetof(CPUX86State, xmm_regs[reg]), offsetof(CPUX86State,xmm_regs[rm])); } break; case 0x210: /* movss xmm, ea */ if (mod != 3) { gen_lea_modrm(env, s, modrm); - gen_op_ld_v(s, MO_32, cpu_T0, cpu_A0); - tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0))); - tcg_gen_movi_tl(cpu_T0, 0); - tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1))); - tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2))); - tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3))); + gen_op_ld_v(s, MO_32, s->T0, s->A0); + tcg_gen_st32_tl(s->T0, cpu_env, + offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0))); + tcg_gen_movi_tl(s->T0, 0); + tcg_gen_st32_tl(s->T0, cpu_env, + offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1))); + tcg_gen_st32_tl(s->T0, cpu_env, + offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2))); + tcg_gen_st32_tl(s->T0, cpu_env, + offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3))); } else { rm = (modrm & 7) | REX_B(s); - gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)), + gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)), offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0))); } break; @@ -3206,12 +3222,14 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_lea_modrm(env, s, modrm); gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0))); - tcg_gen_movi_tl(cpu_T0, 0); - tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2))); - tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3))); + tcg_gen_movi_tl(s->T0, 0); + tcg_gen_st32_tl(s->T0, cpu_env, + offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2))); + tcg_gen_st32_tl(s->T0, cpu_env, + offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3))); } else { rm = (modrm & 7) | REX_B(s); - gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)), + gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)), offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0))); } break; @@ -3224,7 +3242,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } else { /* movhlps */ rm = (modrm & 7) | REX_B(s); - gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)), + gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)), offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(1))); } break; @@ -3234,14 +3252,14 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg])); } else { rm = (modrm & 7) | REX_B(s); - gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)), + gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)), offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0))); - gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)), + gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)), offsetof(CPUX86State,xmm_regs[rm].ZMM_L(2))); } - gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)), + gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)), offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0))); - gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)), + gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)), offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2))); break; case 0x312: /* movddup */ @@ -3251,10 +3269,10 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, xmm_regs[reg].ZMM_Q(0))); } else { rm = (modrm & 7) | REX_B(s); - gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)), + gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)), offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0))); } - gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)), + gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)), offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0))); break; case 0x016: /* movhps */ @@ -3266,7 +3284,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } else { /* movlhps */ rm = (modrm & 7) | REX_B(s); - gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)), + gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1)), offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0))); } break; @@ -3276,14 +3294,14 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg])); } else { rm = (modrm & 7) | REX_B(s); - gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)), + gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)), offsetof(CPUX86State,xmm_regs[rm].ZMM_L(1))); - gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)), + gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)), offsetof(CPUX86State,xmm_regs[rm].ZMM_L(3))); } - gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)), + gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)), offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1))); - gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)), + gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)), offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3))); break; case 0x178: @@ -3295,14 +3313,14 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, goto illegal_op; field_length = x86_ldub_code(env, s) & 0x3F; bit_index = x86_ldub_code(env, s) & 0x3F; - tcg_gen_addi_ptr(cpu_ptr0, cpu_env, + tcg_gen_addi_ptr(s->ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[reg])); if (b1 == 1) - gen_helper_extrq_i(cpu_env, cpu_ptr0, + gen_helper_extrq_i(cpu_env, s->ptr0, tcg_const_i32(bit_index), tcg_const_i32(field_length)); else - gen_helper_insertq_i(cpu_env, cpu_ptr0, + gen_helper_insertq_i(cpu_env, s->ptr0, tcg_const_i32(bit_index), tcg_const_i32(field_length)); } @@ -3310,13 +3328,13 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, case 0x7e: /* movd ea, mm */ #ifdef TARGET_X86_64 if (s->dflag == MO_64) { - tcg_gen_ld_i64(cpu_T0, cpu_env, + tcg_gen_ld_i64(s->T0, cpu_env, offsetof(CPUX86State,fpregs[reg].mmx)); gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1); } else #endif { - tcg_gen_ld32u_tl(cpu_T0, cpu_env, + tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0))); gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1); } @@ -3324,13 +3342,13 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, case 0x17e: /* movd ea, xmm */ #ifdef TARGET_X86_64 if (s->dflag == MO_64) { - tcg_gen_ld_i64(cpu_T0, cpu_env, + tcg_gen_ld_i64(s->T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0))); gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1); } else #endif { - tcg_gen_ld32u_tl(cpu_T0, cpu_env, + tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0))); gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1); } @@ -3342,10 +3360,10 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, xmm_regs[reg].ZMM_Q(0))); } else { rm = (modrm & 7) | REX_B(s); - gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)), + gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)), offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0))); } - gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1))); + gen_op_movq_env_0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1))); break; case 0x7f: /* movq ea, mm */ if (mod != 3) { @@ -3353,7 +3371,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx)); } else { rm = (modrm & 7); - gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx), + gen_op_movq(s, offsetof(CPUX86State, fpregs[rm].mmx), offsetof(CPUX86State,fpregs[reg].mmx)); } break; @@ -3368,18 +3386,19 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg])); } else { rm = (modrm & 7) | REX_B(s); - gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]), + gen_op_movo(s, offsetof(CPUX86State, xmm_regs[rm]), offsetof(CPUX86State,xmm_regs[reg])); } break; case 0x211: /* movss ea, xmm */ if (mod != 3) { gen_lea_modrm(env, s, modrm); - tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0))); - gen_op_st_v(s, MO_32, cpu_T0, cpu_A0); + tcg_gen_ld32u_tl(s->T0, cpu_env, + offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0))); + gen_op_st_v(s, MO_32, s->T0, s->A0); } else { rm = (modrm & 7) | REX_B(s); - gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)), + gen_op_movl(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_L(0)), offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0))); } break; @@ -3390,7 +3409,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, xmm_regs[reg].ZMM_Q(0))); } else { rm = (modrm & 7) | REX_B(s); - gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)), + gen_op_movq(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(0)), offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0))); } break; @@ -3425,16 +3444,20 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } val = x86_ldub_code(env, s); if (is_xmm) { - tcg_gen_movi_tl(cpu_T0, val); - tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_t0.ZMM_L(0))); - tcg_gen_movi_tl(cpu_T0, 0); - tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_t0.ZMM_L(1))); + tcg_gen_movi_tl(s->T0, val); + tcg_gen_st32_tl(s->T0, cpu_env, + offsetof(CPUX86State, xmm_t0.ZMM_L(0))); + tcg_gen_movi_tl(s->T0, 0); + tcg_gen_st32_tl(s->T0, cpu_env, + offsetof(CPUX86State, xmm_t0.ZMM_L(1))); op1_offset = offsetof(CPUX86State,xmm_t0); } else { - tcg_gen_movi_tl(cpu_T0, val); - tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0))); - tcg_gen_movi_tl(cpu_T0, 0); - tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1))); + tcg_gen_movi_tl(s->T0, val); + tcg_gen_st32_tl(s->T0, cpu_env, + offsetof(CPUX86State, mmx_t0.MMX_L(0))); + tcg_gen_movi_tl(s->T0, 0); + tcg_gen_st32_tl(s->T0, cpu_env, + offsetof(CPUX86State, mmx_t0.MMX_L(1))); op1_offset = offsetof(CPUX86State,mmx_t0); } sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 + @@ -3449,23 +3472,23 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, rm = (modrm & 7); op2_offset = offsetof(CPUX86State,fpregs[rm].mmx); } - tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset); - tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset); - sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1); + tcg_gen_addi_ptr(s->ptr0, cpu_env, op2_offset); + tcg_gen_addi_ptr(s->ptr1, cpu_env, op1_offset); + sse_fn_epp(cpu_env, s->ptr0, s->ptr1); break; case 0x050: /* movmskps */ rm = (modrm & 7) | REX_B(s); - tcg_gen_addi_ptr(cpu_ptr0, cpu_env, + tcg_gen_addi_ptr(s->ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm])); - gen_helper_movmskps(cpu_tmp2_i32, cpu_env, cpu_ptr0); - tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32); + gen_helper_movmskps(s->tmp2_i32, cpu_env, s->ptr0); + tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32); break; case 0x150: /* movmskpd */ rm = (modrm & 7) | REX_B(s); - tcg_gen_addi_ptr(cpu_ptr0, cpu_env, + tcg_gen_addi_ptr(s->ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm])); - gen_helper_movmskpd(cpu_tmp2_i32, cpu_env, cpu_ptr0); - tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32); + gen_helper_movmskpd(s->tmp2_i32, cpu_env, s->ptr0); + tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32); break; case 0x02a: /* cvtpi2ps */ case 0x12a: /* cvtpi2pd */ @@ -3479,15 +3502,15 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, op2_offset = offsetof(CPUX86State,fpregs[rm].mmx); } op1_offset = offsetof(CPUX86State,xmm_regs[reg]); - tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); - tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); + tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); + tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); switch(b >> 8) { case 0x0: - gen_helper_cvtpi2ps(cpu_env, cpu_ptr0, cpu_ptr1); + gen_helper_cvtpi2ps(cpu_env, s->ptr0, s->ptr1); break; default: case 0x1: - gen_helper_cvtpi2pd(cpu_env, cpu_ptr0, cpu_ptr1); + gen_helper_cvtpi2pd(cpu_env, s->ptr0, s->ptr1); break; } break; @@ -3496,15 +3519,15 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, ot = mo_64_32(s->dflag); gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); op1_offset = offsetof(CPUX86State,xmm_regs[reg]); - tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); + tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); if (ot == MO_32) { SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1]; - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); - sse_fn_epi(cpu_env, cpu_ptr0, cpu_tmp2_i32); + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); + sse_fn_epi(cpu_env, s->ptr0, s->tmp2_i32); } else { #ifdef TARGET_X86_64 SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1]; - sse_fn_epl(cpu_env, cpu_ptr0, cpu_T0); + sse_fn_epl(cpu_env, s->ptr0, s->T0); #else goto illegal_op; #endif @@ -3524,20 +3547,20 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, op2_offset = offsetof(CPUX86State,xmm_regs[rm]); } op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx); - tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); - tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); + tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); + tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); switch(b) { case 0x02c: - gen_helper_cvttps2pi(cpu_env, cpu_ptr0, cpu_ptr1); + gen_helper_cvttps2pi(cpu_env, s->ptr0, s->ptr1); break; case 0x12c: - gen_helper_cvttpd2pi(cpu_env, cpu_ptr0, cpu_ptr1); + gen_helper_cvttpd2pi(cpu_env, s->ptr0, s->ptr1); break; case 0x02d: - gen_helper_cvtps2pi(cpu_env, cpu_ptr0, cpu_ptr1); + gen_helper_cvtps2pi(cpu_env, s->ptr0, s->ptr1); break; case 0x12d: - gen_helper_cvtpd2pi(cpu_env, cpu_ptr0, cpu_ptr1); + gen_helper_cvtpd2pi(cpu_env, s->ptr0, s->ptr1); break; } break; @@ -3551,30 +3574,31 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, if ((b >> 8) & 1) { gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_Q(0))); } else { - gen_op_ld_v(s, MO_32, cpu_T0, cpu_A0); - tcg_gen_st32_tl(cpu_T0, cpu_env, offsetof(CPUX86State,xmm_t0.ZMM_L(0))); + gen_op_ld_v(s, MO_32, s->T0, s->A0); + tcg_gen_st32_tl(s->T0, cpu_env, + offsetof(CPUX86State, xmm_t0.ZMM_L(0))); } op2_offset = offsetof(CPUX86State,xmm_t0); } else { rm = (modrm & 7) | REX_B(s); op2_offset = offsetof(CPUX86State,xmm_regs[rm]); } - tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset); + tcg_gen_addi_ptr(s->ptr0, cpu_env, op2_offset); if (ot == MO_32) { SSEFunc_i_ep sse_fn_i_ep = sse_op_table3bi[((b >> 7) & 2) | (b & 1)]; - sse_fn_i_ep(cpu_tmp2_i32, cpu_env, cpu_ptr0); - tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32); + sse_fn_i_ep(s->tmp2_i32, cpu_env, s->ptr0); + tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32); } else { #ifdef TARGET_X86_64 SSEFunc_l_ep sse_fn_l_ep = sse_op_table3bq[((b >> 7) & 2) | (b & 1)]; - sse_fn_l_ep(cpu_T0, cpu_env, cpu_ptr0); + sse_fn_l_ep(s->T0, cpu_env, s->ptr0); #else goto illegal_op; #endif } - gen_op_mov_reg_v(ot, reg, cpu_T0); + gen_op_mov_reg_v(s, ot, reg, s->T0); break; case 0xc4: /* pinsrw */ case 0x1c4: @@ -3583,11 +3607,11 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, val = x86_ldub_code(env, s); if (b1) { val &= 7; - tcg_gen_st16_tl(cpu_T0, cpu_env, + tcg_gen_st16_tl(s->T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_W(val))); } else { val &= 3; - tcg_gen_st16_tl(cpu_T0, cpu_env, + tcg_gen_st16_tl(s->T0, cpu_env, offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val))); } break; @@ -3600,16 +3624,16 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, if (b1) { val &= 7; rm = (modrm & 7) | REX_B(s); - tcg_gen_ld16u_tl(cpu_T0, cpu_env, + tcg_gen_ld16u_tl(s->T0, cpu_env, offsetof(CPUX86State,xmm_regs[rm].ZMM_W(val))); } else { val &= 3; rm = (modrm & 7); - tcg_gen_ld16u_tl(cpu_T0, cpu_env, + tcg_gen_ld16u_tl(s->T0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val))); } reg = ((modrm >> 3) & 7) | rex_r; - gen_op_mov_reg_v(ot, reg, cpu_T0); + gen_op_mov_reg_v(s, ot, reg, s->T0); break; case 0x1d6: /* movq ea, xmm */ if (mod != 3) { @@ -3618,22 +3642,23 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, xmm_regs[reg].ZMM_Q(0))); } else { rm = (modrm & 7) | REX_B(s); - gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)), + gen_op_movq(s, offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(0)), offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0))); - gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(1))); + gen_op_movq_env_0(s, + offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(1))); } break; case 0x2d6: /* movq2dq */ gen_helper_enter_mmx(cpu_env); rm = (modrm & 7); - gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)), + gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)), offsetof(CPUX86State,fpregs[rm].mmx)); - gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1))); + gen_op_movq_env_0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1))); break; case 0x3d6: /* movdq2q */ gen_helper_enter_mmx(cpu_env); rm = (modrm & 7) | REX_B(s); - gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx), + gen_op_movq(s, offsetof(CPUX86State, fpregs[reg & 7].mmx), offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0))); break; case 0xd7: /* pmovmskb */ @@ -3642,15 +3667,17 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, goto illegal_op; if (b1) { rm = (modrm & 7) | REX_B(s); - tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm])); - gen_helper_pmovmskb_xmm(cpu_tmp2_i32, cpu_env, cpu_ptr0); + tcg_gen_addi_ptr(s->ptr0, cpu_env, + offsetof(CPUX86State, xmm_regs[rm])); + gen_helper_pmovmskb_xmm(s->tmp2_i32, cpu_env, s->ptr0); } else { rm = (modrm & 7); - tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx)); - gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_env, cpu_ptr0); + tcg_gen_addi_ptr(s->ptr0, cpu_env, + offsetof(CPUX86State, fpregs[rm].mmx)); + gen_helper_pmovmskb_mmx(s->tmp2_i32, cpu_env, s->ptr0); } reg = ((modrm >> 3) & 7) | rex_r; - tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32); + tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32); break; case 0x138: @@ -3690,15 +3717,15 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, break; case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */ case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */ - tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0, + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL); - tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, op2_offset + + tcg_gen_st_i32(s->tmp2_i32, cpu_env, op2_offset + offsetof(ZMMReg, ZMM_L(0))); break; case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */ - tcg_gen_qemu_ld_tl(cpu_tmp0, cpu_A0, + tcg_gen_qemu_ld_tl(s->tmp0, s->A0, s->mem_index, MO_LEUW); - tcg_gen_st16_tl(cpu_tmp0, cpu_env, op2_offset + + tcg_gen_st16_tl(s->tmp0, cpu_env, op2_offset + offsetof(ZMMReg, ZMM_W(0))); break; case 0x2a: /* movntqda */ @@ -3722,9 +3749,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, goto unknown_op; } - tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); - tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); - sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1); + tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); + tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); + sse_fn_epp(cpu_env, s->ptr0, s->ptr1); if (b == 0x17) { set_cc_op(s, CC_OP_EFLAGS); @@ -3754,13 +3781,13 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, ot = MO_64; } - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[reg]); + tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[reg]); gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - gen_helper_crc32(cpu_T0, cpu_tmp2_i32, - cpu_T0, tcg_const_i32(8 << ot)); + gen_helper_crc32(s->T0, s->tmp2_i32, + s->T0, tcg_const_i32(8 << ot)); ot = mo_64_32(s->dflag); - gen_op_mov_reg_v(ot, reg, cpu_T0); + gen_op_mov_reg_v(s, ot, reg, s->T0); break; case 0x1f0: /* crc32 or movbe */ @@ -3785,11 +3812,11 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_lea_modrm(env, s, modrm); if ((b & 1) == 0) { - tcg_gen_qemu_ld_tl(cpu_T0, cpu_A0, + tcg_gen_qemu_ld_tl(s->T0, s->A0, s->mem_index, ot | MO_BE); - gen_op_mov_reg_v(ot, reg, cpu_T0); + gen_op_mov_reg_v(s, ot, reg, s->T0); } else { - tcg_gen_qemu_st_tl(cpu_regs[reg], cpu_A0, + tcg_gen_qemu_st_tl(cpu_regs[reg], s->A0, s->mem_index, ot | MO_BE); } break; @@ -3802,9 +3829,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } ot = mo_64_32(s->dflag); gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - tcg_gen_andc_tl(cpu_T0, cpu_T0, cpu_regs[s->vex_v]); - gen_op_mov_reg_v(ot, reg, cpu_T0); - gen_op_update1_cc(); + tcg_gen_andc_tl(s->T0, s->T0, cpu_regs[s->vex_v]); + gen_op_mov_reg_v(s, ot, reg, s->T0); + gen_op_update1_cc(s); set_cc_op(s, CC_OP_LOGICB + ot); break; @@ -3821,28 +3848,28 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); /* Extract START, and shift the operand. Shifts larger than operand size get zeros. */ - tcg_gen_ext8u_tl(cpu_A0, cpu_regs[s->vex_v]); - tcg_gen_shr_tl(cpu_T0, cpu_T0, cpu_A0); + tcg_gen_ext8u_tl(s->A0, cpu_regs[s->vex_v]); + tcg_gen_shr_tl(s->T0, s->T0, s->A0); bound = tcg_const_tl(ot == MO_64 ? 63 : 31); zero = tcg_const_tl(0); - tcg_gen_movcond_tl(TCG_COND_LEU, cpu_T0, cpu_A0, bound, - cpu_T0, zero); + tcg_gen_movcond_tl(TCG_COND_LEU, s->T0, s->A0, bound, + s->T0, zero); tcg_temp_free(zero); /* Extract the LEN into a mask. Lengths larger than operand size get all ones. */ - tcg_gen_extract_tl(cpu_A0, cpu_regs[s->vex_v], 8, 8); - tcg_gen_movcond_tl(TCG_COND_LEU, cpu_A0, cpu_A0, bound, - cpu_A0, bound); + tcg_gen_extract_tl(s->A0, cpu_regs[s->vex_v], 8, 8); + tcg_gen_movcond_tl(TCG_COND_LEU, s->A0, s->A0, bound, + s->A0, bound); tcg_temp_free(bound); - tcg_gen_movi_tl(cpu_T1, 1); - tcg_gen_shl_tl(cpu_T1, cpu_T1, cpu_A0); - tcg_gen_subi_tl(cpu_T1, cpu_T1, 1); - tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_T1); + tcg_gen_movi_tl(s->T1, 1); + tcg_gen_shl_tl(s->T1, s->T1, s->A0); + tcg_gen_subi_tl(s->T1, s->T1, 1); + tcg_gen_and_tl(s->T0, s->T0, s->T1); - gen_op_mov_reg_v(ot, reg, cpu_T0); - gen_op_update1_cc(); + gen_op_mov_reg_v(s, ot, reg, s->T0); + gen_op_update1_cc(s); set_cc_op(s, CC_OP_LOGICB + ot); } break; @@ -3855,22 +3882,22 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } ot = mo_64_32(s->dflag); gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - tcg_gen_ext8u_tl(cpu_T1, cpu_regs[s->vex_v]); + tcg_gen_ext8u_tl(s->T1, cpu_regs[s->vex_v]); { TCGv bound = tcg_const_tl(ot == MO_64 ? 63 : 31); /* Note that since we're using BMILG (in order to get O cleared) we need to store the inverse into C. */ tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src, - cpu_T1, bound); - tcg_gen_movcond_tl(TCG_COND_GT, cpu_T1, cpu_T1, - bound, bound, cpu_T1); + s->T1, bound); + tcg_gen_movcond_tl(TCG_COND_GT, s->T1, s->T1, + bound, bound, s->T1); tcg_temp_free(bound); } - tcg_gen_movi_tl(cpu_A0, -1); - tcg_gen_shl_tl(cpu_A0, cpu_A0, cpu_T1); - tcg_gen_andc_tl(cpu_T0, cpu_T0, cpu_A0); - gen_op_mov_reg_v(ot, reg, cpu_T0); - gen_op_update1_cc(); + tcg_gen_movi_tl(s->A0, -1); + tcg_gen_shl_tl(s->A0, s->A0, s->T1); + tcg_gen_andc_tl(s->T0, s->T0, s->A0); + gen_op_mov_reg_v(s, ot, reg, s->T0); + gen_op_update1_cc(s); set_cc_op(s, CC_OP_BMILGB + ot); break; @@ -3884,19 +3911,19 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); switch (ot) { default: - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); - tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EDX]); - tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32, - cpu_tmp2_i32, cpu_tmp3_i32); - tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], cpu_tmp2_i32); - tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp3_i32); + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); + tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EDX]); + tcg_gen_mulu2_i32(s->tmp2_i32, s->tmp3_i32, + s->tmp2_i32, s->tmp3_i32); + tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], s->tmp2_i32); + tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp3_i32); break; #ifdef TARGET_X86_64 case MO_64: - tcg_gen_mulu2_i64(cpu_T0, cpu_T1, - cpu_T0, cpu_regs[R_EDX]); - tcg_gen_mov_i64(cpu_regs[s->vex_v], cpu_T0); - tcg_gen_mov_i64(cpu_regs[reg], cpu_T1); + tcg_gen_mulu2_i64(s->T0, s->T1, + s->T0, cpu_regs[R_EDX]); + tcg_gen_mov_i64(cpu_regs[s->vex_v], s->T0); + tcg_gen_mov_i64(cpu_regs[reg], s->T1); break; #endif } @@ -3913,11 +3940,11 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, /* Note that by zero-extending the mask operand, we automatically handle zero-extending the result. */ if (ot == MO_64) { - tcg_gen_mov_tl(cpu_T1, cpu_regs[s->vex_v]); + tcg_gen_mov_tl(s->T1, cpu_regs[s->vex_v]); } else { - tcg_gen_ext32u_tl(cpu_T1, cpu_regs[s->vex_v]); + tcg_gen_ext32u_tl(s->T1, cpu_regs[s->vex_v]); } - gen_helper_pdep(cpu_regs[reg], cpu_T0, cpu_T1); + gen_helper_pdep(cpu_regs[reg], s->T0, s->T1); break; case 0x2f5: /* pext Gy, By, Ey */ @@ -3931,11 +3958,11 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, /* Note that by zero-extending the mask operand, we automatically handle zero-extending the result. */ if (ot == MO_64) { - tcg_gen_mov_tl(cpu_T1, cpu_regs[s->vex_v]); + tcg_gen_mov_tl(s->T1, cpu_regs[s->vex_v]); } else { - tcg_gen_ext32u_tl(cpu_T1, cpu_regs[s->vex_v]); + tcg_gen_ext32u_tl(s->T1, cpu_regs[s->vex_v]); } - gen_helper_pext(cpu_regs[reg], cpu_T0, cpu_T1); + gen_helper_pext(cpu_regs[reg], s->T0, s->T1); break; case 0x1f6: /* adcx Gy, Ey */ @@ -3982,7 +4009,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) { gen_compute_eflags(s); } - carry_in = cpu_tmp0; + carry_in = s->tmp0; tcg_gen_extract_tl(carry_in, cpu_cc_src, ctz32(b == 0x1f6 ? CC_C : CC_O), 1); } @@ -3993,22 +4020,22 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, /* If we know TL is 64-bit, and we want a 32-bit result, just do everything in 64-bit arithmetic. */ tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]); - tcg_gen_ext32u_i64(cpu_T0, cpu_T0); - tcg_gen_add_i64(cpu_T0, cpu_T0, cpu_regs[reg]); - tcg_gen_add_i64(cpu_T0, cpu_T0, carry_in); - tcg_gen_ext32u_i64(cpu_regs[reg], cpu_T0); - tcg_gen_shri_i64(carry_out, cpu_T0, 32); + tcg_gen_ext32u_i64(s->T0, s->T0); + tcg_gen_add_i64(s->T0, s->T0, cpu_regs[reg]); + tcg_gen_add_i64(s->T0, s->T0, carry_in); + tcg_gen_ext32u_i64(cpu_regs[reg], s->T0); + tcg_gen_shri_i64(carry_out, s->T0, 32); break; #endif default: /* Otherwise compute the carry-out in two steps. */ zero = tcg_const_tl(0); - tcg_gen_add2_tl(cpu_T0, carry_out, - cpu_T0, zero, + tcg_gen_add2_tl(s->T0, carry_out, + s->T0, zero, carry_in, zero); tcg_gen_add2_tl(cpu_regs[reg], carry_out, cpu_regs[reg], carry_out, - cpu_T0, zero); + s->T0, zero); tcg_temp_free(zero); break; } @@ -4027,24 +4054,24 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, ot = mo_64_32(s->dflag); gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); if (ot == MO_64) { - tcg_gen_andi_tl(cpu_T1, cpu_regs[s->vex_v], 63); + tcg_gen_andi_tl(s->T1, cpu_regs[s->vex_v], 63); } else { - tcg_gen_andi_tl(cpu_T1, cpu_regs[s->vex_v], 31); + tcg_gen_andi_tl(s->T1, cpu_regs[s->vex_v], 31); } if (b == 0x1f7) { - tcg_gen_shl_tl(cpu_T0, cpu_T0, cpu_T1); + tcg_gen_shl_tl(s->T0, s->T0, s->T1); } else if (b == 0x2f7) { if (ot != MO_64) { - tcg_gen_ext32s_tl(cpu_T0, cpu_T0); + tcg_gen_ext32s_tl(s->T0, s->T0); } - tcg_gen_sar_tl(cpu_T0, cpu_T0, cpu_T1); + tcg_gen_sar_tl(s->T0, s->T0, s->T1); } else { if (ot != MO_64) { - tcg_gen_ext32u_tl(cpu_T0, cpu_T0); + tcg_gen_ext32u_tl(s->T0, s->T0); } - tcg_gen_shr_tl(cpu_T0, cpu_T0, cpu_T1); + tcg_gen_shr_tl(s->T0, s->T0, s->T1); } - gen_op_mov_reg_v(ot, reg, cpu_T0); + gen_op_mov_reg_v(s, ot, reg, s->T0); break; case 0x0f3: @@ -4059,25 +4086,25 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, ot = mo_64_32(s->dflag); gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - tcg_gen_mov_tl(cpu_cc_src, cpu_T0); + tcg_gen_mov_tl(cpu_cc_src, s->T0); switch (reg & 7) { case 1: /* blsr By,Ey */ - tcg_gen_subi_tl(cpu_T1, cpu_T0, 1); - tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_T1); + tcg_gen_subi_tl(s->T1, s->T0, 1); + tcg_gen_and_tl(s->T0, s->T0, s->T1); break; case 2: /* blsmsk By,Ey */ - tcg_gen_subi_tl(cpu_T1, cpu_T0, 1); - tcg_gen_xor_tl(cpu_T0, cpu_T0, cpu_T1); + tcg_gen_subi_tl(s->T1, s->T0, 1); + tcg_gen_xor_tl(s->T0, s->T0, s->T1); break; case 3: /* blsi By, Ey */ - tcg_gen_neg_tl(cpu_T1, cpu_T0); - tcg_gen_and_tl(cpu_T0, cpu_T0, cpu_T1); + tcg_gen_neg_tl(s->T1, s->T0); + tcg_gen_and_tl(s->T0, s->T0, s->T1); break; default: goto unknown_op; } - tcg_gen_mov_tl(cpu_cc_dst, cpu_T0); - gen_op_mov_reg_v(ot, s->vex_v, cpu_T0); + tcg_gen_mov_tl(cpu_cc_dst, s->T0); + gen_op_mov_reg_v(s, ot, s->vex_v, s->T0); set_cc_op(s, CC_OP_BMILGB + ot); break; @@ -4115,45 +4142,45 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, val = x86_ldub_code(env, s); switch (b) { case 0x14: /* pextrb */ - tcg_gen_ld8u_tl(cpu_T0, cpu_env, offsetof(CPUX86State, + tcg_gen_ld8u_tl(s->T0, cpu_env, offsetof(CPUX86State, xmm_regs[reg].ZMM_B(val & 15))); if (mod == 3) { - gen_op_mov_reg_v(ot, rm, cpu_T0); + gen_op_mov_reg_v(s, ot, rm, s->T0); } else { - tcg_gen_qemu_st_tl(cpu_T0, cpu_A0, + tcg_gen_qemu_st_tl(s->T0, s->A0, s->mem_index, MO_UB); } break; case 0x15: /* pextrw */ - tcg_gen_ld16u_tl(cpu_T0, cpu_env, offsetof(CPUX86State, + tcg_gen_ld16u_tl(s->T0, cpu_env, offsetof(CPUX86State, xmm_regs[reg].ZMM_W(val & 7))); if (mod == 3) { - gen_op_mov_reg_v(ot, rm, cpu_T0); + gen_op_mov_reg_v(s, ot, rm, s->T0); } else { - tcg_gen_qemu_st_tl(cpu_T0, cpu_A0, + tcg_gen_qemu_st_tl(s->T0, s->A0, s->mem_index, MO_LEUW); } break; case 0x16: if (ot == MO_32) { /* pextrd */ - tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, + tcg_gen_ld_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(val & 3))); if (mod == 3) { - tcg_gen_extu_i32_tl(cpu_regs[rm], cpu_tmp2_i32); + tcg_gen_extu_i32_tl(cpu_regs[rm], s->tmp2_i32); } else { - tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0, + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL); } } else { /* pextrq */ #ifdef TARGET_X86_64 - tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, + tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(val & 1))); if (mod == 3) { - tcg_gen_mov_i64(cpu_regs[rm], cpu_tmp1_i64); + tcg_gen_mov_i64(cpu_regs[rm], s->tmp1_i64); } else { - tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, + tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ); } #else @@ -4162,35 +4189,35 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } break; case 0x17: /* extractps */ - tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State, + tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(val & 3))); if (mod == 3) { - gen_op_mov_reg_v(ot, rm, cpu_T0); + gen_op_mov_reg_v(s, ot, rm, s->T0); } else { - tcg_gen_qemu_st_tl(cpu_T0, cpu_A0, + tcg_gen_qemu_st_tl(s->T0, s->A0, s->mem_index, MO_LEUL); } break; case 0x20: /* pinsrb */ if (mod == 3) { - gen_op_mov_v_reg(MO_32, cpu_T0, rm); + gen_op_mov_v_reg(s, MO_32, s->T0, rm); } else { - tcg_gen_qemu_ld_tl(cpu_T0, cpu_A0, + tcg_gen_qemu_ld_tl(s->T0, s->A0, s->mem_index, MO_UB); } - tcg_gen_st8_tl(cpu_T0, cpu_env, offsetof(CPUX86State, + tcg_gen_st8_tl(s->T0, cpu_env, offsetof(CPUX86State, xmm_regs[reg].ZMM_B(val & 15))); break; case 0x21: /* insertps */ if (mod == 3) { - tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, + tcg_gen_ld_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State,xmm_regs[rm] .ZMM_L((val >> 6) & 3))); } else { - tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0, + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL); } - tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, + tcg_gen_st_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State,xmm_regs[reg] .ZMM_L((val >> 4) & 3))); if ((val >> 0) & 1) @@ -4213,23 +4240,23 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, case 0x22: if (ot == MO_32) { /* pinsrd */ if (mod == 3) { - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[rm]); + tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[rm]); } else { - tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0, + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL); } - tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, + tcg_gen_st_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(val & 3))); } else { /* pinsrq */ #ifdef TARGET_X86_64 if (mod == 3) { - gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm); + gen_op_mov_v_reg(s, ot, s->tmp1_i64, rm); } else { - tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, + tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ); } - tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, + tcg_gen_st_i64(s->tmp1_i64, cpu_env, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(val & 1))); #else @@ -4271,9 +4298,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } } - tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); - tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); - sse_fn_eppi(cpu_env, cpu_ptr0, cpu_ptr1, tcg_const_i32(val)); + tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); + tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); + sse_fn_eppi(cpu_env, s->ptr0, s->ptr1, tcg_const_i32(val)); break; case 0x33a: @@ -4293,13 +4320,13 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); b = x86_ldub_code(env, s); if (ot == MO_64) { - tcg_gen_rotri_tl(cpu_T0, cpu_T0, b & 63); + tcg_gen_rotri_tl(s->T0, s->T0, b & 63); } else { - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); - tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, b & 31); - tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32); + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); + tcg_gen_rotri_i32(s->tmp2_i32, s->tmp2_i32, b & 31); + tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32); } - gen_op_mov_reg_v(ot, reg, cpu_T0); + gen_op_mov_reg_v(s, ot, reg, s->T0); break; default: @@ -4356,8 +4383,8 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, switch (sz) { case 2: /* 32 bit access */ - gen_op_ld_v(s, MO_32, cpu_T0, cpu_A0); - tcg_gen_st32_tl(cpu_T0, cpu_env, + gen_op_ld_v(s, MO_32, s->T0, s->A0); + tcg_gen_st32_tl(s->T0, cpu_env, offsetof(CPUX86State,xmm_t0.ZMM_L(0))); break; case 3: @@ -4394,18 +4421,18 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) { goto illegal_op; } - tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); - tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); - sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1); + tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); + tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); + sse_fn_epp(cpu_env, s->ptr0, s->ptr1); break; case 0x70: /* pshufx insn */ case 0xc6: /* pshufx insn */ val = x86_ldub_code(env, s); - tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); - tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); + tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); + tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); /* XXX: introduce a new table? */ sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp; - sse_fn_ppi(cpu_ptr0, cpu_ptr1, tcg_const_i32(val)); + sse_fn_ppi(s->ptr0, s->ptr1, tcg_const_i32(val)); break; case 0xc2: /* compare insns */ @@ -4414,28 +4441,28 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, goto unknown_op; sse_fn_epp = sse_op_table4[val][b1]; - tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); - tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); - sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1); + tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); + tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); + sse_fn_epp(cpu_env, s->ptr0, s->ptr1); break; case 0xf7: /* maskmov : we must prepare A0 */ if (mod != 3) goto illegal_op; - tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EDI]); - gen_extu(s->aflag, cpu_A0); + tcg_gen_mov_tl(s->A0, cpu_regs[R_EDI]); + gen_extu(s->aflag, s->A0); gen_add_A0_ds_seg(s); - tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); - tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); + tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); + tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); /* XXX: introduce a new table? */ sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp; - sse_fn_eppt(cpu_env, cpu_ptr0, cpu_ptr1, cpu_A0); + sse_fn_eppt(cpu_env, s->ptr0, s->ptr1, s->A0); break; default: - tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); - tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); - sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1); + tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); + tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); + sse_fn_epp(cpu_env, s->ptr0, s->ptr1); break; } if (b == 0x2e || b == 0x2f) { @@ -4462,7 +4489,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) #ifdef TARGET_X86_64 s->rex_x = 0; s->rex_b = 0; - x86_64_hregs = 0; + s->x86_64_hregs = false; #endif s->rip_offset = 0; /* for relative ip address */ s->vex_l = 0; @@ -4521,7 +4548,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) rex_r = (b & 0x4) << 1; s->rex_x = (b & 0x2) << 2; REX_B(s) = (b & 0x1) << 3; - x86_64_hregs = 1; /* select uniform byte register addressing */ + /* select uniform byte register addressing */ + s->x86_64_hregs = true; goto next_byte; } break; @@ -4549,7 +4577,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) goto illegal_op; } #ifdef TARGET_X86_64 - if (x86_64_hregs) { + if (s->x86_64_hregs) { goto illegal_op; } #endif @@ -4653,13 +4681,13 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) xor_zero: /* xor reg, reg optimisation */ set_cc_op(s, CC_OP_CLR); - tcg_gen_movi_tl(cpu_T0, 0); - gen_op_mov_reg_v(ot, reg, cpu_T0); + tcg_gen_movi_tl(s->T0, 0); + gen_op_mov_reg_v(s, ot, reg, s->T0); break; } else { opreg = rm; } - gen_op_mov_v_reg(ot, cpu_T1, reg); + gen_op_mov_v_reg(s, ot, s->T1, reg); gen_op(s, op, ot, opreg); break; case 1: /* OP Gv, Ev */ @@ -4669,17 +4697,17 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) rm = (modrm & 7) | REX_B(s); if (mod != 3) { gen_lea_modrm(env, s, modrm); - gen_op_ld_v(s, ot, cpu_T1, cpu_A0); + gen_op_ld_v(s, ot, s->T1, s->A0); } else if (op == OP_XORL && rm == reg) { goto xor_zero; } else { - gen_op_mov_v_reg(ot, cpu_T1, rm); + gen_op_mov_v_reg(s, ot, s->T1, rm); } gen_op(s, op, ot, reg); break; case 2: /* OP A, Iv */ val = insn_get(env, s, ot); - tcg_gen_movi_tl(cpu_T1, val); + tcg_gen_movi_tl(s->T1, val); gen_op(s, op, ot, OR_EAX); break; } @@ -4725,7 +4753,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) val = (int8_t)insn_get(env, s, MO_8); break; } - tcg_gen_movi_tl(cpu_T1, val); + tcg_gen_movi_tl(s->T1, val); gen_op(s, op, ot, opreg); } break; @@ -4756,17 +4784,17 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) /* For those below that handle locked memory, don't load here. */ if (!(s->prefix & PREFIX_LOCK) || op != 2) { - gen_op_ld_v(s, ot, cpu_T0, cpu_A0); + gen_op_ld_v(s, ot, s->T0, s->A0); } } else { - gen_op_mov_v_reg(ot, cpu_T0, rm); + gen_op_mov_v_reg(s, ot, s->T0, rm); } switch(op) { case 0: /* test */ val = insn_get(env, s, ot); - tcg_gen_movi_tl(cpu_T1, val); - gen_op_testl_T0_T1_cc(); + tcg_gen_movi_tl(s->T1, val); + gen_op_testl_T0_T1_cc(s); set_cc_op(s, CC_OP_LOGICB + ot); break; case 2: /* not */ @@ -4774,15 +4802,15 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) if (mod == 3) { goto illegal_op; } - tcg_gen_movi_tl(cpu_T0, ~0); - tcg_gen_atomic_xor_fetch_tl(cpu_T0, cpu_A0, cpu_T0, + tcg_gen_movi_tl(s->T0, ~0); + tcg_gen_atomic_xor_fetch_tl(s->T0, s->A0, s->T0, s->mem_index, ot | MO_LE); } else { - tcg_gen_not_tl(cpu_T0, cpu_T0); + tcg_gen_not_tl(s->T0, s->T0); if (mod != 3) { - gen_op_st_v(s, ot, cpu_T0, cpu_A0); + gen_op_st_v(s, ot, s->T0, s->A0); } else { - gen_op_mov_reg_v(ot, rm, cpu_T0); + gen_op_mov_reg_v(s, ot, rm, s->T0); } } break; @@ -4798,8 +4826,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) t0 = tcg_temp_local_new(); label1 = gen_new_label(); - tcg_gen_mov_tl(a0, cpu_A0); - tcg_gen_mov_tl(t0, cpu_T0); + tcg_gen_mov_tl(a0, s->A0); + tcg_gen_mov_tl(t0, s->T0); gen_set_label(label1); t1 = tcg_temp_new(); @@ -4813,53 +4841,53 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) tcg_temp_free(t2); tcg_temp_free(a0); - tcg_gen_mov_tl(cpu_T0, t0); + tcg_gen_mov_tl(s->T0, t0); tcg_temp_free(t0); } else { - tcg_gen_neg_tl(cpu_T0, cpu_T0); + tcg_gen_neg_tl(s->T0, s->T0); if (mod != 3) { - gen_op_st_v(s, ot, cpu_T0, cpu_A0); + gen_op_st_v(s, ot, s->T0, s->A0); } else { - gen_op_mov_reg_v(ot, rm, cpu_T0); + gen_op_mov_reg_v(s, ot, rm, s->T0); } } - gen_op_update_neg_cc(); + gen_op_update_neg_cc(s); set_cc_op(s, CC_OP_SUBB + ot); break; case 4: /* mul */ switch(ot) { case MO_8: - gen_op_mov_v_reg(MO_8, cpu_T1, R_EAX); - tcg_gen_ext8u_tl(cpu_T0, cpu_T0); - tcg_gen_ext8u_tl(cpu_T1, cpu_T1); + gen_op_mov_v_reg(s, MO_8, s->T1, R_EAX); + tcg_gen_ext8u_tl(s->T0, s->T0); + tcg_gen_ext8u_tl(s->T1, s->T1); /* XXX: use 32 bit mul which could be faster */ - tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1); - gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0); - tcg_gen_mov_tl(cpu_cc_dst, cpu_T0); - tcg_gen_andi_tl(cpu_cc_src, cpu_T0, 0xff00); + tcg_gen_mul_tl(s->T0, s->T0, s->T1); + gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); + tcg_gen_mov_tl(cpu_cc_dst, s->T0); + tcg_gen_andi_tl(cpu_cc_src, s->T0, 0xff00); set_cc_op(s, CC_OP_MULB); break; case MO_16: - gen_op_mov_v_reg(MO_16, cpu_T1, R_EAX); - tcg_gen_ext16u_tl(cpu_T0, cpu_T0); - tcg_gen_ext16u_tl(cpu_T1, cpu_T1); + gen_op_mov_v_reg(s, MO_16, s->T1, R_EAX); + tcg_gen_ext16u_tl(s->T0, s->T0); + tcg_gen_ext16u_tl(s->T1, s->T1); /* XXX: use 32 bit mul which could be faster */ - tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1); - gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0); - tcg_gen_mov_tl(cpu_cc_dst, cpu_T0); - tcg_gen_shri_tl(cpu_T0, cpu_T0, 16); - gen_op_mov_reg_v(MO_16, R_EDX, cpu_T0); - tcg_gen_mov_tl(cpu_cc_src, cpu_T0); + tcg_gen_mul_tl(s->T0, s->T0, s->T1); + gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); + tcg_gen_mov_tl(cpu_cc_dst, s->T0); + tcg_gen_shri_tl(s->T0, s->T0, 16); + gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0); + tcg_gen_mov_tl(cpu_cc_src, s->T0); set_cc_op(s, CC_OP_MULW); break; default: case MO_32: - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); - tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]); - tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32, - cpu_tmp2_i32, cpu_tmp3_i32); - tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32); - tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32); + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); + tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EAX]); + tcg_gen_mulu2_i32(s->tmp2_i32, s->tmp3_i32, + s->tmp2_i32, s->tmp3_i32); + tcg_gen_extu_i32_tl(cpu_regs[R_EAX], s->tmp2_i32); + tcg_gen_extu_i32_tl(cpu_regs[R_EDX], s->tmp3_i32); tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]); tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]); set_cc_op(s, CC_OP_MULL); @@ -4867,7 +4895,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) #ifdef TARGET_X86_64 case MO_64: tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX], - cpu_T0, cpu_regs[R_EAX]); + s->T0, cpu_regs[R_EAX]); tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]); tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]); set_cc_op(s, CC_OP_MULQ); @@ -4878,49 +4906,49 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) case 5: /* imul */ switch(ot) { case MO_8: - gen_op_mov_v_reg(MO_8, cpu_T1, R_EAX); - tcg_gen_ext8s_tl(cpu_T0, cpu_T0); - tcg_gen_ext8s_tl(cpu_T1, cpu_T1); + gen_op_mov_v_reg(s, MO_8, s->T1, R_EAX); + tcg_gen_ext8s_tl(s->T0, s->T0); + tcg_gen_ext8s_tl(s->T1, s->T1); /* XXX: use 32 bit mul which could be faster */ - tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1); - gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0); - tcg_gen_mov_tl(cpu_cc_dst, cpu_T0); - tcg_gen_ext8s_tl(cpu_tmp0, cpu_T0); - tcg_gen_sub_tl(cpu_cc_src, cpu_T0, cpu_tmp0); + tcg_gen_mul_tl(s->T0, s->T0, s->T1); + gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); + tcg_gen_mov_tl(cpu_cc_dst, s->T0); + tcg_gen_ext8s_tl(s->tmp0, s->T0); + tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0); set_cc_op(s, CC_OP_MULB); break; case MO_16: - gen_op_mov_v_reg(MO_16, cpu_T1, R_EAX); - tcg_gen_ext16s_tl(cpu_T0, cpu_T0); - tcg_gen_ext16s_tl(cpu_T1, cpu_T1); + gen_op_mov_v_reg(s, MO_16, s->T1, R_EAX); + tcg_gen_ext16s_tl(s->T0, s->T0); + tcg_gen_ext16s_tl(s->T1, s->T1); /* XXX: use 32 bit mul which could be faster */ - tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1); - gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0); - tcg_gen_mov_tl(cpu_cc_dst, cpu_T0); - tcg_gen_ext16s_tl(cpu_tmp0, cpu_T0); - tcg_gen_sub_tl(cpu_cc_src, cpu_T0, cpu_tmp0); - tcg_gen_shri_tl(cpu_T0, cpu_T0, 16); - gen_op_mov_reg_v(MO_16, R_EDX, cpu_T0); + tcg_gen_mul_tl(s->T0, s->T0, s->T1); + gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); + tcg_gen_mov_tl(cpu_cc_dst, s->T0); + tcg_gen_ext16s_tl(s->tmp0, s->T0); + tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0); + tcg_gen_shri_tl(s->T0, s->T0, 16); + gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0); set_cc_op(s, CC_OP_MULW); break; default: case MO_32: - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); - tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]); - tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32, - cpu_tmp2_i32, cpu_tmp3_i32); - tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32); - tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32); - tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31); + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); + tcg_gen_trunc_tl_i32(s->tmp3_i32, cpu_regs[R_EAX]); + tcg_gen_muls2_i32(s->tmp2_i32, s->tmp3_i32, + s->tmp2_i32, s->tmp3_i32); + tcg_gen_extu_i32_tl(cpu_regs[R_EAX], s->tmp2_i32); + tcg_gen_extu_i32_tl(cpu_regs[R_EDX], s->tmp3_i32); + tcg_gen_sari_i32(s->tmp2_i32, s->tmp2_i32, 31); tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]); - tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32); - tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32); + tcg_gen_sub_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32); + tcg_gen_extu_i32_tl(cpu_cc_src, s->tmp2_i32); set_cc_op(s, CC_OP_MULL); break; #ifdef TARGET_X86_64 case MO_64: tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX], - cpu_T0, cpu_regs[R_EAX]); + s->T0, cpu_regs[R_EAX]); tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]); tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63); tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]); @@ -4932,18 +4960,18 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) case 6: /* div */ switch(ot) { case MO_8: - gen_helper_divb_AL(cpu_env, cpu_T0); + gen_helper_divb_AL(cpu_env, s->T0); break; case MO_16: - gen_helper_divw_AX(cpu_env, cpu_T0); + gen_helper_divw_AX(cpu_env, s->T0); break; default: case MO_32: - gen_helper_divl_EAX(cpu_env, cpu_T0); + gen_helper_divl_EAX(cpu_env, s->T0); break; #ifdef TARGET_X86_64 case MO_64: - gen_helper_divq_EAX(cpu_env, cpu_T0); + gen_helper_divq_EAX(cpu_env, s->T0); break; #endif } @@ -4951,18 +4979,18 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) case 7: /* idiv */ switch(ot) { case MO_8: - gen_helper_idivb_AL(cpu_env, cpu_T0); + gen_helper_idivb_AL(cpu_env, s->T0); break; case MO_16: - gen_helper_idivw_AX(cpu_env, cpu_T0); + gen_helper_idivw_AX(cpu_env, s->T0); break; default: case MO_32: - gen_helper_idivl_EAX(cpu_env, cpu_T0); + gen_helper_idivl_EAX(cpu_env, s->T0); break; #ifdef TARGET_X86_64 case MO_64: - gen_helper_idivq_EAX(cpu_env, cpu_T0); + gen_helper_idivq_EAX(cpu_env, s->T0); break; #endif } @@ -4997,9 +5025,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) if (mod != 3) { gen_lea_modrm(env, s, modrm); if (op >= 2 && op != 3 && op != 5) - gen_op_ld_v(s, ot, cpu_T0, cpu_A0); + gen_op_ld_v(s, ot, s->T0, s->A0); } else { - gen_op_mov_v_reg(ot, cpu_T0, rm); + gen_op_mov_v_reg(s, ot, s->T0, rm); } switch(op) { @@ -5020,60 +5048,60 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) case 2: /* call Ev */ /* XXX: optimize if memory (no 'and' is necessary) */ if (dflag == MO_16) { - tcg_gen_ext16u_tl(cpu_T0, cpu_T0); + tcg_gen_ext16u_tl(s->T0, s->T0); } next_eip = s->pc - s->cs_base; - tcg_gen_movi_tl(cpu_T1, next_eip); - gen_push_v(s, cpu_T1); - gen_op_jmp_v(cpu_T0); + tcg_gen_movi_tl(s->T1, next_eip); + gen_push_v(s, s->T1); + gen_op_jmp_v(s->T0); gen_bnd_jmp(s); - gen_jr(s, cpu_T0); + gen_jr(s, s->T0); break; case 3: /* lcall Ev */ - gen_op_ld_v(s, ot, cpu_T1, cpu_A0); + gen_op_ld_v(s, ot, s->T1, s->A0); gen_add_A0_im(s, 1 << ot); - gen_op_ld_v(s, MO_16, cpu_T0, cpu_A0); + gen_op_ld_v(s, MO_16, s->T0, s->A0); do_lcall: if (s->pe && !s->vm86) { - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); - gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T1, + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); + gen_helper_lcall_protected(cpu_env, s->tmp2_i32, s->T1, tcg_const_i32(dflag - 1), tcg_const_tl(s->pc - s->cs_base)); } else { - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); - gen_helper_lcall_real(cpu_env, cpu_tmp2_i32, cpu_T1, + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); + gen_helper_lcall_real(cpu_env, s->tmp2_i32, s->T1, tcg_const_i32(dflag - 1), tcg_const_i32(s->pc - s->cs_base)); } - tcg_gen_ld_tl(cpu_tmp4, cpu_env, offsetof(CPUX86State, eip)); - gen_jr(s, cpu_tmp4); + tcg_gen_ld_tl(s->tmp4, cpu_env, offsetof(CPUX86State, eip)); + gen_jr(s, s->tmp4); break; case 4: /* jmp Ev */ if (dflag == MO_16) { - tcg_gen_ext16u_tl(cpu_T0, cpu_T0); + tcg_gen_ext16u_tl(s->T0, s->T0); } - gen_op_jmp_v(cpu_T0); + gen_op_jmp_v(s->T0); gen_bnd_jmp(s); - gen_jr(s, cpu_T0); + gen_jr(s, s->T0); break; case 5: /* ljmp Ev */ - gen_op_ld_v(s, ot, cpu_T1, cpu_A0); + gen_op_ld_v(s, ot, s->T1, s->A0); gen_add_A0_im(s, 1 << ot); - gen_op_ld_v(s, MO_16, cpu_T0, cpu_A0); + gen_op_ld_v(s, MO_16, s->T0, s->A0); do_ljmp: if (s->pe && !s->vm86) { - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); - gen_helper_ljmp_protected(cpu_env, cpu_tmp2_i32, cpu_T1, + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); + gen_helper_ljmp_protected(cpu_env, s->tmp2_i32, s->T1, tcg_const_tl(s->pc - s->cs_base)); } else { - gen_op_movl_seg_T0_vm(R_CS); - gen_op_jmp_v(cpu_T1); + gen_op_movl_seg_T0_vm(s, R_CS); + gen_op_jmp_v(s->T1); } - tcg_gen_ld_tl(cpu_tmp4, cpu_env, offsetof(CPUX86State, eip)); - gen_jr(s, cpu_tmp4); + tcg_gen_ld_tl(s->tmp4, cpu_env, offsetof(CPUX86State, eip)); + gen_jr(s, s->tmp4); break; case 6: /* push Ev */ - gen_push_v(s, cpu_T0); + gen_push_v(s, s->T0); break; default: goto unknown_op; @@ -5088,8 +5116,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) reg = ((modrm >> 3) & 7) | rex_r; gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - gen_op_mov_v_reg(ot, cpu_T1, reg); - gen_op_testl_T0_T1_cc(); + gen_op_mov_v_reg(s, ot, s->T1, reg); + gen_op_testl_T0_T1_cc(s); set_cc_op(s, CC_OP_LOGICB + ot); break; @@ -5098,9 +5126,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) ot = mo_b_d(b, dflag); val = insn_get(env, s, ot); - gen_op_mov_v_reg(ot, cpu_T0, OR_EAX); - tcg_gen_movi_tl(cpu_T1, val); - gen_op_testl_T0_T1_cc(); + gen_op_mov_v_reg(s, ot, s->T0, OR_EAX); + tcg_gen_movi_tl(s->T1, val); + gen_op_testl_T0_T1_cc(s); set_cc_op(s, CC_OP_LOGICB + ot); break; @@ -5108,20 +5136,20 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) switch (dflag) { #ifdef TARGET_X86_64 case MO_64: - gen_op_mov_v_reg(MO_32, cpu_T0, R_EAX); - tcg_gen_ext32s_tl(cpu_T0, cpu_T0); - gen_op_mov_reg_v(MO_64, R_EAX, cpu_T0); + gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX); + tcg_gen_ext32s_tl(s->T0, s->T0); + gen_op_mov_reg_v(s, MO_64, R_EAX, s->T0); break; #endif case MO_32: - gen_op_mov_v_reg(MO_16, cpu_T0, R_EAX); - tcg_gen_ext16s_tl(cpu_T0, cpu_T0); - gen_op_mov_reg_v(MO_32, R_EAX, cpu_T0); + gen_op_mov_v_reg(s, MO_16, s->T0, R_EAX); + tcg_gen_ext16s_tl(s->T0, s->T0); + gen_op_mov_reg_v(s, MO_32, R_EAX, s->T0); break; case MO_16: - gen_op_mov_v_reg(MO_8, cpu_T0, R_EAX); - tcg_gen_ext8s_tl(cpu_T0, cpu_T0); - gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0); + gen_op_mov_v_reg(s, MO_8, s->T0, R_EAX); + tcg_gen_ext8s_tl(s->T0, s->T0); + gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); break; default: tcg_abort(); @@ -5131,22 +5159,22 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) switch (dflag) { #ifdef TARGET_X86_64 case MO_64: - gen_op_mov_v_reg(MO_64, cpu_T0, R_EAX); - tcg_gen_sari_tl(cpu_T0, cpu_T0, 63); - gen_op_mov_reg_v(MO_64, R_EDX, cpu_T0); + gen_op_mov_v_reg(s, MO_64, s->T0, R_EAX); + tcg_gen_sari_tl(s->T0, s->T0, 63); + gen_op_mov_reg_v(s, MO_64, R_EDX, s->T0); break; #endif case MO_32: - gen_op_mov_v_reg(MO_32, cpu_T0, R_EAX); - tcg_gen_ext32s_tl(cpu_T0, cpu_T0); - tcg_gen_sari_tl(cpu_T0, cpu_T0, 31); - gen_op_mov_reg_v(MO_32, R_EDX, cpu_T0); + gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX); + tcg_gen_ext32s_tl(s->T0, s->T0); + tcg_gen_sari_tl(s->T0, s->T0, 31); + gen_op_mov_reg_v(s, MO_32, R_EDX, s->T0); break; case MO_16: - gen_op_mov_v_reg(MO_16, cpu_T0, R_EAX); - tcg_gen_ext16s_tl(cpu_T0, cpu_T0); - tcg_gen_sari_tl(cpu_T0, cpu_T0, 15); - gen_op_mov_reg_v(MO_16, R_EDX, cpu_T0); + gen_op_mov_v_reg(s, MO_16, s->T0, R_EAX); + tcg_gen_ext16s_tl(s->T0, s->T0); + tcg_gen_sari_tl(s->T0, s->T0, 15); + gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0); break; default: tcg_abort(); @@ -5165,42 +5193,42 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); if (b == 0x69) { val = insn_get(env, s, ot); - tcg_gen_movi_tl(cpu_T1, val); + tcg_gen_movi_tl(s->T1, val); } else if (b == 0x6b) { val = (int8_t)insn_get(env, s, MO_8); - tcg_gen_movi_tl(cpu_T1, val); + tcg_gen_movi_tl(s->T1, val); } else { - gen_op_mov_v_reg(ot, cpu_T1, reg); + gen_op_mov_v_reg(s, ot, s->T1, reg); } switch (ot) { #ifdef TARGET_X86_64 case MO_64: - tcg_gen_muls2_i64(cpu_regs[reg], cpu_T1, cpu_T0, cpu_T1); + tcg_gen_muls2_i64(cpu_regs[reg], s->T1, s->T0, s->T1); tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]); tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63); - tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_T1); + tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, s->T1); break; #endif case MO_32: - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); - tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1); - tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32, - cpu_tmp2_i32, cpu_tmp3_i32); - tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32); - tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31); + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); + tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1); + tcg_gen_muls2_i32(s->tmp2_i32, s->tmp3_i32, + s->tmp2_i32, s->tmp3_i32); + tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32); + tcg_gen_sari_i32(s->tmp2_i32, s->tmp2_i32, 31); tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]); - tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32); - tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32); + tcg_gen_sub_i32(s->tmp2_i32, s->tmp2_i32, s->tmp3_i32); + tcg_gen_extu_i32_tl(cpu_cc_src, s->tmp2_i32); break; default: - tcg_gen_ext16s_tl(cpu_T0, cpu_T0); - tcg_gen_ext16s_tl(cpu_T1, cpu_T1); + tcg_gen_ext16s_tl(s->T0, s->T0); + tcg_gen_ext16s_tl(s->T1, s->T1); /* XXX: use 32 bit mul which could be faster */ - tcg_gen_mul_tl(cpu_T0, cpu_T0, cpu_T1); - tcg_gen_mov_tl(cpu_cc_dst, cpu_T0); - tcg_gen_ext16s_tl(cpu_tmp0, cpu_T0); - tcg_gen_sub_tl(cpu_cc_src, cpu_T0, cpu_tmp0); - gen_op_mov_reg_v(ot, reg, cpu_T0); + tcg_gen_mul_tl(s->T0, s->T0, s->T1); + tcg_gen_mov_tl(cpu_cc_dst, s->T0); + tcg_gen_ext16s_tl(s->tmp0, s->T0); + tcg_gen_sub_tl(cpu_cc_src, s->T0, s->tmp0); + gen_op_mov_reg_v(s, ot, reg, s->T0); break; } set_cc_op(s, CC_OP_MULB + ot); @@ -5211,27 +5239,27 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) modrm = x86_ldub_code(env, s); reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; - gen_op_mov_v_reg(ot, cpu_T0, reg); + gen_op_mov_v_reg(s, ot, s->T0, reg); if (mod == 3) { rm = (modrm & 7) | REX_B(s); - gen_op_mov_v_reg(ot, cpu_T1, rm); - tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1); - gen_op_mov_reg_v(ot, reg, cpu_T1); - gen_op_mov_reg_v(ot, rm, cpu_T0); + gen_op_mov_v_reg(s, ot, s->T1, rm); + tcg_gen_add_tl(s->T0, s->T0, s->T1); + gen_op_mov_reg_v(s, ot, reg, s->T1); + gen_op_mov_reg_v(s, ot, rm, s->T0); } else { gen_lea_modrm(env, s, modrm); if (s->prefix & PREFIX_LOCK) { - tcg_gen_atomic_fetch_add_tl(cpu_T1, cpu_A0, cpu_T0, + tcg_gen_atomic_fetch_add_tl(s->T1, s->A0, s->T0, s->mem_index, ot | MO_LE); - tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1); + tcg_gen_add_tl(s->T0, s->T0, s->T1); } else { - gen_op_ld_v(s, ot, cpu_T1, cpu_A0); - tcg_gen_add_tl(cpu_T0, cpu_T0, cpu_T1); - gen_op_st_v(s, ot, cpu_T0, cpu_A0); + gen_op_ld_v(s, ot, s->T1, s->A0); + tcg_gen_add_tl(s->T0, s->T0, s->T1); + gen_op_st_v(s, ot, s->T0, s->A0); } - gen_op_mov_reg_v(ot, reg, cpu_T1); + gen_op_mov_reg_v(s, ot, reg, s->T1); } - gen_op_update2_cc(); + gen_op_update2_cc(s); set_cc_op(s, CC_OP_ADDB + ot); break; case 0x1b0: @@ -5246,7 +5274,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) oldv = tcg_temp_new(); newv = tcg_temp_new(); cmpv = tcg_temp_new(); - gen_op_mov_v_reg(ot, newv, reg); + gen_op_mov_v_reg(s, ot, newv, reg); tcg_gen_mov_tl(cmpv, cpu_regs[R_EAX]); if (s->prefix & PREFIX_LOCK) { @@ -5254,16 +5282,16 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) goto illegal_op; } gen_lea_modrm(env, s, modrm); - tcg_gen_atomic_cmpxchg_tl(oldv, cpu_A0, cmpv, newv, + tcg_gen_atomic_cmpxchg_tl(oldv, s->A0, cmpv, newv, s->mem_index, ot | MO_LE); - gen_op_mov_reg_v(ot, R_EAX, oldv); + gen_op_mov_reg_v(s, ot, R_EAX, oldv); } else { if (mod == 3) { rm = (modrm & 7) | REX_B(s); - gen_op_mov_v_reg(ot, oldv, rm); + gen_op_mov_v_reg(s, ot, oldv, rm); } else { gen_lea_modrm(env, s, modrm); - gen_op_ld_v(s, ot, oldv, cpu_A0); + gen_op_ld_v(s, ot, oldv, s->A0); rm = 0; /* avoid warning */ } gen_extu(ot, oldv); @@ -5271,19 +5299,19 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) /* store value = (old == cmp ? new : old); */ tcg_gen_movcond_tl(TCG_COND_EQ, newv, oldv, cmpv, newv, oldv); if (mod == 3) { - gen_op_mov_reg_v(ot, R_EAX, oldv); - gen_op_mov_reg_v(ot, rm, newv); + gen_op_mov_reg_v(s, ot, R_EAX, oldv); + gen_op_mov_reg_v(s, ot, rm, newv); } else { /* Perform an unconditional store cycle like physical cpu; must be before changing accumulator to ensure idempotency if the store faults and the instruction is restarted */ - gen_op_st_v(s, ot, newv, cpu_A0); - gen_op_mov_reg_v(ot, R_EAX, oldv); + gen_op_st_v(s, ot, newv, s->A0); + gen_op_mov_reg_v(s, ot, R_EAX, oldv); } } tcg_gen_mov_tl(cpu_cc_src, oldv); - tcg_gen_mov_tl(cpu_cc_srcT, cmpv); + tcg_gen_mov_tl(s->cc_srcT, cmpv); tcg_gen_sub_tl(cpu_cc_dst, cmpv, oldv); set_cc_op(s, CC_OP_SUBB + ot); tcg_temp_free(oldv); @@ -5302,9 +5330,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) goto illegal_op; gen_lea_modrm(env, s, modrm); if ((s->prefix & PREFIX_LOCK) && (tb_cflags(s->base.tb) & CF_PARALLEL)) { - gen_helper_cmpxchg16b(cpu_env, cpu_A0); + gen_helper_cmpxchg16b(cpu_env, s->A0); } else { - gen_helper_cmpxchg16b_unlocked(cpu_env, cpu_A0); + gen_helper_cmpxchg16b_unlocked(cpu_env, s->A0); } } else #endif @@ -5313,9 +5341,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) goto illegal_op; gen_lea_modrm(env, s, modrm); if ((s->prefix & PREFIX_LOCK) && (tb_cflags(s->base.tb) & CF_PARALLEL)) { - gen_helper_cmpxchg8b(cpu_env, cpu_A0); + gen_helper_cmpxchg8b(cpu_env, s->A0); } else { - gen_helper_cmpxchg8b_unlocked(cpu_env, cpu_A0); + gen_helper_cmpxchg8b_unlocked(cpu_env, s->A0); } } set_cc_op(s, CC_OP_EFLAGS); @@ -5324,14 +5352,14 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) /**************************/ /* push/pop */ case 0x50 ... 0x57: /* push */ - gen_op_mov_v_reg(MO_32, cpu_T0, (b & 7) | REX_B(s)); - gen_push_v(s, cpu_T0); + gen_op_mov_v_reg(s, MO_32, s->T0, (b & 7) | REX_B(s)); + gen_push_v(s, s->T0); break; case 0x58 ... 0x5f: /* pop */ ot = gen_pop_T0(s); /* NOTE: order is important for pop %sp */ gen_pop_update(s, ot); - gen_op_mov_reg_v(ot, (b & 7) | REX_B(s), cpu_T0); + gen_op_mov_reg_v(s, ot, (b & 7) | REX_B(s), s->T0); break; case 0x60: /* pusha */ if (CODE64(s)) @@ -5350,8 +5378,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) val = insn_get(env, s, ot); else val = (int8_t)insn_get(env, s, MO_8); - tcg_gen_movi_tl(cpu_T0, val); - gen_push_v(s, cpu_T0); + tcg_gen_movi_tl(s->T0, val); + gen_push_v(s, s->T0); break; case 0x8f: /* pop Ev */ modrm = x86_ldub_code(env, s); @@ -5361,7 +5389,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) /* NOTE: order is important for pop %sp */ gen_pop_update(s, ot); rm = (modrm & 7) | REX_B(s); - gen_op_mov_reg_v(ot, rm, cpu_T0); + gen_op_mov_reg_v(s, ot, rm, s->T0); } else { /* NOTE: order is important too for MMU exceptions */ s->popl_esp_hack = 1 << ot; @@ -5387,13 +5415,13 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) case 0x1e: /* push ds */ if (CODE64(s)) goto illegal_op; - gen_op_movl_T0_seg(b >> 3); - gen_push_v(s, cpu_T0); + gen_op_movl_T0_seg(s, b >> 3); + gen_push_v(s, s->T0); break; case 0x1a0: /* push fs */ case 0x1a8: /* push gs */ - gen_op_movl_T0_seg((b >> 3) & 7); - gen_push_v(s, cpu_T0); + gen_op_movl_T0_seg(s, (b >> 3) & 7); + gen_push_v(s, s->T0); break; case 0x07: /* pop es */ case 0x17: /* pop ss */ @@ -5406,7 +5434,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) gen_pop_update(s, ot); /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */ if (s->base.is_jmp) { - gen_jmp_im(s->pc - s->cs_base); + gen_jmp_im(s, s->pc - s->cs_base); if (reg == R_SS) { s->tf = 0; gen_eob_inhibit_irq(s, true); @@ -5421,7 +5449,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) gen_movl_seg_T0(s, (b >> 3) & 7); gen_pop_update(s, ot); if (s->base.is_jmp) { - gen_jmp_im(s->pc - s->cs_base); + gen_jmp_im(s, s->pc - s->cs_base); gen_eob(s); } break; @@ -5447,11 +5475,11 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) gen_lea_modrm(env, s, modrm); } val = insn_get(env, s, ot); - tcg_gen_movi_tl(cpu_T0, val); + tcg_gen_movi_tl(s->T0, val); if (mod != 3) { - gen_op_st_v(s, ot, cpu_T0, cpu_A0); + gen_op_st_v(s, ot, s->T0, s->A0); } else { - gen_op_mov_reg_v(ot, (modrm & 7) | REX_B(s), cpu_T0); + gen_op_mov_reg_v(s, ot, (modrm & 7) | REX_B(s), s->T0); } break; case 0x8a: @@ -5461,7 +5489,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) reg = ((modrm >> 3) & 7) | rex_r; gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - gen_op_mov_reg_v(ot, reg, cpu_T0); + gen_op_mov_reg_v(s, ot, reg, s->T0); break; case 0x8e: /* mov seg, Gv */ modrm = x86_ldub_code(env, s); @@ -5472,7 +5500,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) gen_movl_seg_T0(s, reg); /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */ if (s->base.is_jmp) { - gen_jmp_im(s->pc - s->cs_base); + gen_jmp_im(s, s->pc - s->cs_base); if (reg == R_SS) { s->tf = 0; gen_eob_inhibit_irq(s, true); @@ -5487,7 +5515,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) mod = (modrm >> 6) & 3; if (reg >= 6) goto illegal_op; - gen_op_movl_T0_seg(reg); + gen_op_movl_T0_seg(s, reg); ot = mod == 3 ? dflag : MO_16; gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1); break; @@ -5513,31 +5541,31 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) rm = (modrm & 7) | REX_B(s); if (mod == 3) { - if (s_ot == MO_SB && byte_reg_is_xH(rm)) { - tcg_gen_sextract_tl(cpu_T0, cpu_regs[rm - 4], 8, 8); + if (s_ot == MO_SB && byte_reg_is_xH(s, rm)) { + tcg_gen_sextract_tl(s->T0, cpu_regs[rm - 4], 8, 8); } else { - gen_op_mov_v_reg(ot, cpu_T0, rm); + gen_op_mov_v_reg(s, ot, s->T0, rm); switch (s_ot) { case MO_UB: - tcg_gen_ext8u_tl(cpu_T0, cpu_T0); + tcg_gen_ext8u_tl(s->T0, s->T0); break; case MO_SB: - tcg_gen_ext8s_tl(cpu_T0, cpu_T0); + tcg_gen_ext8s_tl(s->T0, s->T0); break; case MO_UW: - tcg_gen_ext16u_tl(cpu_T0, cpu_T0); + tcg_gen_ext16u_tl(s->T0, s->T0); break; default: case MO_SW: - tcg_gen_ext16s_tl(cpu_T0, cpu_T0); + tcg_gen_ext16s_tl(s->T0, s->T0); break; } } - gen_op_mov_reg_v(d_ot, reg, cpu_T0); + gen_op_mov_reg_v(s, d_ot, reg, s->T0); } else { gen_lea_modrm(env, s, modrm); - gen_op_ld_v(s, s_ot, cpu_T0, cpu_A0); - gen_op_mov_reg_v(d_ot, reg, cpu_T0); + gen_op_ld_v(s, s_ot, s->T0, s->A0); + gen_op_mov_reg_v(s, d_ot, reg, s->T0); } } break; @@ -5550,9 +5578,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) reg = ((modrm >> 3) & 7) | rex_r; { AddressParts a = gen_lea_modrm_0(env, s, modrm); - TCGv ea = gen_lea_modrm_1(a); + TCGv ea = gen_lea_modrm_1(s, a); gen_lea_v_seg(s, s->aflag, ea, -1, -1); - gen_op_mov_reg_v(dflag, reg, cpu_A0); + gen_op_mov_reg_v(s, dflag, reg, s->A0); } break; @@ -5574,30 +5602,30 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) offset_addr = insn_get(env, s, s->aflag); break; } - tcg_gen_movi_tl(cpu_A0, offset_addr); + tcg_gen_movi_tl(s->A0, offset_addr); gen_add_A0_ds_seg(s); if ((b & 2) == 0) { - gen_op_ld_v(s, ot, cpu_T0, cpu_A0); - gen_op_mov_reg_v(ot, R_EAX, cpu_T0); + gen_op_ld_v(s, ot, s->T0, s->A0); + gen_op_mov_reg_v(s, ot, R_EAX, s->T0); } else { - gen_op_mov_v_reg(ot, cpu_T0, R_EAX); - gen_op_st_v(s, ot, cpu_T0, cpu_A0); + gen_op_mov_v_reg(s, ot, s->T0, R_EAX); + gen_op_st_v(s, ot, s->T0, s->A0); } } break; case 0xd7: /* xlat */ - tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EBX]); - tcg_gen_ext8u_tl(cpu_T0, cpu_regs[R_EAX]); - tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T0); - gen_extu(s->aflag, cpu_A0); + tcg_gen_mov_tl(s->A0, cpu_regs[R_EBX]); + tcg_gen_ext8u_tl(s->T0, cpu_regs[R_EAX]); + tcg_gen_add_tl(s->A0, s->A0, s->T0); + gen_extu(s->aflag, s->A0); gen_add_A0_ds_seg(s); - gen_op_ld_v(s, MO_8, cpu_T0, cpu_A0); - gen_op_mov_reg_v(MO_8, R_EAX, cpu_T0); + gen_op_ld_v(s, MO_8, s->T0, s->A0); + gen_op_mov_reg_v(s, MO_8, R_EAX, s->T0); break; case 0xb0 ... 0xb7: /* mov R, Ib */ val = insn_get(env, s, MO_8); - tcg_gen_movi_tl(cpu_T0, val); - gen_op_mov_reg_v(MO_8, (b & 7) | REX_B(s), cpu_T0); + tcg_gen_movi_tl(s->T0, val); + gen_op_mov_reg_v(s, MO_8, (b & 7) | REX_B(s), s->T0); break; case 0xb8 ... 0xbf: /* mov R, Iv */ #ifdef TARGET_X86_64 @@ -5606,16 +5634,16 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) /* 64 bit case */ tmp = x86_ldq_code(env, s); reg = (b & 7) | REX_B(s); - tcg_gen_movi_tl(cpu_T0, tmp); - gen_op_mov_reg_v(MO_64, reg, cpu_T0); + tcg_gen_movi_tl(s->T0, tmp); + gen_op_mov_reg_v(s, MO_64, reg, s->T0); } else #endif { ot = dflag; val = insn_get(env, s, ot); reg = (b & 7) | REX_B(s); - tcg_gen_movi_tl(cpu_T0, val); - gen_op_mov_reg_v(ot, reg, cpu_T0); + tcg_gen_movi_tl(s->T0, val); + gen_op_mov_reg_v(s, ot, reg, s->T0); } break; @@ -5634,17 +5662,17 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) if (mod == 3) { rm = (modrm & 7) | REX_B(s); do_xchg_reg: - gen_op_mov_v_reg(ot, cpu_T0, reg); - gen_op_mov_v_reg(ot, cpu_T1, rm); - gen_op_mov_reg_v(ot, rm, cpu_T0); - gen_op_mov_reg_v(ot, reg, cpu_T1); + gen_op_mov_v_reg(s, ot, s->T0, reg); + gen_op_mov_v_reg(s, ot, s->T1, rm); + gen_op_mov_reg_v(s, ot, rm, s->T0); + gen_op_mov_reg_v(s, ot, reg, s->T1); } else { gen_lea_modrm(env, s, modrm); - gen_op_mov_v_reg(ot, cpu_T0, reg); + gen_op_mov_v_reg(s, ot, s->T0, reg); /* for xchg, lock is implicit */ - tcg_gen_atomic_xchg_tl(cpu_T1, cpu_A0, cpu_T0, + tcg_gen_atomic_xchg_tl(s->T1, s->A0, s->T0, s->mem_index, ot | MO_LE); - gen_op_mov_reg_v(ot, reg, cpu_T1); + gen_op_mov_reg_v(s, ot, reg, s->T1); } break; case 0xc4: /* les Gv */ @@ -5671,15 +5699,15 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) if (mod == 3) goto illegal_op; gen_lea_modrm(env, s, modrm); - gen_op_ld_v(s, ot, cpu_T1, cpu_A0); + gen_op_ld_v(s, ot, s->T1, s->A0); gen_add_A0_im(s, 1 << ot); /* load the segment first to handle exceptions properly */ - gen_op_ld_v(s, MO_16, cpu_T0, cpu_A0); + gen_op_ld_v(s, MO_16, s->T0, s->A0); gen_movl_seg_T0(s, op); /* then put the data */ - gen_op_mov_reg_v(ot, reg, cpu_T1); + gen_op_mov_reg_v(s, ot, reg, s->T1); if (s->base.is_jmp) { - gen_jmp_im(s->pc - s->cs_base); + gen_jmp_im(s, s->pc - s->cs_base); gen_eob(s); } break; @@ -5756,7 +5784,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) } else { opreg = rm; } - gen_op_mov_v_reg(ot, cpu_T1, reg); + gen_op_mov_v_reg(s, ot, s->T1, reg); if (shift) { TCGv imm = tcg_const_tl(x86_ldub_code(env, s)); @@ -5794,25 +5822,25 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) switch(op >> 4) { case 0: - tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0, + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL); - gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32); + gen_helper_flds_FT0(cpu_env, s->tmp2_i32); break; case 1: - tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0, + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL); - gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32); + gen_helper_fildl_FT0(cpu_env, s->tmp2_i32); break; case 2: - tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, + tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ); - gen_helper_fldl_FT0(cpu_env, cpu_tmp1_i64); + gen_helper_fldl_FT0(cpu_env, s->tmp1_i64); break; case 3: default: - tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0, + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LESW); - gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32); + gen_helper_fildl_FT0(cpu_env, s->tmp2_i32); break; } @@ -5833,25 +5861,25 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) case 0: switch(op >> 4) { case 0: - tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0, + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL); - gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32); + gen_helper_flds_ST0(cpu_env, s->tmp2_i32); break; case 1: - tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0, + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL); - gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32); + gen_helper_fildl_ST0(cpu_env, s->tmp2_i32); break; case 2: - tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, + tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ); - gen_helper_fldl_ST0(cpu_env, cpu_tmp1_i64); + gen_helper_fldl_ST0(cpu_env, s->tmp1_i64); break; case 3: default: - tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0, + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LESW); - gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32); + gen_helper_fildl_ST0(cpu_env, s->tmp2_i32); break; } break; @@ -5859,19 +5887,19 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) /* XXX: the corresponding CPUID bit must be tested ! */ switch(op >> 4) { case 1: - gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0, + gen_helper_fisttl_ST0(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL); break; case 2: - gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env); - tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, + gen_helper_fisttll_ST0(s->tmp1_i64, cpu_env); + tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ); break; case 3: default: - gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0, + gen_helper_fistt_ST0(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUW); break; } @@ -5880,24 +5908,24 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) default: switch(op >> 4) { case 0: - gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0, + gen_helper_fsts_ST0(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL); break; case 1: - gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0, + gen_helper_fistl_ST0(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL); break; case 2: - gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env); - tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, + gen_helper_fstl_ST0(s->tmp1_i64, cpu_env); + tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ); break; case 3: default: - gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0, + gen_helper_fist_ST0(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUW); break; } @@ -5907,53 +5935,53 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) } break; case 0x0c: /* fldenv mem */ - gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1)); + gen_helper_fldenv(cpu_env, s->A0, tcg_const_i32(dflag - 1)); break; case 0x0d: /* fldcw mem */ - tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0, + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUW); - gen_helper_fldcw(cpu_env, cpu_tmp2_i32); + gen_helper_fldcw(cpu_env, s->tmp2_i32); break; case 0x0e: /* fnstenv mem */ - gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1)); + gen_helper_fstenv(cpu_env, s->A0, tcg_const_i32(dflag - 1)); break; case 0x0f: /* fnstcw mem */ - gen_helper_fnstcw(cpu_tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0, + gen_helper_fnstcw(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUW); break; case 0x1d: /* fldt mem */ - gen_helper_fldt_ST0(cpu_env, cpu_A0); + gen_helper_fldt_ST0(cpu_env, s->A0); break; case 0x1f: /* fstpt mem */ - gen_helper_fstt_ST0(cpu_env, cpu_A0); + gen_helper_fstt_ST0(cpu_env, s->A0); gen_helper_fpop(cpu_env); break; case 0x2c: /* frstor mem */ - gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(dflag - 1)); + gen_helper_frstor(cpu_env, s->A0, tcg_const_i32(dflag - 1)); break; case 0x2e: /* fnsave mem */ - gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(dflag - 1)); + gen_helper_fsave(cpu_env, s->A0, tcg_const_i32(dflag - 1)); break; case 0x2f: /* fnstsw mem */ - gen_helper_fnstsw(cpu_tmp2_i32, cpu_env); - tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0, + gen_helper_fnstsw(s->tmp2_i32, cpu_env); + tcg_gen_qemu_st_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUW); break; case 0x3c: /* fbld */ - gen_helper_fbld_ST0(cpu_env, cpu_A0); + gen_helper_fbld_ST0(cpu_env, s->A0); break; case 0x3e: /* fbstp */ - gen_helper_fbst_ST0(cpu_env, cpu_A0); + gen_helper_fbst_ST0(cpu_env, s->A0); gen_helper_fpop(cpu_env); break; case 0x3d: /* fildll */ - tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ); - gen_helper_fildll_ST0(cpu_env, cpu_tmp1_i64); + tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ); + gen_helper_fildll_ST0(cpu_env, s->tmp1_i64); break; case 0x3f: /* fistpll */ - gen_helper_fistll_ST0(cpu_tmp1_i64, cpu_env); - tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ); + gen_helper_fistll_ST0(s->tmp1_i64, cpu_env); + tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ); gen_helper_fpop(cpu_env); break; default: @@ -6215,9 +6243,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) case 0x3c: /* df/4 */ switch(rm) { case 0: - gen_helper_fnstsw(cpu_tmp2_i32, cpu_env); - tcg_gen_extu_i32_tl(cpu_T0, cpu_tmp2_i32); - gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0); + gen_helper_fnstsw(s->tmp2_i32, cpu_env); + tcg_gen_extu_i32_tl(s->T0, s->tmp2_i32); + gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0); break; default: goto unknown_op; @@ -6327,7 +6355,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) case 0x6c: /* insS */ case 0x6d: ot = mo_b_d32(b, dflag); - tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]); + tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]); gen_check_io(s, ot, pc_start - s->cs_base, SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4); if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { @@ -6342,7 +6370,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) case 0x6e: /* outsS */ case 0x6f: ot = mo_b_d32(b, dflag); - tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]); + tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]); gen_check_io(s, ot, pc_start - s->cs_base, svm_is_rep(prefixes) | 4); if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { @@ -6362,16 +6390,16 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) case 0xe5: ot = mo_b_d32(b, dflag); val = x86_ldub_code(env, s); - tcg_gen_movi_tl(cpu_T0, val); + tcg_gen_movi_tl(s->T0, val); gen_check_io(s, ot, pc_start - s->cs_base, SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes)); if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { gen_io_start(); } - tcg_gen_movi_i32(cpu_tmp2_i32, val); - gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32); - gen_op_mov_reg_v(ot, R_EAX, cpu_T1); - gen_bpt_io(s, cpu_tmp2_i32, ot); + tcg_gen_movi_i32(s->tmp2_i32, val); + gen_helper_in_func(ot, s->T1, s->tmp2_i32); + gen_op_mov_reg_v(s, ot, R_EAX, s->T1); + gen_bpt_io(s, s->tmp2_i32, ot); if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { gen_io_end(); gen_jmp(s, s->pc - s->cs_base); @@ -6381,18 +6409,18 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) case 0xe7: ot = mo_b_d32(b, dflag); val = x86_ldub_code(env, s); - tcg_gen_movi_tl(cpu_T0, val); + tcg_gen_movi_tl(s->T0, val); gen_check_io(s, ot, pc_start - s->cs_base, svm_is_rep(prefixes)); - gen_op_mov_v_reg(ot, cpu_T1, R_EAX); + gen_op_mov_v_reg(s, ot, s->T1, R_EAX); if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { gen_io_start(); } - tcg_gen_movi_i32(cpu_tmp2_i32, val); - tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1); - gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32); - gen_bpt_io(s, cpu_tmp2_i32, ot); + tcg_gen_movi_i32(s->tmp2_i32, val); + tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1); + gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32); + gen_bpt_io(s, s->tmp2_i32, ot); if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { gen_io_end(); gen_jmp(s, s->pc - s->cs_base); @@ -6401,16 +6429,16 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) case 0xec: case 0xed: ot = mo_b_d32(b, dflag); - tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]); + tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]); gen_check_io(s, ot, pc_start - s->cs_base, SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes)); if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { gen_io_start(); } - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); - gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32); - gen_op_mov_reg_v(ot, R_EAX, cpu_T1); - gen_bpt_io(s, cpu_tmp2_i32, ot); + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); + gen_helper_in_func(ot, s->T1, s->tmp2_i32); + gen_op_mov_reg_v(s, ot, R_EAX, s->T1); + gen_bpt_io(s, s->tmp2_i32, ot); if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { gen_io_end(); gen_jmp(s, s->pc - s->cs_base); @@ -6419,18 +6447,18 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) case 0xee: case 0xef: ot = mo_b_d32(b, dflag); - tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]); + tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]); gen_check_io(s, ot, pc_start - s->cs_base, svm_is_rep(prefixes)); - gen_op_mov_v_reg(ot, cpu_T1, R_EAX); + gen_op_mov_v_reg(s, ot, s->T1, R_EAX); if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { gen_io_start(); } - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); - tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1); - gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32); - gen_bpt_io(s, cpu_tmp2_i32, ot); + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); + tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1); + gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32); + gen_bpt_io(s, s->tmp2_i32, ot); if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { gen_io_end(); gen_jmp(s, s->pc - s->cs_base); @@ -6444,37 +6472,37 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) ot = gen_pop_T0(s); gen_stack_update(s, val + (1 << ot)); /* Note that gen_pop_T0 uses a zero-extending load. */ - gen_op_jmp_v(cpu_T0); + gen_op_jmp_v(s->T0); gen_bnd_jmp(s); - gen_jr(s, cpu_T0); + gen_jr(s, s->T0); break; case 0xc3: /* ret */ ot = gen_pop_T0(s); gen_pop_update(s, ot); /* Note that gen_pop_T0 uses a zero-extending load. */ - gen_op_jmp_v(cpu_T0); + gen_op_jmp_v(s->T0); gen_bnd_jmp(s); - gen_jr(s, cpu_T0); + gen_jr(s, s->T0); break; case 0xca: /* lret im */ val = x86_ldsw_code(env, s); do_lret: if (s->pe && !s->vm86) { gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1), tcg_const_i32(val)); } else { gen_stack_A0(s); /* pop offset */ - gen_op_ld_v(s, dflag, cpu_T0, cpu_A0); + gen_op_ld_v(s, dflag, s->T0, s->A0); /* NOTE: keeping EIP updated is not a problem in case of exception */ - gen_op_jmp_v(cpu_T0); + gen_op_jmp_v(s->T0); /* pop selector */ gen_add_A0_im(s, 1 << dflag); - gen_op_ld_v(s, dflag, cpu_T0, cpu_A0); - gen_op_movl_seg_T0_vm(R_CS); + gen_op_ld_v(s, dflag, s->T0, s->A0); + gen_op_movl_seg_T0_vm(s, R_CS); /* add stack offset */ gen_stack_update(s, val + (2 << dflag)); } @@ -6517,8 +6545,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) } else if (!CODE64(s)) { tval &= 0xffffffff; } - tcg_gen_movi_tl(cpu_T0, next_eip); - gen_push_v(s, cpu_T0); + tcg_gen_movi_tl(s->T0, next_eip); + gen_push_v(s, s->T0); gen_bnd_jmp(s); gen_jmp(s, tval); } @@ -6533,8 +6561,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) offset = insn_get(env, s, ot); selector = insn_get(env, s, MO_16); - tcg_gen_movi_tl(cpu_T0, selector); - tcg_gen_movi_tl(cpu_T1, offset); + tcg_gen_movi_tl(s->T0, selector); + tcg_gen_movi_tl(s->T1, offset); } goto do_lcall; case 0xe9: /* jmp im */ @@ -6562,8 +6590,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) offset = insn_get(env, s, ot); selector = insn_get(env, s, MO_16); - tcg_gen_movi_tl(cpu_T0, selector); - tcg_gen_movi_tl(cpu_T1, offset); + tcg_gen_movi_tl(s->T0, selector); + tcg_gen_movi_tl(s->T1, offset); } goto do_ljmp; case 0xeb: /* jmp Jb */ @@ -6595,7 +6623,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) case 0x190 ... 0x19f: /* setcc Gv */ modrm = x86_ldub_code(env, s); - gen_setcc1(s, b, cpu_T0); + gen_setcc1(s, b, s->T0); gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1); break; case 0x140 ... 0x14f: /* cmov Gv, Ev */ @@ -6616,8 +6644,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { gen_update_cc_op(s); - gen_helper_read_eflags(cpu_T0, cpu_env); - gen_push_v(s, cpu_T0); + gen_helper_read_eflags(s->T0, cpu_env); + gen_push_v(s, s->T0); } break; case 0x9d: /* popf */ @@ -6628,13 +6656,13 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) ot = gen_pop_T0(s); if (s->cpl == 0) { if (dflag != MO_16) { - gen_helper_write_eflags(cpu_env, cpu_T0, + gen_helper_write_eflags(cpu_env, s->T0, tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK))); } else { - gen_helper_write_eflags(cpu_env, cpu_T0, + gen_helper_write_eflags(cpu_env, s->T0, tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) @@ -6643,14 +6671,14 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) } else { if (s->cpl <= s->iopl) { if (dflag != MO_16) { - gen_helper_write_eflags(cpu_env, cpu_T0, + gen_helper_write_eflags(cpu_env, s->T0, tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK))); } else { - gen_helper_write_eflags(cpu_env, cpu_T0, + gen_helper_write_eflags(cpu_env, s->T0, tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | @@ -6660,11 +6688,11 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) } } else { if (dflag != MO_16) { - gen_helper_write_eflags(cpu_env, cpu_T0, + gen_helper_write_eflags(cpu_env, s->T0, tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK))); } else { - gen_helper_write_eflags(cpu_env, cpu_T0, + gen_helper_write_eflags(cpu_env, s->T0, tcg_const_i32((TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff)); @@ -6674,26 +6702,26 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) gen_pop_update(s, ot); set_cc_op(s, CC_OP_EFLAGS); /* abort translation because TF/AC flag may change */ - gen_jmp_im(s->pc - s->cs_base); + gen_jmp_im(s, s->pc - s->cs_base); gen_eob(s); } break; case 0x9e: /* sahf */ if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM)) goto illegal_op; - gen_op_mov_v_reg(MO_8, cpu_T0, R_AH); + gen_op_mov_v_reg(s, MO_8, s->T0, R_AH); gen_compute_eflags(s); tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O); - tcg_gen_andi_tl(cpu_T0, cpu_T0, CC_S | CC_Z | CC_A | CC_P | CC_C); - tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T0); + tcg_gen_andi_tl(s->T0, s->T0, CC_S | CC_Z | CC_A | CC_P | CC_C); + tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, s->T0); break; case 0x9f: /* lahf */ if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM)) goto illegal_op; gen_compute_eflags(s); /* Note: gen_compute_eflags() only gives the condition codes */ - tcg_gen_ori_tl(cpu_T0, cpu_cc_src, 0x02); - gen_op_mov_reg_v(MO_8, R_AH, cpu_T0); + tcg_gen_ori_tl(s->T0, cpu_cc_src, 0x02); + gen_op_mov_reg_v(s, MO_8, R_AH, s->T0); break; case 0xf5: /* cmc */ gen_compute_eflags(s); @@ -6708,12 +6736,12 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C); break; case 0xfc: /* cld */ - tcg_gen_movi_i32(cpu_tmp2_i32, 1); - tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df)); + tcg_gen_movi_i32(s->tmp2_i32, 1); + tcg_gen_st_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State, df)); break; case 0xfd: /* std */ - tcg_gen_movi_i32(cpu_tmp2_i32, -1); - tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df)); + tcg_gen_movi_i32(s->tmp2_i32, -1); + tcg_gen_st_i32(s->tmp2_i32, cpu_env, offsetof(CPUX86State, df)); break; /************************/ @@ -6728,14 +6756,14 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) s->rip_offset = 1; gen_lea_modrm(env, s, modrm); if (!(s->prefix & PREFIX_LOCK)) { - gen_op_ld_v(s, ot, cpu_T0, cpu_A0); + gen_op_ld_v(s, ot, s->T0, s->A0); } } else { - gen_op_mov_v_reg(ot, cpu_T0, rm); + gen_op_mov_v_reg(s, ot, s->T0, rm); } /* load shift */ val = x86_ldub_code(env, s); - tcg_gen_movi_tl(cpu_T1, val); + tcg_gen_movi_tl(s->T1, val); if (op < 4) goto unknown_op; op -= 4; @@ -6757,70 +6785,70 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); - gen_op_mov_v_reg(MO_32, cpu_T1, reg); + gen_op_mov_v_reg(s, MO_32, s->T1, reg); if (mod != 3) { AddressParts a = gen_lea_modrm_0(env, s, modrm); /* specific case: we need to add a displacement */ - gen_exts(ot, cpu_T1); - tcg_gen_sari_tl(cpu_tmp0, cpu_T1, 3 + ot); - tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot); - tcg_gen_add_tl(cpu_A0, gen_lea_modrm_1(a), cpu_tmp0); - gen_lea_v_seg(s, s->aflag, cpu_A0, a.def_seg, s->override); + gen_exts(ot, s->T1); + tcg_gen_sari_tl(s->tmp0, s->T1, 3 + ot); + tcg_gen_shli_tl(s->tmp0, s->tmp0, ot); + tcg_gen_add_tl(s->A0, gen_lea_modrm_1(s, a), s->tmp0); + gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override); if (!(s->prefix & PREFIX_LOCK)) { - gen_op_ld_v(s, ot, cpu_T0, cpu_A0); + gen_op_ld_v(s, ot, s->T0, s->A0); } } else { - gen_op_mov_v_reg(ot, cpu_T0, rm); + gen_op_mov_v_reg(s, ot, s->T0, rm); } bt_op: - tcg_gen_andi_tl(cpu_T1, cpu_T1, (1 << (3 + ot)) - 1); - tcg_gen_movi_tl(cpu_tmp0, 1); - tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T1); + tcg_gen_andi_tl(s->T1, s->T1, (1 << (3 + ot)) - 1); + tcg_gen_movi_tl(s->tmp0, 1); + tcg_gen_shl_tl(s->tmp0, s->tmp0, s->T1); if (s->prefix & PREFIX_LOCK) { switch (op) { case 0: /* bt */ /* Needs no atomic ops; we surpressed the normal memory load for LOCK above so do it now. */ - gen_op_ld_v(s, ot, cpu_T0, cpu_A0); + gen_op_ld_v(s, ot, s->T0, s->A0); break; case 1: /* bts */ - tcg_gen_atomic_fetch_or_tl(cpu_T0, cpu_A0, cpu_tmp0, + tcg_gen_atomic_fetch_or_tl(s->T0, s->A0, s->tmp0, s->mem_index, ot | MO_LE); break; case 2: /* btr */ - tcg_gen_not_tl(cpu_tmp0, cpu_tmp0); - tcg_gen_atomic_fetch_and_tl(cpu_T0, cpu_A0, cpu_tmp0, + tcg_gen_not_tl(s->tmp0, s->tmp0); + tcg_gen_atomic_fetch_and_tl(s->T0, s->A0, s->tmp0, s->mem_index, ot | MO_LE); break; default: case 3: /* btc */ - tcg_gen_atomic_fetch_xor_tl(cpu_T0, cpu_A0, cpu_tmp0, + tcg_gen_atomic_fetch_xor_tl(s->T0, s->A0, s->tmp0, s->mem_index, ot | MO_LE); break; } - tcg_gen_shr_tl(cpu_tmp4, cpu_T0, cpu_T1); + tcg_gen_shr_tl(s->tmp4, s->T0, s->T1); } else { - tcg_gen_shr_tl(cpu_tmp4, cpu_T0, cpu_T1); + tcg_gen_shr_tl(s->tmp4, s->T0, s->T1); switch (op) { case 0: /* bt */ /* Data already loaded; nothing to do. */ break; case 1: /* bts */ - tcg_gen_or_tl(cpu_T0, cpu_T0, cpu_tmp0); + tcg_gen_or_tl(s->T0, s->T0, s->tmp0); break; case 2: /* btr */ - tcg_gen_andc_tl(cpu_T0, cpu_T0, cpu_tmp0); + tcg_gen_andc_tl(s->T0, s->T0, s->tmp0); break; default: case 3: /* btc */ - tcg_gen_xor_tl(cpu_T0, cpu_T0, cpu_tmp0); + tcg_gen_xor_tl(s->T0, s->T0, s->tmp0); break; } if (op != 0) { if (mod != 3) { - gen_op_st_v(s, ot, cpu_T0, cpu_A0); + gen_op_st_v(s, ot, s->T0, s->A0); } else { - gen_op_mov_reg_v(ot, rm, cpu_T0); + gen_op_mov_reg_v(s, ot, rm, s->T0); } } } @@ -6844,13 +6872,13 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) We can get that same Z value (and the new C value) by leaving CC_DST alone, setting CC_SRC, and using a CC_OP_SAR of the same width. */ - tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4); + tcg_gen_mov_tl(cpu_cc_src, s->tmp4); set_cc_op(s, ((s->cc_op - CC_OP_MULB) & 3) + CC_OP_SARB); break; default: /* Otherwise, generate EFLAGS and replace the C bit. */ gen_compute_eflags(s); - tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, cpu_tmp4, + tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, s->tmp4, ctz32(CC_C), 1); break; } @@ -6861,7 +6889,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) modrm = x86_ldub_code(env, s); reg = ((modrm >> 3) & 7) | rex_r; gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - gen_extu(ot, cpu_T0); + gen_extu(ot, s->T0); /* Note that lzcnt and tzcnt are in different extensions. */ if ((prefixes & PREFIX_REPZ) @@ -6870,23 +6898,23 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) { int size = 8 << ot; /* For lzcnt/tzcnt, C bit is defined related to the input. */ - tcg_gen_mov_tl(cpu_cc_src, cpu_T0); + tcg_gen_mov_tl(cpu_cc_src, s->T0); if (b & 1) { /* For lzcnt, reduce the target_ulong result by the number of zeros that we expect to find at the top. */ - tcg_gen_clzi_tl(cpu_T0, cpu_T0, TARGET_LONG_BITS); - tcg_gen_subi_tl(cpu_T0, cpu_T0, TARGET_LONG_BITS - size); + tcg_gen_clzi_tl(s->T0, s->T0, TARGET_LONG_BITS); + tcg_gen_subi_tl(s->T0, s->T0, TARGET_LONG_BITS - size); } else { /* For tzcnt, a zero input must return the operand size. */ - tcg_gen_ctzi_tl(cpu_T0, cpu_T0, size); + tcg_gen_ctzi_tl(s->T0, s->T0, size); } /* For lzcnt/tzcnt, Z bit is defined related to the result. */ - gen_op_update1_cc(); + gen_op_update1_cc(s); set_cc_op(s, CC_OP_BMILGB + ot); } else { /* For bsr/bsf, only the Z bit is defined and it is related to the input and not the result. */ - tcg_gen_mov_tl(cpu_cc_dst, cpu_T0); + tcg_gen_mov_tl(cpu_cc_dst, s->T0); set_cc_op(s, CC_OP_LOGICB + ot); /* ??? The manual says that the output is undefined when the @@ -6896,14 +6924,14 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) if (b & 1) { /* For bsr, return the bit index of the first 1 bit, not the count of leading zeros. */ - tcg_gen_xori_tl(cpu_T1, cpu_regs[reg], TARGET_LONG_BITS - 1); - tcg_gen_clz_tl(cpu_T0, cpu_T0, cpu_T1); - tcg_gen_xori_tl(cpu_T0, cpu_T0, TARGET_LONG_BITS - 1); + tcg_gen_xori_tl(s->T1, cpu_regs[reg], TARGET_LONG_BITS - 1); + tcg_gen_clz_tl(s->T0, s->T0, s->T1); + tcg_gen_xori_tl(s->T0, s->T0, TARGET_LONG_BITS - 1); } else { - tcg_gen_ctz_tl(cpu_T0, cpu_T0, cpu_regs[reg]); + tcg_gen_ctz_tl(s->T0, s->T0, cpu_regs[reg]); } } - gen_op_mov_reg_v(ot, reg, cpu_T0); + gen_op_mov_reg_v(s, ot, reg, s->T0); break; /************************/ /* bcd */ @@ -6966,7 +6994,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) } if (prefixes & PREFIX_REPZ) { gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start)); s->base.is_jmp = DISAS_NORETURN; } @@ -6994,7 +7022,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) if (CODE64(s)) goto illegal_op; gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start)); break; #ifdef WANT_ICEBP @@ -7028,7 +7056,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) if (s->vm86 ? s->iopl == 3 : s->cpl <= s->iopl) { gen_helper_sti(cpu_env); /* interruptions are enabled only the first insn after sti */ - gen_jmp_im(s->pc - s->cs_base); + gen_jmp_im(s, s->pc - s->cs_base); gen_eob_inhibit_irq(s, true); } else { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); @@ -7043,37 +7071,37 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) mod = (modrm >> 6) & 3; if (mod == 3) goto illegal_op; - gen_op_mov_v_reg(ot, cpu_T0, reg); + gen_op_mov_v_reg(s, ot, s->T0, reg); gen_lea_modrm(env, s, modrm); - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); if (ot == MO_16) { - gen_helper_boundw(cpu_env, cpu_A0, cpu_tmp2_i32); + gen_helper_boundw(cpu_env, s->A0, s->tmp2_i32); } else { - gen_helper_boundl(cpu_env, cpu_A0, cpu_tmp2_i32); + gen_helper_boundl(cpu_env, s->A0, s->tmp2_i32); } break; case 0x1c8 ... 0x1cf: /* bswap reg */ reg = (b & 7) | REX_B(s); #ifdef TARGET_X86_64 if (dflag == MO_64) { - gen_op_mov_v_reg(MO_64, cpu_T0, reg); - tcg_gen_bswap64_i64(cpu_T0, cpu_T0); - gen_op_mov_reg_v(MO_64, reg, cpu_T0); + gen_op_mov_v_reg(s, MO_64, s->T0, reg); + tcg_gen_bswap64_i64(s->T0, s->T0); + gen_op_mov_reg_v(s, MO_64, reg, s->T0); } else #endif { - gen_op_mov_v_reg(MO_32, cpu_T0, reg); - tcg_gen_ext32u_tl(cpu_T0, cpu_T0); - tcg_gen_bswap32_tl(cpu_T0, cpu_T0); - gen_op_mov_reg_v(MO_32, reg, cpu_T0); + gen_op_mov_v_reg(s, MO_32, s->T0, reg); + tcg_gen_ext32u_tl(s->T0, s->T0); + tcg_gen_bswap32_tl(s->T0, s->T0); + gen_op_mov_reg_v(s, MO_32, reg, s->T0); } break; case 0xd6: /* salc */ if (CODE64(s)) goto illegal_op; - gen_compute_eflags_c(s, cpu_T0); - tcg_gen_neg_tl(cpu_T0, cpu_T0); - gen_op_mov_reg_v(MO_8, R_EAX, cpu_T0); + gen_compute_eflags_c(s, s->T0); + tcg_gen_neg_tl(s->T0, s->T0); + gen_op_mov_reg_v(s, MO_8, R_EAX, s->T0); break; case 0xe0: /* loopnz */ case 0xe1: /* loopz */ @@ -7096,26 +7124,26 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) switch(b) { case 0: /* loopnz */ case 1: /* loopz */ - gen_op_add_reg_im(s->aflag, R_ECX, -1); - gen_op_jz_ecx(s->aflag, l3); + gen_op_add_reg_im(s, s->aflag, R_ECX, -1); + gen_op_jz_ecx(s, s->aflag, l3); gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1); break; case 2: /* loop */ - gen_op_add_reg_im(s->aflag, R_ECX, -1); - gen_op_jnz_ecx(s->aflag, l1); + gen_op_add_reg_im(s, s->aflag, R_ECX, -1); + gen_op_jnz_ecx(s, s->aflag, l1); break; default: case 3: /* jcxz */ - gen_op_jz_ecx(s->aflag, l1); + gen_op_jz_ecx(s, s->aflag, l1); break; } gen_set_label(l3); - gen_jmp_im(next_eip); + gen_jmp_im(s, next_eip); tcg_gen_br(l2); gen_set_label(l1); - gen_jmp_im(tval); + gen_jmp_im(s, tval); gen_set_label(l2); gen_eob(s); } @@ -7126,7 +7154,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); if (b & 2) { gen_helper_rdmsr(cpu_env); } else { @@ -7136,7 +7164,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) break; case 0x131: /* rdtsc */ gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { gen_io_start(); } @@ -7148,7 +7176,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) break; case 0x133: /* rdpmc */ gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); gen_helper_rdpmc(cpu_env); break; case 0x134: /* sysenter */ @@ -7177,7 +7205,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) case 0x105: /* syscall */ /* XXX: is it usable in real mode ? */ gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start)); /* TF handling for the syscall insn is different. The TF bit is checked after the syscall insn completes. This allows #DB to not be @@ -7203,7 +7231,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) #endif case 0x1a2: /* cpuid */ gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); gen_helper_cpuid(cpu_env); break; case 0xf4: /* hlt */ @@ -7211,7 +7239,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start)); s->base.is_jmp = DISAS_NORETURN; } @@ -7225,7 +7253,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) if (!s->pe || s->vm86) goto illegal_op; gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ); - tcg_gen_ld32u_tl(cpu_T0, cpu_env, + tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, ldt.selector)); ot = mod == 3 ? dflag : MO_16; gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1); @@ -7238,15 +7266,15 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) } else { gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE); gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0); - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); - gen_helper_lldt(cpu_env, cpu_tmp2_i32); + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); + gen_helper_lldt(cpu_env, s->tmp2_i32); } break; case 1: /* str */ if (!s->pe || s->vm86) goto illegal_op; gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ); - tcg_gen_ld32u_tl(cpu_T0, cpu_env, + tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, tr.selector)); ot = mod == 3 ? dflag : MO_16; gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1); @@ -7259,8 +7287,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) } else { gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE); gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0); - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); - gen_helper_ltr(cpu_env, cpu_tmp2_i32); + tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); + gen_helper_ltr(cpu_env, s->tmp2_i32); } break; case 4: /* verr */ @@ -7270,9 +7298,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0); gen_update_cc_op(s); if (op == 4) { - gen_helper_verr(cpu_env, cpu_T0); + gen_helper_verr(cpu_env, s->T0); } else { - gen_helper_verw(cpu_env, cpu_T0); + gen_helper_verw(cpu_env, s->T0); } set_cc_op(s, CC_OP_EFLAGS); break; @@ -7287,15 +7315,15 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) CASE_MODRM_MEM_OP(0): /* sgdt */ gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ); gen_lea_modrm(env, s, modrm); - tcg_gen_ld32u_tl(cpu_T0, + tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, gdt.limit)); - gen_op_st_v(s, MO_16, cpu_T0, cpu_A0); + gen_op_st_v(s, MO_16, s->T0, s->A0); gen_add_A0_im(s, 2); - tcg_gen_ld_tl(cpu_T0, cpu_env, offsetof(CPUX86State, gdt.base)); + tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, gdt.base)); if (dflag == MO_16) { - tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff); + tcg_gen_andi_tl(s->T0, s->T0, 0xffffff); } - gen_op_st_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0); + gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0); break; case 0xc8: /* monitor */ @@ -7303,11 +7331,11 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) goto illegal_op; } gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); - tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EAX]); - gen_extu(s->aflag, cpu_A0); + gen_jmp_im(s, pc_start - s->cs_base); + tcg_gen_mov_tl(s->A0, cpu_regs[R_EAX]); + gen_extu(s->aflag, s->A0); gen_add_A0_ds_seg(s); - gen_helper_monitor(cpu_env, cpu_A0); + gen_helper_monitor(cpu_env, s->A0); break; case 0xc9: /* mwait */ @@ -7315,7 +7343,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) goto illegal_op; } gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start)); gen_eob(s); break; @@ -7326,7 +7354,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) goto illegal_op; } gen_helper_clac(cpu_env); - gen_jmp_im(s->pc - s->cs_base); + gen_jmp_im(s, s->pc - s->cs_base); gen_eob(s); break; @@ -7336,21 +7364,21 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) goto illegal_op; } gen_helper_stac(cpu_env); - gen_jmp_im(s->pc - s->cs_base); + gen_jmp_im(s, s->pc - s->cs_base); gen_eob(s); break; CASE_MODRM_MEM_OP(1): /* sidt */ gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ); gen_lea_modrm(env, s, modrm); - tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State, idt.limit)); - gen_op_st_v(s, MO_16, cpu_T0, cpu_A0); + tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.limit)); + gen_op_st_v(s, MO_16, s->T0, s->A0); gen_add_A0_im(s, 2); - tcg_gen_ld_tl(cpu_T0, cpu_env, offsetof(CPUX86State, idt.base)); + tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.base)); if (dflag == MO_16) { - tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff); + tcg_gen_andi_tl(s->T0, s->T0, 0xffffff); } - gen_op_st_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0); + gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0); break; case 0xd0: /* xgetbv */ @@ -7359,9 +7387,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) | PREFIX_REPZ | PREFIX_REPNZ))) { goto illegal_op; } - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]); - gen_helper_xgetbv(cpu_tmp1_i64, cpu_env, cpu_tmp2_i32); - tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], cpu_tmp1_i64); + tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]); + gen_helper_xgetbv(s->tmp1_i64, cpu_env, s->tmp2_i32); + tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->tmp1_i64); break; case 0xd1: /* xsetbv */ @@ -7374,12 +7402,12 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); break; } - tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX], + tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX], cpu_regs[R_EDX]); - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]); - gen_helper_xsetbv(cpu_env, cpu_tmp2_i32, cpu_tmp1_i64); + tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]); + gen_helper_xsetbv(cpu_env, s->tmp2_i32, s->tmp1_i64); /* End TB because translation flags may change. */ - gen_jmp_im(s->pc - s->cs_base); + gen_jmp_im(s, s->pc - s->cs_base); gen_eob(s); break; @@ -7392,7 +7420,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) break; } gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1), tcg_const_i32(s->pc - pc_start)); tcg_gen_exit_tb(NULL, 0); @@ -7404,7 +7432,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) goto illegal_op; } gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); gen_helper_vmmcall(cpu_env); break; @@ -7417,7 +7445,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) break; } gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag - 1)); break; @@ -7430,7 +7458,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) break; } gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag - 1)); break; @@ -7446,7 +7474,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) } gen_update_cc_op(s); gen_helper_stgi(cpu_env); - gen_jmp_im(s->pc - s->cs_base); + gen_jmp_im(s, s->pc - s->cs_base); gen_eob(s); break; @@ -7459,7 +7487,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) break; } gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); gen_helper_clgi(cpu_env); break; @@ -7470,7 +7498,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) goto illegal_op; } gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); gen_helper_skinit(cpu_env); break; @@ -7483,7 +7511,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) break; } gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); gen_helper_invlpga(cpu_env, tcg_const_i32(s->aflag - 1)); break; @@ -7494,14 +7522,14 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) } gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_WRITE); gen_lea_modrm(env, s, modrm); - gen_op_ld_v(s, MO_16, cpu_T1, cpu_A0); + gen_op_ld_v(s, MO_16, s->T1, s->A0); gen_add_A0_im(s, 2); - gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0); + gen_op_ld_v(s, CODE64(s) + MO_32, s->T0, s->A0); if (dflag == MO_16) { - tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff); + tcg_gen_andi_tl(s->T0, s->T0, 0xffffff); } - tcg_gen_st_tl(cpu_T0, cpu_env, offsetof(CPUX86State, gdt.base)); - tcg_gen_st32_tl(cpu_T1, cpu_env, offsetof(CPUX86State, gdt.limit)); + tcg_gen_st_tl(s->T0, cpu_env, offsetof(CPUX86State, gdt.base)); + tcg_gen_st32_tl(s->T1, cpu_env, offsetof(CPUX86State, gdt.limit)); break; CASE_MODRM_MEM_OP(3): /* lidt */ @@ -7511,19 +7539,19 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) } gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_WRITE); gen_lea_modrm(env, s, modrm); - gen_op_ld_v(s, MO_16, cpu_T1, cpu_A0); + gen_op_ld_v(s, MO_16, s->T1, s->A0); gen_add_A0_im(s, 2); - gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T0, cpu_A0); + gen_op_ld_v(s, CODE64(s) + MO_32, s->T0, s->A0); if (dflag == MO_16) { - tcg_gen_andi_tl(cpu_T0, cpu_T0, 0xffffff); + tcg_gen_andi_tl(s->T0, s->T0, 0xffffff); } - tcg_gen_st_tl(cpu_T0, cpu_env, offsetof(CPUX86State, idt.base)); - tcg_gen_st32_tl(cpu_T1, cpu_env, offsetof(CPUX86State, idt.limit)); + tcg_gen_st_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.base)); + tcg_gen_st32_tl(s->T1, cpu_env, offsetof(CPUX86State, idt.limit)); break; CASE_MODRM_OP(4): /* smsw */ gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0); - tcg_gen_ld_tl(cpu_T0, cpu_env, offsetof(CPUX86State, cr[0])); + tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, cr[0])); if (CODE64(s)) { mod = (modrm >> 6) & 3; ot = (mod != 3 ? MO_16 : s->dflag); @@ -7536,18 +7564,18 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) if (prefixes & PREFIX_LOCK) { goto illegal_op; } - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]); - gen_helper_rdpkru(cpu_tmp1_i64, cpu_env, cpu_tmp2_i32); - tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], cpu_tmp1_i64); + tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]); + gen_helper_rdpkru(s->tmp1_i64, cpu_env, s->tmp2_i32); + tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], s->tmp1_i64); break; case 0xef: /* wrpkru */ if (prefixes & PREFIX_LOCK) { goto illegal_op; } - tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX], + tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX], cpu_regs[R_EDX]); - tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]); - gen_helper_wrpkru(cpu_env, cpu_tmp2_i32, cpu_tmp1_i64); + tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]); + gen_helper_wrpkru(cpu_env, s->tmp2_i32, s->tmp1_i64); break; CASE_MODRM_OP(6): /* lmsw */ if (s->cpl != 0) { @@ -7556,8 +7584,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) } gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0); gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0); - gen_helper_lmsw(cpu_env, cpu_T0); - gen_jmp_im(s->pc - s->cs_base); + gen_helper_lmsw(cpu_env, s->T0); + gen_jmp_im(s, s->pc - s->cs_base); gen_eob(s); break; @@ -7567,10 +7595,10 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) break; } gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); gen_lea_modrm(env, s, modrm); - gen_helper_invlpg(cpu_env, cpu_A0); - gen_jmp_im(s->pc - s->cs_base); + gen_helper_invlpg(cpu_env, s->A0); + gen_jmp_im(s, s->pc - s->cs_base); gen_eob(s); break; @@ -7580,10 +7608,10 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { - tcg_gen_mov_tl(cpu_T0, cpu_seg_base[R_GS]); + tcg_gen_mov_tl(s->T0, cpu_seg_base[R_GS]); tcg_gen_ld_tl(cpu_seg_base[R_GS], cpu_env, offsetof(CPUX86State, kernelgsbase)); - tcg_gen_st_tl(cpu_T0, cpu_env, + tcg_gen_st_tl(s->T0, cpu_env, offsetof(CPUX86State, kernelgsbase)); } break; @@ -7596,7 +7624,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) goto illegal_op; } gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { gen_io_start(); } @@ -7634,16 +7662,16 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) rm = (modrm & 7) | REX_B(s); if (mod == 3) { - gen_op_mov_v_reg(MO_32, cpu_T0, rm); + gen_op_mov_v_reg(s, MO_32, s->T0, rm); /* sign extend */ if (d_ot == MO_64) { - tcg_gen_ext32s_tl(cpu_T0, cpu_T0); + tcg_gen_ext32s_tl(s->T0, s->T0); } - gen_op_mov_reg_v(d_ot, reg, cpu_T0); + gen_op_mov_reg_v(s, d_ot, reg, s->T0); } else { gen_lea_modrm(env, s, modrm); - gen_op_ld_v(s, MO_32 | MO_SIGN, cpu_T0, cpu_A0); - gen_op_mov_reg_v(d_ot, reg, cpu_T0); + gen_op_ld_v(s, MO_32 | MO_SIGN, s->T0, s->A0); + gen_op_mov_reg_v(s, d_ot, reg, s->T0); } } else #endif @@ -7663,19 +7691,19 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) rm = modrm & 7; if (mod != 3) { gen_lea_modrm(env, s, modrm); - gen_op_ld_v(s, ot, t0, cpu_A0); + gen_op_ld_v(s, ot, t0, s->A0); a0 = tcg_temp_local_new(); - tcg_gen_mov_tl(a0, cpu_A0); + tcg_gen_mov_tl(a0, s->A0); } else { - gen_op_mov_v_reg(ot, t0, rm); + gen_op_mov_v_reg(s, ot, t0, rm); a0 = NULL; } - gen_op_mov_v_reg(ot, t1, reg); - tcg_gen_andi_tl(cpu_tmp0, t0, 3); + gen_op_mov_v_reg(s, ot, t1, reg); + tcg_gen_andi_tl(s->tmp0, t0, 3); tcg_gen_andi_tl(t1, t1, 3); tcg_gen_movi_tl(t2, 0); label1 = gen_new_label(); - tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1); + tcg_gen_brcond_tl(TCG_COND_GE, s->tmp0, t1, label1); tcg_gen_andi_tl(t0, t0, ~3); tcg_gen_or_tl(t0, t0, t1); tcg_gen_movi_tl(t2, CC_Z); @@ -7684,7 +7712,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) gen_op_st_v(s, ot, t0, a0); tcg_temp_free(a0); } else { - gen_op_mov_reg_v(ot, rm, t0); + gen_op_mov_reg_v(s, ot, rm, t0); } gen_compute_eflags(s); tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z); @@ -7708,14 +7736,14 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) t0 = tcg_temp_local_new(); gen_update_cc_op(s); if (b == 0x102) { - gen_helper_lar(t0, cpu_env, cpu_T0); + gen_helper_lar(t0, cpu_env, s->T0); } else { - gen_helper_lsl(t0, cpu_env, cpu_T0); + gen_helper_lsl(t0, cpu_env, s->T0); } - tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z); + tcg_gen_andi_tl(s->tmp0, cpu_cc_src, CC_Z); label1 = gen_new_label(); - tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1); - gen_op_mov_reg_v(ot, reg, t0); + tcg_gen_brcondi_tl(TCG_COND_EQ, s->tmp0, 0, label1); + gen_op_mov_reg_v(s, ot, reg, t0); gen_set_label(label1); set_cc_op(s, CC_OP_EFLAGS); tcg_temp_free(t0); @@ -7781,16 +7809,16 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) } else { gen_lea_modrm(env, s, modrm); if (CODE64(s)) { - tcg_gen_qemu_ld_i64(cpu_bndl[reg], cpu_A0, + tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0, s->mem_index, MO_LEQ); - tcg_gen_addi_tl(cpu_A0, cpu_A0, 8); - tcg_gen_qemu_ld_i64(cpu_bndu[reg], cpu_A0, + tcg_gen_addi_tl(s->A0, s->A0, 8); + tcg_gen_qemu_ld_i64(cpu_bndu[reg], s->A0, s->mem_index, MO_LEQ); } else { - tcg_gen_qemu_ld_i64(cpu_bndl[reg], cpu_A0, + tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0, s->mem_index, MO_LEUL); - tcg_gen_addi_tl(cpu_A0, cpu_A0, 4); - tcg_gen_qemu_ld_i64(cpu_bndu[reg], cpu_A0, + tcg_gen_addi_tl(s->A0, s->A0, 4); + tcg_gen_qemu_ld_i64(cpu_bndu[reg], s->A0, s->mem_index, MO_LEUL); } /* bnd registers are now in-use */ @@ -7806,22 +7834,22 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) goto illegal_op; } if (a.base >= 0) { - tcg_gen_addi_tl(cpu_A0, cpu_regs[a.base], a.disp); + tcg_gen_addi_tl(s->A0, cpu_regs[a.base], a.disp); } else { - tcg_gen_movi_tl(cpu_A0, 0); + tcg_gen_movi_tl(s->A0, 0); } - gen_lea_v_seg(s, s->aflag, cpu_A0, a.def_seg, s->override); + gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override); if (a.index >= 0) { - tcg_gen_mov_tl(cpu_T0, cpu_regs[a.index]); + tcg_gen_mov_tl(s->T0, cpu_regs[a.index]); } else { - tcg_gen_movi_tl(cpu_T0, 0); + tcg_gen_movi_tl(s->T0, 0); } if (CODE64(s)) { - gen_helper_bndldx64(cpu_bndl[reg], cpu_env, cpu_A0, cpu_T0); + gen_helper_bndldx64(cpu_bndl[reg], cpu_env, s->A0, s->T0); tcg_gen_ld_i64(cpu_bndu[reg], cpu_env, offsetof(CPUX86State, mmx_t0.MMX_Q(0))); } else { - gen_helper_bndldx32(cpu_bndu[reg], cpu_env, cpu_A0, cpu_T0); + gen_helper_bndldx32(cpu_bndu[reg], cpu_env, s->A0, s->T0); tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndu[reg]); tcg_gen_shri_i64(cpu_bndu[reg], cpu_bndu[reg], 32); } @@ -7855,11 +7883,11 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) /* rip-relative generates #ud */ goto illegal_op; } - tcg_gen_not_tl(cpu_A0, gen_lea_modrm_1(a)); + tcg_gen_not_tl(s->A0, gen_lea_modrm_1(s, a)); if (!CODE64(s)) { - tcg_gen_ext32u_tl(cpu_A0, cpu_A0); + tcg_gen_ext32u_tl(s->A0, s->A0); } - tcg_gen_extu_tl_i64(cpu_bndu[reg], cpu_A0); + tcg_gen_extu_tl_i64(cpu_bndu[reg], s->A0); /* bnd registers are now in-use */ gen_set_hflag(s, HF_MPX_IU_MASK); break; @@ -7888,16 +7916,16 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) } else { gen_lea_modrm(env, s, modrm); if (CODE64(s)) { - tcg_gen_qemu_st_i64(cpu_bndl[reg], cpu_A0, + tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0, s->mem_index, MO_LEQ); - tcg_gen_addi_tl(cpu_A0, cpu_A0, 8); - tcg_gen_qemu_st_i64(cpu_bndu[reg], cpu_A0, + tcg_gen_addi_tl(s->A0, s->A0, 8); + tcg_gen_qemu_st_i64(cpu_bndu[reg], s->A0, s->mem_index, MO_LEQ); } else { - tcg_gen_qemu_st_i64(cpu_bndl[reg], cpu_A0, + tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0, s->mem_index, MO_LEUL); - tcg_gen_addi_tl(cpu_A0, cpu_A0, 4); - tcg_gen_qemu_st_i64(cpu_bndu[reg], cpu_A0, + tcg_gen_addi_tl(s->A0, s->A0, 4); + tcg_gen_qemu_st_i64(cpu_bndu[reg], s->A0, s->mem_index, MO_LEUL); } } @@ -7911,21 +7939,21 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) goto illegal_op; } if (a.base >= 0) { - tcg_gen_addi_tl(cpu_A0, cpu_regs[a.base], a.disp); + tcg_gen_addi_tl(s->A0, cpu_regs[a.base], a.disp); } else { - tcg_gen_movi_tl(cpu_A0, 0); + tcg_gen_movi_tl(s->A0, 0); } - gen_lea_v_seg(s, s->aflag, cpu_A0, a.def_seg, s->override); + gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override); if (a.index >= 0) { - tcg_gen_mov_tl(cpu_T0, cpu_regs[a.index]); + tcg_gen_mov_tl(s->T0, cpu_regs[a.index]); } else { - tcg_gen_movi_tl(cpu_T0, 0); + tcg_gen_movi_tl(s->T0, 0); } if (CODE64(s)) { - gen_helper_bndstx64(cpu_env, cpu_A0, cpu_T0, + gen_helper_bndstx64(cpu_env, s->A0, s->T0, cpu_bndl[reg], cpu_bndu[reg]); } else { - gen_helper_bndstx32(cpu_env, cpu_A0, cpu_T0, + gen_helper_bndstx32(cpu_env, s->A0, s->T0, cpu_bndl[reg], cpu_bndu[reg]); } } @@ -7964,25 +7992,25 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) case 4: case 8: gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); + gen_jmp_im(s, pc_start - s->cs_base); if (b & 2) { if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { gen_io_start(); } - gen_op_mov_v_reg(ot, cpu_T0, rm); + gen_op_mov_v_reg(s, ot, s->T0, rm); gen_helper_write_crN(cpu_env, tcg_const_i32(reg), - cpu_T0); + s->T0); if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { gen_io_end(); } - gen_jmp_im(s->pc - s->cs_base); + gen_jmp_im(s, s->pc - s->cs_base); gen_eob(s); } else { if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { gen_io_start(); } - gen_helper_read_crN(cpu_T0, cpu_env, tcg_const_i32(reg)); - gen_op_mov_reg_v(ot, rm, cpu_T0); + gen_helper_read_crN(s->T0, cpu_env, tcg_const_i32(reg)); + gen_op_mov_reg_v(s, ot, rm, s->T0); if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) { gen_io_end(); } @@ -8015,16 +8043,16 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) } if (b & 2) { gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg); - gen_op_mov_v_reg(ot, cpu_T0, rm); - tcg_gen_movi_i32(cpu_tmp2_i32, reg); - gen_helper_set_dr(cpu_env, cpu_tmp2_i32, cpu_T0); - gen_jmp_im(s->pc - s->cs_base); + gen_op_mov_v_reg(s, ot, s->T0, rm); + tcg_gen_movi_i32(s->tmp2_i32, reg); + gen_helper_set_dr(cpu_env, s->tmp2_i32, s->T0); + gen_jmp_im(s, s->pc - s->cs_base); gen_eob(s); } else { gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg); - tcg_gen_movi_i32(cpu_tmp2_i32, reg); - gen_helper_get_dr(cpu_T0, cpu_env, cpu_tmp2_i32); - gen_op_mov_reg_v(ot, rm, cpu_T0); + tcg_gen_movi_i32(s->tmp2_i32, reg); + gen_helper_get_dr(s->T0, cpu_env, s->tmp2_i32); + gen_op_mov_reg_v(s, ot, rm, s->T0); } } break; @@ -8035,7 +8063,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0); gen_helper_clts(cpu_env); /* abort block because static cpu state changed */ - gen_jmp_im(s->pc - s->cs_base); + gen_jmp_im(s, s->pc - s->cs_base); gen_eob(s); } break; @@ -8065,7 +8093,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) break; } gen_lea_modrm(env, s, modrm); - gen_helper_fxsave(cpu_env, cpu_A0); + gen_helper_fxsave(cpu_env, s->A0); break; CASE_MODRM_MEM_OP(1): /* fxrstor */ @@ -8078,7 +8106,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) break; } gen_lea_modrm(env, s, modrm); - gen_helper_fxrstor(cpu_env, cpu_A0); + gen_helper_fxrstor(cpu_env, s->A0); break; CASE_MODRM_MEM_OP(2): /* ldmxcsr */ @@ -8090,8 +8118,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) break; } gen_lea_modrm(env, s, modrm); - tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0, s->mem_index, MO_LEUL); - gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32); + tcg_gen_qemu_ld_i32(s->tmp2_i32, s->A0, s->mem_index, MO_LEUL); + gen_helper_ldmxcsr(cpu_env, s->tmp2_i32); break; CASE_MODRM_MEM_OP(3): /* stmxcsr */ @@ -8103,8 +8131,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) break; } gen_lea_modrm(env, s, modrm); - tcg_gen_ld32u_tl(cpu_T0, cpu_env, offsetof(CPUX86State, mxcsr)); - gen_op_st_v(s, MO_32, cpu_T0, cpu_A0); + tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, mxcsr)); + gen_op_st_v(s, MO_32, s->T0, s->A0); break; CASE_MODRM_MEM_OP(4): /* xsave */ @@ -8114,9 +8142,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) goto illegal_op; } gen_lea_modrm(env, s, modrm); - tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX], + tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX], cpu_regs[R_EDX]); - gen_helper_xsave(cpu_env, cpu_A0, cpu_tmp1_i64); + gen_helper_xsave(cpu_env, s->A0, s->tmp1_i64); break; CASE_MODRM_MEM_OP(5): /* xrstor */ @@ -8126,13 +8154,13 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) goto illegal_op; } gen_lea_modrm(env, s, modrm); - tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX], + tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX], cpu_regs[R_EDX]); - gen_helper_xrstor(cpu_env, cpu_A0, cpu_tmp1_i64); + gen_helper_xrstor(cpu_env, s->A0, s->tmp1_i64); /* XRSTOR is how MPX is enabled, which changes how we translate. Thus we need to end the TB. */ gen_update_cc_op(s); - gen_jmp_im(s->pc - s->cs_base); + gen_jmp_im(s, s->pc - s->cs_base); gen_eob(s); break; @@ -8154,9 +8182,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) goto illegal_op; } gen_lea_modrm(env, s, modrm); - tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX], + tcg_gen_concat_tl_i64(s->tmp1_i64, cpu_regs[R_EAX], cpu_regs[R_EDX]); - gen_helper_xsaveopt(cpu_env, cpu_A0, cpu_tmp1_i64); + gen_helper_xsaveopt(cpu_env, s->A0, s->tmp1_i64); } break; @@ -8190,8 +8218,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) TCGv base, treg, src, dst; /* Preserve hflags bits by testing CR4 at runtime. */ - tcg_gen_movi_i32(cpu_tmp2_i32, CR4_FSGSBASE_MASK); - gen_helper_cr4_testbit(cpu_env, cpu_tmp2_i32); + tcg_gen_movi_i32(s->tmp2_i32, CR4_FSGSBASE_MASK); + gen_helper_cr4_testbit(cpu_env, s->tmp2_i32); base = cpu_seg_base[modrm & 8 ? R_GS : R_FS]; treg = cpu_regs[(modrm & 7) | REX_B(s)]; @@ -8262,7 +8290,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) if (!(s->flags & HF_SMM_MASK)) goto illegal_op; gen_update_cc_op(s); - gen_jmp_im(s->pc - s->cs_base); + gen_jmp_im(s, s->pc - s->cs_base); gen_helper_rsm(cpu_env); gen_eob(s); break; @@ -8283,10 +8311,10 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) } gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - gen_extu(ot, cpu_T0); - tcg_gen_mov_tl(cpu_cc_src, cpu_T0); - tcg_gen_ctpop_tl(cpu_T0, cpu_T0); - gen_op_mov_reg_v(ot, reg, cpu_T0); + gen_extu(ot, s->T0); + tcg_gen_mov_tl(cpu_cc_src, s->T0); + tcg_gen_ctpop_tl(s->T0, s->T0); + gen_op_mov_reg_v(s, ot, reg, s->T0); set_cc_op(s, CC_OP_POPCNT); break; @@ -8452,18 +8480,18 @@ static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu) printf("ERROR addseg\n"); #endif - cpu_T0 = tcg_temp_new(); - cpu_T1 = tcg_temp_new(); - cpu_A0 = tcg_temp_new(); + dc->T0 = tcg_temp_new(); + dc->T1 = tcg_temp_new(); + dc->A0 = tcg_temp_new(); - cpu_tmp0 = tcg_temp_new(); - cpu_tmp1_i64 = tcg_temp_new_i64(); - cpu_tmp2_i32 = tcg_temp_new_i32(); - cpu_tmp3_i32 = tcg_temp_new_i32(); - cpu_tmp4 = tcg_temp_new(); - cpu_ptr0 = tcg_temp_new_ptr(); - cpu_ptr1 = tcg_temp_new_ptr(); - cpu_cc_srcT = tcg_temp_local_new(); + dc->tmp0 = tcg_temp_new(); + dc->tmp1_i64 = tcg_temp_new_i64(); + dc->tmp2_i32 = tcg_temp_new_i32(); + dc->tmp3_i32 = tcg_temp_new_i32(); + dc->tmp4 = tcg_temp_new(); + dc->ptr0 = tcg_temp_new_ptr(); + dc->ptr1 = tcg_temp_new_ptr(); + dc->cc_srcT = tcg_temp_local_new(); } static void i386_tr_tb_start(DisasContextBase *db, CPUState *cpu) @@ -8510,10 +8538,10 @@ static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) chance to happen */ dc->base.is_jmp = DISAS_TOO_MANY; } else if ((tb_cflags(dc->base.tb) & CF_USE_ICOUNT) - && ((dc->base.pc_next & TARGET_PAGE_MASK) - != ((dc->base.pc_next + TARGET_MAX_INSN_SIZE - 1) + && ((pc_next & TARGET_PAGE_MASK) + != ((pc_next + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK) - || (dc->base.pc_next & ~TARGET_PAGE_MASK) == 0)) { + || (pc_next & ~TARGET_PAGE_MASK) == 0)) { /* Do not cross the boundary of the pages in icount mode, it can cause an exception. Do it only when boundary is crossed by the first instruction in the block. @@ -8533,7 +8561,7 @@ static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) DisasContext *dc = container_of(dcbase, DisasContext, base); if (dc->base.is_jmp == DISAS_TOO_MANY) { - gen_jmp_im(dc->base.pc_next - dc->cs_base); + gen_jmp_im(dc, dc->base.pc_next - dc->cs_base); gen_eob(dc); } } diff --git a/tests/Makefile.include b/tests/Makefile.include index d0c0a92e67..175d013f4a 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -613,7 +613,7 @@ test-obj-y = tests/check-qnum.o tests/check-qstring.o tests/check-qdict.o \ tests/test-rcu-tailq.o \ tests/test-qdist.o tests/test-shift128.o \ tests/test-qht.o tests/qht-bench.o tests/test-qht-par.o \ - tests/atomic_add-bench.o + tests/atomic_add-bench.o tests/atomic64-bench.o $(test-obj-y): QEMU_INCLUDES += -Itests QEMU_CFLAGS += -I$(SRC_PATH)/tests @@ -668,6 +668,7 @@ tests/test-qht-par$(EXESUF): tests/test-qht-par.o tests/qht-bench$(EXESUF) $(tes tests/qht-bench$(EXESUF): tests/qht-bench.o $(test-util-obj-y) tests/test-bufferiszero$(EXESUF): tests/test-bufferiszero.o $(test-util-obj-y) tests/atomic_add-bench$(EXESUF): tests/atomic_add-bench.o $(test-util-obj-y) +tests/atomic64-bench$(EXESUF): tests/atomic64-bench.o $(test-util-obj-y) tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \ hw/core/qdev.o hw/core/qdev-properties.o hw/core/hotplug.o\ diff --git a/tests/atomic64-bench.c b/tests/atomic64-bench.c new file mode 100644 index 0000000000..71692560ed --- /dev/null +++ b/tests/atomic64-bench.c @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2018, Emilio G. Cota + * + * License: GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#include "qemu/osdep.h" +#include "qemu/thread.h" +#include "qemu/host-utils.h" +#include "qemu/processor.h" + +struct thread_info { + uint64_t r; + uint64_t accesses; +} QEMU_ALIGNED(64); + +struct count { + int64_t i64; +} QEMU_ALIGNED(64); + +static QemuThread *threads; +static struct thread_info *th_info; +static unsigned int n_threads = 1; +static unsigned int n_ready_threads; +static struct count *counts; +static unsigned int duration = 1; +static unsigned int range = 1024; +static bool test_start; +static bool test_stop; + +static const char commands_string[] = + " -d = duration in seconds\n" + " -n = number of threads\n" + " -r = range (will be rounded up to pow2)"; + +static void usage_complete(char *argv[]) +{ + fprintf(stderr, "Usage: %s [options]\n", argv[0]); + fprintf(stderr, "options:\n%s\n", commands_string); +} + +/* + * From: https://en.wikipedia.org/wiki/Xorshift + * This is faster than rand_r(), and gives us a wider range (RAND_MAX is only + * guaranteed to be >= INT_MAX). + */ +static uint64_t xorshift64star(uint64_t x) +{ + x ^= x >> 12; /* a */ + x ^= x << 25; /* b */ + x ^= x >> 27; /* c */ + return x * UINT64_C(2685821657736338717); +} + +static void *thread_func(void *arg) +{ + struct thread_info *info = arg; + + atomic_inc(&n_ready_threads); + while (!atomic_read(&test_start)) { + cpu_relax(); + } + + while (!atomic_read(&test_stop)) { + unsigned int index; + + info->r = xorshift64star(info->r); + index = info->r & (range - 1); + atomic_read_i64(&counts[index].i64); + info->accesses++; + } + return NULL; +} + +static void run_test(void) +{ + unsigned int remaining; + unsigned int i; + + while (atomic_read(&n_ready_threads) != n_threads) { + cpu_relax(); + } + atomic_set(&test_start, true); + do { + remaining = sleep(duration); + } while (remaining); + atomic_set(&test_stop, true); + + for (i = 0; i < n_threads; i++) { + qemu_thread_join(&threads[i]); + } +} + +static void create_threads(void) +{ + unsigned int i; + + threads = g_new(QemuThread, n_threads); + th_info = g_new(struct thread_info, n_threads); + counts = g_malloc0_n(range, sizeof(*counts)); + + for (i = 0; i < n_threads; i++) { + struct thread_info *info = &th_info[i]; + + info->r = (i + 1) ^ time(NULL); + info->accesses = 0; + qemu_thread_create(&threads[i], NULL, thread_func, info, + QEMU_THREAD_JOINABLE); + } +} + +static void pr_params(void) +{ + printf("Parameters:\n"); + printf(" # of threads: %u\n", n_threads); + printf(" duration: %u\n", duration); + printf(" ops' range: %u\n", range); +} + +static void pr_stats(void) +{ + unsigned long long val = 0; + double tx; + int i; + + for (i = 0; i < n_threads; i++) { + val += th_info[i].accesses; + } + tx = val / duration / 1e6; + + printf("Results:\n"); + printf("Duration: %u s\n", duration); + printf(" Throughput: %.2f Mops/s\n", tx); + printf(" Throughput/thread: %.2f Mops/s/thread\n", tx / n_threads); +} + +static void parse_args(int argc, char *argv[]) +{ + int c; + + for (;;) { + c = getopt(argc, argv, "hd:n:r:"); + if (c < 0) { + break; + } + switch (c) { + case 'h': + usage_complete(argv); + exit(0); + case 'd': + duration = atoi(optarg); + break; + case 'n': + n_threads = atoi(optarg); + break; + case 'r': + range = pow2ceil(atoi(optarg)); + break; + } + } +} + +int main(int argc, char *argv[]) +{ + parse_args(argc, argv); + pr_params(); + create_threads(); + run_test(); + pr_stats(); + return 0; +} diff --git a/tests/test-char.c b/tests/test-char.c index 2a2ff32904..831e37fbf4 100644 --- a/tests/test-char.c +++ b/tests/test-char.c @@ -307,7 +307,7 @@ static int socket_can_read_hello(void *opaque) return 10; } -static void char_socket_test_common(Chardev *chr) +static void char_socket_test_common(Chardev *chr, bool reconnect) { Chardev *chr_client; QObject *addr; @@ -327,7 +327,8 @@ static void char_socket_test_common(Chardev *chr) addr = object_property_get_qobject(OBJECT(chr), "addr", &error_abort); qdict = qobject_to(QDict, addr); port = qdict_get_str(qdict, "port"); - tmp = g_strdup_printf("tcp:127.0.0.1:%s", port); + tmp = g_strdup_printf("tcp:127.0.0.1:%s%s", port, + reconnect ? ",reconnect=1" : ""); qobject_unref(qdict); qemu_chr_fe_init(&be, chr, &error_abort); @@ -347,6 +348,12 @@ static void char_socket_test_common(Chardev *chr) g_assert_cmpint(id, >, 0); main_loop(); + d.chr = chr_client; + id = g_idle_add(char_socket_test_idle, &d); + g_source_set_name_by_id(id, "test-idle"); + g_assert_cmpint(id, >, 0); + main_loop(); + g_assert(object_property_get_bool(OBJECT(chr), "connected", &error_abort)); g_assert(object_property_get_bool(OBJECT(chr_client), "connected", &error_abort)); @@ -356,6 +363,7 @@ static void char_socket_test_common(Chardev *chr) object_unparent(OBJECT(chr_client)); + d.chr = chr; d.conn_expected = false; g_idle_add(char_socket_test_idle, &d); main_loop(); @@ -368,7 +376,15 @@ static void char_socket_basic_test(void) { Chardev *chr = qemu_chr_new("server", "tcp:127.0.0.1:0,server,nowait"); - char_socket_test_common(chr); + char_socket_test_common(chr, false); +} + + +static void char_socket_reconnect_test(void) +{ + Chardev *chr = qemu_chr_new("server", "tcp:127.0.0.1:0,server,nowait"); + + char_socket_test_common(chr, true); } @@ -400,7 +416,7 @@ static void char_socket_fdpass_test(void) qemu_opts_del(opts); - char_socket_test_common(chr); + char_socket_test_common(chr, false); } @@ -819,6 +835,7 @@ int main(int argc, char **argv) g_test_add_func("/char/file-fifo", char_file_fifo_test); #endif g_test_add_func("/char/socket/basic", char_socket_basic_test); + g_test_add_func("/char/socket/reconnect", char_socket_reconnect_test); g_test_add_func("/char/socket/fdpass", char_socket_fdpass_test); g_test_add_func("/char/udp", char_udp_test); #ifdef HAVE_CHARDEV_SERIAL diff --git a/tests/test-rcu-list.c b/tests/test-rcu-list.c index 192bfbf02e..2e6f70bd59 100644 --- a/tests/test-rcu-list.c +++ b/tests/test-rcu-list.c @@ -33,8 +33,8 @@ static QemuMutex counts_mutex; static long long n_reads = 0LL; static long long n_updates = 0LL; -static long long n_reclaims = 0LL; -static long long n_nodes_removed = 0LL; +static int64_t n_reclaims; +static int64_t n_nodes_removed; static long long n_nodes = 0LL; static int g_test_in_charge = 0; @@ -104,7 +104,7 @@ static void reclaim_list_el(struct rcu_head *prcu) struct list_element *el = container_of(prcu, struct list_element, rcu); g_free(el); /* Accessed only from call_rcu thread. */ - n_reclaims++; + atomic_set_i64(&n_reclaims, n_reclaims + 1); } #if TEST_LIST_TYPE == 1 @@ -232,7 +232,7 @@ static void *rcu_q_updater(void *arg) qemu_mutex_lock(&counts_mutex); n_nodes += n_nodes_local; n_updates += n_updates_local; - n_nodes_removed += n_removed_local; + atomic_set_i64(&n_nodes_removed, n_nodes_removed + n_removed_local); qemu_mutex_unlock(&counts_mutex); return NULL; } @@ -286,19 +286,21 @@ static void rcu_qtest(const char *test, int duration, int nreaders) n_removed_local++; } qemu_mutex_lock(&counts_mutex); - n_nodes_removed += n_removed_local; + atomic_set_i64(&n_nodes_removed, n_nodes_removed + n_removed_local); qemu_mutex_unlock(&counts_mutex); synchronize_rcu(); - while (n_nodes_removed > n_reclaims) { + while (atomic_read_i64(&n_nodes_removed) > atomic_read_i64(&n_reclaims)) { g_usleep(100); synchronize_rcu(); } if (g_test_in_charge) { - g_assert_cmpint(n_nodes_removed, ==, n_reclaims); + g_assert_cmpint(atomic_read_i64(&n_nodes_removed), ==, + atomic_read_i64(&n_reclaims)); } else { printf("%s: %d readers; 1 updater; nodes read: " \ - "%lld, nodes removed: %lld; nodes reclaimed: %lld\n", - test, nthreadsrunning - 1, n_reads, n_nodes_removed, n_reclaims); + "%lld, nodes removed: %"PRIi64"; nodes reclaimed: %"PRIi64"\n", + test, nthreadsrunning - 1, n_reads, + atomic_read_i64(&n_nodes_removed), atomic_read_i64(&n_reclaims)); exit(0); } } diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c index 716aff7153..45d58d8ea2 100644 --- a/tests/vhost-user-test.c +++ b/tests/vhost-user-test.c @@ -169,7 +169,7 @@ static char *get_qemu_cmd(TestServer *s, int mem, enum test_memfd memfd, const char *mem_path, const char *chr_opts, const char *extra) { - if (memfd == TEST_MEMFD_AUTO && qemu_memfd_check()) { + if (memfd == TEST_MEMFD_AUTO && qemu_memfd_check(0)) { memfd = TEST_MEMFD_YES; } @@ -903,7 +903,7 @@ static void test_multiqueue(void) s->queues = 2; test_server_listen(s); - if (qemu_memfd_check()) { + if (qemu_memfd_check(0)) { cmd = g_strdup_printf( QEMU_CMD_MEMFD QEMU_CMD_CHR QEMU_CMD_NETDEV ",queues=%d " "-device virtio-net-pci,netdev=net0,mq=on,vectors=%d", @@ -963,7 +963,7 @@ int main(int argc, char **argv) /* run the main loop thread so the chardev may operate */ thread = g_thread_new(NULL, thread_function, loop); - if (qemu_memfd_check()) { + if (qemu_memfd_check(0)) { qtest_add_data_func("/vhost-user/read-guest-mem/memfd", GINT_TO_POINTER(TEST_MEMFD_YES), test_read_guest_mem); diff --git a/ui/input.c b/ui/input.c index 51b1019252..dd7f6d7f21 100644 --- a/ui/input.c +++ b/ui/input.c @@ -271,7 +271,7 @@ static void qemu_input_queue_process(void *opaque) item = QTAILQ_FIRST(queue); switch (item->type) { case QEMU_INPUT_QUEUE_DELAY: - timer_mod(item->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + timer_mod(item->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_EXT) + item->delay_ms); return; case QEMU_INPUT_QUEUE_EVENT: @@ -301,7 +301,7 @@ static void qemu_input_queue_delay(struct QemuInputEventQueueHead *queue, queue_count++; if (start_timer) { - timer_mod(item->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + timer_mod(item->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_EXT) + item->delay_ms); } } @@ -448,8 +448,8 @@ void qemu_input_event_send_key_delay(uint32_t delay_ms) } if (!kbd_timer) { - kbd_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, qemu_input_queue_process, - &kbd_queue); + kbd_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL_EXT, + qemu_input_queue_process, &kbd_queue); } if (queue_count < queue_limit) { qemu_input_queue_delay(&kbd_queue, kbd_timer, diff --git a/util/Makefile.objs b/util/Makefile.objs index 0e88899011..0820923c18 100644 --- a/util/Makefile.objs +++ b/util/Makefile.objs @@ -3,6 +3,7 @@ util-obj-y += bufferiszero.o util-obj-y += lockcnt.o util-obj-y += aiocb.o async.o aio-wait.o thread-pool.o qemu-timer.o util-obj-y += main-loop.o iohandler.o +util-obj-$(call lnot,$(CONFIG_ATOMIC64)) += atomic64.o util-obj-$(CONFIG_POSIX) += aio-posix.o util-obj-$(CONFIG_POSIX) += compatfd.o util-obj-$(CONFIG_POSIX) += event_notifier-posix.o diff --git a/util/atomic64.c b/util/atomic64.c new file mode 100644 index 0000000000..b198a6c9c8 --- /dev/null +++ b/util/atomic64.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2018, Emilio G. Cota + * + * License: GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#include "qemu/osdep.h" +#include "qemu/atomic.h" +#include "qemu/thread.h" + +#ifdef CONFIG_ATOMIC64 +#error This file must only be compiled if !CONFIG_ATOMIC64 +#endif + +/* + * When !CONFIG_ATOMIC64, we serialize both reads and writes with spinlocks. + * We use an array of spinlocks, with padding computed at run-time based on + * the host's dcache line size. + * We point to the array with a void * to simplify the padding's computation. + * Each spinlock is located every lock_size bytes. + */ +static void *lock_array; +static size_t lock_size; + +/* + * Systems without CONFIG_ATOMIC64 are unlikely to have many cores, so we use a + * small array of locks. + */ +#define NR_LOCKS 16 + +static QemuSpin *addr_to_lock(const void *addr) +{ + uintptr_t a = (uintptr_t)addr; + uintptr_t idx; + + idx = a >> qemu_dcache_linesize_log; + idx ^= (idx >> 8) ^ (idx >> 16); + idx &= NR_LOCKS - 1; + return lock_array + idx * lock_size; +} + +#define GEN_READ(name, type) \ + type name(const type *ptr) \ + { \ + QemuSpin *lock = addr_to_lock(ptr); \ + type ret; \ + \ + qemu_spin_lock(lock); \ + ret = *ptr; \ + qemu_spin_unlock(lock); \ + return ret; \ + } + +GEN_READ(atomic_read_i64, int64_t) +GEN_READ(atomic_read_u64, uint64_t) +#undef GEN_READ + +#define GEN_SET(name, type) \ + void name(type *ptr, type val) \ + { \ + QemuSpin *lock = addr_to_lock(ptr); \ + \ + qemu_spin_lock(lock); \ + *ptr = val; \ + qemu_spin_unlock(lock); \ + } + +GEN_SET(atomic_set_i64, int64_t) +GEN_SET(atomic_set_u64, uint64_t) +#undef GEN_SET + +void atomic64_init(void) +{ + int i; + + lock_size = ROUND_UP(sizeof(QemuSpin), qemu_dcache_linesize); + lock_array = qemu_memalign(qemu_dcache_linesize, lock_size * NR_LOCKS); + for (i = 0; i < NR_LOCKS; i++) { + QemuSpin *lock = lock_array + i * lock_size; + + qemu_spin_init(lock); + } +} diff --git a/util/cacheinfo.c b/util/cacheinfo.c index db5172d07c..3cd080b83d 100644 --- a/util/cacheinfo.c +++ b/util/cacheinfo.c @@ -7,9 +7,13 @@ */ #include "qemu/osdep.h" +#include "qemu/host-utils.h" +#include "qemu/atomic.h" int qemu_icache_linesize = 0; +int qemu_icache_linesize_log; int qemu_dcache_linesize = 0; +int qemu_dcache_linesize_log; /* * Operating system specific detection mechanisms. @@ -172,6 +176,13 @@ static void __attribute__((constructor)) init_cache_info(void) arch_cache_info(&isize, &dsize); fallback_cache_info(&isize, &dsize); + assert((isize & (isize - 1)) == 0); + assert((dsize & (dsize - 1)) == 0); + qemu_icache_linesize = isize; + qemu_icache_linesize_log = ctz32(isize); qemu_dcache_linesize = dsize; + qemu_dcache_linesize_log = ctz32(dsize); + + atomic64_init(); } diff --git a/util/memfd.c b/util/memfd.c index 6287946b61..8debd0d037 100644 --- a/util/memfd.c +++ b/util/memfd.c @@ -45,22 +45,6 @@ static int memfd_create(const char *name, unsigned int flags) } #endif -#ifndef MFD_CLOEXEC -#define MFD_CLOEXEC 0x0001U -#endif - -#ifndef MFD_ALLOW_SEALING -#define MFD_ALLOW_SEALING 0x0002U -#endif - -#ifndef MFD_HUGETLB -#define MFD_HUGETLB 0x0004U -#endif - -#ifndef MFD_HUGE_SHIFT -#define MFD_HUGE_SHIFT 26 -#endif - int qemu_memfd_create(const char *name, size_t size, bool hugetlb, uint64_t hugetlbsize, unsigned int seals, Error **errp) { @@ -201,23 +185,16 @@ bool qemu_memfd_alloc_check(void) * * Check if host supports memfd. */ -bool qemu_memfd_check(void) +bool qemu_memfd_check(unsigned int flags) { #ifdef CONFIG_LINUX - static int memfd_check = MEMFD_TODO; + int mfd = memfd_create("test", flags); - if (memfd_check == MEMFD_TODO) { - int mfd = memfd_create("test", 0); - if (mfd >= 0) { - memfd_check = MEMFD_OK; - close(mfd); - } else { - memfd_check = MEMFD_KO; - } + if (mfd >= 0) { + close(mfd); + return true; } - - return memfd_check == MEMFD_OK; -#else - return false; #endif + + return false; } diff --git a/util/oslib-posix.c b/util/oslib-posix.c index 13b6f8d776..fbd0dc8c57 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -88,6 +88,79 @@ int qemu_daemon(int nochdir, int noclose) return daemon(nochdir, noclose); } +bool qemu_write_pidfile(const char *path, Error **errp) +{ + int fd; + char pidstr[32]; + + while (1) { + struct stat a, b; + struct flock lock = { + .l_type = F_WRLCK, + .l_whence = SEEK_SET, + .l_len = 0, + }; + + fd = qemu_open(path, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR); + if (fd == -1) { + error_setg_errno(errp, errno, "Cannot open pid file"); + return false; + } + + if (fstat(fd, &b) < 0) { + error_setg_errno(errp, errno, "Cannot stat file"); + goto fail_close; + } + + if (fcntl(fd, F_SETLK, &lock)) { + error_setg_errno(errp, errno, "Cannot lock pid file"); + goto fail_close; + } + + /* + * Now make sure the path we locked is the same one that now + * exists on the filesystem. + */ + if (stat(path, &a) < 0) { + /* + * PID file disappeared, someone else must be racing with + * us, so try again. + */ + close(fd); + continue; + } + + if (a.st_ino == b.st_ino) { + break; + } + + /* + * PID file was recreated, someone else must be racing with + * us, so try again. + */ + close(fd); + } + + if (ftruncate(fd, 0) < 0) { + error_setg_errno(errp, errno, "Failed to truncate pid file"); + goto fail_unlink; + } + + snprintf(pidstr, sizeof(pidstr), FMT_pid "\n", getpid()); + if (write(fd, pidstr, strlen(pidstr)) != strlen(pidstr)) { + error_setg(errp, "Failed to write pid file"); + goto fail_unlink; + } + + return true; + +fail_unlink: + unlink(path); +fail_close: + close(fd); + return false; +} + void *qemu_oom_check(void *ptr) { if (ptr == NULL) { diff --git a/util/oslib-win32.c b/util/oslib-win32.c index 25dd1595ad..b4c17f5dfa 100644 --- a/util/oslib-win32.c +++ b/util/oslib-win32.c @@ -776,3 +776,30 @@ ssize_t qemu_recvfrom_wrap(int sockfd, void *buf, size_t len, int flags, } return ret; } + +bool qemu_write_pidfile(const char *filename, Error **errp) +{ + char buffer[128]; + int len; + HANDLE file; + OVERLAPPED overlap; + BOOL ret; + memset(&overlap, 0, sizeof(overlap)); + + file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, + OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + if (file == INVALID_HANDLE_VALUE) { + error_setg(errp, "Failed to create PID file"); + return false; + } + len = snprintf(buffer, sizeof(buffer), FMT_pid "\n", (pid_t)getpid()); + ret = WriteFile(file, (LPCVOID)buffer, (DWORD)len, + NULL, &overlap); + CloseHandle(file); + if (ret == 0) { + error_setg(errp, "Failed to write PID file"); + return false; + } + return true; +} diff --git a/util/qemu-timer.c b/util/qemu-timer.c index 86bfe84037..eb60d8f73a 100644 --- a/util/qemu-timer.c +++ b/util/qemu-timer.c @@ -496,6 +496,7 @@ bool timerlist_run_timers(QEMUTimerList *timer_list) switch (timer_list->clock->type) { case QEMU_CLOCK_REALTIME: + case QEMU_CLOCK_VIRTUAL_EXT: break; default: case QEMU_CLOCK_VIRTUAL: @@ -597,6 +598,7 @@ int64_t qemu_clock_get_ns(QEMUClockType type) return get_clock(); default: case QEMU_CLOCK_VIRTUAL: + case QEMU_CLOCK_VIRTUAL_EXT: if (use_icount) { return cpu_get_icount(); } else { diff --git a/util/qsp.c b/util/qsp.c index 2de3a97594..a848b09c6d 100644 --- a/util/qsp.c +++ b/util/qsp.c @@ -84,13 +84,6 @@ struct QSPEntry { uint64_t n_acqs; uint64_t ns; unsigned int n_objs; /* count of coalesced objs; only used for reporting */ -#ifndef CONFIG_ATOMIC64 - /* - * If we cannot update the counts atomically, then use a seqlock. - * We don't need an associated lock because the updates are thread-local. - */ - QemuSeqLock sequence; -#endif }; typedef struct QSPEntry QSPEntry; @@ -344,47 +337,16 @@ static QSPEntry *qsp_entry_get(const void *obj, const char *file, int line, return qsp_entry_find(&qsp_ht, &orig, hash); } -/* - * @from is in the global hash table; read it atomically if the host - * supports it, otherwise use the seqlock. - */ -static void qsp_entry_aggregate(QSPEntry *to, const QSPEntry *from) -{ -#ifdef CONFIG_ATOMIC64 - to->ns += atomic_read__nocheck(&from->ns); - to->n_acqs += atomic_read__nocheck(&from->n_acqs); -#else - unsigned int version; - uint64_t ns, n_acqs; - - do { - version = seqlock_read_begin(&from->sequence); - ns = atomic_read__nocheck(&from->ns); - n_acqs = atomic_read__nocheck(&from->n_acqs); - } while (seqlock_read_retry(&from->sequence, version)); - - to->ns += ns; - to->n_acqs += n_acqs; -#endif -} - /* * @e is in the global hash table; it is only written to by the current thread, * so we write to it atomically (as in "write once") to prevent torn reads. - * If the host doesn't support u64 atomics, use the seqlock. */ static inline void do_qsp_entry_record(QSPEntry *e, int64_t delta, bool acq) { -#ifndef CONFIG_ATOMIC64 - seqlock_write_begin(&e->sequence); -#endif - atomic_set__nocheck(&e->ns, e->ns + delta); + atomic_set_u64(&e->ns, e->ns + delta); if (acq) { - atomic_set__nocheck(&e->n_acqs, e->n_acqs + 1); + atomic_set_u64(&e->n_acqs, e->n_acqs + 1); } -#ifndef CONFIG_ATOMIC64 - seqlock_write_end(&e->sequence); -#endif } static inline void qsp_entry_record(QSPEntry *e, int64_t delta) @@ -550,7 +512,12 @@ static void qsp_aggregate(void *p, uint32_t h, void *up) hash = qsp_entry_no_thread_hash(e); agg = qsp_entry_find(ht, e, hash); - qsp_entry_aggregate(agg, e); + /* + * The entry is in the global hash table; read from it atomically (as in + * "read once"). + */ + agg->ns += atomic_read_u64(&e->ns); + agg->n_acqs += atomic_read_u64(&e->n_acqs); } static void qsp_iter_diff(void *p, uint32_t hash, void *htp) diff --git a/vl.c b/vl.c index cc55fe04a2..0388852deb 100644 --- a/vl.c +++ b/vl.c @@ -2560,6 +2560,16 @@ static void qemu_run_exit_notifiers(void) notifier_list_notify(&exit_notifiers, NULL); } +static const char *pid_file; +static Notifier qemu_unlink_pidfile_notifier; + +static void qemu_unlink_pidfile(Notifier *n, void *data) +{ + if (pid_file) { + unlink(pid_file); + } +} + bool machine_init_done; void qemu_add_machine_init_done_notifier(Notifier *notify) @@ -2884,7 +2894,6 @@ int main(int argc, char **argv, char **envp) const char *vga_model = NULL; const char *qtest_chrdev = NULL; const char *qtest_log = NULL; - const char *pid_file = NULL; const char *incoming = NULL; bool userconfig = true; bool nographic = false; @@ -3906,11 +3915,14 @@ int main(int argc, char **argv, char **envp) os_daemonize(); rcu_disable_atfork(); - if (pid_file && qemu_create_pidfile(pid_file) != 0) { - error_report("could not acquire pid file: %s", strerror(errno)); + if (pid_file && !qemu_write_pidfile(pid_file, &err)) { + error_reportf_err(err, "cannot create PID file: "); exit(1); } + qemu_unlink_pidfile_notifier.notify = qemu_unlink_pidfile; + qemu_add_exit_notifier(&qemu_unlink_pidfile_notifier); + if (qemu_init_main_loop(&main_loop_err)) { error_report_err(main_loop_err); exit(1); @@ -4523,9 +4535,7 @@ int main(int argc, char **argv, char **envp) replay_checkpoint(CHECKPOINT_RESET); qemu_system_reset(SHUTDOWN_CAUSE_NONE); register_global_state(); - if (replay_mode != REPLAY_MODE_NONE) { - replay_vmstate_init(); - } else if (loadvm) { + if (loadvm) { Error *local_err = NULL; if (load_snapshot(loadvm, &local_err) < 0) { error_report_err(local_err); @@ -4533,6 +4543,9 @@ int main(int argc, char **argv, char **envp) exit(1); } } + if (replay_mode != REPLAY_MODE_NONE) { + replay_vmstate_init(); + } qdev_prop_check_globals(); if (vmstate_dump_file) { diff --git a/win_dump.c b/win_dump.c index b15c191ad7..e10a7831c2 100644 --- a/win_dump.c +++ b/win_dump.c @@ -30,28 +30,32 @@ static size_t write_run(WinDumpPhyMemRun64 *run, int fd, Error **errp) void *buf; uint64_t addr = run->BasePage << TARGET_PAGE_BITS; uint64_t size = run->PageCount << TARGET_PAGE_BITS; - uint64_t len = size; + uint64_t len, l; + size_t total = 0; - buf = cpu_physical_memory_map(addr, &len, false); - if (!buf) { - error_setg(errp, "win-dump: failed to map run"); - return 0; - } - if (len != size) { - error_setg(errp, "win-dump: failed to map entire run"); - len = 0; - goto out_unmap; + while (size) { + len = size; + + buf = cpu_physical_memory_map(addr, &len, false); + if (!buf) { + error_setg(errp, "win-dump: failed to map physical range" + " 0x%016" PRIx64 "-0x%016" PRIx64, addr, addr + size - 1); + return 0; + } + + l = qemu_write_full(fd, buf, len); + cpu_physical_memory_unmap(buf, addr, false, len); + if (l != len) { + error_setg(errp, QERR_IO_ERROR); + return 0; + } + + addr += l; + size -= l; + total += l; } - len = qemu_write_full(fd, buf, len); - if (len != size) { - error_setg(errp, QERR_IO_ERROR); - } - -out_unmap: - cpu_physical_memory_unmap(buf, addr, false, len); - - return len; + return total; } static void write_runs(DumpState *s, WinDumpHeader64 *h, Error **errp) diff --git a/win_dump.h b/win_dump.h index f9e1faf8eb..b8c25348f4 100644 --- a/win_dump.h +++ b/win_dump.h @@ -8,169 +8,11 @@ * */ -typedef struct WinDumpPhyMemRun64 { - uint64_t BasePage; - uint64_t PageCount; -} QEMU_PACKED WinDumpPhyMemRun64; +#ifndef WIN_DUMP_H +#define WIN_DUMP_H -typedef struct WinDumpPhyMemDesc64 { - uint32_t NumberOfRuns; - uint32_t unused; - uint64_t NumberOfPages; - WinDumpPhyMemRun64 Run[43]; -} QEMU_PACKED WinDumpPhyMemDesc64; - -typedef struct WinDumpExceptionRecord { - uint32_t ExceptionCode; - uint32_t ExceptionFlags; - uint64_t ExceptionRecord; - uint64_t ExceptionAddress; - uint32_t NumberParameters; - uint32_t unused; - uint64_t ExceptionInformation[15]; -} QEMU_PACKED WinDumpExceptionRecord; - -typedef struct WinDumpHeader64 { - char Signature[4]; - char ValidDump[4]; - uint32_t MajorVersion; - uint32_t MinorVersion; - uint64_t DirectoryTableBase; - uint64_t PfnDatabase; - uint64_t PsLoadedModuleList; - uint64_t PsActiveProcessHead; - uint32_t MachineImageType; - uint32_t NumberProcessors; - union { - struct { - uint32_t BugcheckCode; - uint32_t unused0; - uint64_t BugcheckParameter1; - uint64_t BugcheckParameter2; - uint64_t BugcheckParameter3; - uint64_t BugcheckParameter4; - }; - uint8_t BugcheckData[40]; - }; - uint8_t VersionUser[32]; - uint64_t KdDebuggerDataBlock; - union { - WinDumpPhyMemDesc64 PhysicalMemoryBlock; - uint8_t PhysicalMemoryBlockBuffer[704]; - }; - union { - uint8_t ContextBuffer[3000]; - }; - WinDumpExceptionRecord Exception; - uint32_t DumpType; - uint32_t unused1; - uint64_t RequiredDumpSpace; - uint64_t SystemTime; - char Comment[128]; - uint64_t SystemUpTime; - uint32_t MiniDumpFields; - uint32_t SecondaryDataState; - uint32_t ProductType; - uint32_t SuiteMask; - uint32_t WriterStatus; - uint8_t unused2; - uint8_t KdSecondaryVersion; - uint8_t reserved[4018]; -} QEMU_PACKED WinDumpHeader64; +#include "qemu/win_dump_defs.h" void create_win_dump(DumpState *s, Error **errp); -#define KDBG_OWNER_TAG_OFFSET64 0x10 -#define KDBG_MM_PFN_DATABASE_OFFSET64 0xC0 -#define KDBG_KI_BUGCHECK_DATA_OFFSET64 0x88 -#define KDBG_KI_PROCESSOR_BLOCK_OFFSET64 0x218 -#define KDBG_OFFSET_PRCB_CONTEXT_OFFSET64 0x338 - -#define VMCOREINFO_ELF_NOTE_HDR_SIZE 24 - -#define WIN_CTX_X64 0x00100000L - -#define WIN_CTX_CTL 0x00000001L -#define WIN_CTX_INT 0x00000002L -#define WIN_CTX_SEG 0x00000004L -#define WIN_CTX_FP 0x00000008L -#define WIN_CTX_DBG 0x00000010L - -#define WIN_CTX_FULL (WIN_CTX_X64 | WIN_CTX_CTL | WIN_CTX_INT | WIN_CTX_FP) -#define WIN_CTX_ALL (WIN_CTX_FULL | WIN_CTX_SEG | WIN_CTX_DBG) - -#define LIVE_SYSTEM_DUMP 0x00000161 - -typedef struct WinM128A { - uint64_t low; - int64_t high; -} QEMU_ALIGNED(16) WinM128A; - -typedef struct WinContext { - uint64_t PHome[6]; - - uint32_t ContextFlags; - uint32_t MxCsr; - - uint16_t SegCs; - uint16_t SegDs; - uint16_t SegEs; - uint16_t SegFs; - uint16_t SegGs; - uint16_t SegSs; - uint32_t EFlags; - - uint64_t Dr0; - uint64_t Dr1; - uint64_t Dr2; - uint64_t Dr3; - uint64_t Dr6; - uint64_t Dr7; - - uint64_t Rax; - uint64_t Rcx; - uint64_t Rdx; - uint64_t Rbx; - uint64_t Rsp; - uint64_t Rbp; - uint64_t Rsi; - uint64_t Rdi; - uint64_t R8; - uint64_t R9; - uint64_t R10; - uint64_t R11; - uint64_t R12; - uint64_t R13; - uint64_t R14; - uint64_t R15; - - uint64_t Rip; - - struct { - uint16_t ControlWord; - uint16_t StatusWord; - uint8_t TagWord; - uint8_t Reserved1; - uint16_t ErrorOpcode; - uint32_t ErrorOffset; - uint16_t ErrorSelector; - uint16_t Reserved2; - uint32_t DataOffset; - uint16_t DataSelector; - uint16_t Reserved3; - uint32_t MxCsr; - uint32_t MxCsr_Mask; - WinM128A FloatRegisters[8]; - WinM128A XmmRegisters[16]; - uint8_t Reserved4[96]; - } FltSave; - - WinM128A VectorRegister[26]; - uint64_t VectorControl; - - uint64_t DebugControl; - uint64_t LastBranchToRip; - uint64_t LastBranchFromRip; - uint64_t LastExceptionToRip; - uint64_t LastExceptionFromRip; -} QEMU_ALIGNED(16) WinContext; +#endif /* WIN_DUMP_H */