Commit 379f6698d73f476de38682b3ff96ecb226728c43
1 parent
a9ff9df1
Userspace guest address offsetting
Re-implement GUEST_BASE support. Offset guest ddress space by default if the guest binary contains regions below the host mmap_min_addr. Implement support for i386, x86-64 and arm hosts. Signed-off-by: Riku Voipio <riku.voipio@iki.fi> Signed-off-by: Paul Brook <paul@codesourcery.com>
Showing
13 changed files
with
206 additions
and
36 deletions
configure
| @@ -184,6 +184,7 @@ softmmu="yes" | @@ -184,6 +184,7 @@ softmmu="yes" | ||
| 184 | linux_user="no" | 184 | linux_user="no" |
| 185 | darwin_user="no" | 185 | darwin_user="no" |
| 186 | bsd_user="no" | 186 | bsd_user="no" |
| 187 | +guest_base="" | ||
| 187 | build_docs="yes" | 188 | build_docs="yes" |
| 188 | uname_release="" | 189 | uname_release="" |
| 189 | curses="yes" | 190 | curses="yes" |
| @@ -465,6 +466,10 @@ for opt do | @@ -465,6 +466,10 @@ for opt do | ||
| 465 | ;; | 466 | ;; |
| 466 | --enable-bsd-user) bsd_user="yes" | 467 | --enable-bsd-user) bsd_user="yes" |
| 467 | ;; | 468 | ;; |
| 469 | + --enable-guest-base) guest_base="yes" | ||
| 470 | + ;; | ||
| 471 | + --disable-guest-base) guest_base="no" | ||
| 472 | + ;; | ||
| 468 | --enable-uname-release=*) uname_release="$optarg" | 473 | --enable-uname-release=*) uname_release="$optarg" |
| 469 | ;; | 474 | ;; |
| 470 | --sparc_cpu=*) | 475 | --sparc_cpu=*) |
| @@ -544,6 +549,7 @@ fi | @@ -544,6 +549,7 @@ fi | ||
| 544 | # If cpu ~= sparc and sparc_cpu hasn't been defined, plug in the right | 549 | # If cpu ~= sparc and sparc_cpu hasn't been defined, plug in the right |
| 545 | # ARCH_CFLAGS/ARCH_LDFLAGS (assume sparc_v8plus for 32-bit and sparc_v9 for 64-bit) | 550 | # ARCH_CFLAGS/ARCH_LDFLAGS (assume sparc_v8plus for 32-bit and sparc_v9 for 64-bit) |
| 546 | # | 551 | # |
| 552 | +host_guest_base="no" | ||
| 547 | case "$cpu" in | 553 | case "$cpu" in |
| 548 | sparc) if test -z "$sparc_cpu" ; then | 554 | sparc) if test -z "$sparc_cpu" ; then |
| 549 | ARCH_CFLAGS="-m32 -mcpu=ultrasparc -D__sparc_v8plus__" | 555 | ARCH_CFLAGS="-m32 -mcpu=ultrasparc -D__sparc_v8plus__" |
| @@ -576,13 +582,20 @@ case "$cpu" in | @@ -576,13 +582,20 @@ case "$cpu" in | ||
| 576 | i386) | 582 | i386) |
| 577 | ARCH_CFLAGS="-m32" | 583 | ARCH_CFLAGS="-m32" |
| 578 | ARCH_LDFLAGS="-m32" | 584 | ARCH_LDFLAGS="-m32" |
| 585 | + host_guest_base="yes" | ||
| 579 | ;; | 586 | ;; |
| 580 | x86_64) | 587 | x86_64) |
| 581 | ARCH_CFLAGS="-m64" | 588 | ARCH_CFLAGS="-m64" |
| 582 | ARCH_LDFLAGS="-m64" | 589 | ARCH_LDFLAGS="-m64" |
| 590 | + host_guest_base="yes" | ||
| 591 | + ;; | ||
| 592 | + arm*) | ||
| 593 | + host_guest_base="yes" | ||
| 583 | ;; | 594 | ;; |
| 584 | esac | 595 | esac |
| 585 | 596 | ||
| 597 | +[ -z "$guest_base" ] && guest_base="$host_guest_base" | ||
| 598 | + | ||
| 586 | if test x"$show_help" = x"yes" ; then | 599 | if test x"$show_help" = x"yes" ; then |
| 587 | cat << EOF | 600 | cat << EOF |
| 588 | 601 | ||
| @@ -641,6 +654,9 @@ echo " --enable-darwin-user enable all darwin usermode emulation targets" | @@ -641,6 +654,9 @@ echo " --enable-darwin-user enable all darwin usermode emulation targets" | ||
| 641 | echo " --disable-darwin-user disable all darwin usermode emulation targets" | 654 | echo " --disable-darwin-user disable all darwin usermode emulation targets" |
| 642 | echo " --enable-bsd-user enable all BSD usermode emulation targets" | 655 | echo " --enable-bsd-user enable all BSD usermode emulation targets" |
| 643 | echo " --disable-bsd-user disable all BSD usermode emulation targets" | 656 | echo " --disable-bsd-user disable all BSD usermode emulation targets" |
| 657 | +echo " --enable-guest-base enable GUEST_BASE support for usermode" | ||
| 658 | +echo " emulation targets" | ||
| 659 | +echo " --disable-guest-base disable GUEST_BASE support" | ||
| 644 | echo " --fmod-lib path to FMOD library" | 660 | echo " --fmod-lib path to FMOD library" |
| 645 | echo " --fmod-inc path to FMOD includes" | 661 | echo " --fmod-inc path to FMOD includes" |
| 646 | echo " --oss-lib path to OSS library" | 662 | echo " --oss-lib path to OSS library" |
| @@ -1446,6 +1462,7 @@ echo "Documentation $build_docs" | @@ -1446,6 +1462,7 @@ echo "Documentation $build_docs" | ||
| 1446 | [ ! -z "$uname_release" ] && \ | 1462 | [ ! -z "$uname_release" ] && \ |
| 1447 | echo "uname -r $uname_release" | 1463 | echo "uname -r $uname_release" |
| 1448 | echo "NPTL support $nptl" | 1464 | echo "NPTL support $nptl" |
| 1465 | +echo "GUEST_BASE $guest_base" | ||
| 1449 | echo "vde support $vde" | 1466 | echo "vde support $vde" |
| 1450 | echo "AIO support $aio" | 1467 | echo "AIO support $aio" |
| 1451 | echo "IO thread $io_thread" | 1468 | echo "IO thread $io_thread" |
| @@ -2070,6 +2087,9 @@ fi | @@ -2070,6 +2087,9 @@ fi | ||
| 2070 | if test "$target_user_only" = "yes" -a "$elfload32" = "yes"; then | 2087 | if test "$target_user_only" = "yes" -a "$elfload32" = "yes"; then |
| 2071 | echo "TARGET_HAS_ELFLOAD32=y" >> $config_mak | 2088 | echo "TARGET_HAS_ELFLOAD32=y" >> $config_mak |
| 2072 | fi | 2089 | fi |
| 2090 | +if test "$target_user_only" = "yes" -a "$guest_base" = "yes"; then | ||
| 2091 | + echo "CONFIG_USE_GUEST_BASE=y" >> $config_mak | ||
| 2092 | +fi | ||
| 2073 | if test "$target_bsd_user" = "yes" ; then | 2093 | if test "$target_bsd_user" = "yes" ; then |
| 2074 | echo "CONFIG_BSD_USER=y" >> $config_mak | 2094 | echo "CONFIG_BSD_USER=y" >> $config_mak |
| 2075 | fi | 2095 | fi |
cpu-all.h
| @@ -624,8 +624,13 @@ static inline void stfq_be_p(void *ptr, float64 v) | @@ -624,8 +624,13 @@ static inline void stfq_be_p(void *ptr, float64 v) | ||
| 624 | /* On some host systems the guest address space is reserved on the host. | 624 | /* On some host systems the guest address space is reserved on the host. |
| 625 | * This allows the guest address space to be offset to a convenient location. | 625 | * This allows the guest address space to be offset to a convenient location. |
| 626 | */ | 626 | */ |
| 627 | -//#define GUEST_BASE 0x20000000 | ||
| 628 | -#define GUEST_BASE 0 | 627 | +#if defined(CONFIG_USE_GUEST_BASE) |
| 628 | +extern unsigned long guest_base; | ||
| 629 | +extern int have_guest_base; | ||
| 630 | +#define GUEST_BASE guest_base | ||
| 631 | +#else | ||
| 632 | +#define GUEST_BASE 0ul | ||
| 633 | +#endif | ||
| 629 | 634 | ||
| 630 | /* All direct uses of g2h and h2g need to go away for usermode softmmu. */ | 635 | /* All direct uses of g2h and h2g need to go away for usermode softmmu. */ |
| 631 | #define g2h(x) ((void *)((unsigned long)(x) + GUEST_BASE)) | 636 | #define g2h(x) ((void *)((unsigned long)(x) + GUEST_BASE)) |
linux-user/elfload.c
| @@ -1545,6 +1545,29 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, | @@ -1545,6 +1545,29 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, | ||
| 1545 | info->mmap = 0; | 1545 | info->mmap = 0; |
| 1546 | elf_entry = (abi_ulong) elf_ex.e_entry; | 1546 | elf_entry = (abi_ulong) elf_ex.e_entry; |
| 1547 | 1547 | ||
| 1548 | +#if defined(CONFIG_USE_GUEST_BASE) | ||
| 1549 | + /* | ||
| 1550 | + * In case where user has not explicitly set the guest_base, we | ||
| 1551 | + * probe here that should we set it automatically. | ||
| 1552 | + */ | ||
| 1553 | + if (!have_guest_base) { | ||
| 1554 | + /* | ||
| 1555 | + * Go through ELF program header table and find out whether | ||
| 1556 | + * any of the segments drop below our current mmap_min_addr and | ||
| 1557 | + * in that case set guest_base to corresponding address. | ||
| 1558 | + */ | ||
| 1559 | + for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; | ||
| 1560 | + i++, elf_ppnt++) { | ||
| 1561 | + if (elf_ppnt->p_type != PT_LOAD) | ||
| 1562 | + continue; | ||
| 1563 | + if (HOST_PAGE_ALIGN(elf_ppnt->p_vaddr) < mmap_min_addr) { | ||
| 1564 | + guest_base = HOST_PAGE_ALIGN(mmap_min_addr); | ||
| 1565 | + break; | ||
| 1566 | + } | ||
| 1567 | + } | ||
| 1568 | + } | ||
| 1569 | +#endif /* CONFIG_USE_GUEST_BASE */ | ||
| 1570 | + | ||
| 1548 | /* Do this so that we can load the interpreter, if need be. We will | 1571 | /* Do this so that we can load the interpreter, if need be. We will |
| 1549 | change some of these later */ | 1572 | change some of these later */ |
| 1550 | info->rss = 0; | 1573 | info->rss = 0; |
linux-user/main.c
| @@ -39,6 +39,11 @@ | @@ -39,6 +39,11 @@ | ||
| 39 | char *exec_path; | 39 | char *exec_path; |
| 40 | 40 | ||
| 41 | int singlestep; | 41 | int singlestep; |
| 42 | +#if defined(CONFIG_USE_GUEST_BASE) | ||
| 43 | +unsigned long mmap_min_addr; | ||
| 44 | +unsigned long guest_base; | ||
| 45 | +int have_guest_base; | ||
| 46 | +#endif | ||
| 42 | 47 | ||
| 43 | static const char *interp_prefix = CONFIG_QEMU_PREFIX; | 48 | static const char *interp_prefix = CONFIG_QEMU_PREFIX; |
| 44 | const char *qemu_uname_release = CONFIG_UNAME_RELEASE; | 49 | const char *qemu_uname_release = CONFIG_UNAME_RELEASE; |
| @@ -2320,6 +2325,9 @@ static void usage(void) | @@ -2320,6 +2325,9 @@ static void usage(void) | ||
| 2320 | "-E var=value sets/modifies targets environment variable(s)\n" | 2325 | "-E var=value sets/modifies targets environment variable(s)\n" |
| 2321 | "-U var unsets targets environment variable(s)\n" | 2326 | "-U var unsets targets environment variable(s)\n" |
| 2322 | "-0 argv0 forces target process argv[0] to be argv0\n" | 2327 | "-0 argv0 forces target process argv[0] to be argv0\n" |
| 2328 | +#if defined(CONFIG_USE_GUEST_BASE) | ||
| 2329 | + "-B address set guest_base address to address\n" | ||
| 2330 | +#endif | ||
| 2323 | "\n" | 2331 | "\n" |
| 2324 | "Debug options:\n" | 2332 | "Debug options:\n" |
| 2325 | "-d options activate log (logfile=%s)\n" | 2333 | "-d options activate log (logfile=%s)\n" |
| @@ -2495,6 +2503,11 @@ int main(int argc, char **argv, char **envp) | @@ -2495,6 +2503,11 @@ int main(int argc, char **argv, char **envp) | ||
| 2495 | #endif | 2503 | #endif |
| 2496 | exit(1); | 2504 | exit(1); |
| 2497 | } | 2505 | } |
| 2506 | +#if defined(CONFIG_USE_GUEST_BASE) | ||
| 2507 | + } else if (!strcmp(r, "B")) { | ||
| 2508 | + guest_base = strtol(argv[optind++], NULL, 0); | ||
| 2509 | + have_guest_base = 1; | ||
| 2510 | +#endif | ||
| 2498 | } else if (!strcmp(r, "drop-ld-preload")) { | 2511 | } else if (!strcmp(r, "drop-ld-preload")) { |
| 2499 | (void) envlist_unsetenv(envlist, "LD_PRELOAD"); | 2512 | (void) envlist_unsetenv(envlist, "LD_PRELOAD"); |
| 2500 | } else if (!strcmp(r, "singlestep")) { | 2513 | } else if (!strcmp(r, "singlestep")) { |
| @@ -2572,6 +2585,35 @@ int main(int argc, char **argv, char **envp) | @@ -2572,6 +2585,35 @@ int main(int argc, char **argv, char **envp) | ||
| 2572 | target_environ = envlist_to_environ(envlist, NULL); | 2585 | target_environ = envlist_to_environ(envlist, NULL); |
| 2573 | envlist_free(envlist); | 2586 | envlist_free(envlist); |
| 2574 | 2587 | ||
| 2588 | +#if defined(CONFIG_USE_GUEST_BASE) | ||
| 2589 | + /* | ||
| 2590 | + * Now that page sizes are configured in cpu_init() we can do | ||
| 2591 | + * proper page alignment for guest_base. | ||
| 2592 | + */ | ||
| 2593 | + guest_base = HOST_PAGE_ALIGN(guest_base); | ||
| 2594 | + | ||
| 2595 | + /* | ||
| 2596 | + * Read in mmap_min_addr kernel parameter. This value is used | ||
| 2597 | + * When loading the ELF image to determine whether guest_base | ||
| 2598 | + * is needed. | ||
| 2599 | + * | ||
| 2600 | + * When user has explicitly set the quest base, we skip this | ||
| 2601 | + * test. | ||
| 2602 | + */ | ||
| 2603 | + if (!have_guest_base) { | ||
| 2604 | + FILE *fp; | ||
| 2605 | + | ||
| 2606 | + if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) { | ||
| 2607 | + unsigned long tmp; | ||
| 2608 | + if (fscanf(fp, "%lu", &tmp) == 1) { | ||
| 2609 | + mmap_min_addr = tmp; | ||
| 2610 | + qemu_log("host mmap_min_addr=0x%lx\n", mmap_min_addr); | ||
| 2611 | + } | ||
| 2612 | + fclose(fp); | ||
| 2613 | + } | ||
| 2614 | + } | ||
| 2615 | +#endif /* CONFIG_USE_GUEST_BASE */ | ||
| 2616 | + | ||
| 2575 | /* | 2617 | /* |
| 2576 | * Prepare copy of argv vector for target. | 2618 | * Prepare copy of argv vector for target. |
| 2577 | */ | 2619 | */ |
| @@ -2622,6 +2664,9 @@ int main(int argc, char **argv, char **envp) | @@ -2622,6 +2664,9 @@ int main(int argc, char **argv, char **envp) | ||
| 2622 | free(target_environ); | 2664 | free(target_environ); |
| 2623 | 2665 | ||
| 2624 | if (qemu_log_enabled()) { | 2666 | if (qemu_log_enabled()) { |
| 2667 | +#if defined(CONFIG_USE_GUEST_BASE) | ||
| 2668 | + qemu_log("guest_base 0x%lx\n", guest_base); | ||
| 2669 | +#endif | ||
| 2625 | log_page_dump(); | 2670 | log_page_dump(); |
| 2626 | 2671 | ||
| 2627 | qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk); | 2672 | qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk); |
linux-user/qemu.h
| @@ -133,6 +133,9 @@ void init_task_state(TaskState *ts); | @@ -133,6 +133,9 @@ void init_task_state(TaskState *ts); | ||
| 133 | void task_settid(TaskState *); | 133 | void task_settid(TaskState *); |
| 134 | void stop_all_tasks(void); | 134 | void stop_all_tasks(void); |
| 135 | extern const char *qemu_uname_release; | 135 | extern const char *qemu_uname_release; |
| 136 | +#if defined(CONFIG_USE_GUEST_BASE) | ||
| 137 | +extern unsigned long mmap_min_addr; | ||
| 138 | +#endif | ||
| 136 | 139 | ||
| 137 | /* ??? See if we can avoid exposing so much of the loader internals. */ | 140 | /* ??? See if we can avoid exposing so much of the loader internals. */ |
| 138 | /* | 141 | /* |
qemu-doc.texi
| @@ -2026,7 +2026,7 @@ qemu-i386 /usr/local/qemu-i386/wine/bin/wine \ | @@ -2026,7 +2026,7 @@ qemu-i386 /usr/local/qemu-i386/wine/bin/wine \ | ||
| 2026 | @subsection Command line options | 2026 | @subsection Command line options |
| 2027 | 2027 | ||
| 2028 | @example | 2028 | @example |
| 2029 | -usage: qemu-i386 [-h] [-d] [-L path] [-s size] [-cpu model] [-g port] program [arguments...] | 2029 | +usage: qemu-i386 [-h] [-d] [-L path] [-s size] [-cpu model] [-g port] [-B offset] program [arguments...] |
| 2030 | @end example | 2030 | @end example |
| 2031 | 2031 | ||
| 2032 | @table @option | 2032 | @table @option |
| @@ -2038,6 +2038,10 @@ Set the x86 elf interpreter prefix (default=/usr/local/qemu-i386) | @@ -2038,6 +2038,10 @@ Set the x86 elf interpreter prefix (default=/usr/local/qemu-i386) | ||
| 2038 | Set the x86 stack size in bytes (default=524288) | 2038 | Set the x86 stack size in bytes (default=524288) |
| 2039 | @item -cpu model | 2039 | @item -cpu model |
| 2040 | Select CPU model (-cpu ? for list and additional feature selection) | 2040 | Select CPU model (-cpu ? for list and additional feature selection) |
| 2041 | +@item -B offset | ||
| 2042 | +Offset guest address by the specified number of bytes. This is useful when | ||
| 2043 | +the address region rewuired by guest applications is reserved on the host. | ||
| 2044 | +Ths option is currently only supported on some hosts. | ||
| 2041 | @end table | 2045 | @end table |
| 2042 | 2046 | ||
| 2043 | Debug options: | 2047 | Debug options: |
tcg/arm/tcg-target.c
| @@ -990,7 +990,22 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond, | @@ -990,7 +990,22 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond, | ||
| 990 | # endif | 990 | # endif |
| 991 | 991 | ||
| 992 | *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2; | 992 | *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2; |
| 993 | -#else | 993 | +#else /* !CONFIG_SOFTMMU */ |
| 994 | + if (GUEST_BASE) { | ||
| 995 | + uint32_t offset = GUEST_BASE; | ||
| 996 | + int i; | ||
| 997 | + int rot; | ||
| 998 | + | ||
| 999 | + while (offset) { | ||
| 1000 | + i = ctz32(offset) & ~1; | ||
| 1001 | + rot = ((32 - i) << 7) & 0xf00; | ||
| 1002 | + | ||
| 1003 | + tcg_out_dat_imm(s, COND_AL, ARITH_ADD, 8, addr_reg, | ||
| 1004 | + ((offset >> i) & 0xff) | rot); | ||
| 1005 | + addr_reg = 8; | ||
| 1006 | + offset &= ~(0xff << i); | ||
| 1007 | + } | ||
| 1008 | + } | ||
| 994 | switch (opc) { | 1009 | switch (opc) { |
| 995 | case 0: | 1010 | case 0: |
| 996 | tcg_out_ld8_12(s, COND_AL, data_reg, addr_reg, 0); | 1011 | tcg_out_ld8_12(s, COND_AL, data_reg, addr_reg, 0); |
| @@ -1200,7 +1215,22 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond, | @@ -1200,7 +1215,22 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond, | ||
| 1200 | # endif | 1215 | # endif |
| 1201 | 1216 | ||
| 1202 | *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2; | 1217 | *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2; |
| 1203 | -#else | 1218 | +#else /* !CONFIG_SOFTMMU */ |
| 1219 | + if (GUEST_BASE) { | ||
| 1220 | + uint32_t offset = GUEST_BASE; | ||
| 1221 | + int i; | ||
| 1222 | + int rot; | ||
| 1223 | + | ||
| 1224 | + while (offset) { | ||
| 1225 | + i = ctz32(offset) & ~1; | ||
| 1226 | + rot = ((32 - i) << 7) & 0xf00; | ||
| 1227 | + | ||
| 1228 | + tcg_out_dat_imm(s, COND_AL, ARITH_ADD, 8, addr_reg, | ||
| 1229 | + ((offset >> i) & 0xff) | rot); | ||
| 1230 | + addr_reg = 8; | ||
| 1231 | + offset &= ~(0xff << i); | ||
| 1232 | + } | ||
| 1233 | + } | ||
| 1204 | switch (opc) { | 1234 | switch (opc) { |
| 1205 | case 0: | 1235 | case 0: |
| 1206 | tcg_out_st8_12(s, COND_AL, data_reg, addr_reg, 0); | 1236 | tcg_out_st8_12(s, COND_AL, data_reg, addr_reg, 0); |
tcg/arm/tcg-target.h
| @@ -60,6 +60,8 @@ enum { | @@ -60,6 +60,8 @@ enum { | ||
| 60 | #define TCG_TARGET_STACK_ALIGN 8 | 60 | #define TCG_TARGET_STACK_ALIGN 8 |
| 61 | #define TCG_TARGET_CALL_STACK_OFFSET 0 | 61 | #define TCG_TARGET_CALL_STACK_OFFSET 0 |
| 62 | 62 | ||
| 63 | +#define TCG_TARGET_HAS_GUEST_BASE | ||
| 64 | + | ||
| 63 | enum { | 65 | enum { |
| 64 | /* Note: must be synced with dyngen-exec.h */ | 66 | /* Note: must be synced with dyngen-exec.h */ |
| 65 | TCG_AREG0 = TCG_REG_R7, | 67 | TCG_AREG0 = TCG_REG_R7, |
tcg/i386/tcg-target.c
| @@ -427,6 +427,10 @@ static void *qemu_st_helpers[4] = { | @@ -427,6 +427,10 @@ static void *qemu_st_helpers[4] = { | ||
| 427 | }; | 427 | }; |
| 428 | #endif | 428 | #endif |
| 429 | 429 | ||
| 430 | +#ifndef CONFIG_USER_ONLY | ||
| 431 | +#define GUEST_BASE 0 | ||
| 432 | +#endif | ||
| 433 | + | ||
| 430 | /* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and | 434 | /* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and |
| 431 | EAX. It will be useful once fixed registers globals are less | 435 | EAX. It will be useful once fixed registers globals are less |
| 432 | common. */ | 436 | common. */ |
| @@ -572,15 +576,15 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | @@ -572,15 +576,15 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | ||
| 572 | switch(opc) { | 576 | switch(opc) { |
| 573 | case 0: | 577 | case 0: |
| 574 | /* movzbl */ | 578 | /* movzbl */ |
| 575 | - tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, 0); | 579 | + tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, GUEST_BASE); |
| 576 | break; | 580 | break; |
| 577 | case 0 | 4: | 581 | case 0 | 4: |
| 578 | /* movsbl */ | 582 | /* movsbl */ |
| 579 | - tcg_out_modrm_offset(s, 0xbe | P_EXT, data_reg, r0, 0); | 583 | + tcg_out_modrm_offset(s, 0xbe | P_EXT, data_reg, r0, GUEST_BASE); |
| 580 | break; | 584 | break; |
| 581 | case 1: | 585 | case 1: |
| 582 | /* movzwl */ | 586 | /* movzwl */ |
| 583 | - tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, 0); | 587 | + tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, GUEST_BASE); |
| 584 | if (bswap) { | 588 | if (bswap) { |
| 585 | /* rolw $8, data_reg */ | 589 | /* rolw $8, data_reg */ |
| 586 | tcg_out8(s, 0x66); | 590 | tcg_out8(s, 0x66); |
| @@ -590,7 +594,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | @@ -590,7 +594,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | ||
| 590 | break; | 594 | break; |
| 591 | case 1 | 4: | 595 | case 1 | 4: |
| 592 | /* movswl */ | 596 | /* movswl */ |
| 593 | - tcg_out_modrm_offset(s, 0xbf | P_EXT, data_reg, r0, 0); | 597 | + tcg_out_modrm_offset(s, 0xbf | P_EXT, data_reg, r0, GUEST_BASE); |
| 594 | if (bswap) { | 598 | if (bswap) { |
| 595 | /* rolw $8, data_reg */ | 599 | /* rolw $8, data_reg */ |
| 596 | tcg_out8(s, 0x66); | 600 | tcg_out8(s, 0x66); |
| @@ -603,7 +607,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | @@ -603,7 +607,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | ||
| 603 | break; | 607 | break; |
| 604 | case 2: | 608 | case 2: |
| 605 | /* movl (r0), data_reg */ | 609 | /* movl (r0), data_reg */ |
| 606 | - tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0); | 610 | + tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE); |
| 607 | if (bswap) { | 611 | if (bswap) { |
| 608 | /* bswap */ | 612 | /* bswap */ |
| 609 | tcg_out_opc(s, (0xc8 + data_reg) | P_EXT); | 613 | tcg_out_opc(s, (0xc8 + data_reg) | P_EXT); |
| @@ -619,13 +623,13 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | @@ -619,13 +623,13 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | ||
| 619 | r0 = r1; | 623 | r0 = r1; |
| 620 | } | 624 | } |
| 621 | if (!bswap) { | 625 | if (!bswap) { |
| 622 | - tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0); | ||
| 623 | - tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, 4); | 626 | + tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE); |
| 627 | + tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, GUEST+BASE + 4); | ||
| 624 | } else { | 628 | } else { |
| 625 | - tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 4); | 629 | + tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE + 4); |
| 626 | tcg_out_opc(s, (0xc8 + data_reg) | P_EXT); | 630 | tcg_out_opc(s, (0xc8 + data_reg) | P_EXT); |
| 627 | 631 | ||
| 628 | - tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, 0); | 632 | + tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, GUEST_BASE); |
| 629 | /* bswap */ | 633 | /* bswap */ |
| 630 | tcg_out_opc(s, (0xc8 + data_reg2) | P_EXT); | 634 | tcg_out_opc(s, (0xc8 + data_reg2) | P_EXT); |
| 631 | } | 635 | } |
| @@ -806,7 +810,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, | @@ -806,7 +810,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, | ||
| 806 | switch(opc) { | 810 | switch(opc) { |
| 807 | case 0: | 811 | case 0: |
| 808 | /* movb */ | 812 | /* movb */ |
| 809 | - tcg_out_modrm_offset(s, 0x88, data_reg, r0, 0); | 813 | + tcg_out_modrm_offset(s, 0x88, data_reg, r0, GUEST_BASE); |
| 810 | break; | 814 | break; |
| 811 | case 1: | 815 | case 1: |
| 812 | if (bswap) { | 816 | if (bswap) { |
| @@ -818,7 +822,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, | @@ -818,7 +822,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, | ||
| 818 | } | 822 | } |
| 819 | /* movw */ | 823 | /* movw */ |
| 820 | tcg_out8(s, 0x66); | 824 | tcg_out8(s, 0x66); |
| 821 | - tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0); | 825 | + tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE); |
| 822 | break; | 826 | break; |
| 823 | case 2: | 827 | case 2: |
| 824 | if (bswap) { | 828 | if (bswap) { |
| @@ -828,21 +832,21 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, | @@ -828,21 +832,21 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, | ||
| 828 | data_reg = r1; | 832 | data_reg = r1; |
| 829 | } | 833 | } |
| 830 | /* movl */ | 834 | /* movl */ |
| 831 | - tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0); | 835 | + tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE); |
| 832 | break; | 836 | break; |
| 833 | case 3: | 837 | case 3: |
| 834 | if (bswap) { | 838 | if (bswap) { |
| 835 | tcg_out_mov(s, r1, data_reg2); | 839 | tcg_out_mov(s, r1, data_reg2); |
| 836 | /* bswap data_reg */ | 840 | /* bswap data_reg */ |
| 837 | tcg_out_opc(s, (0xc8 + r1) | P_EXT); | 841 | tcg_out_opc(s, (0xc8 + r1) | P_EXT); |
| 838 | - tcg_out_modrm_offset(s, 0x89, r1, r0, 0); | 842 | + tcg_out_modrm_offset(s, 0x89, r1, r0, GUEST_BASE); |
| 839 | tcg_out_mov(s, r1, data_reg); | 843 | tcg_out_mov(s, r1, data_reg); |
| 840 | /* bswap data_reg */ | 844 | /* bswap data_reg */ |
| 841 | tcg_out_opc(s, (0xc8 + r1) | P_EXT); | 845 | tcg_out_opc(s, (0xc8 + r1) | P_EXT); |
| 842 | - tcg_out_modrm_offset(s, 0x89, r1, r0, 4); | 846 | + tcg_out_modrm_offset(s, 0x89, r1, r0, GUEST_BASE + 4); |
| 843 | } else { | 847 | } else { |
| 844 | - tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0); | ||
| 845 | - tcg_out_modrm_offset(s, 0x89, data_reg2, r0, 4); | 848 | + tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE); |
| 849 | + tcg_out_modrm_offset(s, 0x89, data_reg2, r0, GUEST_BASE + 4); | ||
| 846 | } | 850 | } |
| 847 | break; | 851 | break; |
| 848 | default: | 852 | default: |
tcg/i386/tcg-target.h
| @@ -53,6 +53,8 @@ enum { | @@ -53,6 +53,8 @@ enum { | ||
| 53 | #define TCG_TARGET_HAS_ext16s_i32 | 53 | #define TCG_TARGET_HAS_ext16s_i32 |
| 54 | #define TCG_TARGET_HAS_rot_i32 | 54 | #define TCG_TARGET_HAS_rot_i32 |
| 55 | 55 | ||
| 56 | +#define TCG_TARGET_HAS_GUEST_BASE | ||
| 57 | + | ||
| 56 | /* Note: must be synced with dyngen-exec.h */ | 58 | /* Note: must be synced with dyngen-exec.h */ |
| 57 | #define TCG_AREG0 TCG_REG_EBP | 59 | #define TCG_AREG0 TCG_REG_EBP |
| 58 | #define TCG_AREG1 TCG_REG_EBX | 60 | #define TCG_AREG1 TCG_REG_EBX |
tcg/tcg.c
| @@ -46,6 +46,7 @@ | @@ -46,6 +46,7 @@ | ||
| 46 | 46 | ||
| 47 | #include "qemu-common.h" | 47 | #include "qemu-common.h" |
| 48 | #include "cache-utils.h" | 48 | #include "cache-utils.h" |
| 49 | +#include "host-utils.h" | ||
| 49 | 50 | ||
| 50 | /* Note: the long term plan is to reduce the dependancies on the QEMU | 51 | /* Note: the long term plan is to reduce the dependancies on the QEMU |
| 51 | CPU definitions. Currently they are used for qemu_ld/st | 52 | CPU definitions. Currently they are used for qemu_ld/st |
| @@ -57,6 +58,9 @@ | @@ -57,6 +58,9 @@ | ||
| 57 | #include "tcg-op.h" | 58 | #include "tcg-op.h" |
| 58 | #include "elf.h" | 59 | #include "elf.h" |
| 59 | 60 | ||
| 61 | +#if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE) | ||
| 62 | +#error GUEST_BASE not supported on this host. | ||
| 63 | +#endif | ||
| 60 | 64 | ||
| 61 | static void patch_reloc(uint8_t *code_ptr, int type, | 65 | static void patch_reloc(uint8_t *code_ptr, int type, |
| 62 | tcg_target_long value, tcg_target_long addend); | 66 | tcg_target_long value, tcg_target_long addend); |
tcg/x86_64/tcg-target.c
| @@ -508,6 +508,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | @@ -508,6 +508,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | ||
| 508 | int opc) | 508 | int opc) |
| 509 | { | 509 | { |
| 510 | int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw; | 510 | int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw; |
| 511 | + int32_t offset; | ||
| 511 | #if defined(CONFIG_SOFTMMU) | 512 | #if defined(CONFIG_SOFTMMU) |
| 512 | uint8_t *label1_ptr, *label2_ptr; | 513 | uint8_t *label1_ptr, *label2_ptr; |
| 513 | #endif | 514 | #endif |
| @@ -604,8 +605,20 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | @@ -604,8 +605,20 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | ||
| 604 | /* add x(r1), r0 */ | 605 | /* add x(r1), r0 */ |
| 605 | tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) - | 606 | tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) - |
| 606 | offsetof(CPUTLBEntry, addr_read)); | 607 | offsetof(CPUTLBEntry, addr_read)); |
| 608 | + offset = 0; | ||
| 607 | #else | 609 | #else |
| 608 | - r0 = addr_reg; | 610 | + if (GUEST_BASE == (int32_t)GUEST_BASE) { |
| 611 | + r0 = addr_reg; | ||
| 612 | + offset = GUEST_BASE; | ||
| 613 | + } else { | ||
| 614 | + offset = 0; | ||
| 615 | + /* movq $GUEST_BASE, r0 */ | ||
| 616 | + tcg_out_opc(s, (0xb8 + (r0 & 7)) | P_REXW, 0, r0, 0); | ||
| 617 | + tcg_out32(s, GUEST_BASE); | ||
| 618 | + tcg_out32(s, GUEST_BASE >> 32); | ||
| 619 | + /* addq addr_reg, r0 */ | ||
| 620 | + tcg_out_modrm(s, 0x01 | P_REXW, addr_reg, r0); | ||
| 621 | + } | ||
| 609 | #endif | 622 | #endif |
| 610 | 623 | ||
| 611 | #ifdef TARGET_WORDS_BIGENDIAN | 624 | #ifdef TARGET_WORDS_BIGENDIAN |
| @@ -616,15 +629,15 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | @@ -616,15 +629,15 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | ||
| 616 | switch(opc) { | 629 | switch(opc) { |
| 617 | case 0: | 630 | case 0: |
| 618 | /* movzbl */ | 631 | /* movzbl */ |
| 619 | - tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, 0); | 632 | + tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, offset); |
| 620 | break; | 633 | break; |
| 621 | case 0 | 4: | 634 | case 0 | 4: |
| 622 | /* movsbX */ | 635 | /* movsbX */ |
| 623 | - tcg_out_modrm_offset(s, 0xbe | P_EXT | rexw, data_reg, r0, 0); | 636 | + tcg_out_modrm_offset(s, 0xbe | P_EXT | rexw, data_reg, r0, offset); |
| 624 | break; | 637 | break; |
| 625 | case 1: | 638 | case 1: |
| 626 | /* movzwl */ | 639 | /* movzwl */ |
| 627 | - tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, 0); | 640 | + tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, offset); |
| 628 | if (bswap) { | 641 | if (bswap) { |
| 629 | /* rolw $8, data_reg */ | 642 | /* rolw $8, data_reg */ |
| 630 | tcg_out8(s, 0x66); | 643 | tcg_out8(s, 0x66); |
| @@ -635,7 +648,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | @@ -635,7 +648,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | ||
| 635 | case 1 | 4: | 648 | case 1 | 4: |
| 636 | if (bswap) { | 649 | if (bswap) { |
| 637 | /* movzwl */ | 650 | /* movzwl */ |
| 638 | - tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, 0); | 651 | + tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, offset); |
| 639 | /* rolw $8, data_reg */ | 652 | /* rolw $8, data_reg */ |
| 640 | tcg_out8(s, 0x66); | 653 | tcg_out8(s, 0x66); |
| 641 | tcg_out_modrm(s, 0xc1, 0, data_reg); | 654 | tcg_out_modrm(s, 0xc1, 0, data_reg); |
| @@ -645,12 +658,12 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | @@ -645,12 +658,12 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | ||
| 645 | tcg_out_modrm(s, 0xbf | P_EXT | rexw, data_reg, data_reg); | 658 | tcg_out_modrm(s, 0xbf | P_EXT | rexw, data_reg, data_reg); |
| 646 | } else { | 659 | } else { |
| 647 | /* movswX */ | 660 | /* movswX */ |
| 648 | - tcg_out_modrm_offset(s, 0xbf | P_EXT | rexw, data_reg, r0, 0); | 661 | + tcg_out_modrm_offset(s, 0xbf | P_EXT | rexw, data_reg, r0, offset); |
| 649 | } | 662 | } |
| 650 | break; | 663 | break; |
| 651 | case 2: | 664 | case 2: |
| 652 | /* movl (r0), data_reg */ | 665 | /* movl (r0), data_reg */ |
| 653 | - tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0); | 666 | + tcg_out_modrm_offset(s, 0x8b, data_reg, r0, offset); |
| 654 | if (bswap) { | 667 | if (bswap) { |
| 655 | /* bswap */ | 668 | /* bswap */ |
| 656 | tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0); | 669 | tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0); |
| @@ -659,19 +672,19 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | @@ -659,19 +672,19 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | ||
| 659 | case 2 | 4: | 672 | case 2 | 4: |
| 660 | if (bswap) { | 673 | if (bswap) { |
| 661 | /* movl (r0), data_reg */ | 674 | /* movl (r0), data_reg */ |
| 662 | - tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0); | 675 | + tcg_out_modrm_offset(s, 0x8b, data_reg, r0, offset); |
| 663 | /* bswap */ | 676 | /* bswap */ |
| 664 | tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0); | 677 | tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0); |
| 665 | /* movslq */ | 678 | /* movslq */ |
| 666 | tcg_out_modrm(s, 0x63 | P_REXW, data_reg, data_reg); | 679 | tcg_out_modrm(s, 0x63 | P_REXW, data_reg, data_reg); |
| 667 | } else { | 680 | } else { |
| 668 | /* movslq */ | 681 | /* movslq */ |
| 669 | - tcg_out_modrm_offset(s, 0x63 | P_REXW, data_reg, r0, 0); | 682 | + tcg_out_modrm_offset(s, 0x63 | P_REXW, data_reg, r0, offset); |
| 670 | } | 683 | } |
| 671 | break; | 684 | break; |
| 672 | case 3: | 685 | case 3: |
| 673 | /* movq (r0), data_reg */ | 686 | /* movq (r0), data_reg */ |
| 674 | - tcg_out_modrm_offset(s, 0x8b | P_REXW, data_reg, r0, 0); | 687 | + tcg_out_modrm_offset(s, 0x8b | P_REXW, data_reg, r0, offset); |
| 675 | if (bswap) { | 688 | if (bswap) { |
| 676 | /* bswap */ | 689 | /* bswap */ |
| 677 | tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT | P_REXW, 0, data_reg, 0); | 690 | tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT | P_REXW, 0, data_reg, 0); |
| @@ -691,6 +704,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, | @@ -691,6 +704,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, | ||
| 691 | int opc) | 704 | int opc) |
| 692 | { | 705 | { |
| 693 | int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw; | 706 | int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw; |
| 707 | + int32_t offset; | ||
| 694 | #if defined(CONFIG_SOFTMMU) | 708 | #if defined(CONFIG_SOFTMMU) |
| 695 | uint8_t *label1_ptr, *label2_ptr; | 709 | uint8_t *label1_ptr, *label2_ptr; |
| 696 | #endif | 710 | #endif |
| @@ -775,8 +789,20 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, | @@ -775,8 +789,20 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, | ||
| 775 | /* add x(r1), r0 */ | 789 | /* add x(r1), r0 */ |
| 776 | tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) - | 790 | tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) - |
| 777 | offsetof(CPUTLBEntry, addr_write)); | 791 | offsetof(CPUTLBEntry, addr_write)); |
| 792 | + offset = 0; | ||
| 778 | #else | 793 | #else |
| 779 | - r0 = addr_reg; | 794 | + if (GUEST_BASE == (int32_t)GUEST_BASE) { |
| 795 | + r0 = addr_reg; | ||
| 796 | + offset = GUEST_BASE; | ||
| 797 | + } else { | ||
| 798 | + offset = 0; | ||
| 799 | + /* movq $GUEST_BASE, r0 */ | ||
| 800 | + tcg_out_opc(s, (0xb8 + (r0 & 7)) | P_REXW, 0, r0, 0); | ||
| 801 | + tcg_out32(s, GUEST_BASE); | ||
| 802 | + tcg_out32(s, GUEST_BASE >> 32); | ||
| 803 | + /* addq addr_reg, r0 */ | ||
| 804 | + tcg_out_modrm(s, 0x01 | P_REXW, addr_reg, r0); | ||
| 805 | + } | ||
| 780 | #endif | 806 | #endif |
| 781 | 807 | ||
| 782 | #ifdef TARGET_WORDS_BIGENDIAN | 808 | #ifdef TARGET_WORDS_BIGENDIAN |
| @@ -787,7 +813,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, | @@ -787,7 +813,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, | ||
| 787 | switch(opc) { | 813 | switch(opc) { |
| 788 | case 0: | 814 | case 0: |
| 789 | /* movb */ | 815 | /* movb */ |
| 790 | - tcg_out_modrm_offset(s, 0x88 | P_REXB, data_reg, r0, 0); | 816 | + tcg_out_modrm_offset(s, 0x88 | P_REXB, data_reg, r0, offset); |
| 791 | break; | 817 | break; |
| 792 | case 1: | 818 | case 1: |
| 793 | if (bswap) { | 819 | if (bswap) { |
| @@ -799,7 +825,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, | @@ -799,7 +825,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, | ||
| 799 | } | 825 | } |
| 800 | /* movw */ | 826 | /* movw */ |
| 801 | tcg_out8(s, 0x66); | 827 | tcg_out8(s, 0x66); |
| 802 | - tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0); | 828 | + tcg_out_modrm_offset(s, 0x89, data_reg, r0, offset); |
| 803 | break; | 829 | break; |
| 804 | case 2: | 830 | case 2: |
| 805 | if (bswap) { | 831 | if (bswap) { |
| @@ -809,7 +835,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, | @@ -809,7 +835,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, | ||
| 809 | data_reg = r1; | 835 | data_reg = r1; |
| 810 | } | 836 | } |
| 811 | /* movl */ | 837 | /* movl */ |
| 812 | - tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0); | 838 | + tcg_out_modrm_offset(s, 0x89, data_reg, r0, offset); |
| 813 | break; | 839 | break; |
| 814 | case 3: | 840 | case 3: |
| 815 | if (bswap) { | 841 | if (bswap) { |
| @@ -819,7 +845,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, | @@ -819,7 +845,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, | ||
| 819 | data_reg = r1; | 845 | data_reg = r1; |
| 820 | } | 846 | } |
| 821 | /* movq */ | 847 | /* movq */ |
| 822 | - tcg_out_modrm_offset(s, 0x89 | P_REXW, data_reg, r0, 0); | 848 | + tcg_out_modrm_offset(s, 0x89 | P_REXW, data_reg, r0, offset); |
| 823 | break; | 849 | break; |
| 824 | default: | 850 | default: |
| 825 | tcg_abort(); | 851 | tcg_abort(); |
tcg/x86_64/tcg-target.h
| @@ -73,6 +73,8 @@ enum { | @@ -73,6 +73,8 @@ enum { | ||
| 73 | #define TCG_TARGET_HAS_rot_i32 | 73 | #define TCG_TARGET_HAS_rot_i32 |
| 74 | #define TCG_TARGET_HAS_rot_i64 | 74 | #define TCG_TARGET_HAS_rot_i64 |
| 75 | 75 | ||
| 76 | +#define TCG_TARGET_HAS_GUEST_BASE | ||
| 77 | + | ||
| 76 | /* Note: must be synced with dyngen-exec.h */ | 78 | /* Note: must be synced with dyngen-exec.h */ |
| 77 | #define TCG_AREG0 TCG_REG_R14 | 79 | #define TCG_AREG0 TCG_REG_R14 |
| 78 | #define TCG_AREG1 TCG_REG_R15 | 80 | #define TCG_AREG1 TCG_REG_R15 |