Revision 379f6698
b/configure | ||
---|---|---|
184 | 184 |
linux_user="no" |
185 | 185 |
darwin_user="no" |
186 | 186 |
bsd_user="no" |
187 |
guest_base="" |
|
187 | 188 |
build_docs="yes" |
188 | 189 |
uname_release="" |
189 | 190 |
curses="yes" |
... | ... | |
465 | 466 |
;; |
466 | 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 | 473 |
--enable-uname-release=*) uname_release="$optarg" |
469 | 474 |
;; |
470 | 475 |
--sparc_cpu=*) |
... | ... | |
544 | 549 |
# If cpu ~= sparc and sparc_cpu hasn't been defined, plug in the right |
545 | 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 | 553 |
case "$cpu" in |
548 | 554 |
sparc) if test -z "$sparc_cpu" ; then |
549 | 555 |
ARCH_CFLAGS="-m32 -mcpu=ultrasparc -D__sparc_v8plus__" |
... | ... | |
576 | 582 |
i386) |
577 | 583 |
ARCH_CFLAGS="-m32" |
578 | 584 |
ARCH_LDFLAGS="-m32" |
585 |
host_guest_base="yes" |
|
579 | 586 |
;; |
580 | 587 |
x86_64) |
581 | 588 |
ARCH_CFLAGS="-m64" |
582 | 589 |
ARCH_LDFLAGS="-m64" |
590 |
host_guest_base="yes" |
|
591 |
;; |
|
592 |
arm*) |
|
593 |
host_guest_base="yes" |
|
583 | 594 |
;; |
584 | 595 |
esac |
585 | 596 |
|
597 |
[ -z "$guest_base" ] && guest_base="$host_guest_base" |
|
598 |
|
|
586 | 599 |
if test x"$show_help" = x"yes" ; then |
587 | 600 |
cat << EOF |
588 | 601 |
|
... | ... | |
641 | 654 |
echo " --disable-darwin-user disable all darwin usermode emulation targets" |
642 | 655 |
echo " --enable-bsd-user enable all BSD usermode emulation targets" |
643 | 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 | 660 |
echo " --fmod-lib path to FMOD library" |
645 | 661 |
echo " --fmod-inc path to FMOD includes" |
646 | 662 |
echo " --oss-lib path to OSS library" |
... | ... | |
1446 | 1462 |
[ ! -z "$uname_release" ] && \ |
1447 | 1463 |
echo "uname -r $uname_release" |
1448 | 1464 |
echo "NPTL support $nptl" |
1465 |
echo "GUEST_BASE $guest_base" |
|
1449 | 1466 |
echo "vde support $vde" |
1450 | 1467 |
echo "AIO support $aio" |
1451 | 1468 |
echo "IO thread $io_thread" |
... | ... | |
2070 | 2087 |
if test "$target_user_only" = "yes" -a "$elfload32" = "yes"; then |
2071 | 2088 |
echo "TARGET_HAS_ELFLOAD32=y" >> $config_mak |
2072 | 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 | 2093 |
if test "$target_bsd_user" = "yes" ; then |
2074 | 2094 |
echo "CONFIG_BSD_USER=y" >> $config_mak |
2075 | 2095 |
fi |
b/cpu-all.h | ||
---|---|---|
624 | 624 |
/* On some host systems the guest address space is reserved on the host. |
625 | 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 | 635 |
/* All direct uses of g2h and h2g need to go away for usermode softmmu. */ |
631 | 636 |
#define g2h(x) ((void *)((unsigned long)(x) + GUEST_BASE)) |
b/linux-user/elfload.c | ||
---|---|---|
1545 | 1545 |
info->mmap = 0; |
1546 | 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 | 1571 |
/* Do this so that we can load the interpreter, if need be. We will |
1549 | 1572 |
change some of these later */ |
1550 | 1573 |
info->rss = 0; |
b/linux-user/main.c | ||
---|---|---|
39 | 39 |
char *exec_path; |
40 | 40 |
|
41 | 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 | 48 |
static const char *interp_prefix = CONFIG_QEMU_PREFIX; |
44 | 49 |
const char *qemu_uname_release = CONFIG_UNAME_RELEASE; |
... | ... | |
2320 | 2325 |
"-E var=value sets/modifies targets environment variable(s)\n" |
2321 | 2326 |
"-U var unsets targets environment variable(s)\n" |
2322 | 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 | 2331 |
"\n" |
2324 | 2332 |
"Debug options:\n" |
2325 | 2333 |
"-d options activate log (logfile=%s)\n" |
... | ... | |
2495 | 2503 |
#endif |
2496 | 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 | 2511 |
} else if (!strcmp(r, "drop-ld-preload")) { |
2499 | 2512 |
(void) envlist_unsetenv(envlist, "LD_PRELOAD"); |
2500 | 2513 |
} else if (!strcmp(r, "singlestep")) { |
... | ... | |
2572 | 2585 |
target_environ = envlist_to_environ(envlist, NULL); |
2573 | 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 | 2618 |
* Prepare copy of argv vector for target. |
2577 | 2619 |
*/ |
... | ... | |
2622 | 2664 |
free(target_environ); |
2623 | 2665 |
|
2624 | 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 | 2670 |
log_page_dump(); |
2626 | 2671 |
|
2627 | 2672 |
qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk); |
b/linux-user/qemu.h | ||
---|---|---|
133 | 133 |
void task_settid(TaskState *); |
134 | 134 |
void stop_all_tasks(void); |
135 | 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 | 140 |
/* ??? See if we can avoid exposing so much of the loader internals. */ |
138 | 141 |
/* |
b/qemu-doc.texi | ||
---|---|---|
2026 | 2026 |
@subsection Command line options |
2027 | 2027 |
|
2028 | 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 | 2030 |
@end example |
2031 | 2031 |
|
2032 | 2032 |
@table @option |
... | ... | |
2038 | 2038 |
Set the x86 stack size in bytes (default=524288) |
2039 | 2039 |
@item -cpu model |
2040 | 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 | 2045 |
@end table |
2042 | 2046 |
|
2043 | 2047 |
Debug options: |
b/tcg/arm/tcg-target.c | ||
---|---|---|
990 | 990 |
# endif |
991 | 991 |
|
992 | 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 | 1009 |
switch (opc) { |
995 | 1010 |
case 0: |
996 | 1011 |
tcg_out_ld8_12(s, COND_AL, data_reg, addr_reg, 0); |
... | ... | |
1200 | 1215 |
# endif |
1201 | 1216 |
|
1202 | 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 | 1234 |
switch (opc) { |
1205 | 1235 |
case 0: |
1206 | 1236 |
tcg_out_st8_12(s, COND_AL, data_reg, addr_reg, 0); |
b/tcg/arm/tcg-target.h | ||
---|---|---|
60 | 60 |
#define TCG_TARGET_STACK_ALIGN 8 |
61 | 61 |
#define TCG_TARGET_CALL_STACK_OFFSET 0 |
62 | 62 |
|
63 |
#define TCG_TARGET_HAS_GUEST_BASE |
|
64 |
|
|
63 | 65 |
enum { |
64 | 66 |
/* Note: must be synced with dyngen-exec.h */ |
65 | 67 |
TCG_AREG0 = TCG_REG_R7, |
b/tcg/i386/tcg-target.c | ||
---|---|---|
427 | 427 |
}; |
428 | 428 |
#endif |
429 | 429 |
|
430 |
#ifndef CONFIG_USER_ONLY |
|
431 |
#define GUEST_BASE 0 |
|
432 |
#endif |
|
433 |
|
|
430 | 434 |
/* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and |
431 | 435 |
EAX. It will be useful once fixed registers globals are less |
432 | 436 |
common. */ |
... | ... | |
572 | 576 |
switch(opc) { |
573 | 577 |
case 0: |
574 | 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 | 580 |
break; |
577 | 581 |
case 0 | 4: |
578 | 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 | 584 |
break; |
581 | 585 |
case 1: |
582 | 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 | 588 |
if (bswap) { |
585 | 589 |
/* rolw $8, data_reg */ |
586 | 590 |
tcg_out8(s, 0x66); |
... | ... | |
590 | 594 |
break; |
591 | 595 |
case 1 | 4: |
592 | 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 | 598 |
if (bswap) { |
595 | 599 |
/* rolw $8, data_reg */ |
596 | 600 |
tcg_out8(s, 0x66); |
... | ... | |
603 | 607 |
break; |
604 | 608 |
case 2: |
605 | 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 | 611 |
if (bswap) { |
608 | 612 |
/* bswap */ |
609 | 613 |
tcg_out_opc(s, (0xc8 + data_reg) | P_EXT); |
... | ... | |
619 | 623 |
r0 = r1; |
620 | 624 |
} |
621 | 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 | 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 | 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 | 633 |
/* bswap */ |
630 | 634 |
tcg_out_opc(s, (0xc8 + data_reg2) | P_EXT); |
631 | 635 |
} |
... | ... | |
806 | 810 |
switch(opc) { |
807 | 811 |
case 0: |
808 | 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 | 814 |
break; |
811 | 815 |
case 1: |
812 | 816 |
if (bswap) { |
... | ... | |
818 | 822 |
} |
819 | 823 |
/* movw */ |
820 | 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 | 826 |
break; |
823 | 827 |
case 2: |
824 | 828 |
if (bswap) { |
... | ... | |
828 | 832 |
data_reg = r1; |
829 | 833 |
} |
830 | 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 | 836 |
break; |
833 | 837 |
case 3: |
834 | 838 |
if (bswap) { |
835 | 839 |
tcg_out_mov(s, r1, data_reg2); |
836 | 840 |
/* bswap data_reg */ |
837 | 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 | 843 |
tcg_out_mov(s, r1, data_reg); |
840 | 844 |
/* bswap data_reg */ |
841 | 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 | 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 | 851 |
break; |
848 | 852 |
default: |
b/tcg/i386/tcg-target.h | ||
---|---|---|
53 | 53 |
#define TCG_TARGET_HAS_ext16s_i32 |
54 | 54 |
#define TCG_TARGET_HAS_rot_i32 |
55 | 55 |
|
56 |
#define TCG_TARGET_HAS_GUEST_BASE |
|
57 |
|
|
56 | 58 |
/* Note: must be synced with dyngen-exec.h */ |
57 | 59 |
#define TCG_AREG0 TCG_REG_EBP |
58 | 60 |
#define TCG_AREG1 TCG_REG_EBX |
b/tcg/tcg.c | ||
---|---|---|
46 | 46 |
|
47 | 47 |
#include "qemu-common.h" |
48 | 48 |
#include "cache-utils.h" |
49 |
#include "host-utils.h" |
|
49 | 50 |
|
50 | 51 |
/* Note: the long term plan is to reduce the dependancies on the QEMU |
51 | 52 |
CPU definitions. Currently they are used for qemu_ld/st |
... | ... | |
57 | 58 |
#include "tcg-op.h" |
58 | 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 | 65 |
static void patch_reloc(uint8_t *code_ptr, int type, |
62 | 66 |
tcg_target_long value, tcg_target_long addend); |
b/tcg/x86_64/tcg-target.c | ||
---|---|---|
508 | 508 |
int opc) |
509 | 509 |
{ |
510 | 510 |
int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw; |
511 |
int32_t offset; |
|
511 | 512 |
#if defined(CONFIG_SOFTMMU) |
512 | 513 |
uint8_t *label1_ptr, *label2_ptr; |
513 | 514 |
#endif |
... | ... | |
604 | 605 |
/* add x(r1), r0 */ |
605 | 606 |
tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) - |
606 | 607 |
offsetof(CPUTLBEntry, addr_read)); |
608 |
offset = 0; |
|
607 | 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 | 622 |
#endif |
610 | 623 |
|
611 | 624 |
#ifdef TARGET_WORDS_BIGENDIAN |
... | ... | |
616 | 629 |
switch(opc) { |
617 | 630 |
case 0: |
618 | 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 | 633 |
break; |
621 | 634 |
case 0 | 4: |
622 | 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 | 637 |
break; |
625 | 638 |
case 1: |
626 | 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 | 641 |
if (bswap) { |
629 | 642 |
/* rolw $8, data_reg */ |
630 | 643 |
tcg_out8(s, 0x66); |
... | ... | |
635 | 648 |
case 1 | 4: |
636 | 649 |
if (bswap) { |
637 | 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 | 652 |
/* rolw $8, data_reg */ |
640 | 653 |
tcg_out8(s, 0x66); |
641 | 654 |
tcg_out_modrm(s, 0xc1, 0, data_reg); |
... | ... | |
645 | 658 |
tcg_out_modrm(s, 0xbf | P_EXT | rexw, data_reg, data_reg); |
646 | 659 |
} else { |
647 | 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 | 663 |
break; |
651 | 664 |
case 2: |
652 | 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 | 667 |
if (bswap) { |
655 | 668 |
/* bswap */ |
656 | 669 |
tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0); |
... | ... | |
659 | 672 |
case 2 | 4: |
660 | 673 |
if (bswap) { |
661 | 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 | 676 |
/* bswap */ |
664 | 677 |
tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0); |
665 | 678 |
/* movslq */ |
666 | 679 |
tcg_out_modrm(s, 0x63 | P_REXW, data_reg, data_reg); |
667 | 680 |
} else { |
668 | 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 | 684 |
break; |
672 | 685 |
case 3: |
673 | 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 | 688 |
if (bswap) { |
676 | 689 |
/* bswap */ |
677 | 690 |
tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT | P_REXW, 0, data_reg, 0); |
... | ... | |
691 | 704 |
int opc) |
692 | 705 |
{ |
693 | 706 |
int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw; |
707 |
int32_t offset; |
|
694 | 708 |
#if defined(CONFIG_SOFTMMU) |
695 | 709 |
uint8_t *label1_ptr, *label2_ptr; |
696 | 710 |
#endif |
... | ... | |
775 | 789 |
/* add x(r1), r0 */ |
776 | 790 |
tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) - |
777 | 791 |
offsetof(CPUTLBEntry, addr_write)); |
792 |
offset = 0; |
|
778 | 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 | 806 |
#endif |
781 | 807 |
|
782 | 808 |
#ifdef TARGET_WORDS_BIGENDIAN |
... | ... | |
787 | 813 |
switch(opc) { |
788 | 814 |
case 0: |
789 | 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 | 817 |
break; |
792 | 818 |
case 1: |
793 | 819 |
if (bswap) { |
... | ... | |
799 | 825 |
} |
800 | 826 |
/* movw */ |
801 | 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 | 829 |
break; |
804 | 830 |
case 2: |
805 | 831 |
if (bswap) { |
... | ... | |
809 | 835 |
data_reg = r1; |
810 | 836 |
} |
811 | 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 | 839 |
break; |
814 | 840 |
case 3: |
815 | 841 |
if (bswap) { |
... | ... | |
819 | 845 |
data_reg = r1; |
820 | 846 |
} |
821 | 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 | 849 |
break; |
824 | 850 |
default: |
825 | 851 |
tcg_abort(); |
b/tcg/x86_64/tcg-target.h | ||
---|---|---|
73 | 73 |
#define TCG_TARGET_HAS_rot_i32 |
74 | 74 |
#define TCG_TARGET_HAS_rot_i64 |
75 | 75 |
|
76 |
#define TCG_TARGET_HAS_GUEST_BASE |
|
77 |
|
|
76 | 78 |
/* Note: must be synced with dyngen-exec.h */ |
77 | 79 |
#define TCG_AREG0 TCG_REG_R14 |
78 | 80 |
#define TCG_AREG1 TCG_REG_R15 |
Also available in: Unified diff