From c170cb66490aa20bfc8d2c2421481dd9195dbb8b Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 6 Apr 2012 08:06:41 +0200 Subject: [PATCH 01/17] tcg/i386: Use GDB JIT debugging interface only for hosts with ELF Not all i386 / x86_64 hosts use ELF. Ask the compiler whether ELF is used. On w64, gdb crashes when ELF_HOST_MACHINE is defined. Cc: Blue Swirl Acked-by: Richard Henderson Signed-off-by: Stefan Weil --- tcg/i386/tcg-target.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 871a7e74f5..79545e31c2 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -2102,7 +2102,9 @@ typedef struct { DebugFrameFDE fde; } DebugFrame; -#if TCG_TARGET_REG_BITS == 64 +#if !defined(__ELF__) + /* Host machine without ELF. */ +#elif TCG_TARGET_REG_BITS == 64 #define ELF_HOST_MACHINE EM_X86_64 static DebugFrame debug_frame = { .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */ @@ -2156,6 +2158,7 @@ static DebugFrame debug_frame = { }; #endif +#if defined(ELF_HOST_MACHINE) void tcg_register_jit(void *buf, size_t buf_size) { /* We're expecting a 2 byte uleb128 encoded value. */ @@ -2166,3 +2169,4 @@ void tcg_register_jit(void *buf, size_t buf_size) tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame)); } +#endif From 8d918718edcd6753aa12be96b71d1bd4fb6ed7cd Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 12 Apr 2012 20:46:32 +0200 Subject: [PATCH 02/17] tcg/i386: Add support for w64 ABI w64 uses the registers rcx, rdx, r8 and r9 for function arguments, so it needs a different declaration of tcg_target_call_iarg_regs. rax, rcx, rdx, r8, r9, r10 and r11 may be changed by function calls. rbx, rbp, rdi, rsi, r12, r13, r14 and r15 remain unchanged by function calls. Reviewed-by: Richard Henderson Signed-off-by: Stefan Weil --- tcg/i386/tcg-target.c | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 79545e31c2..da17bba39d 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -63,10 +63,15 @@ static const int tcg_target_reg_alloc_order[] = { static const int tcg_target_call_iarg_regs[] = { #if TCG_TARGET_REG_BITS == 64 +#if defined(_WIN64) + TCG_REG_RCX, + TCG_REG_RDX, +#else TCG_REG_RDI, TCG_REG_RSI, TCG_REG_RDX, TCG_REG_RCX, +#endif TCG_REG_R8, TCG_REG_R9, #else @@ -176,10 +181,10 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) ct->ct |= TCG_CT_REG; if (TCG_TARGET_REG_BITS == 64) { tcg_regset_set32(ct->u.regs, 0, 0xffff); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_RSI); - tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDI); + tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[0]); + tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[1]); #ifdef CONFIG_TCG_PASS_AREG0 - tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDX); + tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[2]); #endif } else { tcg_regset_set32(ct->u.regs, 0, 0xff); @@ -1300,9 +1305,12 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, use the ADDR32 prefix. For now, do nothing. */ if (offset != GUEST_BASE) { - tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_RDI, GUEST_BASE); - tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_RDI, base); - base = TCG_REG_RDI, offset = 0; + tcg_out_movi(s, TCG_TYPE_I64, + tcg_target_call_iarg_regs[0], GUEST_BASE); + tgen_arithr(s, ARITH_ADD + P_REXW, + tcg_target_call_iarg_regs[0], base); + base = tcg_target_call_iarg_regs[0]; + offset = 0; } } @@ -1434,8 +1442,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, #endif #else tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32), - TCG_REG_RSI, data_reg); - tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index); + tcg_target_call_iarg_regs[1], data_reg); + tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2], mem_index); stack_adjust = 0; #ifdef CONFIG_TCG_PASS_AREG0 /* XXX/FIXME: suboptimal */ @@ -1474,9 +1482,12 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, use the ADDR32 prefix. For now, do nothing. */ if (offset != GUEST_BASE) { - tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_RDI, GUEST_BASE); - tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_RDI, base); - base = TCG_REG_RDI, offset = 0; + tcg_out_movi(s, TCG_TYPE_I64, + tcg_target_call_iarg_regs[0], GUEST_BASE); + tgen_arithr(s, ARITH_ADD + P_REXW, + tcg_target_call_iarg_regs[0], base); + base = tcg_target_call_iarg_regs[0]; + offset = 0; } } @@ -1977,6 +1988,10 @@ static int tcg_target_callee_save_regs[] = { #if TCG_TARGET_REG_BITS == 64 TCG_REG_RBP, TCG_REG_RBX, +#if defined(_WIN64) + TCG_REG_RDI, + TCG_REG_RSI, +#endif TCG_REG_R12, TCG_REG_R13, TCG_REG_R14, /* Currently used for the global env. */ @@ -2064,8 +2079,10 @@ static void tcg_target_init(TCGContext *s) tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EDX); tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_ECX); if (TCG_TARGET_REG_BITS == 64) { +#if !defined(_WIN64) tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RDI); tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RSI); +#endif tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R8); tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R9); tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R10); From 27b0dc16b4e50b59aeefff2bfa73cf2eb8c7a70d Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sun, 15 Apr 2012 15:18:29 +0200 Subject: [PATCH 03/17] w64: Fix type casts used in some macros in cpu-all.h Instead of type casts to long, w64 needs type casts to intptr_t. For other hosts, this changes nothing. Signed-off-by: Stefan Weil --- cpu-all.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpu-all.h b/cpu-all.h index 4512518065..58420be86f 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -222,8 +222,8 @@ extern unsigned long reserved_va; #else /* !CONFIG_USER_ONLY */ /* NOTE: we use double casts if pointers and target_ulong have different sizes */ -#define saddr(x) (uint8_t *)(long)(x) -#define laddr(x) (uint8_t *)(long)(x) +#define saddr(x) (uint8_t *)(intptr_t)(x) +#define laddr(x) (uint8_t *)(intptr_t)(x) #endif #define ldub_raw(p) ldub_p(laddr((p))) From c6d506742fd997a29b611fda11f67c53d60dd5ef Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 16 Mar 2012 20:23:49 +0100 Subject: [PATCH 04/17] w64: Fix data types in cpu-all.h, exec.c w64 needs uintptr_t instead of unsigned long. For other hosts, nothing changes. Signed-off-by: Stefan Weil --- cpu-all.h | 8 ++++---- exec.c | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cpu-all.h b/cpu-all.h index 58420be86f..f7d6867b0d 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -299,10 +299,10 @@ extern unsigned long reserved_va; #define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1) #define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK) -/* ??? These should be the larger of unsigned long and target_ulong. */ -extern unsigned long qemu_real_host_page_size; -extern unsigned long qemu_host_page_size; -extern unsigned long qemu_host_page_mask; +/* ??? These should be the larger of uintptr_t and target_ulong. */ +extern uintptr_t qemu_real_host_page_size; +extern uintptr_t qemu_host_page_size; +extern uintptr_t qemu_host_page_mask; #define HOST_PAGE_ALIGN(addr) (((addr) + qemu_host_page_size - 1) & qemu_host_page_mask) diff --git a/exec.c b/exec.c index 68b8a6a2ba..3dda2ca271 100644 --- a/exec.c +++ b/exec.c @@ -177,9 +177,9 @@ typedef struct PageDesc { #define V_L1_SHIFT (L1_MAP_ADDR_SPACE_BITS - TARGET_PAGE_BITS - V_L1_BITS) -unsigned long qemu_real_host_page_size; -unsigned long qemu_host_page_size; -unsigned long qemu_host_page_mask; +uintptr_t qemu_real_host_page_size; +uintptr_t qemu_host_page_size; +uintptr_t qemu_host_page_mask; /* This is a multi-level map on the virtual address space. The bottom level has pointers to PageDesc. */ From 6840981dfb76a1a1d2401efdb237ed5ddac8bf2f Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Wed, 4 Apr 2012 07:45:21 +0200 Subject: [PATCH 05/17] w64: Use larger alignment for section with generated code The MinGW-w64 compiler allows __attribute__((aligned (32)). Signed-off-by: Stefan Weil --- exec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/exec.c b/exec.c index 3dda2ca271..6d10595b8e 100644 --- a/exec.c +++ b/exec.c @@ -93,8 +93,7 @@ spinlock_t tb_lock = SPIN_LOCK_UNLOCKED; #define code_gen_section \ __attribute__((__section__(".gen_code"))) \ __attribute__((aligned (32))) -#elif defined(_WIN32) -/* Maximum alignment for Win32 is 16. */ +#elif defined(_WIN32) && !defined(_WIN64) #define code_gen_section \ __attribute__((aligned (16))) #else From acf126ba58425f11e74fbb9c1095224cb142fffa Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 12 Apr 2012 21:13:15 +0200 Subject: [PATCH 06/17] w32: Move defines for socket specific errors to qemu-os-win32.h As those defines are only used for w32, they should be in the header file for w32. All files which include slirp.h or qemu_socket.h also include qemu-os-win32.h. Signed-off-by: Stefan Weil --- qemu-os-win32.h | 26 ++++++++++++++++++++++++++ qemu_socket.h | 6 ------ slirp/slirp.h | 12 ------------ 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/qemu-os-win32.h b/qemu-os-win32.h index 8eda4bdc20..b6533c0979 100644 --- a/qemu-os-win32.h +++ b/qemu-os-win32.h @@ -30,6 +30,32 @@ #include #include "main-loop.h" +/* Workaround for older versions of MinGW. */ +#ifndef ECONNREFUSED +# define ECONNREFUSED WSAECONNREFUSED +#endif +#ifndef EINPROGRESS +# define EINPROGRESS WSAEINPROGRESS +#endif +#ifndef EHOSTUNREACH +# define EHOSTUNREACH WSAEHOSTUNREACH +#endif +#ifndef EINTR +# define EINTR WSAEINTR +#endif +#ifndef EINPROGRESS +# define EINPROGRESS WSAEINPROGRESS +#endif +#ifndef ENETUNREACH +# define ENETUNREACH WSAENETUNREACH +#endif +#ifndef ENOTCONN +# define ENOTCONN WSAENOTCONN +#endif +#ifndef EWOULDBLOCK +# define EWOULDBLOCK WSAEWOULDBLOCK +#endif + /* Declaration of ffs() is missing in MinGW's strings.h. */ int ffs(int i); diff --git a/qemu_socket.h b/qemu_socket.h index 51ad210a7f..a5d0a84fb6 100644 --- a/qemu_socket.h +++ b/qemu_socket.h @@ -8,12 +8,6 @@ #include #define socket_error() WSAGetLastError() -#undef EWOULDBLOCK -#undef EINTR -#undef EINPROGRESS -#define EWOULDBLOCK WSAEWOULDBLOCK -#define EINTR WSAEINTR -#define EINPROGRESS WSAEINPROGRESS int inet_aton(const char *cp, struct in_addr *ia); diff --git a/slirp/slirp.h b/slirp/slirp.h index 46bfe4636d..f2c5eca892 100644 --- a/slirp/slirp.h +++ b/slirp/slirp.h @@ -15,18 +15,6 @@ typedef char *caddr_t; # include # include -# undef EWOULDBLOCK -# undef EINPROGRESS -# undef ENOTCONN -# undef EHOSTUNREACH -# undef ENETUNREACH -# undef ECONNREFUSED -# define EWOULDBLOCK WSAEWOULDBLOCK -# define EINPROGRESS WSAEINPROGRESS -# define ENOTCONN WSAENOTCONN -# define EHOSTUNREACH WSAEHOSTUNREACH -# define ENETUNREACH WSAENETUNREACH -# define ECONNREFUSED WSAECONNREFUSED #else # define ioctlsocket ioctl # define closesocket(s) close(s) From 5cf6dd51abb252d25cb77d3b7a95a744bed1a69c Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 12 Apr 2012 21:13:28 +0200 Subject: [PATCH 07/17] w64: Fix definition of setjmp The default definition of setjmp which is implemented in MinGW-w64 cannot be used with programs like QEMU which call longjmp from code without structured exception handling (SEH). This code therefore disables stack unwinding. We could also implement SEH for QEMU's generated JIT code, but that is much more difficult. Stack unwinding would also cost execution time. Signed-off-by: Stefan Weil --- qemu-os-win32.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/qemu-os-win32.h b/qemu-os-win32.h index b6533c0979..753679b194 100644 --- a/qemu-os-win32.h +++ b/qemu-os-win32.h @@ -56,6 +56,15 @@ # define EWOULDBLOCK WSAEWOULDBLOCK #endif +#if defined(_WIN64) +/* On w64, setjmp is implemented by _setjmp which needs a second parameter. + * If this parameter is NULL, longjump does no stack unwinding. + * That is what we need for QEMU. Passing the value of register rsp (default) + * lets longjmp try a stack unwinding which will crash with generated code. */ +# undef setjmp +# define setjmp(env) _setjmp(env, NULL) +#endif + /* Declaration of ffs() is missing in MinGW's strings.h. */ int ffs(int i); From 3b2992e42f8945f4bc6b9151f83dbf2bb5bcd538 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 12 Apr 2012 20:29:36 +0200 Subject: [PATCH 08/17] w64: Fix struct CPUTLBEntry For w64, some entries need 'uintptr_t' instead of 'unsigned long'. For other host systems, both data types are identical, so nothing changes. Signed-off-by: Stefan Weil --- cpu-defs.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpu-defs.h b/cpu-defs.h index 88d8093d22..f49e9500a9 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -98,12 +98,12 @@ typedef struct CPUTLBEntry { target_ulong addr_code; /* Addend to virtual address to get host address. IO accesses use the corresponding iotlb value. */ - unsigned long addend; + uintptr_t addend; /* padding to get a power of two size */ - uint8_t dummy[(1 << CPU_TLB_ENTRY_BITS) - - (sizeof(target_ulong) * 3 + - ((-sizeof(target_ulong) * 3) & (sizeof(unsigned long) - 1)) + - sizeof(unsigned long))]; + uint8_t dummy[(1 << CPU_TLB_ENTRY_BITS) - + (sizeof(target_ulong) * 3 + + ((-sizeof(target_ulong) * 3) & (sizeof(uintptr_t) - 1)) + + sizeof(uintptr_t))]; } CPUTLBEntry; extern int CPUTLBEntry_wrong_size[sizeof(CPUTLBEntry) == (1 << CPU_TLB_ENTRY_BITS) ? 1 : -1]; From 23ddbf08bfe3cf3e9d6993bd7918b6c4339ba2bb Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sun, 15 Apr 2012 21:02:09 +0200 Subject: [PATCH 09/17] softmmu: Use uintptr_t for physaddr and rename it Variable physaddr is a host address which should be represented by data type 'uintptr_t'. This is needed for w64 and changes nothing for other hosts. v2: Rename physaddr -> hostaddr (suggested by Blue Swirl). Signed-off-by: Stefan Weil --- softmmu_header.h | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/softmmu_header.h b/softmmu_header.h index 6b72093a0c..289dae2e54 100644 --- a/softmmu_header.h +++ b/softmmu_header.h @@ -99,7 +99,6 @@ glue(glue(glue(CPU_PREFIX, ld), USUFFIX), MEMSUFFIX)(ENV_PARAM int page_index; RES_TYPE res; target_ulong addr; - unsigned long physaddr; int mmu_idx; addr = ptr; @@ -111,8 +110,8 @@ glue(glue(glue(CPU_PREFIX, ld), USUFFIX), MEMSUFFIX)(ENV_PARAM addr, mmu_idx); } else { - physaddr = addr + env->tlb_table[mmu_idx][page_index].addend; - res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr); + uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; + res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)hostaddr); } return res; } @@ -124,7 +123,6 @@ glue(glue(glue(CPU_PREFIX, lds), SUFFIX), MEMSUFFIX)(ENV_PARAM { int res, page_index; target_ulong addr; - unsigned long physaddr; int mmu_idx; addr = ptr; @@ -135,8 +133,8 @@ glue(glue(glue(CPU_PREFIX, lds), SUFFIX), MEMSUFFIX)(ENV_PARAM res = (DATA_STYPE)glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_VAR addr, mmu_idx); } else { - physaddr = addr + env->tlb_table[mmu_idx][page_index].addend; - res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr); + uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; + res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)hostaddr); } return res; } @@ -152,7 +150,6 @@ glue(glue(glue(CPU_PREFIX, st), SUFFIX), MEMSUFFIX)(ENV_PARAM target_ulong ptr, { int page_index; target_ulong addr; - unsigned long physaddr; int mmu_idx; addr = ptr; @@ -163,8 +160,8 @@ glue(glue(glue(CPU_PREFIX, st), SUFFIX), MEMSUFFIX)(ENV_PARAM target_ulong ptr, glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_VAR addr, v, mmu_idx); } else { - physaddr = addr + env->tlb_table[mmu_idx][page_index].addend; - glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v); + uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; + glue(glue(st, SUFFIX), _raw)((uint8_t *)hostaddr, v); } } From 8efe0ca83eb9c5f996acc7a37d522da5c542ec79 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 12 Apr 2012 15:42:19 +0200 Subject: [PATCH 10/17] w64: Use uintptr_t in exec.c Replace all type casts to 'long' or 'unsigned long' by 'intptr_t' or 'uintptr_t'. For type casts which are only used to extract the lower bits of an address or to modify those bits, signedness does not matter. There I always use 'uintptr_t'. Signed-off-by: Stefan Weil --- exec.c | 77 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/exec.c b/exec.c index 6d10595b8e..77d6866c38 100644 --- a/exec.c +++ b/exec.c @@ -887,8 +887,8 @@ static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb) for(;;) { tb1 = *ptb; - n1 = (long)tb1 & 3; - tb1 = (TranslationBlock *)((long)tb1 & ~3); + n1 = (uintptr_t)tb1 & 3; + tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); if (tb1 == tb) { *ptb = tb1->page_next[n1]; break; @@ -908,8 +908,8 @@ static inline void tb_jmp_remove(TranslationBlock *tb, int n) /* find tb(n) in circular list */ for(;;) { tb1 = *ptb; - n1 = (long)tb1 & 3; - tb1 = (TranslationBlock *)((long)tb1 & ~3); + n1 = (uintptr_t)tb1 & 3; + tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); if (n1 == n && tb1 == tb) break; if (n1 == 2) { @@ -929,7 +929,7 @@ static inline void tb_jmp_remove(TranslationBlock *tb, int n) another TB */ static inline void tb_reset_jump(TranslationBlock *tb, int n) { - tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n])); + tb_set_jmp_target(tb, n, (uintptr_t)(tb->tc_ptr + tb->tb_next_offset[n])); } void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr) @@ -974,16 +974,16 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr) /* suppress any remaining jumps to this TB */ tb1 = tb->jmp_first; for(;;) { - n1 = (long)tb1 & 3; + n1 = (uintptr_t)tb1 & 3; if (n1 == 2) break; - tb1 = (TranslationBlock *)((long)tb1 & ~3); + tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); tb2 = tb1->jmp_next[n1]; tb_reset_jump(tb1, n1); tb1->jmp_next[n1] = NULL; tb1 = tb2; } - tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */ + tb->jmp_first = (TranslationBlock *)((uintptr_t)tb | 2); /* fail safe */ tb_phys_invalidate_count++; } @@ -1024,8 +1024,8 @@ static void build_page_bitmap(PageDesc *p) tb = p->first_tb; while (tb != NULL) { - n = (long)tb & 3; - tb = (TranslationBlock *)((long)tb & ~3); + n = (uintptr_t)tb & 3; + tb = (TranslationBlock *)((uintptr_t)tb & ~3); /* NOTE: this is subtle as a TB may span two physical pages */ if (n == 0) { /* NOTE: tb_end may be after the end of the page, but @@ -1069,7 +1069,8 @@ TranslationBlock *tb_gen_code(CPUArchState *env, tb->flags = flags; tb->cflags = cflags; cpu_gen_code(env, tb, &code_gen_size); - code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); + code_gen_ptr = (void *)(((uintptr_t)code_gen_ptr + code_gen_size + + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); /* check next page if needed */ virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK; @@ -1117,8 +1118,8 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, /* XXX: see if in some cases it could be faster to invalidate all the code */ tb = p->first_tb; while (tb != NULL) { - n = (long)tb & 3; - tb = (TranslationBlock *)((long)tb & ~3); + n = (uintptr_t)tb & 3; + tb = (TranslationBlock *)((uintptr_t)tb & ~3); tb_next = tb->page_next[n]; /* NOTE: this is subtle as a TB may span two physical pages */ if (n == 0) { @@ -1201,7 +1202,8 @@ static inline void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len) 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 + (long)cpu_single_env->segs[R_CS].base); + cpu_single_env->eip + + (intptr_t)cpu_single_env->segs[R_CS].base); } #endif p = page_find(start >> TARGET_PAGE_BITS); @@ -1245,8 +1247,8 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr, } #endif while (tb != NULL) { - n = (long)tb & 3; - tb = (TranslationBlock *)((long)tb & ~3); + n = (uintptr_t)tb & 3; + tb = (TranslationBlock *)((uintptr_t)tb & ~3); #ifdef TARGET_HAS_PRECISE_SMC if (current_tb == tb && (current_tb->cflags & CF_COUNT_MASK) != 1) { @@ -1294,7 +1296,7 @@ static inline void tb_alloc_page(TranslationBlock *tb, #ifndef CONFIG_USER_ONLY page_already_protected = p->first_tb != NULL; #endif - p->first_tb = (TranslationBlock *)((long)tb | n); + p->first_tb = (TranslationBlock *)((uintptr_t)tb | n); invalidate_page_bitmap(p); #if defined(TARGET_HAS_SMC) || 1 @@ -1361,7 +1363,7 @@ void tb_link_page(TranslationBlock *tb, else tb->page_addr[1] = -1; - tb->jmp_first = (TranslationBlock *)((long)tb | 2); + tb->jmp_first = (TranslationBlock *)((uintptr_t)tb | 2); tb->jmp_next[0] = NULL; tb->jmp_next[1] = NULL; @@ -1382,21 +1384,22 @@ void tb_link_page(TranslationBlock *tb, TranslationBlock *tb_find_pc(uintptr_t tc_ptr) { int m_min, m_max, m; - unsigned long v; + uintptr_t v; TranslationBlock *tb; if (nb_tbs <= 0) return NULL; - if (tc_ptr < (unsigned long)code_gen_buffer || - tc_ptr >= (unsigned long)code_gen_ptr) + if (tc_ptr < (uintptr_t)code_gen_buffer || + tc_ptr >= (uintptr_t)code_gen_ptr) { return NULL; + } /* binary search (cf Knuth) */ m_min = 0; m_max = nb_tbs - 1; while (m_min <= m_max) { m = (m_min + m_max) >> 1; tb = &tbs[m]; - v = (unsigned long)tb->tc_ptr; + v = (uintptr_t)tb->tc_ptr; if (v == tc_ptr) return tb; else if (tc_ptr < v) { @@ -1419,8 +1422,8 @@ static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n) if (tb1 != NULL) { /* find head of list */ for(;;) { - n1 = (long)tb1 & 3; - tb1 = (TranslationBlock *)((long)tb1 & ~3); + n1 = (uintptr_t)tb1 & 3; + tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); if (n1 == 2) break; tb1 = tb1->jmp_next[n1]; @@ -1432,8 +1435,8 @@ static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n) ptb = &tb_next->jmp_first; for(;;) { tb1 = *ptb; - n1 = (long)tb1 & 3; - tb1 = (TranslationBlock *)((long)tb1 & ~3); + n1 = (uintptr_t)tb1 & 3; + tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3); if (n1 == n && tb1 == tb) break; ptb = &tb1->jmp_next[n1]; @@ -2040,9 +2043,9 @@ static bool tlb_is_dirty_ram(CPUTLBEntry *tlbe) } static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, - unsigned long start, unsigned long length) + uintptr_t start, uintptr_t length) { - unsigned long addr; + uintptr_t addr; if (tlb_is_dirty_ram(tlb_entry)) { addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend; if ((addr - start) < length) { @@ -2056,7 +2059,7 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, int dirty_flags) { CPUArchState *env; - unsigned long length, start1; + uintptr_t length, start1; int i; start &= TARGET_PAGE_MASK; @@ -2069,10 +2072,10 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, /* we modify the TLB cache so that the dirty bit will be set again when accessing the range */ - start1 = (unsigned long)qemu_safe_ram_ptr(start); + start1 = (uintptr_t)qemu_safe_ram_ptr(start); /* Check that we don't span multiple blocks - this breaks the address comparisons below. */ - if ((unsigned long)qemu_safe_ram_ptr(end - 1) - start1 + if ((uintptr_t)qemu_safe_ram_ptr(end - 1) - start1 != (end - 1) - start) { abort(); } @@ -2100,7 +2103,7 @@ static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry) void *p; if (tlb_is_dirty_ram(tlb_entry)) { - p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK) + p = (void *)(uintptr_t)((tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend); ram_addr = qemu_ram_addr_from_host_nofail(p); if (!cpu_physical_memory_is_dirty(ram_addr)) { @@ -2190,7 +2193,7 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr, unsigned int index; target_ulong address; target_ulong code_address; - unsigned long addend; + uintptr_t addend; CPUTLBEntry *te; CPUWatchpoint *wp; target_phys_addr_t iotlb; @@ -2212,7 +2215,7 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr, address |= TLB_MMIO; } if (is_ram_rom_romd(section)) { - addend = (unsigned long)memory_region_get_ram_ptr(section->mr) + addend = (uintptr_t)memory_region_get_ram_ptr(section->mr) + section_addr(section, paddr); } else { addend = 0; @@ -2302,7 +2305,7 @@ struct walk_memory_regions_data { walk_memory_regions_fn fn; void *priv; - unsigned long start; + uintptr_t start; int prot; }; @@ -2363,7 +2366,7 @@ static int walk_memory_regions_1(struct walk_memory_regions_data *data, int walk_memory_regions(void *priv, walk_memory_regions_fn fn) { struct walk_memory_regions_data data; - unsigned long i; + uintptr_t i; data.fn = fn; data.priv = priv; @@ -2551,7 +2554,7 @@ int page_unprotect(target_ulong address, uintptr_t pc, void *puc) } static inline void tlb_set_dirty(CPUArchState *env, - unsigned long addr, target_ulong vaddr) + uintptr_t addr, target_ulong vaddr) { } #endif /* defined(CONFIG_USER_ONLY) */ From b065927a02cbbaca032ed20d3039baca0914165c Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 12 Apr 2012 14:14:51 +0200 Subject: [PATCH 11/17] w64: Fix data types in softmmu*.h w64 requires uintptr_t. Signed-off-by: Stefan Weil --- softmmu_header.h | 6 +++--- softmmu_template.h | 22 ++++++++++++---------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/softmmu_header.h b/softmmu_header.h index 289dae2e54..cf1aa38fc7 100644 --- a/softmmu_header.h +++ b/softmmu_header.h @@ -111,7 +111,7 @@ glue(glue(glue(CPU_PREFIX, ld), USUFFIX), MEMSUFFIX)(ENV_PARAM mmu_idx); } else { uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; - res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)hostaddr); + res = glue(glue(ld, USUFFIX), _raw)(hostaddr); } return res; } @@ -134,7 +134,7 @@ glue(glue(glue(CPU_PREFIX, lds), SUFFIX), MEMSUFFIX)(ENV_PARAM MMUSUFFIX)(ENV_VAR addr, mmu_idx); } else { uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; - res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)hostaddr); + res = glue(glue(lds, SUFFIX), _raw)(hostaddr); } return res; } @@ -161,7 +161,7 @@ glue(glue(glue(CPU_PREFIX, st), SUFFIX), MEMSUFFIX)(ENV_PARAM target_ulong ptr, mmu_idx); } else { uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; - glue(glue(st, SUFFIX), _raw)((uint8_t *)hostaddr, v); + glue(glue(st, SUFFIX), _raw)(hostaddr, v); } } diff --git a/softmmu_template.h b/softmmu_template.h index b285d7823b..b8bd700325 100644 --- a/softmmu_template.h +++ b/softmmu_template.h @@ -112,7 +112,6 @@ glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM int index; target_ulong tlb_addr; target_phys_addr_t ioaddr; - unsigned long addend; uintptr_t retaddr; /* test if there is match for unaligned or IO access */ @@ -139,6 +138,7 @@ glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM mmu_idx, retaddr); } else { /* unaligned/aligned access in the same page */ + uintptr_t addend; #ifdef ALIGNED_ONLY if ((addr & (DATA_SIZE - 1)) != 0) { retaddr = GETPC(); @@ -146,7 +146,8 @@ glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM } #endif addend = env->tlb_table[mmu_idx][index].addend; - res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(long)(addr+addend)); + res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(intptr_t) + (addr + addend)); } } else { /* the page is not in the TLB : fill it */ @@ -171,7 +172,6 @@ glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM DATA_TYPE res, res1, res2; int index, shift; target_phys_addr_t ioaddr; - unsigned long addend; target_ulong tlb_addr, addr1, addr2; index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); @@ -202,8 +202,9 @@ glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM res = (DATA_TYPE)res; } else { /* unaligned/aligned access in the same page */ - addend = env->tlb_table[mmu_idx][index].addend; - res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(long)(addr+addend)); + uintptr_t addend = env->tlb_table[mmu_idx][index].addend; + res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(intptr_t) + (addr + addend)); } } else { /* the page is not in the TLB : fill it */ @@ -258,7 +259,6 @@ void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM int mmu_idx) { target_phys_addr_t ioaddr; - unsigned long addend; target_ulong tlb_addr; uintptr_t retaddr; int index; @@ -284,6 +284,7 @@ void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM mmu_idx, retaddr); } else { /* aligned/unaligned access in the same page */ + uintptr_t addend; #ifdef ALIGNED_ONLY if ((addr & (DATA_SIZE - 1)) != 0) { retaddr = GETPC(); @@ -291,7 +292,8 @@ void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM } #endif addend = env->tlb_table[mmu_idx][index].addend; - glue(glue(st, SUFFIX), _raw)((uint8_t *)(long)(addr+addend), val); + glue(glue(st, SUFFIX), _raw)((uint8_t *)(intptr_t) + (addr + addend), val); } } else { /* the page is not in the TLB : fill it */ @@ -313,7 +315,6 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM uintptr_t retaddr) { target_phys_addr_t ioaddr; - unsigned long addend; target_ulong tlb_addr; int index, i; @@ -345,8 +346,9 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM } } else { /* aligned/unaligned access in the same page */ - addend = env->tlb_table[mmu_idx][index].addend; - glue(glue(st, SUFFIX), _raw)((uint8_t *)(long)(addr+addend), val); + uintptr_t addend = env->tlb_table[mmu_idx][index].addend; + glue(glue(st, SUFFIX), _raw)((uint8_t *)(intptr_t) + (addr + addend), val); } } else { /* the page is not in the TLB : fill it */ From 58b9630d7e2252d077b632c3a26d1aa334cf5fe6 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 12 Apr 2012 20:42:34 +0200 Subject: [PATCH 12/17] w64: Fix type cast in os_host_main_loop_wait Casting a pointer to an integer must use (DWORD_PTR) instead of (DWORD). This also matches the definition of 'fd' (gint for w32, gint64 for w64). Signed-off-by: Stefan Weil --- main-loop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main-loop.c b/main-loop.c index 1ebdc4baf1..4887c732fa 100644 --- a/main-loop.c +++ b/main-loop.c @@ -430,7 +430,7 @@ static int os_host_main_loop_wait(int timeout) g_assert(n_poll_fds <= ARRAY_SIZE(poll_fds)); for (i = 0; i < w->num; i++) { - poll_fds[n_poll_fds + i].fd = (DWORD) w->events[i]; + poll_fds[n_poll_fds + i].fd = (DWORD_PTR)w->events[i]; poll_fds[n_poll_fds + i].events = G_IO_IN; } From b69e48a84d83162efd4782472572783e99840cf5 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 12 Apr 2012 15:43:09 +0200 Subject: [PATCH 13/17] target-mips: Fix type cast for w64 (uintptr_t) This changes nothing for other hosts. Signed-off-by: Stefan Weil --- target-mips/op_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index bca1d70e1a..5627447953 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -2275,7 +2275,7 @@ void helper_pmon (int function) break; case 158: { - unsigned char *fmt = (void *)(unsigned long)env->active_tc.gpr[4]; + unsigned char *fmt = (void *)(uintptr_t)env->active_tc.gpr[4]; printf("%s", fmt); } break; From 3ba19255450666869ecfe764774c2371f989e68b Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 12 Apr 2012 15:44:24 +0200 Subject: [PATCH 14/17] cpu-exec: Remove non-portable type cast and fix format string This change is needed for w64, but also changes the code for other hosts. Signed-off-by: Stefan Weil --- cpu-exec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpu-exec.c b/cpu-exec.c index d153f978e1..0344cd5c59 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -541,8 +541,8 @@ int cpu_exec(CPUArchState *env) tb_invalidated_flag = 0; } #ifdef CONFIG_DEBUG_EXEC - qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n", - (long)tb->tc_ptr, tb->pc, + qemu_log_mask(CPU_LOG_EXEC, "Trace %p [" TARGET_FMT_lx "] %s\n", + tb->tc_ptr, tb->pc, lookup_symbol(tb->pc)); #endif /* see if we can patch the calling TB. When the TB From b0b0f1c964bb7643a6d4469ffd8157de84741d1f Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 12 Apr 2012 15:44:35 +0200 Subject: [PATCH 15/17] disas: Replace 'unsigned long' by 'uintptr_t' This is needed for w64. It changes nothing for other hosts. Signed-off-by: Stefan Weil --- disas.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/disas.c b/disas.c index 4f2c4e4cb9..27071c3bc1 100644 --- a/disas.c +++ b/disas.c @@ -268,7 +268,7 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags) /* Disassemble this for me please... (debugging). */ void disas(FILE *out, void *code, unsigned long size) { - unsigned long pc; + uintptr_t pc; int count; struct disassemble_info disasm_info; int (*print_insn)(bfd_vma pc, disassemble_info *info); @@ -276,7 +276,7 @@ void disas(FILE *out, void *code, unsigned long size) INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf); disasm_info.buffer = code; - disasm_info.buffer_vma = (unsigned long)code; + disasm_info.buffer_vma = (uintptr_t)code; disasm_info.buffer_length = size; #ifdef HOST_WORDS_BIGENDIAN @@ -320,8 +320,8 @@ void disas(FILE *out, void *code, unsigned long size) (long) code); return; #endif - for (pc = (unsigned long)code; size > 0; pc += count, size -= count) { - fprintf(out, "0x%08lx: ", pc); + for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) { + fprintf(out, "0x%08" PRIxPTR ": ", pc); count = print_insn(pc, &disasm_info); fprintf(out, "\n"); if (count < 0) From 0fee8f342884e96b29d7df28475d0c485a317d54 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 12 Apr 2012 22:30:16 +0200 Subject: [PATCH 16/17] nbd: Fix compiler warning (w64) Portable printing of dev_offset (data type off_t) needs a type cast. Signed-off-by: Stefan Weil --- nbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nbd.c b/nbd.c index 567e94e27a..406e555bc6 100644 --- a/nbd.c +++ b/nbd.c @@ -813,7 +813,7 @@ static void nbd_trip(void *opaque) LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64 ", Offset: %" PRIu64 "\n", request.from, request.len, - (uint64_t)exp->size, exp->dev_offset); + (uint64_t)exp->size, (uint64_t)exp->dev_offset); LOG("requested operation past EOF--bad client?"); goto invalid_request; } From 55dd9ffa70eb44f461b12c248c3df106ba8deca9 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 12 Apr 2012 22:33:12 +0200 Subject: [PATCH 17/17] w64: Fix time conversion for some versions of MinGW-w64 tb.time is a time value, but not necessarily of the same size as time_t: while time_t is 64 bit for w64, tb.time still is 32 bit only. Therefore we need en explicit conversion. Signed-off-by: Stefan Weil --- savevm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/savevm.c b/savevm.c index 12fb20954f..2d18babd6e 100644 --- a/savevm.c +++ b/savevm.c @@ -2106,7 +2106,8 @@ void do_savevm(Monitor *mon, const QDict *qdict) } } else { #ifdef _WIN32 - ptm = localtime(&tb.time); + time_t t = tb.time; + ptm = localtime(&t); strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", ptm); #else /* cast below needed for OpenBSD where tv_sec is still 'long' */