summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile22
-rw-r--r--Makefile.objs4
-rw-r--r--Makefile.target41
-rw-r--r--audio/Makefile.objs2
-rw-r--r--backends/Makefile.objs2
-rw-r--r--block.c34
-rw-r--r--block/gluster.c7
-rw-r--r--block/iscsi.c2
-rw-r--r--block/nfs.c4
-rw-r--r--block/qcow2-refcount.c4
-rw-r--r--block/raw-posix.c127
-rw-r--r--block/vmdk.c35
-rw-r--r--bsd-user/main.c2
-rwxr-xr-xconfigure17
-rw-r--r--disas/Makefile.objs2
-rw-r--r--hw/intc/xilinx_intc.c3
-rw-r--r--hw/microblaze/boot.c14
-rw-r--r--hw/timer/xilinx_timer.c2
-rw-r--r--hw/usb/Makefile.objs1
-rw-r--r--include/block/block.h6
-rw-r--r--include/exec/exec-all.h4
-rw-r--r--include/glib-compat.h9
-rw-r--r--libcacard/Makefile1
-rw-r--r--qemu-img.c29
-rw-r--r--qemu-timer.c3
-rw-r--r--rules.mak23
-rw-r--r--target-microblaze/cpu.c2
-rw-r--r--tcg/aarch64/tcg-target.c141
-rw-r--r--tcg/aarch64/tcg-target.h1
-rw-r--r--tcg/arm/tcg-target.c174
-rw-r--r--tcg/arm/tcg-target.h1
-rw-r--r--tcg/i386/tcg-target.c82
-rw-r--r--tcg/i386/tcg-target.h2
-rw-r--r--tcg/ia64/tcg-target.c255
-rw-r--r--tcg/ia64/tcg-target.h6
-rw-r--r--tcg/mips/tcg-target.c145
-rw-r--r--tcg/mips/tcg-target.h1
-rw-r--r--tcg/optimize.c75
-rw-r--r--tcg/ppc/tcg-target.c202
-rw-r--r--tcg/ppc/tcg-target.h1
-rw-r--r--tcg/ppc64/tcg-target.c170
-rw-r--r--tcg/ppc64/tcg-target.h1
-rw-r--r--tcg/s390/tcg-target.c124
-rw-r--r--tcg/s390/tcg-target.h2
-rw-r--r--tcg/sparc/tcg-target.c161
-rw-r--r--tcg/sparc/tcg-target.h1
-rw-r--r--tcg/tcg-be-ldst.h4
-rw-r--r--tcg/tcg-op.h16
-rw-r--r--tcg/tcg-opc.h10
-rw-r--r--tcg/tcg.c257
-rw-r--r--tcg/tcg.h85
-rw-r--r--tcg/tci/tcg-target.c50
-rw-r--r--tcg/tci/tcg-target.h1
-rwxr-xr-xtests/qemu-iotests/0514
-rw-r--r--tests/qemu-iotests/051.out10
-rwxr-xr-xtests/qemu-iotests/0597
-rw-r--r--tests/qemu-iotests/059.out8
-rwxr-xr-xtests/qemu-iotests/08573
-rwxr-xr-xtests/qemu-iotests/091105
-rw-r--r--tests/qemu-iotests/091.out28
-rw-r--r--tests/qemu-iotests/common.qemu200
-rw-r--r--tests/qemu-iotests/group1
-rw-r--r--translate-all.c13
-rw-r--r--ui/Makefile.objs2
-rw-r--r--util/oslib-win32.c112
-rw-r--r--vl.c1
66 files changed, 1575 insertions, 1359 deletions
diff --git a/Makefile b/Makefile
index a120aabac6..d830483685 100644
--- a/Makefile
+++ b/Makefile
@@ -148,10 +148,6 @@ endif
all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all modules
-vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
-
-vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
-
config-host.h: config-host.h-timestamp
config-host.h-timestamp: config-host.mak
qemu-options.def: $(SRC_PATH)/qemu-options.hx
@@ -195,8 +191,6 @@ ALL_SUBDIRS=$(TARGET_DIRS) $(patsubst %,pc-bios/%, $(ROMS))
recurse-all: $(SUBDIR_RULES) $(ROMSUBDIR_RULES)
-bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS)
-
$(BUILD_DIR)/version.o: $(SRC_PATH)/version.rc $(BUILD_DIR)/config-host.h | $(BUILD_DIR)/version.lo
$(call quiet-command,$(WINDRES) -I$(BUILD_DIR) -o $@ $<," RC version.o")
$(BUILD_DIR)/version.lo: $(SRC_PATH)/version.rc $(BUILD_DIR)/config-host.h
@@ -384,17 +378,25 @@ install: all $(if $(BUILD_DOCS),install-doc) install-sysconfig \
install-datadir install-localstatedir
$(INSTALL_DIR) "$(DESTDIR)$(bindir)"
ifneq ($(TOOLS),)
- $(INSTALL_PROG) $(STRIP_OPT) $(TOOLS) "$(DESTDIR)$(bindir)"
+ $(INSTALL_PROG) $(TOOLS) "$(DESTDIR)$(bindir)"
+ifneq ($(STRIP),)
+ $(STRIP) $(TOOLS:%="$(DESTDIR)$(bindir)/%")
+endif
endif
ifneq ($(CONFIG_MODULES),)
$(INSTALL_DIR) "$(DESTDIR)$(qemu_moddir)"
- for s in $(patsubst %.mo,%$(DSOSUF),$(modules-m)); do \
- $(INSTALL_PROG) $(STRIP_OPT) $$s "$(DESTDIR)$(qemu_moddir)/$$(echo $$s | tr / -)"; \
+ for s in $(modules-m:.mo=$(DSOSUF)); do \
+ t="$(DESTDIR)$(qemu_moddir)/$$(echo $$s | tr / -)"; \
+ $(INSTALL_LIB) $$s "$$t"; \
+ test -z "$(STRIP)" || $(STRIP) "$$t"; \
done
endif
ifneq ($(HELPERS-y),)
$(INSTALL_DIR) "$(DESTDIR)$(libexecdir)"
- $(INSTALL_PROG) $(STRIP_OPT) $(HELPERS-y) "$(DESTDIR)$(libexecdir)"
+ $(INSTALL_PROG) $(HELPERS-y) "$(DESTDIR)$(libexecdir)"
+ifneq ($(STRIP),)
+ $(STRIP) $(HELPERS-y:%="$(DESTDIR)$(libexecdir)/%")
+endif
endif
ifneq ($(BLOBS),)
set -e; for x in $(BLOBS); do \
diff --git a/Makefile.objs b/Makefile.objs
index a6e0e2aacc..b897e1dc34 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -31,6 +31,8 @@ libcacard-y += libcacard/vcard_emul_nss.o
libcacard-y += libcacard/vcard_emul_type.o
libcacard-y += libcacard/card_7816.o
libcacard-y += libcacard/vcardt.o
+libcacard/vcard_emul_nss.o-cflags := $(NSS_CFLAGS)
+libcacard/vcard_emul_nss.o-libs := $(NSS_LIBS)
######################################################################
# Target independent part of system emulation. The long term path is to
@@ -64,9 +66,11 @@ common-obj-y += hw/
common-obj-y += ui/
common-obj-y += bt-host.o bt-vhci.o
+bt-host.o-cflags := $(BLUEZ_CFLAGS)
common-obj-y += dma-helpers.o
common-obj-y += vl.o
+vl.o-cflags := $(GPROF_CFLAGS) $(SDL_CFLAGS)
common-obj-y += tpm.o
common-obj-$(CONFIG_SLIRP) += slirp/
diff --git a/Makefile.target b/Makefile.target
index 6d8fde8b9e..9986047545 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -16,19 +16,22 @@ QEMU_CFLAGS+=-I$(SRC_PATH)/include
ifdef CONFIG_USER_ONLY
# user emulator name
QEMU_PROG=qemu-$(TARGET_NAME)
+QEMU_PROG_BUILD = $(QEMU_PROG)
else
# system emulator name
+QEMU_PROG=qemu-system-$(TARGET_NAME)$(EXESUF)
ifneq (,$(findstring -mwindows,$(libs_softmmu)))
# Terminate program name with a 'w' because the linker builds a windows executable.
QEMU_PROGW=qemu-system-$(TARGET_NAME)w$(EXESUF)
-endif # windows executable
-QEMU_PROG=qemu-system-$(TARGET_NAME)$(EXESUF)
+$(QEMU_PROG): $(QEMU_PROGW)
+ $(call quiet-command,$(OBJCOPY) --subsystem console $(QEMU_PROGW) $(QEMU_PROG)," GEN $(TARGET_DIR)$(QEMU_PROG)")
+QEMU_PROG_BUILD = $(QEMU_PROGW)
+else
+QEMU_PROG_BUILD = $(QEMU_PROG)
endif
-
-PROGS=$(QEMU_PROG)
-ifdef QEMU_PROGW
-PROGS+=$(QEMU_PROGW)
endif
+
+PROGS=$(QEMU_PROG) $(QEMU_PROGW)
STPFILES=
config-target.h: config-target.h-timestamp
@@ -140,10 +143,7 @@ endif # CONFIG_SOFTMMU
%/translate.o: QEMU_CFLAGS += $(TRANSLATE_OPT_CFLAGS)
dummy := $(call unnest-vars,,obj-y)
-
-# we are making another call to unnest-vars with different vars, protect obj-y,
-# it can be overriden in subdir Makefile.objs
-obj-y-save := $(obj-y)
+all-obj-y := $(obj-y)
block-obj-y :=
common-obj-y :=
@@ -153,27 +153,16 @@ dummy := $(call unnest-vars,.., \
block-obj-m \
common-obj-y \
common-obj-m)
-
-# Now restore obj-y
-obj-y := $(obj-y-save)
-
-all-obj-y = $(obj-y) $(common-obj-y)
+all-obj-y += $(common-obj-y)
all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y)
ifndef CONFIG_HAIKU
LIBS+=-lm
endif
-ifdef QEMU_PROGW
-# The linker builds a windows executable. Make also a console executable.
-$(QEMU_PROGW): $(all-obj-y) ../libqemuutil.a ../libqemustub.a
+# build either PROG or PROGW
+$(QEMU_PROG_BUILD): $(all-obj-y) ../libqemuutil.a ../libqemustub.a
$(call LINK,$^)
-$(QEMU_PROG): $(QEMU_PROGW)
- $(call quiet-command,$(OBJCOPY) --subsystem console $(QEMU_PROGW) $(QEMU_PROG)," GEN $(TARGET_DIR)$(QEMU_PROG)")
-else
-$(QEMU_PROG): $(all-obj-y) ../libqemuutil.a ../libqemustub.a
- $(call LINK,$^)
-endif
gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh
$(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/scripts/feature_to_c.sh $@ $(TARGET_XML_FILES)," GEN $(TARGET_DIR)$@")
@@ -194,9 +183,9 @@ endif
install: all
ifneq ($(PROGS),)
- $(INSTALL) -m 755 $(PROGS) "$(DESTDIR)$(bindir)"
+ $(INSTALL_PROG) $(PROGS) "$(DESTDIR)$(bindir)"
ifneq ($(STRIP),)
- $(STRIP) $(patsubst %,"$(DESTDIR)$(bindir)/%",$(PROGS))
+ $(STRIP) $(PROGS:%="$(DESTDIR)$(bindir)/%")
endif
endif
ifdef CONFIG_TRACE_SYSTEMTAP
diff --git a/audio/Makefile.objs b/audio/Makefile.objs
index d71a877249..26a0ac9507 100644
--- a/audio/Makefile.objs
+++ b/audio/Makefile.objs
@@ -14,4 +14,4 @@ common-obj-$(CONFIG_AUDIO_WIN_INT) += audio_win_int.o
common-obj-y += wavcapture.o
$(obj)/audio.o $(obj)/fmodaudio.o: QEMU_CFLAGS += $(FMOD_CFLAGS)
-$(obj)/sdlaudio.o: QEMU_CFLAGS += $(SDL_CFLAGS)
+sdlaudio.o-cflags := $(SDL_CFLAGS)
diff --git a/backends/Makefile.objs b/backends/Makefile.objs
index 42557d54ea..591ddcf6f3 100644
--- a/backends/Makefile.objs
+++ b/backends/Makefile.objs
@@ -3,6 +3,6 @@ common-obj-$(CONFIG_POSIX) += rng-random.o
common-obj-y += msmouse.o
common-obj-$(CONFIG_BRLAPI) += baum.o
-$(obj)/baum.o: QEMU_CFLAGS += $(SDL_CFLAGS)
+baum.o-cflags := $(SDL_CFLAGS)
common-obj-$(CONFIG_TPM) += tpm.o
diff --git a/block.c b/block.c
index b749d31ad4..c90c71aa32 100644
--- a/block.c
+++ b/block.c
@@ -775,6 +775,16 @@ void bdrv_disable_copy_on_read(BlockDriverState *bs)
}
/*
+ * Returns the flags that a temporary snapshot should get, based on the
+ * originally requested flags (the originally requested image will have flags
+ * like a backing file)
+ */
+static int bdrv_temp_snapshot_flags(int flags)
+{
+ return (flags & ~BDRV_O_SNAPSHOT) | BDRV_O_TEMPORARY;
+}
+
+/*
* Returns the flags that bs->file should get, based on the given flags for
* the parent BDS
*/
@@ -787,11 +797,6 @@ static int bdrv_inherited_flags(int flags)
* so we can enable both unconditionally on lower layers. */
flags |= BDRV_O_CACHE_WB | BDRV_O_UNMAP;
- /* The backing file of a temporary snapshot is read-only */
- if (flags & BDRV_O_SNAPSHOT) {
- flags &= ~BDRV_O_RDWR;
- }
-
/* Clear flags that only apply to the top layer */
flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | BDRV_O_COPY_ON_READ);
@@ -817,11 +822,6 @@ static int bdrv_open_flags(BlockDriverState *bs, int flags)
{
int open_flags = flags | BDRV_O_CACHE_WB;
- /* The backing file of a temporary snapshot is read-only */
- if (flags & BDRV_O_SNAPSHOT) {
- open_flags &= ~BDRV_O_RDWR;
- }
-
/*
* Clear flags that are internal to the block layer before opening the
* image.
@@ -1206,7 +1206,7 @@ done:
return ret;
}
-void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp)
+void bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp)
{
/* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
char *tmp_filename = g_malloc0(PATH_MAX + 1);
@@ -1262,8 +1262,7 @@ void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp)
bs_snapshot = bdrv_new("", &error_abort);
ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options,
- (bs->open_flags & ~BDRV_O_SNAPSHOT) | BDRV_O_TEMPORARY,
- bdrv_qcow2, &local_err);
+ flags, bdrv_qcow2, &local_err);
if (ret < 0) {
error_propagate(errp, local_err);
goto out;
@@ -1298,6 +1297,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
BlockDriverState *file = NULL, *bs;
const char *drvname;
Error *local_err = NULL;
+ int snapshot_flags = 0;
assert(pbs);
@@ -1358,6 +1358,10 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
if (flags & BDRV_O_RDWR) {
flags |= BDRV_O_ALLOW_RDWR;
}
+ if (flags & BDRV_O_SNAPSHOT) {
+ snapshot_flags = bdrv_temp_snapshot_flags(flags);
+ flags = bdrv_backing_flags(flags);
+ }
assert(file == NULL);
ret = bdrv_open_image(&file, filename, options, "file",
@@ -1417,8 +1421,8 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
/* For snapshot=on, create a temporary qcow2 overlay. bs points to the
* temporary snapshot afterwards. */
- if (flags & BDRV_O_SNAPSHOT) {
- bdrv_append_temp_snapshot(bs, &local_err);
+ if (snapshot_flags) {
+ bdrv_append_temp_snapshot(bs, snapshot_flags, &local_err);
if (local_err) {
error_propagate(errp, local_err);
goto close_and_fail;
diff --git a/block/gluster.c b/block/gluster.c
index 8836085646..d0726ec92c 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -207,6 +207,11 @@ static struct glfs *qemu_gluster_init(GlusterConf *gconf, const char *filename,
"volume=%s image=%s transport=%s", gconf->server,
gconf->port, gconf->volname, gconf->image,
gconf->transport);
+
+ /* glfs_init sometimes doesn't set errno although docs suggest that */
+ if (errno == 0)
+ errno = EINVAL;
+
goto out;
}
return glfs;
@@ -482,7 +487,7 @@ static int qemu_gluster_create(const char *filename,
glfs = qemu_gluster_init(gconf, filename, errp);
if (!glfs) {
- ret = -EINVAL;
+ ret = -errno;
goto out;
}
diff --git a/block/iscsi.c b/block/iscsi.c
index a30202b4fe..52355b8bce 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -2,7 +2,7 @@
* QEMU Block driver for iSCSI images
*
* Copyright (c) 2010-2011 Ronnie Sahlberg <ronniesahlberg@gmail.com>
- * Copyright (c) 2012-2013 Peter Lieven <pl@kamp.de>
+ * Copyright (c) 2012-2014 Peter Lieven <pl@kamp.de>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/block/nfs.c b/block/nfs.c
index 9fa831f160..539bd951df 100644
--- a/block/nfs.c
+++ b/block/nfs.c
@@ -256,6 +256,10 @@ static int64_t nfs_client_open(NFSClient *client, const char *filename,
error_setg(errp, "Invalid URL specified");
goto fail;
}
+ if (!uri->server) {
+ error_setg(errp, "Invalid URL specified");
+ goto fail;
+ }
strp = strrchr(uri->path, '/');
if (strp == NULL) {
error_setg(errp, "Invalid URL specified");
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index e79895d11d..9507aef847 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -656,7 +656,9 @@ retry:
/* Make sure that all offsets in the "allocated" range are representable
* in an int64_t */
- if (s->free_cluster_index - 1 > (INT64_MAX >> s->cluster_bits)) {
+ if (s->free_cluster_index > 0 &&
+ s->free_cluster_index - 1 > (INT64_MAX >> s->cluster_bits))
+ {
return -EFBIG;
}
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 3ce026db58..6586a0c9e1 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -146,6 +146,9 @@ typedef struct BDRVRawState {
bool has_discard:1;
bool has_write_zeroes:1;
bool discard_zeroes:1;
+#ifdef CONFIG_FIEMAP
+ bool skip_fiemap;
+#endif
} BDRVRawState;
typedef struct BDRVRawReopenState {
@@ -1272,53 +1275,29 @@ static int raw_create(const char *filename, QEMUOptionParameter *options,
return result;
}
-/*
- * Returns true iff the specified sector is present in the disk image. Drivers
- * not implementing the functionality are assumed to not support backing files,
- * hence all their sectors are reported as allocated.
- *
- * If 'sector_num' is beyond the end of the disk image the return value is 0
- * and 'pnum' is set to 0.
- *
- * 'pnum' is set to the number of sectors (including and immediately following
- * the specified sector) that are known to be in the same
- * allocated/unallocated state.
- *
- * 'nb_sectors' is the max value 'pnum' should be set to. If nb_sectors goes
- * beyond the end of the disk image it will be clamped.
- */
-static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
- int64_t sector_num,
- int nb_sectors, int *pnum)
+static int64_t try_fiemap(BlockDriverState *bs, off_t start, off_t *data,
+ off_t *hole, int nb_sectors, int *pnum)
{
- off_t start, data, hole;
- int64_t ret;
-
- ret = fd_open(bs);
- if (ret < 0) {
- return ret;
- }
-
- start = sector_num * BDRV_SECTOR_SIZE;
- ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start;
-
#ifdef CONFIG_FIEMAP
-
BDRVRawState *s = bs->opaque;
+ int64_t ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start;
struct {
struct fiemap fm;
struct fiemap_extent fe;
} f;
+ if (s->skip_fiemap) {
+ return -ENOTSUP;
+ }
+
f.fm.fm_start = start;
f.fm.fm_length = (int64_t)nb_sectors * BDRV_SECTOR_SIZE;
f.fm.fm_flags = 0;
f.fm.fm_extent_count = 1;
f.fm.fm_reserved = 0;
if (ioctl(s->fd, FS_IOC_FIEMAP, &f) == -1) {
- /* Assume everything is allocated. */
- *pnum = nb_sectors;
- return ret;
+ s->skip_fiemap = true;
+ return -errno;
}
if (f.fm.fm_mapped_extents == 0) {
@@ -1326,44 +1305,92 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
* f.fm.fm_start + f.fm.fm_length must be clamped to the file size!
*/
off_t length = lseek(s->fd, 0, SEEK_END);
- hole = f.fm.fm_start;
- data = MIN(f.fm.fm_start + f.fm.fm_length, length);
+ *hole = f.fm.fm_start;
+ *data = MIN(f.fm.fm_start + f.fm.fm_length, length);
} else {
- data = f.fe.fe_logical;
- hole = f.fe.fe_logical + f.fe.fe_length;
+ *data = f.fe.fe_logical;
+ *hole = f.fe.fe_logical + f.fe.fe_length;
if (f.fe.fe_flags & FIEMAP_EXTENT_UNWRITTEN) {
ret |= BDRV_BLOCK_ZERO;
}
}
-#elif defined SEEK_HOLE && defined SEEK_DATA
+ return ret;
+#else
+ return -ENOTSUP;
+#endif
+}
+static int64_t try_seek_hole(BlockDriverState *bs, off_t start, off_t *data,
+ off_t *hole, int *pnum)
+{
+#if defined SEEK_HOLE && defined SEEK_DATA
BDRVRawState *s = bs->opaque;
- hole = lseek(s->fd, start, SEEK_HOLE);
- if (hole == -1) {
+ *hole = lseek(s->fd, start, SEEK_HOLE);
+ if (*hole == -1) {
/* -ENXIO indicates that sector_num was past the end of the file.
* There is a virtual hole there. */
assert(errno != -ENXIO);
- /* Most likely EINVAL. Assume everything is allocated. */
- *pnum = nb_sectors;
- return ret;
+ return -errno;
}
- if (hole > start) {
- data = start;
+ if (*hole > start) {
+ *data = start;
} else {
/* On a hole. We need another syscall to find its end. */
- data = lseek(s->fd, start, SEEK_DATA);
- if (data == -1) {
- data = lseek(s->fd, 0, SEEK_END);
+ *data = lseek(s->fd, start, SEEK_DATA);
+ if (*data == -1) {
+ *data = lseek(s->fd, 0, SEEK_END);
}
}
+
+ return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start;
#else
- data = 0;
- hole = start + nb_sectors * BDRV_SECTOR_SIZE;
+ return -ENOTSUP;
#endif
+}
+
+/*
+ * Returns true iff the specified sector is present in the disk image. Drivers
+ * not implementing the functionality are assumed to not support backing files,
+ * hence all their sectors are reported as allocated.
+ *
+ * If 'sector_num' is beyond the end of the disk image the return value is 0
+ * and 'pnum' is set to 0.
+ *
+ * 'pnum' is set to the number of sectors (including and immediately following
+ * the specified sector) that are known to be in the same
+ * allocated/unallocated state.
+ *
+ * 'nb_sectors' is the max value 'pnum' should be set to. If nb_sectors goes
+ * beyond the end of the disk image it will be clamped.
+ */
+static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
+ int64_t sector_num,
+ int nb_sectors, int *pnum)
+{
+ off_t start, data = 0, hole = 0;
+ int64_t ret;
+
+ ret = fd_open(bs);
+ if (ret < 0) {
+ return ret;
+ }
+
+ start = sector_num * BDRV_SECTOR_SIZE;
+
+ ret = try_fiemap(bs, start, &data, &hole, nb_sectors, pnum);
+ if (ret < 0) {
+ ret = try_seek_hole(bs, start, &data, &hole, pnum);
+ if (ret < 0) {
+ /* Assume everything is allocated. */
+ data = 0;
+ hole = start + nb_sectors * BDRV_SECTOR_SIZE;
+ ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start;
+ }
+ }
if (data <= start) {
/* On a data extent, compute sectors to the end of the extent. */
diff --git a/block/vmdk.c b/block/vmdk.c
index 06a1f9f93b..480ea37d7c 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1496,6 +1496,19 @@ static coroutine_fn int vmdk_co_write(BlockDriverState *bs, int64_t sector_num,
return ret;
}
+static int vmdk_write_compressed(BlockDriverState *bs,
+ int64_t sector_num,
+ const uint8_t *buf,
+ int nb_sectors)
+{
+ BDRVVmdkState *s = bs->opaque;
+ if (s->num_extents == 1 && s->extents[0].compressed) {
+ return vmdk_write(bs, sector_num, buf, nb_sectors, false, false);
+ } else {
+ return -ENOTSUP;
+ }
+}
+
static int coroutine_fn vmdk_co_write_zeroes(BlockDriverState *bs,
int64_t sector_num,
int nb_sectors,
@@ -2063,6 +2076,26 @@ static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs)
return spec_info;
}
+static int vmdk_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
+{
+ int i;
+ BDRVVmdkState *s = bs->opaque;
+ assert(s->num_extents);
+ bdi->needs_compressed_writes = s->extents[0].compressed;
+ if (!s->extents[0].flat) {
+ bdi->cluster_size = s->extents[0].cluster_sectors << BDRV_SECTOR_BITS;
+ }
+ /* See if we have multiple extents but they have different cases */
+ for (i = 1; i < s->num_extents; i++) {
+ if (bdi->needs_compressed_writes != s->extents[i].compressed ||
+ (bdi->cluster_size && bdi->cluster_size !=
+ s->extents[i].cluster_sectors << BDRV_SECTOR_BITS)) {
+ return -ENOTSUP;
+ }
+ }
+ return 0;
+}
+
static QEMUOptionParameter vmdk_create_options[] = {
{
.name = BLOCK_OPT_SIZE,
@@ -2109,6 +2142,7 @@ static BlockDriver bdrv_vmdk = {
.bdrv_reopen_prepare = vmdk_reopen_prepare,
.bdrv_read = vmdk_co_read,
.bdrv_write = vmdk_co_write,
+ .bdrv_write_compressed = vmdk_write_compressed,
.bdrv_co_write_zeroes = vmdk_co_write_zeroes,
.bdrv_close = vmdk_close,
.bdrv_create = vmdk_create,
@@ -2118,6 +2152,7 @@ static BlockDriver bdrv_vmdk = {
.bdrv_has_zero_init = vmdk_has_zero_init,
.bdrv_get_specific_info = vmdk_get_specific_info,
.bdrv_refresh_limits = vmdk_refresh_limits,
+ .bdrv_get_info = vmdk_get_info,
.create_options = vmdk_create_options,
};
diff --git a/bsd-user/main.c b/bsd-user/main.c
index f81ba55af8..0f9169d6dd 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -43,7 +43,7 @@ unsigned long reserved_va;
#endif
static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
-const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
+const char *qemu_uname_release;
extern char **environ;
enum BSDType bsd_type;
diff --git a/configure b/configure
index 46bc0c91f4..e565e59f04 100755
--- a/configure
+++ b/configure
@@ -3470,10 +3470,10 @@ if test "$smartcard_nss" != "no"; then
#include <pk11pub.h>
int main(void) { PK11_FreeSlot(0); return 0; }
EOF
- smartcard_includes="-I\$(SRC_PATH)/libcacard"
- libcacard_libs="$($pkg_config --libs nss 2>/dev/null) $glib_libs"
- libcacard_cflags="$($pkg_config --cflags nss 2>/dev/null) $glib_cflags"
- test_cflags="$libcacard_cflags"
+ # FIXME: do not include $glib_* in here
+ nss_libs="$($pkg_config --libs nss 2>/dev/null) $glib_libs"
+ nss_cflags="$($pkg_config --cflags nss 2>/dev/null) $glib_cflags"
+ test_cflags="$nss_cflags"
# The header files in nss < 3.13.3 have a bug which causes them to
# emit a warning. If we're going to compile QEMU with -Werror, then
# test that the headers don't have this bug. Otherwise we would pass
@@ -3483,11 +3483,8 @@ EOF
fi
if test -n "$libtool" &&
$pkg_config --atleast-version=3.12.8 nss && \
- compile_prog "$test_cflags" "$libcacard_libs"; then
+ compile_prog "$test_cflags" "$nss_libs"; then
smartcard_nss="yes"
- QEMU_CFLAGS="$QEMU_CFLAGS $libcacard_cflags"
- QEMU_INCLUDES="$QEMU_INCLUDES $smartcard_includes"
- libs_softmmu="$libcacard_libs $libs_softmmu"
else
if test "$smartcard_nss" = "yes"; then
feature_not_found "nss"
@@ -4501,8 +4498,8 @@ fi
if test "$smartcard_nss" = "yes" ; then
echo "CONFIG_SMARTCARD_NSS=y" >> $config_host_mak
- echo "libcacard_libs=$libcacard_libs" >> $config_host_mak
- echo "libcacard_cflags=$libcacard_cflags" >> $config_host_mak
+ echo "NSS_LIBS=$nss_libs" >> $config_host_mak
+ echo "NSS_CFLAGS=$nss_cflags" >> $config_host_mak
fi
if test "$libusb" = "yes" ; then
diff --git a/disas/Makefile.objs b/disas/Makefile.objs
index 41c237424a..8dae4daec0 100644
--- a/disas/Makefile.objs
+++ b/disas/Makefile.objs
@@ -4,7 +4,7 @@ common-obj-$(CONFIG_ARM_DIS) += arm.o
common-obj-$(CONFIG_ARM_A64_DIS) += arm-a64.o
common-obj-$(CONFIG_ARM_A64_DIS) += libvixl/
libvixldir = $(SRC_PATH)/disas/libvixl
-$(obj)/arm-a64.o: QEMU_CFLAGS += -I$(libvixldir)
+arm-a64.o-cflags := -I$(libvixldir)
common-obj-$(CONFIG_CRIS_DIS) += cris.o
common-obj-$(CONFIG_HPPA_DIS) += hppa.o
common-obj-$(CONFIG_I386_DIS) += i386.o
diff --git a/hw/intc/xilinx_intc.c b/hw/intc/xilinx_intc.c
index 1b228ff4e0..c3682f1b20 100644
--- a/hw/intc/xilinx_intc.c
+++ b/hw/intc/xilinx_intc.c
@@ -121,6 +121,9 @@ pic_write(void *opaque, hwaddr addr,
case R_CIE:
p->regs[R_IER] &= ~value; /* Atomic clear ie. */
break;
+ case R_MER:
+ p->regs[R_MER] = value & 0x3;
+ break;
case R_ISR:
if ((p->regs[R_MER] & 2)) {
break;
diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c
index 48d9e7afa4..6bf36d046f 100644
--- a/hw/microblaze/boot.c
+++ b/hw/microblaze/boot.c
@@ -148,7 +148,7 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
big_endian, ELF_MACHINE, 0);
}
/* Always boot into physical ram. */
- boot_info.bootstrap_pc = ddr_base + (entry & 0x0fffffff);
+ boot_info.bootstrap_pc = (uint32_t)entry;
/* If it wasn't an ELF image, try an u-boot image. */
if (kernel_size < 0) {
@@ -174,9 +174,15 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
high = ROUND_UP(high + kernel_size, 4);
boot_info.initrd_start = high;
initrd_offset = boot_info.initrd_start - ddr_base;
- initrd_size = load_image_targphys(initrd_filename,
- boot_info.initrd_start,
- ram_size - initrd_offset);
+
+ initrd_size = load_ramdisk(initrd_filename,
+ boot_info.initrd_start,
+ ram_size - initrd_offset);
+ if (initrd_size < 0) {
+ initrd_size = load_image_targphys(initrd_filename,
+ boot_info.initrd_start,
+ ram_size - initrd_offset);
+ }
if (initrd_size < 0) {
error_report("qemu: could not load initrd '%s'\n",
initrd_filename);
diff --git a/hw/timer/xilinx_timer.c b/hw/timer/xilinx_timer.c
index 6113b975bf..3ff1da9caf 100644
--- a/hw/timer/xilinx_timer.c
+++ b/hw/timer/xilinx_timer.c
@@ -169,7 +169,7 @@ timer_write(void *opaque, hwaddr addr,
if (value & TCSR_TINT)
value &= ~TCSR_TINT;
- xt->regs[addr] = value;
+ xt->regs[addr] = value & 0x7ff;
if (value & TCSR_ENT)
timer_enable(xt);
break;
diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs
index 17d460cb04..3fe4dff3bd 100644
--- a/hw/usb/Makefile.objs
+++ b/hw/usb/Makefile.objs
@@ -24,6 +24,7 @@ ifeq ($(CONFIG_USB_SMARTCARD),y)
common-obj-y += dev-smartcard-reader.o
common-obj-y += ccid-card-passthru.o
common-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
+ccid-card-emulated.o-cflags := -I$(SRC_PATH)/libcacard
endif
ifeq ($(CONFIG_POSIX),y)
diff --git a/include/block/block.h b/include/block/block.h
index 467fb2ba0a..1b119aac24 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -34,6 +34,10 @@ typedef struct BlockDriverInfo {
* opened with BDRV_O_UNMAP flag for this to work.
*/
bool can_write_zeroes_with_unmap;
+ /*
+ * True if this block driver only supports compressed writes
+ */
+ bool needs_compressed_writes;
} BlockDriverInfo;
typedef struct BlockFragInfo {
@@ -191,7 +195,7 @@ int bdrv_open_image(BlockDriverState **pbs, const char *filename,
QDict *options, const char *bdref_key, int flags,
bool allow_none, Error **errp);
int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp);
-void bdrv_append_temp_snapshot(BlockDriverState *bs, Error **errp);
+void bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp);
int bdrv_open(BlockDriverState **pbs, const char *filename,
const char *reference, QDict *options, int flags,
BlockDriver *drv, Error **errp);
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index f9ac332f9d..444b4d9a1d 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -145,7 +145,7 @@ struct TranslationBlock {
#define CF_COUNT_MASK 0x7fff
#define CF_LAST_IO 0x8000 /* Last insn may be an IO access. */
- uint8_t *tc_ptr; /* pointer to the translated code */
+ void *tc_ptr; /* pointer to the translated code */
/* next matching tb for physical address. */
struct TranslationBlock *phys_hash_next;
/* first and second physical page containing code. The lower bit
@@ -229,7 +229,7 @@ void ppc_tb_set_jmp_target(unsigned long jmp_addr, unsigned long addr);
static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
{
/* patch the branch destination */
- *(uint32_t *)jmp_addr = addr - (jmp_addr + 4);
+ stl_le_p((void*)jmp_addr, addr - (jmp_addr + 4));
/* no need to flush icache explicitly */
}
#elif defined(__aarch64__)
diff --git a/include/glib-compat.h b/include/glib-compat.h
index 8d25900700..1280fb2c1f 100644
--- a/include/glib-compat.h
+++ b/include/glib-compat.h
@@ -24,7 +24,14 @@ static inline guint g_timeout_add_seconds(guint interval, GSourceFunc function,
}
#endif
-#if !GLIB_CHECK_VERSION(2, 20, 0)
+#ifdef _WIN32
+/*
+ * g_poll has a problem on Windows when using
+ * timeouts < 10ms, so use wrapper.
+ */
+#define g_poll(fds, nfds, timeout) g_poll_fixed(fds, nfds, timeout)
+gint g_poll_fixed(GPollFD *fds, guint nfds, gint timeout);
+#elif !GLIB_CHECK_VERSION(2, 20, 0)
/*
* Glib before 2.20.0 doesn't implement g_poll, so wrap it to compile properly
* on older systems.
diff --git a/libcacard/Makefile b/libcacard/Makefile
index 6b064485fa..881b222f93 100644
--- a/libcacard/Makefile
+++ b/libcacard/Makefile
@@ -25,7 +25,6 @@ vscclient$(EXESUF): libcacard/vscclient.o libcacard.la
libcacard.la: LDFLAGS += -rpath $(libdir) -no-undefined \
-export-syms $(SRC_PATH)/libcacard/libcacard.syms
-libcacard.la: LIBS = $(libcacard_libs)
libcacard.la: $(libcacard-lobj-y)
$(call LINK,$^)
diff --git a/qemu-img.c b/qemu-img.c
index 96f44638b7..04ce02aeb4 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -32,6 +32,7 @@
#include "block/block_int.h"
#include "block/qapi.h"
#include <getopt.h>
+#include <glib.h>
#define QEMU_IMG_VERSION "qemu-img version " QEMU_VERSION \
", Copyright (c) 2004-2008 Fabrice Bellard\n"
@@ -55,9 +56,25 @@ typedef enum OutputFormat {
#define BDRV_O_FLAGS BDRV_O_CACHE_WB
#define BDRV_DEFAULT_CACHE "writeback"
-static void format_print(void *opaque, const char *name)
+static gint compare_data(gconstpointer a, gconstpointer b, gpointer user)
{
- printf(" %s", name);
+ return g_strcmp0(a, b);
+}
+
+static void print_format(gpointer data, gpointer user)
+{
+ printf(" %s", (char *)data);
+}
+
+static void add_format_to_seq(void *opaque, const char *fmt_name)
+{
+ GSequence *seq = opaque;
+
+ if (!g_sequence_lookup(seq, (gpointer)fmt_name,
+ compare_data, NULL)) {
+ g_sequence_insert_sorted(seq, (gpointer)fmt_name,
+ compare_data, NULL);
+ }
}
static void QEMU_NORETURN GCC_FMT_ATTR(1, 2) error_exit(const char *fmt, ...)
@@ -142,10 +159,15 @@ static void QEMU_NORETURN help(void)
" '-f' first image format\n"
" '-F' second image format\n"
" '-s' run in Strict mode - fail on different image size or sector allocation\n";
+ GSequence *seq;
printf("%s\nSupported formats:", help_msg);
- bdrv_iterate_format(format_print, NULL);
+ seq = g_sequence_new(NULL);
+ bdrv_iterate_format(add_format_to_seq, seq);
+ g_sequence_foreach(seq, print_format, NULL);
printf("\n");
+ g_sequence_free(seq);
+
exit(EXIT_SUCCESS);
}
@@ -1480,6 +1502,7 @@ static int img_convert(int argc, char **argv)
goto out;
}
} else {
+ compress = compress || bdi.needs_compressed_writes;
cluster_sectors = bdi.cluster_size / BDRV_SECTOR_SIZE;
}
diff --git a/qemu-timer.c b/qemu-timer.c
index 9be1a4131d..00a5d35c3f 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -126,6 +126,9 @@ static void qemu_clock_init(QEMUClockType type)
{
QEMUClock *clock = qemu_clock_ptr(type);
+ /* Assert that the clock of type TYPE has not been initialized yet. */
+ assert(main_loop_tlg.tl[type] == NULL);
+
clock->type = type;
clock->enabled = true;
clock->last = INT64_MIN;
diff --git a/rules.mak b/rules.mak
index 5c454d80d5..b12d3125d3 100644
--- a/rules.mak
+++ b/rules.mak
@@ -45,7 +45,7 @@ LINK = $(call quiet-command,$(LINKPROG) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $
else
LIBTOOL += $(if $(V),,--quiet)
%.lo: %.c
- $(call quiet-command,$(LIBTOOL) --mode=compile --tag=CC $(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," lt CC $@")
+ $(call quiet-command,$(LIBTOOL) --mode=compile --tag=CC $(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($*.o-cflags) -c -o $@ $<," lt CC $@")
%.lo: %.rc
$(call quiet-command,$(LIBTOOL) --mode=compile --tag=RC $(WINDRES) -I. -o $@ $<,"lt RC $(TARGET_DIR)$@")
%.lo: %.dtrace
@@ -57,7 +57,7 @@ LINK = $(call quiet-command,\
$(call expand-objs,$1) \
$(if $(filter %.lo %.la,$1),$(version-lobj-y),$(version-obj-y)) \
$(if $(filter %.lo %.la,$1),$(LIBTOOLFLAGS)) \
- $(call extract-libs,$1) $(LIBS),$(if $(filter %.lo %.la,$1),"lt LINK ", " LINK ")"$(TARGET_DIR)$@")
+ $(call extract-libs,$(1:.lo=.o)) $(LIBS),$(if $(filter %.lo %.la,$1),"lt LINK ", " LINK ")"$(TARGET_DIR)$@")
endif
%.asm: %.S
@@ -67,13 +67,13 @@ endif
$(call quiet-command,$(AS) $(ASFLAGS) -o $@ $<," AS $(TARGET_DIR)$@")
%.o: %.cc
- $(call quiet-command,$(CXX) $(QEMU_INCLUDES) $(QEMU_CXXFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," CXX $(TARGET_DIR)$@")
+ $(call quiet-command,$(CXX) $(QEMU_INCLUDES) $(QEMU_CXXFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) -c -o $@ $<," CXX $(TARGET_DIR)$@")
%.o: %.cpp
- $(call quiet-command,$(CXX) $(QEMU_INCLUDES) $(QEMU_CXXFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," CXX $(TARGET_DIR)$@")
+ $(call quiet-command,$(CXX) $(QEMU_INCLUDES) $(QEMU_CXXFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) -c -o $@ $<," CXX $(TARGET_DIR)$@")
%.o: %.m
- $(call quiet-command,$(OBJCC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," OBJC $(TARGET_DIR)$@")
+ $(call quiet-command,$(OBJCC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) -c -o $@ $<," OBJC $(TARGET_DIR)$@")
%.o: %.dtrace
$(call quiet-command,dtrace -o $@ -G -s $<, " GEN $(TARGET_DIR)$@")
@@ -175,16 +175,16 @@ $(eval save-$2-$1 :=)
endef
define fix-obj-vars
-$(foreach v,$($1), \
+$(if $2, $(foreach v,$($1), \
$(if $($v-cflags), \
- $(eval $2$v-cflags := $($v-cflags)) \
+ $(eval $2/$v-cflags := $($v-cflags)) \
$(eval $v-cflags := )) \
$(if $($v-libs), \
- $(eval $2$v-libs := $($v-libs)) \
+ $(eval $2/$v-libs := $($v-libs)) \
$(eval $v-libs := )) \
$(if $($v-objs), \
- $(eval $2$v-objs := $(addprefix $2,$($v-objs))) \
- $(eval $v-objs := )))
+ $(eval $2/$v-objs := $(addprefix $2/,$($v-objs))) \
+ $(eval $v-objs := ))))
endef
define unnest-dir
@@ -192,7 +192,7 @@ $(foreach var,$(nested-vars),$(call push-var,$(var),$1/))
$(eval obj-parent-$1 := $(obj))
$(eval obj := $(if $(obj),$(obj)/$1,$1))
$(eval include $(SRC_PATH)/$1/Makefile.objs)
-$(foreach v,$(nested-vars),$(call fix-obj-vars,$v,$(if $(obj),$(obj)/)))
+$(foreach v,$(nested-vars),$(call fix-obj-vars,$v,$(obj)))
$(eval obj := $(obj-parent-$1))
$(eval obj-parent-$1 := )
$(foreach var,$(nested-vars),$(call pop-var,$(var),$1/))
@@ -228,6 +228,7 @@ endef
define unnest-vars
$(eval obj := $1)
$(eval nested-vars := $2)
+$(foreach v,$(nested-vars),$(call fix-obj-vars,$v,$(obj)))
$(eval old-nested-dirs := )
$(call unnest-vars-1)
$(if $1,$(foreach v,$(nested-vars),$(eval \
diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c
index 8e0481186a..0379f2be2c 100644
--- a/target-microblaze/cpu.c
+++ b/target-microblaze/cpu.c
@@ -96,6 +96,8 @@ static void mb_cpu_reset(CPUState *s)
env->pvr.regs[10] = 0x0c000000; /* Default to spartan 3a dsp family. */
env->pvr.regs[11] = PVR11_USE_MMU | (16 << 17);
+ env->sregs[SR_PC] = cpu->base_vectors;
+
#if defined(CONFIG_USER_ONLY)
/* start in user mode with interrupts enabled. */
env->sregs[SR_MSR] = MSR_EE | MSR_IE | MSR_VM | MSR_UM;
diff --git a/tcg/aarch64/tcg-target.c b/tcg/aarch64/tcg-target.c
index 0a580b65ea..77bb6d97de 100644
--- a/tcg/aarch64/tcg-target.c
+++ b/tcg/aarch64/tcg-target.c
@@ -63,40 +63,34 @@ static const int tcg_target_call_oarg_regs[1] = {
# endif
#endif
-static inline void reloc_pc26(void *code_ptr, intptr_t target)
+static inline void reloc_pc26(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
{
- intptr_t offset = (target - (intptr_t)code_ptr) / 4;
+ ptrdiff_t offset = target - code_ptr;
+ assert(offset == sextract64(offset, 0, 26));
/* read instruction, mask away previous PC_REL26 parameter contents,
set the proper offset, then write back the instruction. */
- uint32_t insn = *(uint32_t *)code_ptr;
- insn = deposit32(insn, 0, 26, offset);
- *(uint32_t *)code_ptr = insn;
+ *code_ptr = deposit32(*code_ptr, 0, 26, offset);
}
-static inline void reloc_pc19(void *code_ptr, intptr_t target)
+static inline void reloc_pc19(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
{
- intptr_t offset = (target - (intptr_t)code_ptr) / 4;
- /* read instruction, mask away previous PC_REL19 parameter contents,
- set the proper offset, then write back the instruction. */
- uint32_t insn = *(uint32_t *)code_ptr;
- insn = deposit32(insn, 5, 19, offset);
- *(uint32_t *)code_ptr = insn;
+ ptrdiff_t offset = target - code_ptr;
+ assert(offset == sextract64(offset, 0, 19));
+ *code_ptr = deposit32(*code_ptr, 5, 19, offset);
}
-static inline void patch_reloc(uint8_t *code_ptr, int type,
+static inline void patch_reloc(tcg_insn_unit *code_ptr, int type,
intptr_t value, intptr_t addend)
{
- value += addend;
-
+ assert(addend == 0);
switch (type) {
case R_AARCH64_JUMP26:
case R_AARCH64_CALL26:
- reloc_pc26(code_ptr, value);
+ reloc_pc26(code_ptr, (tcg_insn_unit *)value);
break;
case R_AARCH64_CONDBR19:
- reloc_pc19(code_ptr, value);
+ reloc_pc19(code_ptr, (tcg_insn_unit *)value);
break;
-
default:
tcg_abort();
}
@@ -794,15 +788,10 @@ static void tcg_out_cmp(TCGContext *s, TCGType ext, TCGReg a,
}
}
-static inline void tcg_out_goto(TCGContext *s, intptr_t target)
+static inline void tcg_out_goto(TCGContext *s, tcg_insn_unit *target)
{
- intptr_t offset = (target - (intptr_t)s->code_ptr) / 4;
-
- if (offset < -0x02000000 || offset >= 0x02000000) {
- /* out of 26bit range */
- tcg_abort();
- }
-
+ ptrdiff_t offset = target - s->code_ptr;
+ assert(offset == sextract64(offset, 0, 26));
tcg_out_insn(s, 3206, B, offset);
}
@@ -828,29 +817,23 @@ static inline void tcg_out_callr(TCGContext *s, TCGReg reg)
tcg_out_insn(s, 3207, BLR, reg);
}
-static inline void tcg_out_call(TCGContext *s, intptr_t target)
+static inline void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
{
- intptr_t offset = (target - (intptr_t)s->code_ptr) / 4;
-
- if (offset < -0x02000000 || offset >= 0x02000000) { /* out of 26bit rng */
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, target);
- tcg_out_callr(s, TCG_REG_TMP);
- } else {
+ ptrdiff_t offset = target - s->code_ptr;
+ if (offset == sextract64(offset, 0, 26)) {
tcg_out_insn(s, 3206, BL, offset);
+ } else {
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, (intptr_t)target);
+ tcg_out_callr(s, TCG_REG_TMP);
}
}
void aarch64_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr)
{
- intptr_t target = addr;
- intptr_t offset = (target - (intptr_t)jmp_addr) / 4;
+ tcg_insn_unit *code_ptr = (tcg_insn_unit *)jmp_addr;
+ tcg_insn_unit *target = (tcg_insn_unit *)addr;
- if (offset < -0x02000000 || offset >= 0x02000000) {
- /* out of 26bit range */
- tcg_abort();
- }
-
- patch_reloc((uint8_t *)jmp_addr, R_AARCH64_JUMP26, target, 0);
+ reloc_pc26(code_ptr, target);
flush_icache_range(jmp_addr, jmp_addr + 4);
}
@@ -862,7 +845,7 @@ static inline void tcg_out_goto_label(TCGContext *s, int label_index)
tcg_out_reloc(s, s->code_ptr, R_AARCH64_JUMP26, label_index, 0);
tcg_out_goto_noaddr(s);
} else {
- tcg_out_goto(s, l->u.value);
+ tcg_out_goto(s, l->u.value_ptr);
}
}
@@ -884,9 +867,8 @@ static void tcg_out_brcond(TCGContext *s, TCGMemOp ext, TCGCond c, TCGArg a,
tcg_out_reloc(s, s->code_ptr, R_AARCH64_CONDBR19, label, 0);
offset = tcg_in32(s) >> 5;
} else {
- offset = l->u.value - (uintptr_t)s->code_ptr;
- offset >>= 2;
- assert(offset >= -0x40000 && offset < 0x40000);
+ offset = l->u.value_ptr - s->code_ptr;
+ assert(offset == sextract64(offset, 0, 19));
}
if (need_cmp) {
@@ -982,7 +964,7 @@ static inline void tcg_out_addsub2(TCGContext *s, int ext, TCGReg rl,
/* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
* int mmu_idx, uintptr_t ra)
*/
-static const void * const qemu_ld_helpers[16] = {
+static void * const qemu_ld_helpers[16] = {
[MO_UB] = helper_ret_ldub_mmu,
[MO_LEUW] = helper_le_lduw_mmu,
[MO_LEUL] = helper_le_ldul_mmu,
@@ -995,7 +977,7 @@ static const void * const qemu_ld_helpers[16] = {
/* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
* uintxx_t val, int mmu_idx, uintptr_t ra)
*/
-static const void * const qemu_st_helpers[16] = {
+static void * const qemu_st_helpers[16] = {
[MO_UB] = helper_ret_stb_mmu,
[MO_LEUW] = helper_le_stw_mmu,
[MO_LEUL] = helper_le_stl_mmu,
@@ -1005,11 +987,11 @@ static const void * const qemu_st_helpers[16] = {
[MO_BEQ] = helper_be_stq_mmu,
};
-static inline void tcg_out_adr(TCGContext *s, TCGReg rd, uintptr_t addr)
+static inline void tcg_out_adr(TCGContext *s, TCGReg rd, void *target)
{
- addr -= (uintptr_t)s->code_ptr;
- assert(addr == sextract64(addr, 0, 21));
- tcg_out_insn(s, 3406, ADR, rd, addr);
+ ptrdiff_t offset = tcg_pcrel_diff(s, target);
+ assert(offset == sextract64(offset, 0, 21));
+ tcg_out_insn(s, 3406, ADR, rd, offset);
}
static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
@@ -1017,20 +999,20 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
TCGMemOp opc = lb->opc;
TCGMemOp size = opc & MO_SIZE;
- reloc_pc19(lb->label_ptr[0], (intptr_t)s->code_ptr);
+ reloc_pc19(lb->label_ptr[0], s->code_ptr);
tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_X0, TCG_AREG0);
tcg_out_mov(s, TARGET_LONG_BITS == 64, TCG_REG_X1, lb->addrlo_reg);
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X2, lb->mem_index);
- tcg_out_adr(s, TCG_REG_X3, (intptr_t)lb->raddr);
- tcg_out_call(s, (intptr_t)qemu_ld_helpers[opc & ~MO_SIGN]);
+ tcg_out_adr(s, TCG_REG_X3, lb->raddr);
+ tcg_out_call(s, qemu_ld_helpers[opc & ~MO_SIGN]);
if (opc & MO_SIGN) {
tcg_out_sxt(s, TCG_TYPE_I64, size, lb->datalo_reg, TCG_REG_X0);
} else {
tcg_out_mov(s, size == MO_64, lb->datalo_reg, TCG_REG_X0);
}
- tcg_out_goto(s, (intptr_t)lb->raddr);
+ tcg_out_goto(s, lb->raddr);
}
static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
@@ -1038,21 +1020,21 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
TCGMemOp opc = lb->opc;
TCGMemOp size = opc & MO_SIZE;
- reloc_pc19(lb->label_ptr[0], (intptr_t)s->code_ptr);
+ reloc_pc19(lb->label_ptr[0], s->code_ptr);
tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_X0, TCG_AREG0);
tcg_out_mov(s, TARGET_LONG_BITS == 64, TCG_REG_X1, lb->addrlo_reg);
tcg_out_mov(s, size == MO_64, TCG_REG_X2, lb->datalo_reg);
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X3, lb->mem_index);
- tcg_out_adr(s, TCG_REG_X4, (intptr_t)lb->raddr);
- tcg_out_call(s, (intptr_t)qemu_st_helpers[opc]);
- tcg_out_goto(s, (intptr_t)lb->raddr);
+ tcg_out_adr(s, TCG_REG_X4, lb->raddr);
+ tcg_out_call(s, qemu_st_helpers[opc]);
+ tcg_out_goto(s, lb->raddr);
}
static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
TCGReg data_reg, TCGReg addr_reg,
- int mem_index,
- uint8_t *raddr, uint8_t *label_ptr)
+ int mem_index, tcg_insn_unit *raddr,
+ tcg_insn_unit *label_ptr)
{
TCGLabelQemuLdst *label = new_ldst_label(s);
@@ -1070,7 +1052,8 @@ static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
the slow path. Generated code returns the host addend in X1,
clobbers X0,X2,X3,TMP. */
static void tcg_out_tlb_read(TCGContext *s, TCGReg addr_reg, TCGMemOp s_bits,
- uint8_t **label_ptr, int mem_index, bool is_read)
+ tcg_insn_unit **label_ptr, int mem_index,
+ bool is_read)
{
TCGReg base = TCG_AREG0;
int tlb_offset = is_read ?
@@ -1218,7 +1201,7 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
{
#ifdef CONFIG_SOFTMMU
TCGMemOp s_bits = memop & MO_SIZE;
- uint8_t *label_ptr;
+ tcg_insn_unit *label_ptr;
tcg_out_tlb_read(s, addr_reg, s_bits, &label_ptr, mem_index, 1);
tcg_out_qemu_ld_direct(s, memop, data_reg, addr_reg, TCG_REG_X1);
@@ -1235,7 +1218,7 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
{
#ifdef CONFIG_SOFTMMU
TCGMemOp s_bits = memop & MO_SIZE;
- uint8_t *label_ptr;
+ tcg_insn_unit *label_ptr;
tcg_out_tlb_read(s, addr_reg, s_bits, &label_ptr, mem_index, 0);
tcg_out_qemu_st_direct(s, memop, data_reg, addr_reg, TCG_REG_X1);
@@ -1247,7 +1230,7 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
#endif /* CONFIG_SOFTMMU */
}
-static uint8_t *tb_ret_addr;
+static tcg_insn_unit *tb_ret_addr;
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
const TCGArg args[TCG_MAX_OP_ARGS],
@@ -1270,7 +1253,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
switch (opc) {
case INDEX_op_exit_tb:
tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, a0);
- tcg_out_goto(s, (intptr_t)tb_ret_addr);
+ tcg_out_goto(s, tb_ret_addr);
break;
case INDEX_op_goto_tb:
@@ -1278,19 +1261,11 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
#error "USE_DIRECT_JUMP required for aarch64"
#endif
assert(s->tb_jmp_offset != NULL); /* consistency for USE_DIRECT_JUMP */
- s->tb_jmp_offset[a0] = s->code_ptr - s->code_buf;
+ s->tb_jmp_offset[a0] = tcg_current_code_size(s);
/* actual branch destination will be patched by
aarch64_tb_set_jmp_target later, beware retranslation. */
tcg_out_goto_noaddr(s);
- s->tb_next_offset[a0] = s->code_ptr - s->code_buf;
- break;
-
- case INDEX_op_call:
- if (const_args[0]) {
- tcg_out_call(s, a0);
- } else {
- tcg_out_callr(s, a0);
- }
+ s->tb_next_offset[a0] = tcg_current_code_size(s);
break;
case INDEX_op_br:
@@ -1613,13 +1588,12 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_insn(s, 3508, SMULH, TCG_TYPE_I64, a0, a1, a2);
break;
+ case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
case INDEX_op_mov_i64:
- case INDEX_op_mov_i32:
+ case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
case INDEX_op_movi_i64:
- case INDEX_op_movi_i32:
- /* Always implemented with tcg_out_mov/i, never with tcg_out_op. */
+ case INDEX_op_call: /* Always emitted via tcg_out_call. */
default:
- /* Opcode not implemented. */
tcg_abort();
}
@@ -1629,15 +1603,8 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
static const TCGTargetOpDef aarch64_op_defs[] = {
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
- { INDEX_op_call, { "ri" } },
{ INDEX_op_br, { } },
- { INDEX_op_mov_i32, { "r", "r" } },
- { INDEX_op_mov_i64, { "r", "r" } },
-
- { INDEX_op_movi_i32, { "r" } },
- { INDEX_op_movi_i64, { "r" } },
-
{ INDEX_op_ld8u_i32, { "r", "r" } },
{ INDEX_op_ld8s_i32, { "r", "r" } },
{ INDEX_op_ld16u_i32, { "r", "r" } },
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
index a1d4322165..a32aea66fa 100644
--- a/tcg/aarch64/tcg-target.h
+++ b/tcg/aarch64/tcg-target.h
@@ -13,6 +13,7 @@
#ifndef TCG_TARGET_AARCH64
#define TCG_TARGET_AARCH64 1
+#define TCG_TARGET_INSN_UNIT_SIZE 4
#undef TCG_TARGET_STACK_GROWSUP
typedef enum {
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 7535175f9c..538ca2aed0 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -115,36 +115,18 @@ static const int tcg_target_call_oarg_regs[2] = {
#define TCG_REG_TMP TCG_REG_R12
-static inline void reloc_abs32(void *code_ptr, intptr_t target)
+static inline void reloc_pc24(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
{
- *(uint32_t *) code_ptr = target;
+ ptrdiff_t offset = (tcg_ptr_byte_diff(target, code_ptr) - 8) >> 2;
+ *code_ptr = (*code_ptr & ~0xffffff) | (offset & 0xffffff);
}
-static inline void reloc_pc24(void *code_ptr, intptr_t target)
-{
- uint32_t offset = ((target - ((intptr_t)code_ptr + 8)) >> 2);
-
- *(uint32_t *) code_ptr = ((*(uint32_t *) code_ptr) & ~0xffffff)
- | (offset & 0xffffff);
-}
-
-static void patch_reloc(uint8_t *code_ptr, int type,
+static void patch_reloc(tcg_insn_unit *code_ptr, int type,
intptr_t value, intptr_t addend)
{
- switch (type) {
- case R_ARM_ABS32:
- reloc_abs32(code_ptr, value);
- break;
-
- case R_ARM_CALL:
- case R_ARM_JUMP24:
- default:
- tcg_abort();
-
- case R_ARM_PC24:
- reloc_pc24(code_ptr, value);
- break;
- }
+ assert(type == R_ARM_PC24);
+ assert(addend == 0);
+ reloc_pc24(code_ptr, (tcg_insn_unit *)value);
}
#define TCG_CT_CONST_ARM 0x100
@@ -379,20 +361,18 @@ static inline void tcg_out_b(TCGContext *s, int cond, int32_t offset)
static inline void tcg_out_b_noaddr(TCGContext *s, int cond)
{
- /* We pay attention here to not modify the branch target by skipping
- the corresponding bytes. This ensure that caches and memory are
+ /* We pay attention here to not modify the branch target by masking
+ the corresponding bytes. This ensure that caches and memory are
kept coherent during retranslation. */
- s->code_ptr += 3;
- tcg_out8(s, (cond << 4) | 0x0a);
+ tcg_out32(s, deposit32(*s->code_ptr, 24, 8, (cond << 4) | 0x0a));
}
static inline void tcg_out_bl_noaddr(TCGContext *s, int cond)
{
- /* We pay attention here to not modify the branch target by skipping
- the corresponding bytes. This ensure that caches and memory are
+ /* We pay attention here to not modify the branch target by masking
+ the corresponding bytes. This ensure that caches and memory are
kept coherent during retranslation. */
- s->code_ptr += 3;
- tcg_out8(s, (cond << 4) | 0x0b);
+ tcg_out32(s, deposit32(*s->code_ptr, 24, 8, (cond << 4) | 0x0b));
}
static inline void tcg_out_bl(TCGContext *s, int cond, int32_t offset)
@@ -1010,20 +990,21 @@ static inline void tcg_out_st8(TCGContext *s, int cond,
* with the code buffer limited to 16MB we wouldn't need the long case.
* But we also use it for the tail-call to the qemu_ld/st helpers, which does.
*/
-static inline void tcg_out_goto(TCGContext *s, int cond, uint32_t addr)
+static inline void tcg_out_goto(TCGContext *s, int cond, tcg_insn_unit *addr)
{
- int32_t disp = addr - (tcg_target_long) s->code_ptr;
+ intptr_t addri = (intptr_t)addr;
+ ptrdiff_t disp = tcg_pcrel_diff(s, addr);
- if ((addr & 1) == 0 && disp - 8 < 0x01fffffd && disp - 8 > -0x01fffffd) {
+ if ((addri & 1) == 0 && disp - 8 < 0x01fffffd && disp - 8 > -0x01fffffd) {
tcg_out_b(s, cond, disp);
return;
}
- tcg_out_movi32(s, cond, TCG_REG_TMP, addr);
+ tcg_out_movi32(s, cond, TCG_REG_TMP, addri);
if (use_armv5t_instructions) {
tcg_out_bx(s, cond, TCG_REG_TMP);
} else {
- if (addr & 1) {
+ if (addri & 1) {
tcg_abort();
}
tcg_out_mov_reg(s, cond, TCG_REG_PC, TCG_REG_TMP);
@@ -1032,39 +1013,28 @@ static inline void tcg_out_goto(TCGContext *s, int cond, uint32_t addr)
/* The call case is mostly used for helpers - so it's not unreasonable
* for them to be beyond branch range */
-static inline void tcg_out_call(TCGContext *s, uint32_t addr)
+static void tcg_out_call(TCGContext *s, tcg_insn_unit *addr)
{
- int32_t val;
+ intptr_t addri = (intptr_t)addr;
+ ptrdiff_t disp = tcg_pcrel_diff(s, addr);
- val = addr - (tcg_target_long) s->code_ptr;
- if (val - 8 < 0x02000000 && val - 8 >= -0x02000000) {
- if (addr & 1) {
+ if (disp - 8 < 0x02000000 && disp - 8 >= -0x02000000) {
+ if (addri & 1) {
/* Use BLX if the target is in Thumb mode */
if (!use_armv5t_instructions) {
tcg_abort();
}
- tcg_out_blx_imm(s, val);
+ tcg_out_blx_imm(s, disp);
} else {
- tcg_out_bl(s, COND_AL, val);
+ tcg_out_bl(s, COND_AL, disp);
}
} else if (use_armv7_instructions) {
- tcg_out_movi32(s, COND_AL, TCG_REG_TMP, addr);
+ tcg_out_movi32(s, COND_AL, TCG_REG_TMP, addri);
tcg_out_blx(s, COND_AL, TCG_REG_TMP);
} else {
tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R14, TCG_REG_PC, 4);
tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
- tcg_out32(s, addr);
- }
-}
-
-static inline void tcg_out_callr(TCGContext *s, int cond, int arg)
-{
- if (use_armv5t_instructions) {
- tcg_out_blx(s, cond, arg);
- } else {
- tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0,
- TCG_REG_PC, SHIFT_IMM_LSL(0));
- tcg_out_bx(s, cond, arg);
+ tcg_out32(s, addri);
}
}
@@ -1073,9 +1043,9 @@ static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index)
TCGLabel *l = &s->labels[label_index];
if (l->has_value) {
- tcg_out_goto(s, cond, l->u.value);
+ tcg_out_goto(s, cond, l->u.value_ptr);
} else {
- tcg_out_reloc(s, s->code_ptr, R_ARM_PC24, label_index, 31337);
+ tcg_out_reloc(s, s->code_ptr, R_ARM_PC24, label_index, 0);
tcg_out_b_noaddr(s, cond);
}
}
@@ -1084,7 +1054,7 @@ static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index)
/* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
* int mmu_idx, uintptr_t ra)
*/
-static const void * const qemu_ld_helpers[16] = {
+static void * const qemu_ld_helpers[16] = {
[MO_UB] = helper_ret_ldub_mmu,
[MO_SB] = helper_ret_ldsb_mmu,
@@ -1104,7 +1074,7 @@ static const void * const qemu_ld_helpers[16] = {
/* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
* uintxx_t val, int mmu_idx, uintptr_t ra)
*/
-static const void * const qemu_st_helpers[16] = {
+static void * const qemu_st_helpers[16] = {
[MO_UB] = helper_ret_stb_mmu,
[MO_LEUW] = helper_le_stw_mmu,
[MO_LEUL] = helper_le_stl_mmu,
@@ -1256,7 +1226,7 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
TCGReg datalo, TCGReg datahi, TCGReg addrlo,
TCGReg addrhi, int mem_index,
- uint8_t *raddr, uint8_t *label_ptr)
+ tcg_insn_unit *raddr, tcg_insn_unit *label_ptr)
{
TCGLabelQemuLdst *label = new_ldst_label(s);
@@ -1275,9 +1245,9 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
{
TCGReg argreg, datalo, datahi;
TCGMemOp opc = lb->opc;
- uintptr_t func;
+ void *func;
- reloc_pc24(lb->label_ptr[0], (tcg_target_long)s->code_ptr);
+ reloc_pc24(lb->label_ptr[0], s->code_ptr);
argreg = tcg_out_arg_reg32(s, TCG_REG_R0, TCG_AREG0);
if (TARGET_LONG_BITS == 64) {
@@ -1292,9 +1262,9 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
icache usage. For pre-armv6, use the signed helpers since we do
not have a single insn sign-extend. */
if (use_armv6_instructions) {
- func = (uintptr_t)qemu_ld_helpers[opc & ~MO_SIGN];
+ func = qemu_ld_helpers[opc & ~MO_SIGN];
} else {
- func = (uintptr_t)qemu_ld_helpers[opc];
+ func = qemu_ld_helpers[opc];
if (opc & MO_SIGN) {
opc = MO_UL;
}
@@ -1328,7 +1298,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
break;
}
- tcg_out_goto(s, COND_AL, (tcg_target_long)lb->raddr);
+ tcg_out_goto(s, COND_AL, lb->raddr);
}
static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
@@ -1336,7 +1306,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
TCGReg argreg, datalo, datahi;
TCGMemOp opc = lb->opc;
- reloc_pc24(lb->label_ptr[0], (tcg_target_long)s->code_ptr);
+ reloc_pc24(lb->label_ptr[0], s->code_ptr);
argreg = TCG_REG_R0;
argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0);
@@ -1368,7 +1338,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
argreg = tcg_out_arg_reg32(s, argreg, TCG_REG_R14);
/* Tail-call to the helper, which will return to the fast path. */
- tcg_out_goto(s, COND_AL, (uintptr_t)qemu_st_helpers[opc]);
+ tcg_out_goto(s, COND_AL, qemu_st_helpers[opc]);
}
#endif /* SOFTMMU */
@@ -1499,7 +1469,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
#ifdef CONFIG_SOFTMMU
int mem_index;
TCGReg addend;
- uint8_t *label_ptr;
+ tcg_insn_unit *label_ptr;
#endif
datalo = *args++;
@@ -1628,7 +1598,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
#ifdef CONFIG_SOFTMMU
int mem_index;
TCGReg addend;
- uint8_t *label_ptr;
+ tcg_insn_unit *label_ptr;
#endif
datalo = *args++;
@@ -1660,7 +1630,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
#endif
}
-static uint8_t *tb_ret_addr;
+static tcg_insn_unit *tb_ret_addr;
static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
const TCGArg *args, const int *const_args)
@@ -1670,51 +1640,21 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
switch (opc) {
case INDEX_op_exit_tb:
- if (use_armv7_instructions || check_fit_imm(args[0])) {
- tcg_out_movi32(s, COND_AL, TCG_REG_R0, args[0]);
- tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr);
- } else {
- uint8_t *ld_ptr = s->code_ptr;
- tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0);
- tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr);
- *ld_ptr = (uint8_t) (s->code_ptr - ld_ptr) - 8;
- tcg_out32(s, args[0]);
- }
+ tcg_out_movi32(s, COND_AL, TCG_REG_R0, args[0]);
+ tcg_out_goto(s, COND_AL, tb_ret_addr);
break;
case INDEX_op_goto_tb:
if (s->tb_jmp_offset) {
/* Direct jump method */
-#if defined(USE_DIRECT_JUMP)
- s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
+ s->tb_jmp_offset[args[0]] = tcg_current_code_size(s);
tcg_out_b_noaddr(s, COND_AL);
-#else
- tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
- s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
- tcg_out32(s, 0);
-#endif
} else {
/* Indirect jump method */
-#if 1
- c = (int) (s->tb_next + args[0]) - ((int) s->code_ptr + 8);
- if (c > 0xfff || c < -0xfff) {
- tcg_out_movi32(s, COND_AL, TCG_REG_R0,
- (tcg_target_long) (s->tb_next + args[0]));
- tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, 0);
- } else
- tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, c);
-#else
- tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0);
- tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, 0);
- tcg_out32(s, (tcg_target_long) (s->tb_next + args[0]));
-#endif
+ intptr_t ptr = (intptr_t)(s->tb_next + args[0]);
+ tcg_out_movi32(s, COND_AL, TCG_REG_R0, ptr & ~0xfff);
+ tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, ptr & 0xfff);
}
- s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
- break;
- case INDEX_op_call:
- if (const_args[0])
- tcg_out_call(s, args[0]);
- else
- tcg_out_callr(s, COND_AL, args[0]);
+ s->tb_next_offset[args[0]] = tcg_current_code_size(s);
break;
case INDEX_op_br:
tcg_out_goto_label(s, COND_AL, args[0]);
@@ -1745,13 +1685,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_st32(s, COND_AL, args[0], args[1], args[2]);
break;
- case INDEX_op_mov_i32:
- tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
- args[0], 0, args[1], SHIFT_IMM_LSL(0));
- break;
- case INDEX_op_movi_i32:
- tcg_out_movi32(s, COND_AL, args[0], args[1]);
- break;
case INDEX_op_movcond_i32:
/* Constraints mean that v2 is always in the same register as dest,
* so we only need to do "if condition passed, move v1 to dest".
@@ -1967,6 +1900,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_udiv(s, COND_AL, args[0], args[1], args[2]);
break;
+ case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
+ case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
+ case INDEX_op_call: /* Always emitted via tcg_out_call. */
default:
tcg_abort();
}
@@ -1975,12 +1911,8 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
static const TCGTargetOpDef arm_op_defs[] = {
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
- { INDEX_op_call, { "ri" } },
{ INDEX_op_br, { } },
- { INDEX_op_mov_i32, { "r", "r" } },
- { INDEX_op_movi_i32, { "r" } },
-
{ INDEX_op_ld8u_i32, { "r", "r" } },
{ INDEX_op_ld8s_i32, { "r", "r" } },
{ INDEX_op_ld16u_i32, { "r", "r" } },
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 1bc5dacec0..73f10c4424 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -26,6 +26,7 @@
#define TCG_TARGET_ARM 1
#undef TCG_TARGET_STACK_GROWSUP
+#define TCG_TARGET_INSN_UNIT_SIZE 4
typedef enum {
TCG_REG_R0 = 0,
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 34ece1f80b..a373073ff8 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -139,9 +139,9 @@ static bool have_bmi2;
# define have_bmi2 0
#endif
-static uint8_t *tb_ret_addr;
+static tcg_insn_unit *tb_ret_addr;
-static void patch_reloc(uint8_t *code_ptr, int type,
+static void patch_reloc(tcg_insn_unit *code_ptr, int type,
intptr_t value, intptr_t addend)
{
value += addend;
@@ -151,14 +151,14 @@ static void patch_reloc(uint8_t *code_ptr, int type,
if (value != (int32_t)value) {
tcg_abort();
}
- *(uint32_t *)code_ptr = value;
+ tcg_patch32(code_ptr, value);
break;
case R_386_PC8:
value -= (uintptr_t)code_ptr;
if (value != (int8_t)value) {
tcg_abort();
}
- *(uint8_t *)code_ptr = value;
+ tcg_patch8(code_ptr, value);
break;
default:
tcg_abort();
@@ -859,7 +859,7 @@ static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small)
TCGLabel *l = &s->labels[label_index];
if (l->has_value) {
- val = l->u.value - (intptr_t)s->code_ptr;
+ val = tcg_pcrel_diff(s, l->u.value_ptr);
val1 = val - 2;
if ((int8_t)val1 == val1) {
if (opc == -1) {
@@ -1099,26 +1099,26 @@ static void tcg_out_movcond64(TCGContext *s, TCGCond cond, TCGArg dest,
}
#endif
-static void tcg_out_branch(TCGContext *s, int call, uintptr_t dest)
+static void tcg_out_branch(TCGContext *s, int call, tcg_insn_unit *dest)
{
- intptr_t disp = dest - (intptr_t)s->code_ptr - 5;
+ intptr_t disp = tcg_pcrel_diff(s, dest) - 5;
if (disp == (int32_t)disp) {
tcg_out_opc(s, call ? OPC_CALL_Jz : OPC_JMP_long, 0, 0, 0);
tcg_out32(s, disp);
} else {
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R10, dest);
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R10, (uintptr_t)dest);
tcg_out_modrm(s, OPC_GRP5,
call ? EXT5_CALLN_Ev : EXT5_JMPN_Ev, TCG_REG_R10);
}
}
-static inline void tcg_out_calli(TCGContext *s, uintptr_t dest)
+static inline void tcg_out_call(TCGContext *s, tcg_insn_unit *dest)
{
tcg_out_branch(s, 1, dest);
}
-static void tcg_out_jmp(TCGContext *s, uintptr_t dest)
+static void tcg_out_jmp(TCGContext *s, tcg_insn_unit *dest)
{
tcg_out_branch(s, 0, dest);
}
@@ -1127,7 +1127,7 @@ static void tcg_out_jmp(TCGContext *s, uintptr_t dest)
/* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
* int mmu_idx, uintptr_t ra)
*/
-static const void * const qemu_ld_helpers[16] = {
+static void * const qemu_ld_helpers[16] = {
[MO_UB] = helper_ret_ldub_mmu,
[MO_LEUW] = helper_le_lduw_mmu,
[MO_LEUL] = helper_le_ldul_mmu,
@@ -1140,7 +1140,7 @@ static const void * const qemu_ld_helpers[16] = {
/* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
* uintxx_t val, int mmu_idx, uintptr_t ra)
*/
-static const void * const qemu_st_helpers[16] = {
+static void * const qemu_st_helpers[16] = {
[MO_UB] = helper_ret_stb_mmu,
[MO_LEUW] = helper_le_stw_mmu,
[MO_LEUL] = helper_le_stl_mmu,
@@ -1173,7 +1173,7 @@ static const void * const qemu_st_helpers[16] = {
static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
int mem_index, TCGMemOp s_bits,
- uint8_t **label_ptr, int which)
+ tcg_insn_unit **label_ptr, int which)
{
const TCGReg r0 = TCG_REG_L0;
const TCGReg r1 = TCG_REG_L1;
@@ -1247,8 +1247,8 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
TCGReg datalo, TCGReg datahi,
TCGReg addrlo, TCGReg addrhi,
- int mem_index, uint8_t *raddr,
- uint8_t **label_ptr)
+ int mem_index, tcg_insn_unit *raddr,
+ tcg_insn_unit **label_ptr)
{
TCGLabelQemuLdst *label = new_ldst_label(s);
@@ -1273,12 +1273,12 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
{
TCGMemOp opc = l->opc;
TCGReg data_reg;
- uint8_t **label_ptr = &l->label_ptr[0];
+ tcg_insn_unit **label_ptr = &l->label_ptr[0];
/* resolve label address */
- *(uint32_t *)label_ptr[0] = (uint32_t)(s->code_ptr - label_ptr[0] - 4);
+ tcg_patch32(label_ptr[0], s->code_ptr - label_ptr[0] - 4);
if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
- *(uint32_t *)label_ptr[1] = (uint32_t)(s->code_ptr - label_ptr[1] - 4);
+ tcg_patch32(label_ptr[1], s->code_ptr - label_ptr[1] - 4);
}
if (TCG_TARGET_REG_BITS == 32) {
@@ -1308,7 +1308,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
(uintptr_t)l->raddr);
}
- tcg_out_calli(s, (uintptr_t)qemu_ld_helpers[opc & ~MO_SIGN]);
+ tcg_out_call(s, qemu_ld_helpers[opc & ~MO_SIGN]);
data_reg = l->datalo_reg;
switch (opc & MO_SSIZE) {
@@ -1346,7 +1346,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
}
/* Jump to the code corresponding to next IR of qemu_st */
- tcg_out_jmp(s, (uintptr_t)l->raddr);
+ tcg_out_jmp(s, l->raddr);
}
/*
@@ -1356,13 +1356,13 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
{
TCGMemOp opc = l->opc;
TCGMemOp s_bits = opc & MO_SIZE;
- uint8_t **label_ptr = &l->label_ptr[0];
+ tcg_insn_unit **label_ptr = &l->label_ptr[0];
TCGReg retaddr;
/* resolve label address */
- *(uint32_t *)label_ptr[0] = (uint32_t)(s->code_ptr - label_ptr[0] - 4);
+ tcg_patch32(label_ptr[0], s->code_ptr - label_ptr[0] - 4);
if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
- *(uint32_t *)label_ptr[1] = (uint32_t)(s->code_ptr - label_ptr[1] - 4);
+ tcg_patch32(label_ptr[1], s->code_ptr - label_ptr[1] - 4);
}
if (TCG_TARGET_REG_BITS == 32) {
@@ -1413,7 +1413,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
/* "Tail call" to the helper, with the return address back inline. */
tcg_out_push(s, retaddr);
- tcg_out_jmp(s, (uintptr_t)qemu_st_helpers[opc]);
+ tcg_out_jmp(s, qemu_st_helpers[opc]);
}
#elif defined(__x86_64__) && defined(__linux__)
# include <asm/prctl.h>
@@ -1534,7 +1534,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
#if defined(CONFIG_SOFTMMU)
int mem_index;
TCGMemOp s_bits;
- uint8_t *label_ptr[2];
+ tcg_insn_unit *label_ptr[2];
#endif
datalo = *args++;
@@ -1665,7 +1665,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
#if defined(CONFIG_SOFTMMU)
int mem_index;
TCGMemOp s_bits;
- uint8_t *label_ptr[2];
+ tcg_insn_unit *label_ptr[2];
#endif
datalo = *args++;
@@ -1731,35 +1731,24 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
switch(opc) {
case INDEX_op_exit_tb:
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_EAX, args[0]);
- tcg_out_jmp(s, (uintptr_t)tb_ret_addr);
+ tcg_out_jmp(s, tb_ret_addr);
break;
case INDEX_op_goto_tb:
if (s->tb_jmp_offset) {
/* direct jump method */
tcg_out8(s, OPC_JMP_long); /* jmp im */
- s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
+ s->tb_jmp_offset[args[0]] = tcg_current_code_size(s);
tcg_out32(s, 0);
} else {
/* indirect jump method */
tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, -1,
(intptr_t)(s->tb_next + args[0]));
}
- s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
- break;
- case INDEX_op_call:
- if (const_args[0]) {
- tcg_out_calli(s, args[0]);
- } else {
- /* call *reg */
- tcg_out_modrm(s, OPC_GRP5, EXT5_CALLN_Ev, args[0]);
- }
+ s->tb_next_offset[args[0]] = tcg_current_code_size(s);
break;
case INDEX_op_br:
tcg_out_jxx(s, JCC_JMP, args[0], 0);
break;
- case INDEX_op_movi_i32:
- tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
- break;
OP_32_64(ld8u):
/* Note that we can ignore REXW for the zero-extend to 64-bit. */
tcg_out_modrm_offset(s, OPC_MOVZBL, args[0], args[1], args[2]);
@@ -2009,9 +1998,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_setcond2(s, args, const_args);
break;
#else /* TCG_TARGET_REG_BITS == 64 */
- case INDEX_op_movi_i64:
- tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
- break;
case INDEX_op_ld32s_i64:
tcg_out_modrm_offset(s, OPC_MOVSLQ, args[0], args[1], args[2]);
break;
@@ -2068,6 +2054,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
}
break;
+ case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
+ case INDEX_op_mov_i64:
+ case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
+ case INDEX_op_movi_i64:
+ case INDEX_op_call: /* Always emitted via tcg_out_call. */
default:
tcg_abort();
}
@@ -2078,10 +2069,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
static const TCGTargetOpDef x86_op_defs[] = {
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
- { INDEX_op_call, { "ri" } },
{ INDEX_op_br, { } },
- { INDEX_op_mov_i32, { "r", "r" } },
- { INDEX_op_movi_i32, { "r" } },
{ INDEX_op_ld8u_i32, { "r", "r" } },
{ INDEX_op_ld8s_i32, { "r", "r" } },
{ INDEX_op_ld16u_i32, { "r", "r" } },
@@ -2135,8 +2123,6 @@ static const TCGTargetOpDef x86_op_defs[] = {
{ INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
{ INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } },
#else
- { INDEX_op_mov_i64, { "r", "r" } },
- { INDEX_op_movi_i64, { "r" } },
{ INDEX_op_ld8u_i64, { "r", "r" } },
{ INDEX_op_ld8s_i64, { "r", "r" } },
{ INDEX_op_ld16u_i64, { "r", "r" } },
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index dbeb16d3ac..6c94e5cde0 100644
--- a/tcg/i386/tcg-target.h
+++ b/tcg/i386/tcg-target.h
@@ -24,6 +24,8 @@
#ifndef TCG_TARGET_I386
#define TCG_TARGET_I386 1
+#define TCG_TARGET_INSN_UNIT_SIZE 1
+
#ifdef __x86_64__
# define TCG_TARGET_REG_BITS 64
# define TCG_TARGET_NB_REGS 16
diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index 1f523d6466..6bc9924641 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -692,112 +692,32 @@ static inline uint64_t tcg_opc_x4(int qp, uint64_t opc, int b1, uint64_t imm)
/*
- * Relocations
+ * Relocations - Note that we never encode branches elsewhere than slot 2.
*/
-static inline void reloc_pcrel21b(void *pc, intptr_t target)
+static void reloc_pcrel21b_slot2(tcg_insn_unit *pc, tcg_insn_unit *target)
{
- uint64_t imm;
- int64_t disp;
- int slot;
-
- slot = (intptr_t)pc & 3;
- pc = (void *)((intptr_t)pc & ~3);
-
- disp = target - (intptr_t)pc;
- imm = (uint64_t) disp >> 4;
-
- switch(slot) {
- case 0:
- *(uint64_t *)(pc + 0) = (*(uint64_t *)(pc + 8) & 0xfffffdc00003ffffull)
- | ((imm & 0x100000) << 21) /* s */
- | ((imm & 0x0fffff) << 18); /* imm20b */
- break;
- case 1:
- *(uint64_t *)(pc + 8) = (*(uint64_t *)(pc + 8) & 0xfffffffffffb8000ull)
- | ((imm & 0x100000) >> 2) /* s */
- | ((imm & 0x0fffe0) >> 5); /* imm20b */
- *(uint64_t *)(pc + 0) = (*(uint64_t *)(pc + 0) & 0x07ffffffffffffffull)
- | ((imm & 0x00001f) << 59); /* imm20b */
- break;
- case 2:
- *(uint64_t *)(pc + 8) = (*(uint64_t *)(pc + 8) & 0xf700000fffffffffull)
- | ((imm & 0x100000) << 39) /* s */
- | ((imm & 0x0fffff) << 36); /* imm20b */
- break;
- }
-}
+ uint64_t imm = target - pc;
-static inline uint64_t get_reloc_pcrel21b (void *pc)
-{
- int64_t low, high;
- int slot;
-
- slot = (tcg_target_long) pc & 3;
- pc = (void *)((tcg_target_long) pc & ~3);
-
- low = (*(uint64_t *)(pc + 0));
- high = (*(uint64_t *)(pc + 8));
-
- switch(slot) {
- case 0:
- return ((low >> 21) & 0x100000) + /* s */
- ((low >> 18) & 0x0fffff); /* imm20b */
- case 1:
- return ((high << 2) & 0x100000) + /* s */
- ((high << 5) & 0x0fffe0) + /* imm20b */
- ((low >> 59) & 0x00001f); /* imm20b */
- case 2:
- return ((high >> 39) & 0x100000) + /* s */
- ((high >> 36) & 0x0fffff); /* imm20b */
- default:
- tcg_abort();
- }
+ pc->hi = (pc->hi & 0xf700000fffffffffull)
+ | ((imm & 0x100000) << 39) /* s */
+ | ((imm & 0x0fffff) << 36); /* imm20b */
}
-static inline void reloc_pcrel60b(void *pc, intptr_t target)
+static uint64_t get_reloc_pcrel21b_slot2(tcg_insn_unit *pc)
{
- int64_t disp;
- uint64_t imm;
-
- disp = target - (intptr_t)pc;
- imm = (uint64_t) disp >> 4;
+ int64_t high = pc->hi;
- *(uint64_t *)(pc + 8) = (*(uint64_t *)(pc + 8) & 0xf700000fff800000ull)
- | (imm & 0x0800000000000000ull) /* s */
- | ((imm & 0x07fffff000000000ull) >> 36) /* imm39 */
- | ((imm & 0x00000000000fffffull) << 36); /* imm20b */
- *(uint64_t *)(pc + 0) = (*(uint64_t *)(pc + 0) & 0x00003fffffffffffull)
- | ((imm & 0x0000000ffff00000ull) << 28); /* imm39 */
+ return ((high >> 39) & 0x100000) + /* s */
+ ((high >> 36) & 0x0fffff); /* imm20b */
}
-static inline uint64_t get_reloc_pcrel60b (void *pc)
-{
- int64_t low, high;
-
- low = (*(uint64_t *)(pc + 0));
- high = (*(uint64_t *)(pc + 8));
-
- return ((high) & 0x0800000000000000ull) + /* s */
- ((high >> 36) & 0x00000000000fffffull) + /* imm20b */
- ((high << 36) & 0x07fffff000000000ull) + /* imm39 */
- ((low >> 28) & 0x0000000ffff00000ull); /* imm39 */
-}
-
-
-static void patch_reloc(uint8_t *code_ptr, int type,
+static void patch_reloc(tcg_insn_unit *code_ptr, int type,
intptr_t value, intptr_t addend)
{
- value += addend;
- switch (type) {
- case R_IA64_PCREL21B:
- reloc_pcrel21b(code_ptr, value);
- break;
- case R_IA64_PCREL60B:
- reloc_pcrel60b(code_ptr, value);
- default:
- tcg_abort();
- }
+ assert(addend == 0);
+ assert(type == R_IA64_PCREL21B);
+ reloc_pcrel21b_slot2(code_ptr, (tcg_insn_unit *)value);
}
/*
@@ -861,7 +781,7 @@ static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
* Code generation
*/
-static uint8_t *tb_ret_addr;
+static tcg_insn_unit *tb_ret_addr;
static inline void tcg_out_bundle(TCGContext *s, int template,
uint64_t slot0, uint64_t slot1,
@@ -872,9 +792,10 @@ static inline void tcg_out_bundle(TCGContext *s, int template,
slot1 &= 0x1ffffffffffull; /* 41 bits */
slot2 &= 0x1ffffffffffull; /* 41 bits */
- *(uint64_t *)(s->code_ptr + 0) = (slot1 << 46) | (slot0 << 5) | template;
- *(uint64_t *)(s->code_ptr + 8) = (slot2 << 23) | (slot1 >> 18);
- s->code_ptr += 16;
+ *s->code_ptr++ = (tcg_insn_unit){
+ (slot1 << 46) | (slot0 << 5) | template,
+ (slot2 << 23) | (slot1 >> 18)
+ };
}
static inline uint64_t tcg_opc_mov_a(int qp, TCGReg dst, TCGReg src)
@@ -909,33 +830,34 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type,
static void tcg_out_br(TCGContext *s, int label_index)
{
TCGLabel *l = &s->labels[label_index];
+ uint64_t imm;
/* We pay attention here to not modify the branch target by reading
the existing value and using it again. This ensure that caches and
memory are kept coherent during retranslation. */
- tcg_out_bundle(s, mmB,
- INSN_NOP_M,
- INSN_NOP_M,
- tcg_opc_b1 (TCG_REG_P0, OPC_BR_SPTK_MANY_B1,
- get_reloc_pcrel21b(s->code_ptr + 2)));
-
if (l->has_value) {
- reloc_pcrel21b((s->code_ptr - 16) + 2, l->u.value);
+ imm = l->u.value_ptr - s->code_ptr;
} else {
- tcg_out_reloc(s, (s->code_ptr - 16) + 2,
- R_IA64_PCREL21B, label_index, 0);
+ imm = get_reloc_pcrel21b_slot2(s->code_ptr);
+ tcg_out_reloc(s, s->code_ptr, R_IA64_PCREL21B, label_index, 0);
}
+
+ tcg_out_bundle(s, mmB,
+ INSN_NOP_M,
+ INSN_NOP_M,
+ tcg_opc_b1(TCG_REG_P0, OPC_BR_SPTK_MANY_B1, imm));
}
-static inline void tcg_out_calli(TCGContext *s, uintptr_t addr)
+static inline void tcg_out_call(TCGContext *s, tcg_insn_unit *desc)
{
+ uintptr_t func = desc->lo, gp = desc->hi, disp;
+
/* Look through the function descriptor. */
- uintptr_t disp, *desc = (uintptr_t *)addr;
tcg_out_bundle(s, mlx,
INSN_NOP_M,
- tcg_opc_l2 (desc[1]),
- tcg_opc_x2 (TCG_REG_P0, OPC_MOVL_X2, TCG_REG_R1, desc[1]));
- disp = (desc[0] - (uintptr_t)s->code_ptr) >> 4;
+ tcg_opc_l2 (gp),
+ tcg_opc_x2 (TCG_REG_P0, OPC_MOVL_X2, TCG_REG_R1, gp));
+ disp = (tcg_insn_unit *)func - s->code_ptr;
tcg_out_bundle(s, mLX,
INSN_NOP_M,
tcg_opc_l4 (disp),
@@ -943,23 +865,8 @@ static inline void tcg_out_calli(TCGContext *s, uintptr_t addr)
TCG_REG_B0, disp));
}
-static inline void tcg_out_callr(TCGContext *s, TCGReg addr)
-{
- tcg_out_bundle(s, MmI,
- tcg_opc_m1 (TCG_REG_P0, OPC_LD8_M1, TCG_REG_R2, addr),
- tcg_opc_a4 (TCG_REG_P0, OPC_ADDS_A4, TCG_REG_R3, 8, addr),
- tcg_opc_i21(TCG_REG_P0, OPC_MOV_I21,
- TCG_REG_B6, TCG_REG_R2, 0));
- tcg_out_bundle(s, mmB,
- tcg_opc_m1 (TCG_REG_P0, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R3),
- INSN_NOP_M,
- tcg_opc_b5 (TCG_REG_P0, OPC_BR_CALL_SPTK_MANY_B5,
- TCG_REG_B0, TCG_REG_B6));
-}
-
static void tcg_out_exit_tb(TCGContext *s, tcg_target_long arg)
{
- int64_t disp;
uint64_t imm, opc1;
/* At least arg == 0 is a common operation. */
@@ -970,8 +877,7 @@ static void tcg_out_exit_tb(TCGContext *s, tcg_target_long arg)
opc1 = INSN_NOP_M;
}
- disp = tb_ret_addr - s->code_ptr;
- imm = (uint64_t)disp >> 4;
+ imm = tb_ret_addr - s->code_ptr;
tcg_out_bundle(s, mLX,
opc1,
@@ -1000,7 +906,7 @@ static inline void tcg_out_goto_tb(TCGContext *s, TCGArg arg)
tcg_opc_b4 (TCG_REG_P0, OPC_BR_SPTK_MANY_B4,
TCG_REG_B6));
}
- s->tb_next_offset[arg] = s->code_ptr - s->code_buf;
+ s->tb_next_offset[arg] = tcg_current_code_size(s);
}
static inline void tcg_out_jmp(TCGContext *s, TCGArg addr)
@@ -1521,19 +1427,22 @@ static inline void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
TCGReg arg2, int label_index, int cmp4)
{
TCGLabel *l = &s->labels[label_index];
+ uint64_t imm;
- tcg_out_bundle(s, miB,
- INSN_NOP_M,
- tcg_opc_cmp_a(TCG_REG_P0, cond, arg1, arg2, cmp4),
- tcg_opc_b1(TCG_REG_P6, OPC_BR_DPTK_FEW_B1,
- get_reloc_pcrel21b(s->code_ptr + 2)));
-
+ /* We pay attention here to not modify the branch target by reading
+ the existing value and using it again. This ensure that caches and
+ memory are kept coherent during retranslation. */
if (l->has_value) {
- reloc_pcrel21b((s->code_ptr - 16) + 2, l->u.value);
+ imm = l->u.value_ptr - s->code_ptr;
} else {
- tcg_out_reloc(s, (s->code_ptr - 16) + 2,
- R_IA64_PCREL21B, label_index, 0);
+ imm = get_reloc_pcrel21b_slot2(s->code_ptr);
+ tcg_out_reloc(s, s->code_ptr, R_IA64_PCREL21B, label_index, 0);
}
+
+ tcg_out_bundle(s, miB,
+ INSN_NOP_M,
+ tcg_opc_cmp_a(TCG_REG_P0, cond, arg1, arg2, cmp4),
+ tcg_opc_b1(TCG_REG_P6, OPC_BR_DPTK_FEW_B1, imm));
}
static inline void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGArg ret,
@@ -1646,7 +1555,7 @@ static inline void tcg_out_qemu_tlb(TCGContext *s, TCGReg addr_reg,
typedef struct TCGLabelQemuLdst {
bool is_ld;
TCGMemOp size;
- uint8_t *label_ptr; /* label pointers to be updated */
+ tcg_insn_unit *label_ptr; /* label pointers to be updated */
} TCGLabelQemuLdst;
typedef struct TCGBackendData {
@@ -1660,7 +1569,7 @@ static inline void tcg_out_tb_init(TCGContext *s)
}
static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
- uint8_t *label_ptr)
+ tcg_insn_unit *label_ptr)
{
TCGBackendData *be = s->be;
TCGLabelQemuLdst *l = &be->ldst_labels[be->nb_ldst_labels++];
@@ -1683,43 +1592,44 @@ static void tcg_out_tb_finalize(TCGContext *s)
helper_le_ldul_mmu,
helper_le_ldq_mmu,
};
- uintptr_t thunks[8] = { };
+ tcg_insn_unit *thunks[8] = { };
TCGBackendData *be = s->be;
size_t i, n = be->nb_ldst_labels;
for (i = 0; i < n; i++) {
TCGLabelQemuLdst *l = &be->ldst_labels[i];
long x = l->is_ld * 4 + l->size;
- uintptr_t dest = thunks[x];
+ tcg_insn_unit *dest = thunks[x];
/* The out-of-line thunks are all the same; load the return address
from B0, load the GP, and branch to the code. Note that we are
always post-call, so the register window has rolled, so we're
using incomming parameter register numbers, not outgoing. */
- if (dest == 0) {
- uintptr_t disp, *desc = (uintptr_t *)helpers[x];
+ if (dest == NULL) {
+ uintptr_t *desc = (uintptr_t *)helpers[x];
+ uintptr_t func = desc[0], gp = desc[1], disp;
- thunks[x] = dest = (uintptr_t)s->code_ptr;
+ thunks[x] = dest = s->code_ptr;
tcg_out_bundle(s, mlx,
INSN_NOP_M,
- tcg_opc_l2 (desc[1]),
+ tcg_opc_l2 (gp),
tcg_opc_x2 (TCG_REG_P0, OPC_MOVL_X2,
- TCG_REG_R1, desc[1]));
+ TCG_REG_R1, gp));
tcg_out_bundle(s, mii,
INSN_NOP_M,
INSN_NOP_I,
tcg_opc_i22(TCG_REG_P0, OPC_MOV_I22,
l->is_ld ? TCG_REG_R35 : TCG_REG_R36,
TCG_REG_B0));
- disp = (desc[0] - (uintptr_t)s->code_ptr) >> 4;
+ disp = (tcg_insn_unit *)func - s->code_ptr;
tcg_out_bundle(s, mLX,
INSN_NOP_M,
tcg_opc_l3 (disp),
tcg_opc_x3 (TCG_REG_P0, OPC_BRL_SPTK_MANY_X3, disp));
}
- reloc_pcrel21b(l->label_ptr, dest);
+ reloc_pcrel21b_slot2(l->label_ptr, dest);
}
}
@@ -1731,7 +1641,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args)
int addr_reg, data_reg, mem_index;
TCGMemOp opc, s_bits;
uint64_t fin1, fin2;
- uint8_t *label_ptr;
+ tcg_insn_unit *label_ptr;
data_reg = args[0];
addr_reg = args[1];
@@ -1765,13 +1675,13 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args)
tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R2,
TCG_REG_R2, TCG_REG_R57),
tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R58, mem_index));
- label_ptr = s->code_ptr + 2;
+ label_ptr = s->code_ptr;
tcg_out_bundle(s, miB,
tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits],
TCG_REG_R8, TCG_REG_R2),
INSN_NOP_I,
tcg_opc_b3 (TCG_REG_P7, OPC_BR_CALL_SPNT_FEW_B3, TCG_REG_B0,
- get_reloc_pcrel21b(label_ptr)));
+ get_reloc_pcrel21b_slot2(label_ptr)));
add_qemu_ldst_label(s, 1, opc, label_ptr);
@@ -1792,7 +1702,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args)
int mem_index;
uint64_t pre1, pre2;
TCGMemOp opc, s_bits;
- uint8_t *label_ptr;
+ tcg_insn_unit *label_ptr;
data_reg = args[0];
addr_reg = args[1];
@@ -1827,13 +1737,13 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args)
tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R2,
TCG_REG_R2, TCG_REG_R57),
tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R59, mem_index));
- label_ptr = s->code_ptr + 2;
+ label_ptr = s->code_ptr;
tcg_out_bundle(s, miB,
tcg_opc_m4 (TCG_REG_P6, opc_st_m4[s_bits],
TCG_REG_R58, TCG_REG_R2),
INSN_NOP_I,
tcg_opc_b3 (TCG_REG_P7, OPC_BR_CALL_SPNT_FEW_B3, TCG_REG_B0,
- get_reloc_pcrel21b(label_ptr)));
+ get_reloc_pcrel21b_slot2(label_ptr)));
add_qemu_ldst_label(s, 0, opc, label_ptr);
}
@@ -2085,24 +1995,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_br:
tcg_out_br(s, args[0]);
break;
- case INDEX_op_call:
- if (likely(const_args[0])) {
- tcg_out_calli(s, args[0]);
- } else {
- tcg_out_callr(s, args[0]);
- }
- break;
case INDEX_op_goto_tb:
tcg_out_goto_tb(s, args[0]);
break;
- case INDEX_op_movi_i32:
- tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
- break;
- case INDEX_op_movi_i64:
- tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
- break;
-
case INDEX_op_ld8u_i32:
case INDEX_op_ld8u_i64:
tcg_out_ld_rel(s, OPC_LD1_M1, args[0], args[1], args[2]);
@@ -2312,6 +2208,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_qemu_st(s, args);
break;
+ case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
+ case INDEX_op_mov_i64:
+ case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
+ case INDEX_op_movi_i64:
+ case INDEX_op_call: /* Always emitted via tcg_out_call. */
default:
tcg_abort();
}
@@ -2319,13 +2220,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
static const TCGTargetOpDef ia64_op_defs[] = {
{ INDEX_op_br, { } },
- { INDEX_op_call, { "ri" } },
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
- { INDEX_op_mov_i32, { "r", "r" } },
- { INDEX_op_movi_i32, { "r" } },
-
{ INDEX_op_ld8u_i32, { "r", "r" } },
{ INDEX_op_ld8s_i32, { "r", "r" } },
{ INDEX_op_ld16u_i32, { "r", "r" } },
@@ -2367,9 +2264,6 @@ static const TCGTargetOpDef ia64_op_defs[] = {
{ INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rI", "rI" } },
- { INDEX_op_mov_i64, { "r", "r" } },
- { INDEX_op_movi_i64, { "r" } },
-
{ INDEX_op_ld8u_i64, { "r", "r" } },
{ INDEX_op_ld8s_i64, { "r", "r" } },
{ INDEX_op_ld16u_i64, { "r", "r" } },
@@ -2442,8 +2336,11 @@ static void tcg_target_qemu_prologue(TCGContext *s)
CPU_TEMP_BUF_NLONGS * sizeof(long));
/* First emit adhoc function descriptor */
- *(uint64_t *)(s->code_ptr) = (uint64_t)s->code_ptr + 16; /* entry point */
- s->code_ptr += 16; /* skip GP */
+ *s->code_ptr = (tcg_insn_unit){
+ (uint64_t)(s->code_ptr + 1), /* entry point */
+ 0 /* skip gp */
+ };
+ s->code_ptr++;
/* prologue */
tcg_out_bundle(s, miI,
diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h
index d834beb323..3a59b50349 100644
--- a/tcg/ia64/tcg-target.h
+++ b/tcg/ia64/tcg-target.h
@@ -25,6 +25,12 @@
#ifndef TCG_TARGET_IA64
#define TCG_TARGET_IA64 1
+#define TCG_TARGET_INSN_UNIT_SIZE 16
+typedef struct {
+ uint64_t lo __attribute__((aligned(16)));
+ uint64_t hi;
+} tcg_insn_unit;
+
/* We only map the first 64 registers */
#define TCG_TARGET_NB_REGS 64
typedef enum {
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 37241b224b..0ae495c586 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -108,83 +108,38 @@ static const TCGReg tcg_target_call_oarg_regs[2] = {
TCG_REG_V1
};
-static uint8_t *tb_ret_addr;
+static tcg_insn_unit *tb_ret_addr;
-static inline uint32_t reloc_lo16_val(void *pc, intptr_t target)
+static inline uint32_t reloc_pc16_val(tcg_insn_unit *pc, tcg_insn_unit *target)
{
- return target & 0xffff;
+ /* Let the compiler perform the right-shift as part of the arithmetic. */
+ ptrdiff_t disp = target - (pc + 1);
+ assert(disp == (int16_t)disp);
+ return disp & 0xffff;
}
-static inline void reloc_lo16(void *pc, intptr_t target)
+static inline void reloc_pc16(tcg_insn_unit *pc, tcg_insn_unit *target)
{
- *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
- | reloc_lo16_val(pc, target);
+ *pc = deposit32(*pc, 0, 16, reloc_pc16_val(pc, target));
}
-static inline uint32_t reloc_hi16_val(void *pc, intptr_t target)
+static inline uint32_t reloc_26_val(tcg_insn_unit *pc, tcg_insn_unit *target)
{
- return (target >> 16) & 0xffff;
+ assert((((uintptr_t)pc ^ (uintptr_t)target) & 0xf0000000) == 0);
+ return ((uintptr_t)target >> 2) & 0x3ffffff;
}
-static inline void reloc_hi16(void *pc, intptr_t target)
+static inline void reloc_26(tcg_insn_unit *pc, tcg_insn_unit *target)
{
- *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
- | reloc_hi16_val(pc, target);
+ *pc = deposit32(*pc, 0, 26, reloc_26_val(pc, target));
}
-static inline uint32_t reloc_pc16_val(void *pc, intptr_t target)
-{
- int32_t disp;
-
- disp = target - (intptr_t)pc - 4;
- if (disp != (disp << 14) >> 14) {
- tcg_abort ();
- }
-
- return (disp >> 2) & 0xffff;
-}
-
-static inline void reloc_pc16 (void *pc, tcg_target_long target)
-{
- *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
- | reloc_pc16_val(pc, target);
-}
-
-static inline uint32_t reloc_26_val (void *pc, tcg_target_long target)
-{
- if ((((tcg_target_long)pc + 4) & 0xf0000000) != (target & 0xf0000000)) {
- tcg_abort ();
- }
-
- return (target >> 2) & 0x3ffffff;
-}
-
-static inline void reloc_pc26(void *pc, intptr_t target)
-{
- *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3ffffff)
- | reloc_26_val(pc, target);
-}
-
-static void patch_reloc(uint8_t *code_ptr, int type,
+static void patch_reloc(tcg_insn_unit *code_ptr, int type,
intptr_t value, intptr_t addend)
{
- value += addend;
- switch(type) {
- case R_MIPS_LO16:
- reloc_lo16(code_ptr, value);
- break;
- case R_MIPS_HI16:
- reloc_hi16(code_ptr, value);
- break;
- case R_MIPS_PC16:
- reloc_pc16(code_ptr, value);
- break;
- case R_MIPS_26:
- reloc_pc26(code_ptr, value);
- break;
- default:
- tcg_abort();
- }
+ assert(type == R_MIPS_PC16);
+ assert(addend == 0);
+ reloc_pc16(code_ptr, (tcg_insn_unit *)value);
}
/* parse target specific constraints */
@@ -198,11 +153,6 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
ct->ct |= TCG_CT_REG;
tcg_regset_set(ct->u.regs, 0xffffffff);
break;
- case 'C':
- ct->ct |= TCG_CT_REG;
- tcg_regset_clear(ct->u.regs);
- tcg_regset_set_reg(ct->u.regs, TCG_REG_T9);
- break;
case 'L': /* qemu_ld output arg constraint */
ct->ct |= TCG_CT_REG;
tcg_regset_set(ct->u.regs, 0xffffffff);
@@ -374,7 +324,7 @@ static inline void tcg_out_opc_br(TCGContext *s, int opc,
/* We pay attention here to not modify the branch target by reading
the existing value and using it again. This ensure that caches and
memory are kept coherent during retranslation. */
- uint16_t offset = (uint16_t)(*(uint32_t *) s->code_ptr);
+ uint16_t offset = (uint16_t)*s->code_ptr;
tcg_out_opc_imm(s, opc, rt, rs, offset);
}
@@ -663,9 +613,9 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGArg arg1,
break;
}
if (l->has_value) {
- reloc_pc16(s->code_ptr - 4, l->u.value);
+ reloc_pc16(s->code_ptr - 1, l->u.value_ptr);
} else {
- tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
+ tcg_out_reloc(s, s->code_ptr - 1, R_MIPS_PC16, label_index, 0);
}
tcg_out_nop(s);
}
@@ -676,7 +626,7 @@ static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGArg arg1,
TCGArg arg2, TCGArg arg3, TCGArg arg4,
int label_index)
{
- void *label_ptr;
+ tcg_insn_unit *label_ptr;
switch(cond) {
case TCG_COND_NE:
@@ -733,7 +683,7 @@ static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGArg arg1,
tcg_abort();
}
- reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
+ reloc_pc16(label_ptr, s->code_ptr);
}
static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
@@ -945,12 +895,12 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
{
TCGReg addr_regl, data_regl, data_regh, data_reg1, data_reg2;
#if defined(CONFIG_SOFTMMU)
- void *label1_ptr, *label2_ptr;
+ tcg_insn_unit *label1_ptr, *label2_ptr;
int arg_num;
int mem_index, s_bits;
int addr_meml;
# if TARGET_LONG_BITS == 64
- uint8_t *label3_ptr;
+ tcg_insn_unit *label3_ptr;
TCGReg addr_regh;
int addr_memh;
# endif
@@ -1011,7 +961,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
tcg_out_nop(s);
- reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
+ reloc_pc16(label3_ptr, s->code_ptr);
# else
label1_ptr = s->code_ptr;
tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
@@ -1060,7 +1010,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out_nop(s);
/* label1: fast path */
- reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
+ reloc_pc16(label1_ptr, s->code_ptr);
tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
offsetof(CPUArchState, tlb_table[mem_index][0].addend));
@@ -1121,7 +1071,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
}
#if defined(CONFIG_SOFTMMU)
- reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
+ reloc_pc16(label2_ptr, s->code_ptr);
#endif
}
@@ -1130,14 +1080,14 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
{
TCGReg addr_regl, data_regl, data_regh, data_reg1, data_reg2;
#if defined(CONFIG_SOFTMMU)
- uint8_t *label1_ptr, *label2_ptr;
+ tcg_insn_unit *label1_ptr, *label2_ptr;
int arg_num;
int mem_index, s_bits;
int addr_meml;
#endif
#if TARGET_LONG_BITS == 64
# if defined(CONFIG_SOFTMMU)
- uint8_t *label3_ptr;
+ tcg_insn_unit *label3_ptr;
TCGReg addr_regh;
int addr_memh;
# endif
@@ -1200,7 +1150,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
tcg_out_nop(s);
- reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
+ reloc_pc16(label3_ptr, s->code_ptr);
# else
label1_ptr = s->code_ptr;
tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
@@ -1241,7 +1191,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out_nop(s);
/* label1: fast path */
- reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
+ reloc_pc16(label1_ptr, s->code_ptr);
tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
offsetof(CPUArchState, tlb_table[mem_index][0].addend));
@@ -1293,17 +1243,24 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
}
#if defined(CONFIG_SOFTMMU)
- reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
+ reloc_pc16(label2_ptr, s->code_ptr);
#endif
}
+static void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
+{
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T9, (intptr_t)target);
+ tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
+ tcg_out_nop(s);
+}
+
static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
const TCGArg *args, const int *const_args)
{
switch(opc) {
case INDEX_op_exit_tb:
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
- tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (uintptr_t)tb_ret_addr);
tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
tcg_out_nop(s);
break;
@@ -1313,28 +1270,18 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_abort();
} else {
/* indirect jump method */
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT,
+ (uintptr_t)(s->tb_next + args[0]));
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
}
tcg_out_nop(s);
- s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
- break;
- case INDEX_op_call:
- tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
- tcg_out_nop(s);
+ s->tb_next_offset[args[0]] = tcg_current_code_size(s);
break;
case INDEX_op_br:
tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
break;
- case INDEX_op_mov_i32:
- tcg_out_mov(s, TCG_TYPE_I32, args[0], args[1]);
- break;
- case INDEX_op_movi_i32:
- tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
- break;
-
case INDEX_op_ld8u_i32:
tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
break;
@@ -1582,6 +1529,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_qemu_st(s, args, 3);
break;
+ case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
+ case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
+ case INDEX_op_call: /* Always emitted via tcg_out_call. */
default:
tcg_abort();
}
@@ -1590,11 +1540,8 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
static const TCGTargetOpDef mips_op_defs[] = {
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
- { INDEX_op_call, { "C" } },
{ INDEX_op_br, { } },
- { INDEX_op_mov_i32, { "r", "r" } },
- { INDEX_op_movi_i32, { "r" } },
{ INDEX_op_ld8u_i32, { "r", "r" } },
{ INDEX_op_ld8s_i32, { "r", "r" } },
{ INDEX_op_ld16u_i32, { "r", "r" } },
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 9576db514d..c6d2267d77 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -26,6 +26,7 @@
#ifndef TCG_TARGET_MIPS
#define TCG_TARGET_MIPS 1
+#define TCG_TARGET_INSN_UNIT_SIZE 4
#define TCG_TARGET_NB_REGS 32
typedef enum {
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 0302f4f99a..3a504a1961 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -513,12 +513,8 @@ static bool swap_commutative2(TCGArg *p1, TCGArg *p2)
static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
TCGArg *args, TCGOpDef *tcg_op_defs)
{
- int i, nb_ops, op_index, nb_temps, nb_globals, nb_call_args;
- tcg_target_ulong mask, affected;
- TCGOpcode op;
- const TCGOpDef *def;
+ int nb_ops, op_index, nb_temps, nb_globals;
TCGArg *gen_args;
- TCGArg tmp;
/* Array VALS has an element for each temp.
If this temp holds a constant then its value is kept in VALS' element.
@@ -532,22 +528,27 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
nb_ops = tcg_opc_ptr - s->gen_opc_buf;
gen_args = args;
for (op_index = 0; op_index < nb_ops; op_index++) {
- op = s->gen_opc_buf[op_index];
- def = &tcg_op_defs[op];
- /* Do copy propagation */
+ TCGOpcode op = s->gen_opc_buf[op_index];
+ const TCGOpDef *def = &tcg_op_defs[op];
+ tcg_target_ulong mask, affected;
+ int nb_oargs, nb_iargs, nb_args, i;
+ TCGArg tmp;
+
if (op == INDEX_op_call) {
- int nb_oargs = args[0] >> 16;
- int nb_iargs = args[0] & 0xffff;
- for (i = nb_oargs + 1; i < nb_oargs + nb_iargs + 1; i++) {
- if (temps[args[i]].state == TCG_TEMP_COPY) {
- args[i] = find_better_copy(s, args[i]);
- }
- }
+ *gen_args++ = tmp = *args++;
+ nb_oargs = tmp >> 16;
+ nb_iargs = tmp & 0xffff;
+ nb_args = nb_oargs + nb_iargs + def->nb_cargs;
} else {
- for (i = def->nb_oargs; i < def->nb_oargs + def->nb_iargs; i++) {
- if (temps[args[i]].state == TCG_TEMP_COPY) {
- args[i] = find_better_copy(s, args[i]);
- }
+ nb_oargs = def->nb_oargs;
+ nb_iargs = def->nb_iargs;
+ nb_args = def->nb_args;
+ }
+
+ /* Do copy propagation */
+ for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
+ if (temps[args[i]].state == TCG_TEMP_COPY) {
+ args[i] = find_better_copy(s, args[i]);
}
}
@@ -882,7 +883,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
CASE_OP_32_64(qemu_ld):
{
- TCGMemOp mop = args[def->nb_oargs + def->nb_iargs];
+ TCGMemOp mop = args[nb_oargs + nb_iargs];
if (!(mop & MO_SIGN)) {
mask = (2ULL << ((8 << (mop & MO_SIZE)) - 1)) - 1;
}
@@ -900,15 +901,15 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
}
if (mask == 0) {
- assert(def->nb_oargs == 1);
+ assert(nb_oargs == 1);
s->gen_opc_buf[op_index] = op_to_movi(op);
tcg_opt_gen_movi(gen_args, args[0], 0);
- args += def->nb_oargs + def->nb_iargs + def->nb_cargs;
+ args += nb_args;
gen_args += 2;
continue;
}
if (affected == 0) {
- assert(def->nb_oargs == 1);
+ assert(nb_oargs == 1);
if (temps_are_copies(args[0], args[1])) {
s->gen_opc_buf[op_index] = INDEX_op_nop;
} else if (temps[args[1]].state != TCG_TEMP_CONST) {
@@ -920,7 +921,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
tcg_opt_gen_movi(gen_args, args[0], temps[args[1]].val);
gen_args += 2;
}
- args += def->nb_iargs + 1;
+ args += nb_args;
continue;
}
@@ -1246,24 +1247,13 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
break;
case INDEX_op_call:
- nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
- if (!(args[nb_call_args + 1] & (TCG_CALL_NO_READ_GLOBALS |
- TCG_CALL_NO_WRITE_GLOBALS))) {
+ if (!(args[nb_oargs + nb_iargs + 1]
+ & (TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_WRITE_GLOBALS))) {
for (i = 0; i < nb_globals; i++) {
reset_temp(i);
}
}
- for (i = 0; i < (args[0] >> 16); i++) {
- reset_temp(args[i + 1]);
- }
- i = nb_call_args + 3;
- while (i) {
- *gen_args = *args;
- args++;
- gen_args++;
- i--;
- }
- break;
+ goto do_reset_output;
default:
do_default:
@@ -1275,7 +1265,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
if (def->flags & TCG_OPF_BB_END) {
reset_all_temps(nb_temps);
} else {
- for (i = 0; i < def->nb_oargs; i++) {
+ do_reset_output:
+ for (i = 0; i < nb_oargs; i++) {
reset_temp(args[i]);
/* Save the corresponding known-zero bits mask for the
first output argument (only one supported so far). */
@@ -1284,11 +1275,11 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
}
}
}
- for (i = 0; i < def->nb_args; i++) {
+ for (i = 0; i < nb_args; i++) {
gen_args[i] = args[i];
}
- args += def->nb_args;
- gen_args += def->nb_args;
+ args += nb_args;
+ gen_args += nb_args;
break;
}
}
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 83d9340fca..436b65bffb 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -24,7 +24,7 @@
#include "tcg-be-ldst.h"
-static uint8_t *tb_ret_addr;
+static tcg_insn_unit *tb_ret_addr;
#if defined _CALL_DARWIN || defined __APPLE__
#define TCG_TARGET_CALL_DARWIN
@@ -171,50 +171,47 @@ static const int tcg_target_callee_save_regs[] = {
TCG_REG_R31
};
-static uint32_t reloc_pc24_val (void *pc, tcg_target_long target)
+static inline bool in_range_b(tcg_target_long target)
{
- tcg_target_long disp;
-
- disp = target - (tcg_target_long) pc;
- if ((disp << 6) >> 6 != disp)
- tcg_abort ();
+ return target == sextract32(target, 0, 26);
+}
+static uint32_t reloc_pc24_val(tcg_insn_unit *pc, tcg_insn_unit *target)
+{
+ ptrdiff_t disp = tcg_ptr_byte_diff(target, pc);
+ assert(in_range_b(disp));
return disp & 0x3fffffc;
}
-static void reloc_pc24 (void *pc, tcg_target_long target)
+static void reloc_pc24(tcg_insn_unit *pc, tcg_insn_unit *target)
{
- *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3fffffc)
- | reloc_pc24_val (pc, target);
+ *pc = (*pc & ~0x3fffffc) | reloc_pc24_val(pc, target);
}
-static uint16_t reloc_pc14_val (void *pc, tcg_target_long target)
+static uint16_t reloc_pc14_val(tcg_insn_unit *pc, tcg_insn_unit *target)
{
- tcg_target_long disp;
-
- disp = target - (tcg_target_long) pc;
- if (disp != (int16_t) disp)
- tcg_abort ();
-
+ ptrdiff_t disp = tcg_ptr_byte_diff(target, pc);
+ assert(disp == (int16_t) disp);
return disp & 0xfffc;
}
-static void reloc_pc14 (void *pc, tcg_target_long target)
+static void reloc_pc14(tcg_insn_unit *pc, tcg_insn_unit *target)
{
- *(uint32_t *) pc = (*(uint32_t *) pc & ~0xfffc)
- | reloc_pc14_val (pc, target);
+ *pc = (*pc & ~0xfffc) | reloc_pc14_val(pc, target);
}
-static void patch_reloc(uint8_t *code_ptr, int type,
+static void patch_reloc(tcg_insn_unit *code_ptr, int type,
intptr_t value, intptr_t addend)
{
- value += addend;
+ tcg_insn_unit *target = (tcg_insn_unit *)value;
+
+ assert(addend == 0);
switch (type) {
case R_PPC_REL14:
- reloc_pc14 (code_ptr, value);
+ reloc_pc14(code_ptr, target);
break;
case R_PPC_REL24:
- reloc_pc24 (code_ptr, value);
+ reloc_pc24(code_ptr, target);
break;
default:
tcg_abort();
@@ -480,47 +477,36 @@ static void tcg_out_ldst (TCGContext *s, int ret, int addr,
}
}
-static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target)
+static void tcg_out_b(TCGContext *s, int mask, tcg_insn_unit *target)
{
- tcg_target_long disp;
-
- disp = target - (tcg_target_long) s->code_ptr;
- if ((disp << 6) >> 6 == disp)
- tcg_out32 (s, B | (disp & 0x3fffffc) | mask);
- else {
- tcg_out_movi (s, TCG_TYPE_I32, 0, (tcg_target_long) target);
- tcg_out32 (s, MTSPR | RS (0) | CTR);
- tcg_out32 (s, BCCTR | BO_ALWAYS | mask);
+ ptrdiff_t disp = tcg_pcrel_diff(s, target);
+ if (in_range_b(disp)) {
+ tcg_out32(s, B | (disp & 0x3fffffc) | mask);
+ } else {
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R0, (uintptr_t)target);
+ tcg_out32(s, MTSPR | RS(TCG_REG_R0) | CTR);
+ tcg_out32(s, BCCTR | BO_ALWAYS | mask);
}
}
-static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg,
- int lk)
+static void tcg_out_call1(TCGContext *s, tcg_insn_unit *target, int lk)
{
#ifdef _CALL_AIX
- int reg;
-
- if (const_arg) {
- reg = 2;
- tcg_out_movi (s, TCG_TYPE_I32, reg, arg);
- }
- else reg = arg;
-
- tcg_out32 (s, LWZ | RT (0) | RA (reg));
- tcg_out32 (s, MTSPR | RA (0) | CTR);
- tcg_out32 (s, LWZ | RT (2) | RA (reg) | 4);
- tcg_out32 (s, BCCTR | BO_ALWAYS | lk);
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, (uintptr_t)target);
+ tcg_out32(s, LWZ | RT(TCG_REG_R0) | RA(reg));
+ tcg_out32(s, MTSPR | RA(TCG_REG_R0) | CTR);
+ tcg_out32(s, LWZ | RT(TCG_REG_R2) | RA(reg) | 4);
+ tcg_out32(s, BCCTR | BO_ALWAYS | lk);
#else
- if (const_arg) {
- tcg_out_b (s, lk, arg);
- }
- else {
- tcg_out32 (s, MTSPR | RS (arg) | LR);
- tcg_out32 (s, BCLR | BO_ALWAYS | lk);
- }
+ tcg_out_b(s, lk, target);
#endif
}
+static void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
+{
+ tcg_out_call1(s, target, LK);
+}
+
#if defined(CONFIG_SOFTMMU)
static void add_qemu_ldst_label (TCGContext *s,
@@ -531,8 +517,8 @@ static void add_qemu_ldst_label (TCGContext *s,
int addrlo_reg,
int addrhi_reg,
int mem_index,
- uint8_t *raddr,
- uint8_t *label_ptr)
+ tcg_insn_unit *raddr,
+ tcg_insn_unit *label_ptr)
{
TCGLabelQemuLdst *label = new_ldst_label(s);
@@ -550,7 +536,7 @@ static void add_qemu_ldst_label (TCGContext *s,
/* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
* int mmu_idx, uintptr_t ra)
*/
-static const void * const qemu_ld_helpers[16] = {
+static void * const qemu_ld_helpers[16] = {
[MO_UB] = helper_ret_ldub_mmu,
[MO_LEUW] = helper_le_lduw_mmu,
[MO_LEUL] = helper_le_ldul_mmu,
@@ -563,7 +549,7 @@ static const void * const qemu_ld_helpers[16] = {
/* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
* uintxx_t val, int mmu_idx, uintptr_t ra)
*/
-static const void * const qemu_st_helpers[16] = {
+static void * const qemu_st_helpers[16] = {
[MO_UB] = helper_ret_stb_mmu,
[MO_LEUW] = helper_le_stw_mmu,
[MO_LEUL] = helper_le_stl_mmu,
@@ -573,8 +559,8 @@ static const void * const qemu_st_helpers[16] = {
[MO_BEQ] = helper_be_stq_mmu,
};
-static void *ld_trampolines[16];
-static void *st_trampolines[16];
+static tcg_insn_unit *ld_trampolines[16];
+static tcg_insn_unit *st_trampolines[16];
/* Perform the TLB load and compare. Branches to the slow path, placing the
address of the branch in *LABEL_PTR. Loads the addend of the TLB into R0.
@@ -582,14 +568,15 @@ static void *st_trampolines[16];
static void tcg_out_tlb_check(TCGContext *s, TCGReg r0, TCGReg r1, TCGReg r2,
TCGReg addrlo, TCGReg addrhi, TCGMemOp s_bits,
- int mem_index, int is_load, uint8_t **label_ptr)
+ int mem_index, int is_load,
+ tcg_insn_unit **label_ptr)
{
int cmp_off =
(is_load
? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
: offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
- uint16_t retranst;
+ tcg_insn_unit retranst;
TCGReg base = TCG_AREG0;
/* Extract the page index, shifted into place for tlb index. */
@@ -648,7 +635,7 @@ static void tcg_out_tlb_check(TCGContext *s, TCGReg r0, TCGReg r1, TCGReg r2,
This address cannot be used for a tail call, but it's shorter
than forming an address from scratch. */
*label_ptr = s->code_ptr;
- retranst = ((uint16_t *) s->code_ptr)[1] & ~3;
+ retranst = *s->code_ptr & 0xfffc;
tcg_out32(s, BC | BI(7, CR_EQ) | retranst | BO_COND_FALSE | LK);
}
#endif
@@ -659,7 +646,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
TCGMemOp opc, bswap;
#ifdef CONFIG_SOFTMMU
int mem_index;
- uint8_t *label_ptr;
+ tcg_insn_unit *label_ptr;
#endif
datalo = *args++;
@@ -731,7 +718,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
TCGMemOp opc, bswap, s_bits;
#ifdef CONFIG_SOFTMMU
int mem_index;
- uint8_t *label_ptr;
+ tcg_insn_unit *label_ptr;
#endif
datalo = *args++;
@@ -790,7 +777,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
TCGReg ir, datalo, datahi;
TCGMemOp opc = l->opc;
- reloc_pc14 (l->label_ptr[0], (uintptr_t)s->code_ptr);
+ reloc_pc14(l->label_ptr[0], s->code_ptr);
ir = TCG_REG_R4;
if (TARGET_LONG_BITS == 32) {
@@ -804,7 +791,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
}
tcg_out_movi(s, TCG_TYPE_I32, ir++, l->mem_index);
tcg_out32(s, MFSPR | RT(ir++) | LR);
- tcg_out_b(s, LK, (uintptr_t)ld_trampolines[opc & ~MO_SIGN]);
+ tcg_out_b(s, LK, ld_trampolines[opc & ~MO_SIGN]);
datalo = l->datalo_reg;
switch (opc & MO_SSIZE) {
@@ -832,7 +819,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
}
break;
}
- tcg_out_b (s, 0, (uintptr_t)l->raddr);
+ tcg_out_b(s, 0, l->raddr);
}
static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
@@ -840,7 +827,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
TCGReg ir, datalo;
TCGMemOp opc = l->opc;
- reloc_pc14 (l->label_ptr[0], (tcg_target_long) s->code_ptr);
+ reloc_pc14(l->label_ptr[0], s->code_ptr);
ir = TCG_REG_R4;
if (TARGET_LONG_BITS == 32) {
@@ -878,16 +865,16 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
tcg_out_movi(s, TCG_TYPE_I32, ir++, l->mem_index);
tcg_out32(s, MFSPR | RT(ir++) | LR);
- tcg_out_b(s, LK, (uintptr_t)st_trampolines[opc]);
- tcg_out_b(s, 0, (uintptr_t)l->raddr);
+ tcg_out_b(s, LK, st_trampolines[opc]);
+ tcg_out_b(s, 0, l->raddr);
}
#endif
#ifdef CONFIG_SOFTMMU
-static void emit_ldst_trampoline (TCGContext *s, const void *ptr)
+static void emit_ldst_trampoline(TCGContext *s, tcg_insn_unit *ptr)
{
- tcg_out_mov (s, TCG_TYPE_I32, 3, TCG_AREG0);
- tcg_out_call (s, (tcg_target_long) ptr, 1, 0);
+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_R3, TCG_AREG0);
+ tcg_out_call1(s, ptr, 0);
}
#endif
@@ -909,12 +896,13 @@ static void tcg_target_qemu_prologue (TCGContext *s)
#ifdef _CALL_AIX
{
- uint32_t addr;
+ uintptr_t addr;
/* First emit adhoc function descriptor */
- addr = (uint32_t) s->code_ptr + 12;
- tcg_out32 (s, addr); /* entry point */
- s->code_ptr += 8; /* skip TOC and environment pointer */
+ addr = (uintptr_t)s->code_ptr + 12;
+ tcg_out32(s, addr); /* entry point */
+ tcg_out32(s, 0); /* toc */
+ tcg_out32(s, 0); /* environment pointer */
}
#endif
tcg_out32 (s, MFSPR | RT (0) | LR);
@@ -1065,18 +1053,17 @@ static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
}
-static void tcg_out_bc (TCGContext *s, int bc, int label_index)
+static void tcg_out_bc(TCGContext *s, int bc, int label_index)
{
TCGLabel *l = &s->labels[label_index];
- if (l->has_value)
- tcg_out32 (s, bc | reloc_pc14_val (s->code_ptr, l->u.value));
- else {
- uint16_t val = *(uint16_t *) &s->code_ptr[2];
-
+ if (l->has_value) {
+ tcg_out32(s, bc | reloc_pc14_val(s->code_ptr, l->u.value_ptr));
+ } else {
/* Thanks to Andrzej Zaborowski */
- tcg_out32 (s, bc | (val & 0xfffc));
- tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0);
+ tcg_insn_unit retrans = *s->code_ptr & 0xfffc;
+ tcg_out_reloc(s, s->code_ptr, R_PPC_REL14, label_index, 0);
+ tcg_out32(s, bc | retrans);
}
}
@@ -1367,43 +1354,33 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
{
switch (opc) {
case INDEX_op_exit_tb:
- tcg_out_movi (s, TCG_TYPE_I32, TCG_REG_R3, args[0]);
- tcg_out_b (s, 0, (tcg_target_long) tb_ret_addr);
+ tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R3, args[0]);
+ tcg_out_b(s, 0, tb_ret_addr);
break;
case INDEX_op_goto_tb:
if (s->tb_jmp_offset) {
/* direct jump method */
-
- s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
- s->code_ptr += 16;
- }
- else {
+ s->tb_jmp_offset[args[0]] = tcg_current_code_size(s);
+ s->code_ptr += 4;
+ } else {
tcg_abort ();
}
- s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
+ s->tb_next_offset[args[0]] = tcg_current_code_size(s);
break;
case INDEX_op_br:
{
TCGLabel *l = &s->labels[args[0]];
if (l->has_value) {
- tcg_out_b (s, 0, l->u.value);
- }
- else {
- uint32_t val = *(uint32_t *) s->code_ptr;
-
+ tcg_out_b(s, 0, l->u.value_ptr);
+ } else {
/* Thanks to Andrzej Zaborowski */
- tcg_out32 (s, B | (val & 0x3fffffc));
- tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL24, args[0], 0);
+ tcg_insn_unit retrans = *s->code_ptr & 0x3fffffc;
+ tcg_out_reloc(s, s->code_ptr, R_PPC_REL24, args[0], 0);
+ tcg_out32(s, B | retrans);
}
}
break;
- case INDEX_op_call:
- tcg_out_call (s, args[0], const_args[0], LK);
- break;
- case INDEX_op_movi_i32:
- tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
- break;
case INDEX_op_ld8u_i32:
tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
break;
@@ -1839,20 +1816,19 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
const_args[2]);
break;
+ case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
+ case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
+ case INDEX_op_call: /* Always emitted via tcg_out_call. */
default:
- tcg_dump_ops (s);
- tcg_abort ();
+ tcg_abort();
}
}
static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
- { INDEX_op_call, { "ri" } },
{ INDEX_op_br, { } },
- { INDEX_op_mov_i32, { "r", "r" } },
- { INDEX_op_movi_i32, { "r" } },
{ INDEX_op_ld8u_i32, { "r", "r" } },
{ INDEX_op_ld8s_i32, { "r", "r" } },
{ INDEX_op_ld16u_i32, { "r", "r" } },
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index 0d4f5959a7..dd7e557948 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -25,6 +25,7 @@
#define TCG_TARGET_PPC 1
#define TCG_TARGET_NB_REGS 32
+#define TCG_TARGET_INSN_UNIT_SIZE 4
typedef enum {
TCG_REG_R0 = 0,
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 45b1c06910..c90ddcd03a 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -31,7 +31,7 @@
#define TCG_CT_CONST_ZERO 0x1000
#define TCG_CT_CONST_MONE 0x2000
-static uint8_t *tb_ret_addr;
+static tcg_insn_unit *tb_ret_addr;
#if TARGET_LONG_BITS == 32
#define LD_ADDR LWZ
@@ -168,61 +168,54 @@ static inline bool in_range_b(tcg_target_long target)
return target == sextract64(target, 0, 26);
}
-static uint32_t reloc_pc24_val(void *pc, tcg_target_long target)
+static uint32_t reloc_pc24_val(tcg_insn_unit *pc, tcg_insn_unit *target)
{
- tcg_target_long disp;
-
- disp = target - (tcg_target_long)pc;
+ ptrdiff_t disp = tcg_ptr_byte_diff(target, pc);
assert(in_range_b(disp));
-
return disp & 0x3fffffc;
}
-static void reloc_pc24(void *pc, tcg_target_long target)
+static void reloc_pc24(tcg_insn_unit *pc, tcg_insn_unit *target)
{
- *(uint32_t *)pc = (*(uint32_t *)pc & ~0x3fffffc)
- | reloc_pc24_val(pc, target);
+ *pc = (*pc & ~0x3fffffc) | reloc_pc24_val(pc, target);
}
-static uint16_t reloc_pc14_val(void *pc, tcg_target_long target)
+static uint16_t reloc_pc14_val(tcg_insn_unit *pc, tcg_insn_unit *target)
{
- tcg_target_long disp;
-
- disp = target - (tcg_target_long)pc;
- if (disp != (int16_t) disp) {
- tcg_abort();
- }
-
+ ptrdiff_t disp = tcg_ptr_byte_diff(target, pc);
+ assert(disp == (int16_t) disp);
return disp & 0xfffc;
}
-static void reloc_pc14(void *pc, tcg_target_long target)
+static void reloc_pc14(tcg_insn_unit *pc, tcg_insn_unit *target)
{
- *(uint32_t *)pc = (*(uint32_t *)pc & ~0xfffc) | reloc_pc14_val(pc, target);
+ *pc = (*pc & ~0xfffc) | reloc_pc14_val(pc, target);
}
static inline void tcg_out_b_noaddr(TCGContext *s, int insn)
{
- unsigned retrans = *(uint32_t *)s->code_ptr & 0x3fffffc;
+ unsigned retrans = *s->code_ptr & 0x3fffffc;
tcg_out32(s, insn | retrans);
}
static inline void tcg_out_bc_noaddr(TCGContext *s, int insn)
{
- unsigned retrans = *(uint32_t *)s->code_ptr & 0xfffc;
+ unsigned retrans = *s->code_ptr & 0xfffc;
tcg_out32(s, insn | retrans);
}
-static void patch_reloc(uint8_t *code_ptr, int type,
+static void patch_reloc(tcg_insn_unit *code_ptr, int type,
intptr_t value, intptr_t addend)
{
- value += addend;
+ tcg_insn_unit *target = (tcg_insn_unit *)value;
+
+ assert(addend == 0);
switch (type) {
case R_PPC_REL14:
- reloc_pc14(code_ptr, value);
+ reloc_pc14(code_ptr, target);
break;
case R_PPC_REL24:
- reloc_pc24(code_ptr, value);
+ reloc_pc24(code_ptr, target);
break;
default:
tcg_abort();
@@ -702,61 +695,48 @@ static void tcg_out_xori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
tcg_out_zori32(s, dst, src, c, XORI, XORIS);
}
-static void tcg_out_b(TCGContext *s, int mask, tcg_target_long target)
+static void tcg_out_b(TCGContext *s, int mask, tcg_insn_unit *target)
{
- tcg_target_long disp;
-
- disp = target - (tcg_target_long)s->code_ptr;
+ ptrdiff_t disp = tcg_pcrel_diff(s, target);
if (in_range_b(disp)) {
tcg_out32(s, B | (disp & 0x3fffffc) | mask);
} else {
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R0, (tcg_target_long)target);
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R0, (uintptr_t)target);
tcg_out32(s, MTSPR | RS(TCG_REG_R0) | CTR);
tcg_out32(s, BCCTR | BO_ALWAYS | mask);
}
}
-static void tcg_out_call(TCGContext *s, tcg_target_long arg, int const_arg)
+static void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
{
#ifdef __APPLE__
- if (const_arg) {
- tcg_out_b(s, LK, arg);
- } else {
- tcg_out32(s, MTSPR | RS(arg) | LR);
- tcg_out32(s, BCLR | BO_ALWAYS | LK);
- }
+ tcg_out_b(s, LK, target);
#else
- TCGReg reg = arg;
- int ofs = 0;
-
- if (const_arg) {
- /* Look through the descriptor. If the branch is in range, and we
- don't have to spend too much effort on building the toc. */
- intptr_t tgt = ((intptr_t *)arg)[0];
- intptr_t toc = ((intptr_t *)arg)[1];
- intptr_t diff = tgt - (intptr_t)s->code_ptr;
-
- if (in_range_b(diff) && toc == (uint32_t)toc) {
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R2, toc);
- tcg_out_b(s, LK, tgt);
- return;
- }
-
+ /* Look through the descriptor. If the branch is in range, and we
+ don't have to spend too much effort on building the toc. */
+ void *tgt = ((void **)target)[0];
+ uintptr_t toc = ((uintptr_t *)target)[1];
+ intptr_t diff = tcg_pcrel_diff(s, tgt);
+
+ if (in_range_b(diff) && toc == (uint32_t)toc) {
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R2, toc);
+ tcg_out_b(s, LK, tgt);
+ } else {
/* Fold the low bits of the constant into the addresses below. */
- ofs = (int16_t)arg;
+ intptr_t arg = (intptr_t)target;
+ int ofs = (int16_t)arg;
+
if (ofs + 8 < 0x8000) {
arg -= ofs;
} else {
ofs = 0;
}
- reg = TCG_REG_R2;
- tcg_out_movi(s, TCG_TYPE_I64, reg, arg);
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R2, arg);
+ tcg_out32(s, LD | TAI(TCG_REG_R0, TCG_REG_R2, ofs));
+ tcg_out32(s, MTSPR | RA(TCG_REG_R0) | CTR);
+ tcg_out32(s, LD | TAI(TCG_REG_R2, TCG_REG_R2, ofs + 8));
+ tcg_out32(s, BCCTR | BO_ALWAYS | LK);
}
-
- tcg_out32(s, LD | TAI(TCG_REG_R0, reg, ofs));
- tcg_out32(s, MTSPR | RA(TCG_REG_R0) | CTR);
- tcg_out32(s, LD | TAI(TCG_REG_R2, reg, ofs + 8));
- tcg_out32(s, BCCTR | BO_ALWAYS | LK);
#endif
}
@@ -844,7 +824,7 @@ static const uint32_t qemu_exts_opc[4] = {
/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
* int mmu_idx, uintptr_t ra)
*/
-static const void * const qemu_ld_helpers[16] = {
+static void * const qemu_ld_helpers[16] = {
[MO_UB] = helper_ret_ldub_mmu,
[MO_LEUW] = helper_le_lduw_mmu,
[MO_LEUL] = helper_le_ldul_mmu,
@@ -857,7 +837,7 @@ static const void * const qemu_ld_helpers[16] = {
/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
* uintxx_t val, int mmu_idx, uintptr_t ra)
*/
-static const void * const qemu_st_helpers[16] = {
+static void * const qemu_st_helpers[16] = {
[MO_UB] = helper_ret_stb_mmu,
[MO_LEUW] = helper_le_stw_mmu,
[MO_LEUL] = helper_le_stl_mmu,
@@ -946,7 +926,7 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp s_bits, TCGReg addr_reg,
helper code. */
static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
int data_reg, int addr_reg, int mem_index,
- uint8_t *raddr, uint8_t *label_ptr)
+ tcg_insn_unit *raddr, tcg_insn_unit *label_ptr)
{
TCGLabelQemuLdst *label = new_ldst_label(s);
@@ -963,7 +943,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
{
TCGMemOp opc = lb->opc;
- reloc_pc14(lb->label_ptr[0], (uintptr_t)s->code_ptr);
+ reloc_pc14(lb->label_ptr[0], s->code_ptr);
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_R3, TCG_AREG0);
@@ -974,7 +954,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R5, lb->mem_index);
tcg_out32(s, MFSPR | RT(TCG_REG_R6) | LR);
- tcg_out_call(s, (tcg_target_long)qemu_ld_helpers[opc & ~MO_SIGN], 1);
+ tcg_out_call(s, qemu_ld_helpers[opc & ~MO_SIGN]);
if (opc & MO_SIGN) {
uint32_t insn = qemu_exts_opc[opc & MO_SIZE];
@@ -983,7 +963,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
tcg_out_mov(s, TCG_TYPE_I64, lb->datalo_reg, TCG_REG_R3);
}
- tcg_out_b(s, 0, (uintptr_t)lb->raddr);
+ tcg_out_b(s, 0, lb->raddr);
}
static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
@@ -991,7 +971,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
TCGMemOp opc = lb->opc;
TCGMemOp s_bits = opc & MO_SIZE;
- reloc_pc14(lb->label_ptr[0], (uintptr_t)s->code_ptr);
+ reloc_pc14(lb->label_ptr[0], s->code_ptr);
tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R3, TCG_AREG0);
@@ -1004,9 +984,9 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R6, lb->mem_index);
tcg_out32(s, MFSPR | RT(TCG_REG_R7) | LR);
- tcg_out_call(s, (tcg_target_long)qemu_st_helpers[opc], 1);
+ tcg_out_call(s, qemu_st_helpers[opc]);
- tcg_out_b(s, 0, (uintptr_t)lb->raddr);
+ tcg_out_b(s, 0, lb->raddr);
}
#endif /* SOFTMMU */
@@ -1017,7 +997,7 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
uint32_t insn;
TCGMemOp s_bits = opc & MO_SIZE;
#ifdef CONFIG_SOFTMMU
- void *label_ptr;
+ tcg_insn_unit *label_ptr;
#endif
#ifdef CONFIG_SOFTMMU
@@ -1063,7 +1043,7 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
TCGReg rbase;
uint32_t insn;
#ifdef CONFIG_SOFTMMU
- void *label_ptr;
+ tcg_insn_unit *label_ptr;
#endif
#ifdef CONFIG_SOFTMMU
@@ -1123,7 +1103,8 @@ static void tcg_target_qemu_prologue(TCGContext *s)
#ifndef __APPLE__
/* First emit adhoc function descriptor */
tcg_out64(s, (uint64_t)s->code_ptr + 24); /* entry point */
- s->code_ptr += 16; /* skip TOC and environment pointer */
+ tcg_out64(s, 0); /* toc */
+ tcg_out64(s, 0); /* environment pointer */
#endif
/* Prologue */
@@ -1415,7 +1396,7 @@ static void tcg_out_bc(TCGContext *s, int bc, int label_index)
TCGLabel *l = &s->labels[label_index];
if (l->has_value) {
- tcg_out32(s, bc | reloc_pc14_val(s->code_ptr, l->u.value));
+ tcg_out32(s, bc | reloc_pc14_val(s->code_ptr, l->u.value_ptr));
} else {
tcg_out_reloc(s, s->code_ptr, R_PPC_REL14, label_index, 0);
tcg_out_bc_noaddr(s, bc);
@@ -1478,15 +1459,13 @@ static void tcg_out_movcond(TCGContext *s, TCGType type, TCGCond cond,
}
}
-void ppc_tb_set_jmp_target(unsigned long jmp_addr, unsigned long addr)
+void ppc_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr)
{
TCGContext s;
- unsigned long patch_size;
- s.code_ptr = (uint8_t *) jmp_addr;
- tcg_out_b(&s, 0, addr);
- patch_size = s.code_ptr - (uint8_t *) jmp_addr;
- flush_icache_range(jmp_addr, jmp_addr + patch_size);
+ s.code_buf = s.code_ptr = (tcg_insn_unit *)jmp_addr;
+ tcg_out_b(&s, 0, (tcg_insn_unit *)addr);
+ flush_icache_range(jmp_addr, jmp_addr + tcg_current_code_size(&s));
}
static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
@@ -1498,40 +1477,31 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
switch (opc) {
case INDEX_op_exit_tb:
tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R3, args[0]);
- tcg_out_b(s, 0, (tcg_target_long)tb_ret_addr);
+ tcg_out_b(s, 0, tb_ret_addr);
break;
case INDEX_op_goto_tb:
if (s->tb_jmp_offset) {
/* Direct jump method. */
- s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
- s->code_ptr += 28;
+ s->tb_jmp_offset[args[0]] = tcg_current_code_size(s);
+ s->code_ptr += 7;
} else {
/* Indirect jump method. */
tcg_abort();
}
- s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
+ s->tb_next_offset[args[0]] = tcg_current_code_size(s);
break;
case INDEX_op_br:
{
TCGLabel *l = &s->labels[args[0]];
if (l->has_value) {
- tcg_out_b(s, 0, l->u.value);
+ tcg_out_b(s, 0, l->u.value_ptr);
} else {
tcg_out_reloc(s, s->code_ptr, R_PPC_REL24, args[0], 0);
tcg_out_b_noaddr(s, B);
}
}
break;
- case INDEX_op_call:
- tcg_out_call(s, args[0], const_args[0]);
- break;
- case INDEX_op_movi_i32:
- tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
- break;
- case INDEX_op_movi_i64:
- tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
- break;
case INDEX_op_ld8u_i32:
case INDEX_op_ld8u_i64:
tcg_out_mem_long(s, LBZ, LBZX, args[0], args[1], args[2]);
@@ -2012,8 +1982,12 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
tcg_out32(s, MULHD | TAB(args[0], args[1], args[2]));
break;
+ case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
+ case INDEX_op_mov_i64:
+ case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
+ case INDEX_op_movi_i64:
+ case INDEX_op_call: /* Always emitted via tcg_out_call. */
default:
- tcg_dump_ops(s);
tcg_abort();
}
}
@@ -2021,14 +1995,8 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
- { INDEX_op_call, { "ri" } },
{ INDEX_op_br, { } },
- { INDEX_op_mov_i32, { "r", "r" } },
- { INDEX_op_mov_i64, { "r", "r" } },
- { INDEX_op_movi_i32, { "r" } },
- { INDEX_op_movi_i64, { "r" } },
-
{ INDEX_op_ld8u_i32, { "r", "r" } },
{ INDEX_op_ld8s_i32, { "r", "r" } },
{ INDEX_op_ld16u_i32, { "r", "r" } },
diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h
index 3815b840a6..29f479a3cf 100644
--- a/tcg/ppc64/tcg-target.h
+++ b/tcg/ppc64/tcg-target.h
@@ -25,6 +25,7 @@
#define TCG_TARGET_PPC64 1
#define TCG_TARGET_NB_REGS 32
+#define TCG_TARGET_INSN_UNIT_SIZE 4
typedef enum {
TCG_REG_R0 = 0,
diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index 1d912a7937..ebdd0743cf 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -320,7 +320,7 @@ static const uint8_t tcg_cond_to_ltr_cond[] = {
#ifdef CONFIG_SOFTMMU
/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
int mmu_idx) */
-static const void * const qemu_ld_helpers[4] = {
+static void * const qemu_ld_helpers[4] = {
helper_ldb_mmu,
helper_ldw_mmu,
helper_ldl_mmu,
@@ -329,7 +329,7 @@ static const void * const qemu_ld_helpers[4] = {
/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
uintxx_t val, int mmu_idx) */
-static const void * const qemu_st_helpers[4] = {
+static void * const qemu_st_helpers[4] = {
helper_stb_mmu,
helper_stw_mmu,
helper_stl_mmu,
@@ -337,7 +337,7 @@ static const void * const qemu_st_helpers[4] = {
};
#endif
-static uint8_t *tb_ret_addr;
+static tcg_insn_unit *tb_ret_addr;
/* A list of relevant facilities used by this translator. Some of these
are required for proper operation, and these are checked at startup. */
@@ -350,23 +350,20 @@ static uint8_t *tb_ret_addr;
static uint64_t facilities;
-static void patch_reloc(uint8_t *code_ptr, int type,
+static void patch_reloc(tcg_insn_unit *code_ptr, int type,
intptr_t value, intptr_t addend)
{
- intptr_t code_ptr_tl = (intptr_t)code_ptr;
- intptr_t pcrel2;
-
- /* ??? Not the usual definition of "addend". */
- pcrel2 = (value - (code_ptr_tl + addend)) >> 1;
+ intptr_t pcrel2 = (tcg_insn_unit *)value - (code_ptr - 1);
+ assert(addend == -2);
switch (type) {
case R_390_PC16DBL:
assert(pcrel2 == (int16_t)pcrel2);
- *(int16_t *)code_ptr = pcrel2;
+ tcg_patch16(code_ptr, pcrel2);
break;
case R_390_PC32DBL:
assert(pcrel2 == (int32_t)pcrel2);
- *(int32_t *)code_ptr = pcrel2;
+ tcg_patch32(code_ptr, pcrel2);
break;
default:
tcg_abort();
@@ -672,7 +669,7 @@ static void tcg_out_movi(TCGContext *s, TCGType type,
/* Try for PC-relative address load. */
if ((sval & 1) == 0) {
- intptr_t off = (sval - (intptr_t)s->code_ptr) >> 1;
+ ptrdiff_t off = tcg_pcrel_diff(s, (void *)sval) >> 1;
if (off == (int32_t)off) {
tcg_out_insn(s, RIL, LARL, ret, off);
return;
@@ -789,10 +786,10 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg data,
/* load data from an absolute host address */
static void tcg_out_ld_abs(TCGContext *s, TCGType type, TCGReg dest, void *abs)
{
- tcg_target_long addr = (tcg_target_long)abs;
+ intptr_t addr = (intptr_t)abs;
- if (facilities & FACILITY_GEN_INST_EXT) {
- tcg_target_long disp = (addr - (tcg_target_long)s->code_ptr) >> 1;
+ if ((facilities & FACILITY_GEN_INST_EXT) && !(addr & 1)) {
+ ptrdiff_t disp = tcg_pcrel_diff(s, abs) >> 1;
if (disp == (int32_t)disp) {
if (type == TCG_TYPE_I32) {
tcg_out_insn(s, RIL, LRL, dest, disp);
@@ -1154,15 +1151,15 @@ static void tgen_deposit(TCGContext *s, TCGReg dest, TCGReg src,
tcg_out_risbg(s, dest, src, msb, lsb, ofs, 0);
}
-static void tgen_gotoi(TCGContext *s, int cc, tcg_target_long dest)
+static void tgen_gotoi(TCGContext *s, int cc, tcg_insn_unit *dest)
{
- tcg_target_long off = (dest - (tcg_target_long)s->code_ptr) >> 1;
- if (off > -0x8000 && off < 0x7fff) {
+ ptrdiff_t off = dest - s->code_ptr;
+ if (off == (int16_t)off) {
tcg_out_insn(s, RI, BRC, cc, off);
} else if (off == (int32_t)off) {
tcg_out_insn(s, RIL, BRCL, cc, off);
} else {
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, dest);
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, (uintptr_t)dest);
tcg_out_insn(s, RR, BCR, cc, TCG_TMP0);
}
}
@@ -1171,15 +1168,15 @@ static void tgen_branch(TCGContext *s, int cc, int labelno)
{
TCGLabel* l = &s->labels[labelno];
if (l->has_value) {
- tgen_gotoi(s, cc, l->u.value);
+ tgen_gotoi(s, cc, l->u.value_ptr);
} else if (USE_LONG_BRANCHES) {
tcg_out16(s, RIL_BRCL | (cc << 4));
tcg_out_reloc(s, s->code_ptr, R_390_PC32DBL, labelno, -2);
- s->code_ptr += 4;
+ s->code_ptr += 2;
} else {
tcg_out16(s, RI_BRC | (cc << 4));
tcg_out_reloc(s, s->code_ptr, R_390_PC16DBL, labelno, -2);
- s->code_ptr += 2;
+ s->code_ptr += 1;
}
}
@@ -1187,14 +1184,14 @@ static void tgen_compare_branch(TCGContext *s, S390Opcode opc, int cc,
TCGReg r1, TCGReg r2, int labelno)
{
TCGLabel* l = &s->labels[labelno];
- tcg_target_long off;
+ intptr_t off;
if (l->has_value) {
- off = (l->u.value - (tcg_target_long)s->code_ptr) >> 1;
+ off = l->u.value_ptr - s->code_ptr;
} else {
/* We need to keep the offset unchanged for retranslation. */
- off = ((int16_t *)s->code_ptr)[1];
- tcg_out_reloc(s, s->code_ptr + 2, R_390_PC16DBL, labelno, -2);
+ off = s->code_ptr[1];
+ tcg_out_reloc(s, s->code_ptr + 1, R_390_PC16DBL, labelno, -2);
}
tcg_out16(s, (opc & 0xff00) | (r1 << 4) | r2);
@@ -1209,11 +1206,11 @@ static void tgen_compare_imm_branch(TCGContext *s, S390Opcode opc, int cc,
tcg_target_long off;
if (l->has_value) {
- off = (l->u.value - (tcg_target_long)s->code_ptr) >> 1;
+ off = l->u.value_ptr - s->code_ptr;
} else {
/* We need to keep the offset unchanged for retranslation. */
- off = ((int16_t *)s->code_ptr)[1];
- tcg_out_reloc(s, s->code_ptr + 2, R_390_PC16DBL, labelno, -2);
+ off = s->code_ptr[1];
+ tcg_out_reloc(s, s->code_ptr + 1, R_390_PC16DBL, labelno, -2);
}
tcg_out16(s, (opc & 0xff00) | (r1 << 4) | cc);
@@ -1272,13 +1269,13 @@ static void tgen_brcond(TCGContext *s, TCGType type, TCGCond c,
tgen_branch(s, cc, labelno);
}
-static void tgen_calli(TCGContext *s, tcg_target_long dest)
+static void tcg_out_call(TCGContext *s, tcg_insn_unit *dest)
{
- tcg_target_long off = (dest - (tcg_target_long)s->code_ptr) >> 1;
+ ptrdiff_t off = dest - s->code_ptr;
if (off == (int32_t)off) {
tcg_out_insn(s, RIL, BRASL, TCG_REG_R14, off);
} else {
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, dest);
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, (uintptr_t)dest);
tcg_out_insn(s, RR, BASR, TCG_REG_R14, TCG_TMP0);
}
}
@@ -1395,14 +1392,14 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int opc, TCGReg data,
#if defined(CONFIG_SOFTMMU)
static TCGReg tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg,
TCGReg addr_reg, int mem_index, int opc,
- uint16_t **label2_ptr_p, int is_store)
+ tcg_insn_unit **label2_ptr_p, int is_store)
{
const TCGReg arg0 = tcg_target_call_iarg_regs[0];
const TCGReg arg1 = tcg_target_call_iarg_regs[1];
const TCGReg arg2 = tcg_target_call_iarg_regs[2];
const TCGReg arg3 = tcg_target_call_iarg_regs[3];
int s_bits = opc & 3;
- uint16_t *label1_ptr;
+ tcg_insn_unit *label1_ptr;
tcg_target_long ofs;
if (TARGET_LONG_BITS == 32) {
@@ -1436,7 +1433,7 @@ static TCGReg tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg,
tcg_out_mov(s, TCG_TYPE_I64, arg1, addr_reg);
}
- label1_ptr = (uint16_t*)s->code_ptr;
+ label1_ptr = s->code_ptr;
/* je label1 (offset will be patched in later) */
tcg_out_insn(s, RI, BRC, S390_CC_EQ, 0);
@@ -1463,11 +1460,11 @@ static TCGReg tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg,
}
tcg_out_movi(s, TCG_TYPE_I32, arg3, mem_index);
tcg_out_mov(s, TCG_TYPE_I64, arg0, TCG_AREG0);
- tgen_calli(s, (tcg_target_ulong)qemu_st_helpers[s_bits]);
+ tcg_out_call(s, qemu_st_helpers[s_bits]);
} else {
tcg_out_movi(s, TCG_TYPE_I32, arg2, mem_index);
tcg_out_mov(s, TCG_TYPE_I64, arg0, TCG_AREG0);
- tgen_calli(s, (tcg_target_ulong)qemu_ld_helpers[s_bits]);
+ tcg_out_call(s, qemu_ld_helpers[s_bits]);
/* sign extension */
switch (opc) {
@@ -1488,13 +1485,12 @@ static TCGReg tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg,
}
/* jump to label2 (end) */
- *label2_ptr_p = (uint16_t*)s->code_ptr;
+ *label2_ptr_p = s->code_ptr;
tcg_out_insn(s, RI, BRC, S390_CC_ALWAYS, 0);
/* this is label1, patch branch */
- *(label1_ptr + 1) = ((unsigned long)s->code_ptr -
- (unsigned long)label1_ptr) >> 1;
+ label1_ptr[1] = s->code_ptr - label1_ptr;
ofs = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
assert(ofs < 0x80000);
@@ -1504,11 +1500,10 @@ static TCGReg tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg,
return arg1;
}
-static void tcg_finish_qemu_ldst(TCGContext* s, uint16_t *label2_ptr)
+static void tcg_finish_qemu_ldst(TCGContext* s, tcg_insn_unit *label2_ptr)
{
/* patch branch */
- *(label2_ptr + 1) = ((unsigned long)s->code_ptr -
- (unsigned long)label2_ptr) >> 1;
+ label2_ptr[1] = s->code_ptr - label2_ptr;
}
#else
static void tcg_prepare_user_ldst(TCGContext *s, TCGReg *addr_reg,
@@ -1535,7 +1530,7 @@ static void tcg_out_qemu_ld(TCGContext* s, const TCGArg* args, int opc)
TCGReg addr_reg, data_reg;
#if defined(CONFIG_SOFTMMU)
int mem_index;
- uint16_t *label2_ptr;
+ tcg_insn_unit *label2_ptr;
#else
TCGReg index_reg;
tcg_target_long disp;
@@ -1564,7 +1559,7 @@ static void tcg_out_qemu_st(TCGContext* s, const TCGArg* args, int opc)
TCGReg addr_reg, data_reg;
#if defined(CONFIG_SOFTMMU)
int mem_index;
- uint16_t *label2_ptr;
+ tcg_insn_unit *label2_ptr;
#else
TCGReg index_reg;
tcg_target_long disp;
@@ -1602,7 +1597,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_exit_tb:
/* return value */
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, args[0]);
- tgen_gotoi(s, S390_CC_ALWAYS, (unsigned long)tb_ret_addr);
+ tgen_gotoi(s, S390_CC_ALWAYS, tb_ret_addr);
break;
case INDEX_op_goto_tb:
@@ -1614,22 +1609,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
/* and go there */
tcg_out_insn(s, RR, BCR, S390_CC_ALWAYS, TCG_TMP0);
}
- s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
- break;
-
- case INDEX_op_call:
- if (const_args[0]) {
- tgen_calli(s, args[0]);
- } else {
- tcg_out_insn(s, RR, BASR, TCG_REG_R14, args[0]);
- }
- break;
-
- case INDEX_op_mov_i32:
- tcg_out_mov(s, TCG_TYPE_I32, args[0], args[1]);
- break;
- case INDEX_op_movi_i32:
- tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
+ s->tb_next_offset[args[0]] = tcg_current_code_size(s);
break;
OP_32_64(ld8u):
@@ -1864,13 +1844,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_qemu_st(s, args, LD_UINT64);
break;
- case INDEX_op_mov_i64:
- tcg_out_mov(s, TCG_TYPE_I64, args[0], args[1]);
- break;
- case INDEX_op_movi_i64:
- tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
- break;
-
case INDEX_op_ld16s_i64:
tcg_out_mem(s, 0, RXY_LGH, args[0], args[1], TCG_REG_NONE, args[2]);
break;
@@ -2075,8 +2048,12 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tgen_deposit(s, args[0], args[2], args[3], args[4]);
break;
+ case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
+ case INDEX_op_mov_i64:
+ case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
+ case INDEX_op_movi_i64:
+ case INDEX_op_call: /* Always emitted via tcg_out_call. */
default:
- fprintf(stderr,"unimplemented opc 0x%x\n",opc);
tcg_abort();
}
}
@@ -2084,12 +2061,8 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
static const TCGTargetOpDef s390_op_defs[] = {
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
- { INDEX_op_call, { "ri" } },
{ INDEX_op_br, { } },
- { INDEX_op_mov_i32, { "r", "r" } },
- { INDEX_op_movi_i32, { "r" } },
-
{ INDEX_op_ld8u_i32, { "r", "r" } },
{ INDEX_op_ld8s_i32, { "r", "r" } },
{ INDEX_op_ld16u_i32, { "r", "r" } },
@@ -2147,9 +2120,6 @@ static const TCGTargetOpDef s390_op_defs[] = {
{ INDEX_op_qemu_st32, { "L", "L" } },
{ INDEX_op_qemu_st64, { "L", "L" } },
- { INDEX_op_mov_i64, { "r", "r" } },
- { INDEX_op_movi_i64, { "r" } },
-
{ INDEX_op_ld8u_i64, { "r", "r" } },
{ INDEX_op_ld8s_i64, { "r", "r" } },
{ INDEX_op_ld16u_i64, { "r", "r" } },
diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h
index 755c00237e..5bf733eb3d 100644
--- a/tcg/s390/tcg-target.h
+++ b/tcg/s390/tcg-target.h
@@ -24,6 +24,8 @@
#ifndef TCG_TARGET_S390
#define TCG_TARGET_S390 1
+#define TCG_TARGET_INSN_UNIT_SIZE 2
+
typedef enum TCGReg {
TCG_REG_R0 = 0,
TCG_REG_R1,
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 5468ff5c16..17ff5773ad 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -279,37 +279,32 @@ static inline int check_fit_i32(int32_t val, unsigned int bits)
# define check_fit_ptr check_fit_i32
#endif
-static void patch_reloc(uint8_t *code_ptr, int type,
+static void patch_reloc(tcg_insn_unit *code_ptr, int type,
intptr_t value, intptr_t addend)
{
uint32_t insn;
- value += addend;
+
+ assert(addend == 0);
+ value = tcg_ptr_byte_diff((tcg_insn_unit *)value, code_ptr);
+
switch (type) {
- case R_SPARC_32:
- if (value != (uint32_t)value) {
- tcg_abort();
- }
- *(uint32_t *)code_ptr = value;
- break;
case R_SPARC_WDISP16:
- value -= (intptr_t)code_ptr;
if (!check_fit_ptr(value >> 2, 16)) {
tcg_abort();
}
- insn = *(uint32_t *)code_ptr;
+ insn = *code_ptr;
insn &= ~INSN_OFF16(-1);
insn |= INSN_OFF16(value);
- *(uint32_t *)code_ptr = insn;
+ *code_ptr = insn;
break;
case R_SPARC_WDISP19:
- value -= (intptr_t)code_ptr;
if (!check_fit_ptr(value >> 2, 19)) {
tcg_abort();
}
- insn = *(uint32_t *)code_ptr;
+ insn = *code_ptr;
insn &= ~INSN_OFF19(-1);
insn |= INSN_OFF19(value);
- *(uint32_t *)code_ptr = insn;
+ *code_ptr = insn;
break;
default:
tcg_abort();
@@ -573,10 +568,10 @@ static void tcg_out_bpcc(TCGContext *s, int scond, int flags, int label)
int off19;
if (l->has_value) {
- off19 = INSN_OFF19(l->u.value - (unsigned long)s->code_ptr);
+ off19 = INSN_OFF19(tcg_pcrel_diff(s, l->u.value_ptr));
} else {
/* Make sure to preserve destinations during retranslation. */
- off19 = *(uint32_t *)s->code_ptr & INSN_OFF19(-1);
+ off19 = *s->code_ptr & INSN_OFF19(-1);
tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP19, label, 0);
}
tcg_out_bpcc0(s, scond, flags, off19);
@@ -620,10 +615,10 @@ static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, TCGReg arg1,
int off16;
if (l->has_value) {
- off16 = INSN_OFF16(l->u.value - (unsigned long)s->code_ptr);
+ off16 = INSN_OFF16(tcg_pcrel_diff(s, l->u.value_ptr));
} else {
/* Make sure to preserve destinations during retranslation. */
- off16 = *(uint32_t *)s->code_ptr & INSN_OFF16(-1);
+ off16 = *s->code_ptr & INSN_OFF16(-1);
tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP16, label, 0);
}
tcg_out32(s, INSN_OP(0) | INSN_OP2(3) | BPR_PT | INSN_RS1(arg1)
@@ -740,62 +735,66 @@ static void tcg_out_addsub2(TCGContext *s, TCGReg rl, TCGReg rh,
tcg_out_mov(s, TCG_TYPE_I32, rl, tmp);
}
-static void tcg_out_calli(TCGContext *s, uintptr_t dest)
+static void tcg_out_call_nodelay(TCGContext *s, tcg_insn_unit *dest)
{
- intptr_t disp = dest - (uintptr_t)s->code_ptr;
+ ptrdiff_t disp = tcg_pcrel_diff(s, dest);
if (disp == (int32_t)disp) {
tcg_out32(s, CALL | (uint32_t)disp >> 2);
} else {
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, dest & ~0xfff);
- tcg_out_arithi(s, TCG_REG_O7, TCG_REG_T1, dest & 0xfff, JMPL);
+ uintptr_t desti = (uintptr_t)dest;
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, desti & ~0xfff);
+ tcg_out_arithi(s, TCG_REG_O7, TCG_REG_T1, desti & 0xfff, JMPL);
}
}
+static void tcg_out_call(TCGContext *s, tcg_insn_unit *dest)
+{
+ tcg_out_call_nodelay(s, dest);
+ tcg_out_nop(s);
+}
+
#ifdef CONFIG_SOFTMMU
-static uintptr_t qemu_ld_trampoline[16];
-static uintptr_t qemu_st_trampoline[16];
+static tcg_insn_unit *qemu_ld_trampoline[16];
+static tcg_insn_unit *qemu_st_trampoline[16];
static void build_trampolines(TCGContext *s)
{
- static uintptr_t const qemu_ld_helpers[16] = {
- [MO_UB] = (uintptr_t)helper_ret_ldub_mmu,
- [MO_SB] = (uintptr_t)helper_ret_ldsb_mmu,
- [MO_LEUW] = (uintptr_t)helper_le_lduw_mmu,
- [MO_LESW] = (uintptr_t)helper_le_ldsw_mmu,
- [MO_LEUL] = (uintptr_t)helper_le_ldul_mmu,
- [MO_LEQ] = (uintptr_t)helper_le_ldq_mmu,
- [MO_BEUW] = (uintptr_t)helper_be_lduw_mmu,
- [MO_BESW] = (uintptr_t)helper_be_ldsw_mmu,
- [MO_BEUL] = (uintptr_t)helper_be_ldul_mmu,
- [MO_BEQ] = (uintptr_t)helper_be_ldq_mmu,
+ static void * const qemu_ld_helpers[16] = {
+ [MO_UB] = helper_ret_ldub_mmu,
+ [MO_SB] = helper_ret_ldsb_mmu,
+ [MO_LEUW] = helper_le_lduw_mmu,
+ [MO_LESW] = helper_le_ldsw_mmu,
+ [MO_LEUL] = helper_le_ldul_mmu,
+ [MO_LEQ] = helper_le_ldq_mmu,
+ [MO_BEUW] = helper_be_lduw_mmu,
+ [MO_BESW] = helper_be_ldsw_mmu,
+ [MO_BEUL] = helper_be_ldul_mmu,
+ [MO_BEQ] = helper_be_ldq_mmu,
};
- static uintptr_t const qemu_st_helpers[16] = {
- [MO_UB] = (uintptr_t)helper_ret_stb_mmu,
- [MO_LEUW] = (uintptr_t)helper_le_stw_mmu,
- [MO_LEUL] = (uintptr_t)helper_le_stl_mmu,
- [MO_LEQ] = (uintptr_t)helper_le_stq_mmu,
- [MO_BEUW] = (uintptr_t)helper_be_stw_mmu,
- [MO_BEUL] = (uintptr_t)helper_be_stl_mmu,
- [MO_BEQ] = (uintptr_t)helper_be_stq_mmu,
+ static void * const qemu_st_helpers[16] = {
+ [MO_UB] = helper_ret_stb_mmu,
+ [MO_LEUW] = helper_le_stw_mmu,
+ [MO_LEUL] = helper_le_stl_mmu,
+ [MO_LEQ] = helper_le_stq_mmu,
+ [MO_BEUW] = helper_be_stw_mmu,
+ [MO_BEUL] = helper_be_stl_mmu,
+ [MO_BEQ] = helper_be_stq_mmu,
};
int i;
TCGReg ra;
- uintptr_t tramp;
for (i = 0; i < 16; ++i) {
- if (qemu_ld_helpers[i] == 0) {
+ if (qemu_ld_helpers[i] == NULL) {
continue;
}
/* May as well align the trampoline. */
- tramp = (uintptr_t)s->code_ptr;
- while (tramp & 15) {
+ while ((uintptr_t)s->code_ptr & 15) {
tcg_out_nop(s);
- tramp += 4;
}
- qemu_ld_trampoline[i] = tramp;
+ qemu_ld_trampoline[i] = s->code_ptr;
if (SPARC64 || TARGET_LONG_BITS == 32) {
ra = TCG_REG_O3;
@@ -810,22 +809,20 @@ static void build_trampolines(TCGContext *s)
/* Set the env operand. */
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_O0, TCG_AREG0);
/* Tail call. */
- tcg_out_calli(s, qemu_ld_helpers[i]);
+ tcg_out_call_nodelay(s, qemu_ld_helpers[i]);
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_O7, ra);
}
for (i = 0; i < 16; ++i) {
- if (qemu_st_helpers[i] == 0) {
+ if (qemu_st_helpers[i] == NULL) {
continue;
}
/* May as well align the trampoline. */
- tramp = (uintptr_t)s->code_ptr;
- while (tramp & 15) {
+ while ((uintptr_t)s->code_ptr & 15) {
tcg_out_nop(s);
- tramp += 4;
}
- qemu_st_trampoline[i] = tramp;
+ qemu_st_trampoline[i] = s->code_ptr;
if (SPARC64) {
ra = TCG_REG_O4;
@@ -859,7 +856,7 @@ static void build_trampolines(TCGContext *s)
/* Set the env operand. */
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_O0, TCG_AREG0);
/* Tail call. */
- tcg_out_calli(s, qemu_st_helpers[i]);
+ tcg_out_call_nodelay(s, qemu_st_helpers[i]);
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_O7, ra);
}
}
@@ -1005,8 +1002,8 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data, TCGReg addr,
#ifdef CONFIG_SOFTMMU
TCGMemOp s_bits = memop & MO_SIZE;
TCGReg addrz, param;
- uintptr_t func;
- uint32_t *label_ptr;
+ tcg_insn_unit *func;
+ tcg_insn_unit *label_ptr;
addrz = tcg_out_tlb_load(s, addr, memi, s_bits,
offsetof(CPUTLBEntry, addr_read));
@@ -1016,7 +1013,7 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data, TCGReg addr,
over the TLB Miss case. */
/* beq,a,pt %[xi]cc, label0 */
- label_ptr = (uint32_t *)s->code_ptr;
+ label_ptr = s->code_ptr;
tcg_out_bpcc0(s, COND_E, BPCC_A | BPCC_PT
| (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
/* delay slot */
@@ -1038,8 +1035,8 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data, TCGReg addr,
} else {
func = qemu_ld_trampoline[memop];
}
- assert(func != 0);
- tcg_out_calli(s, func);
+ assert(func != NULL);
+ tcg_out_call_nodelay(s, func);
/* delay slot */
tcg_out_movi(s, TCG_TYPE_I32, param, memi);
@@ -1067,7 +1064,7 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data, TCGReg addr,
}
}
- *label_ptr |= INSN_OFF19((uintptr_t)s->code_ptr - (uintptr_t)label_ptr);
+ *label_ptr |= INSN_OFF19(tcg_ptr_byte_diff(s->code_ptr, label_ptr));
#else
if (SPARC64 && TARGET_LONG_BITS == 32) {
tcg_out_arithi(s, TCG_REG_T1, addr, 0, SHIFT_SRL);
@@ -1085,8 +1082,8 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data, TCGReg addr,
#ifdef CONFIG_SOFTMMU
TCGMemOp s_bits = memop & MO_SIZE;
TCGReg addrz, param;
- uintptr_t func;
- uint32_t *label_ptr;
+ tcg_insn_unit *func;
+ tcg_insn_unit *label_ptr;
addrz = tcg_out_tlb_load(s, addr, memi, s_bits,
offsetof(CPUTLBEntry, addr_write));
@@ -1094,7 +1091,7 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data, TCGReg addr,
/* The fast path is exactly one insn. Thus we can perform the entire
TLB Hit in the (annulled) delay slot of the branch over TLB Miss. */
/* beq,a,pt %[xi]cc, label0 */
- label_ptr = (uint32_t *)s->code_ptr;
+ label_ptr = s->code_ptr;
tcg_out_bpcc0(s, COND_E, BPCC_A | BPCC_PT
| (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
/* delay slot */
@@ -1115,12 +1112,12 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data, TCGReg addr,
tcg_out_mov(s, TCG_TYPE_REG, param++, data);
func = qemu_st_trampoline[memop];
- assert(func != 0);
- tcg_out_calli(s, func);
+ assert(func != NULL);
+ tcg_out_call_nodelay(s, func);
/* delay slot */
tcg_out_movi(s, TCG_TYPE_REG, param, memi);
- *label_ptr |= INSN_OFF19((uintptr_t)s->code_ptr - (uintptr_t)label_ptr);
+ *label_ptr |= INSN_OFF19(tcg_ptr_byte_diff(s->code_ptr, label_ptr));
#else
if (SPARC64 && TARGET_LONG_BITS == 32) {
tcg_out_arithi(s, TCG_REG_T1, addr, 0, SHIFT_SRL);
@@ -1159,26 +1156,16 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_goto_tb:
if (s->tb_jmp_offset) {
/* direct jump method */
- uint32_t old_insn = *(uint32_t *)s->code_ptr;
- s->tb_jmp_offset[a0] = s->code_ptr - s->code_buf;
+ s->tb_jmp_offset[a0] = tcg_current_code_size(s);
/* Make sure to preserve links during retranslation. */
- tcg_out32(s, CALL | (old_insn & ~INSN_OP(-1)));
+ tcg_out32(s, CALL | (*s->code_ptr & ~INSN_OP(-1)));
} else {
/* indirect jump method */
tcg_out_ld_ptr(s, TCG_REG_T1, (uintptr_t)(s->tb_next + a0));
tcg_out_arithi(s, TCG_REG_G0, TCG_REG_T1, 0, JMPL);
}
tcg_out_nop(s);
- s->tb_next_offset[a0] = s->code_ptr - s->code_buf;
- break;
- case INDEX_op_call:
- if (const_args[0]) {
- tcg_out_calli(s, a0);
- } else {
- tcg_out_arithi(s, TCG_REG_O7, a0, 0, JMPL);
- }
- /* delay slot */
- tcg_out_nop(s);
+ s->tb_next_offset[a0] = tcg_current_code_size(s);
break;
case INDEX_op_br:
tcg_out_bpcc(s, COND_A, BPCC_PT, a0);
@@ -1373,13 +1360,12 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_arithc(s, a0, TCG_REG_G0, a1, const_args[1], c);
break;
+ case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
case INDEX_op_mov_i64:
- case INDEX_op_mov_i32:
+ case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
case INDEX_op_movi_i64:
- case INDEX_op_movi_i32:
- /* Always implemented with tcg_out_mov/i, never with tcg_out_op. */
+ case INDEX_op_call: /* Always emitted via tcg_out_call. */
default:
- /* Opcode not implemented. */
tcg_abort();
}
}
@@ -1387,11 +1373,8 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
static const TCGTargetOpDef sparc_op_defs[] = {
{ INDEX_op_exit_tb, { } },
{ INDEX_op_goto_tb, { } },
- { INDEX_op_call, { "ri" } },
{ INDEX_op_br, { } },
- { INDEX_op_mov_i32, { "r", "r" } },
- { INDEX_op_movi_i32, { "r" } },
{ INDEX_op_ld8u_i32, { "r", "r" } },
{ INDEX_op_ld8s_i32, { "r", "r" } },
{ INDEX_op_ld16u_i32, { "r", "r" } },
@@ -1428,8 +1411,6 @@ static const TCGTargetOpDef sparc_op_defs[] = {
{ INDEX_op_mulu2_i32, { "r", "r", "rZ", "rJ" } },
{ INDEX_op_muls2_i32, { "r", "r", "rZ", "rJ" } },
- { INDEX_op_mov_i64, { "R", "R" } },
- { INDEX_op_movi_i64, { "R" } },
{ INDEX_op_ld8u_i64, { "R", "r" } },
{ INDEX_op_ld8s_i64, { "R", "r" } },
{ INDEX_op_ld16u_i64, { "R", "r" } },
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
index 3a903dbfd0..473bfc71fd 100644
--- a/tcg/sparc/tcg-target.h
+++ b/tcg/sparc/tcg-target.h
@@ -26,6 +26,7 @@
#define TCG_TARGET_REG_BITS 64
+#define TCG_TARGET_INSN_UNIT_SIZE 4
#define TCG_TARGET_NB_REGS 32
typedef enum {
diff --git a/tcg/tcg-be-ldst.h b/tcg/tcg-be-ldst.h
index ad94c0ca51..49b3de61ea 100644
--- a/tcg/tcg-be-ldst.h
+++ b/tcg/tcg-be-ldst.h
@@ -31,8 +31,8 @@ typedef struct TCGLabelQemuLdst {
TCGReg datalo_reg; /* reg index for low word to be loaded or stored */
TCGReg datahi_reg; /* reg index for high word to be loaded or stored */
int mem_index; /* soft MMU memory index */
- uint8_t *raddr; /* gen code addr of the next IR of qemu_ld/st IR */
- uint8_t *label_ptr[2]; /* label pointers to be updated */
+ tcg_insn_unit *raddr; /* gen code addr of the next IR of qemu_ld/st IR */
+ tcg_insn_unit *label_ptr[2]; /* label pointers to be updated */
} TCGLabelQemuLdst;
typedef struct TCGBackendData {
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index 6dbbb38838..bdd0139482 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -390,11 +390,7 @@ static inline int tcg_gen_sizemask(int n, int is_64bit, int is_signed)
static inline void tcg_gen_helperN(void *func, int flags, int sizemask,
TCGArg ret, int nargs, TCGArg *args)
{
- TCGv_ptr fn;
- fn = tcg_const_ptr(func);
- tcg_gen_callN(&tcg_ctx, fn, flags, sizemask, ret,
- nargs, args);
- tcg_temp_free_ptr(fn);
+ tcg_gen_callN(&tcg_ctx, func, flags, sizemask, ret, nargs, args);
}
/* Note: Both tcg_gen_helper32() and tcg_gen_helper64() are currently
@@ -405,29 +401,23 @@ static inline void tcg_gen_helperN(void *func, int flags, int sizemask,
static inline void tcg_gen_helper32(void *func, int sizemask, TCGv_i32 ret,
TCGv_i32 a, TCGv_i32 b)
{
- TCGv_ptr fn;
TCGArg args[2];
- fn = tcg_const_ptr(func);
args[0] = GET_TCGV_I32(a);
args[1] = GET_TCGV_I32(b);
- tcg_gen_callN(&tcg_ctx, fn,
+ tcg_gen_callN(&tcg_ctx, func,
TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_SIDE_EFFECTS,
sizemask, GET_TCGV_I32(ret), 2, args);
- tcg_temp_free_ptr(fn);
}
static inline void tcg_gen_helper64(void *func, int sizemask, TCGv_i64 ret,
TCGv_i64 a, TCGv_i64 b)
{
- TCGv_ptr fn;
TCGArg args[2];
- fn = tcg_const_ptr(func);
args[0] = GET_TCGV_I64(a);
args[1] = GET_TCGV_I64(b);
- tcg_gen_callN(&tcg_ctx, fn,
+ tcg_gen_callN(&tcg_ctx, func,
TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_SIDE_EFFECTS,
sizemask, GET_TCGV_I64(ret), 2, args);
- tcg_temp_free_ptr(fn);
}
/* 32 bit ops */
diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h
index adb6ce1bb9..71ba64ac16 100644
--- a/tcg/tcg-opc.h
+++ b/tcg/tcg-opc.h
@@ -40,7 +40,7 @@ DEF(discard, 1, 0, 0, TCG_OPF_NOT_PRESENT)
DEF(set_label, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_NOT_PRESENT)
/* variable number of parameters */
-DEF(call, 0, 1, 2, TCG_OPF_CALL_CLOBBER)
+DEF(call, 0, 0, 3, TCG_OPF_CALL_CLOBBER | TCG_OPF_NOT_PRESENT)
DEF(br, 0, 0, 1, TCG_OPF_BB_END)
@@ -51,8 +51,8 @@ DEF(br, 0, 0, 1, TCG_OPF_BB_END)
# define IMPL64 TCG_OPF_64BIT
#endif
-DEF(mov_i32, 1, 1, 0, 0)
-DEF(movi_i32, 1, 0, 1, 0)
+DEF(mov_i32, 1, 1, 0, TCG_OPF_NOT_PRESENT)
+DEF(movi_i32, 1, 0, 1, TCG_OPF_NOT_PRESENT)
DEF(setcond_i32, 1, 2, 1, 0)
DEF(movcond_i32, 1, 4, 1, IMPL(TCG_TARGET_HAS_movcond_i32))
/* load/store */
@@ -110,8 +110,8 @@ DEF(eqv_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_eqv_i32))
DEF(nand_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_nand_i32))
DEF(nor_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_nor_i32))
-DEF(mov_i64, 1, 1, 0, IMPL64)
-DEF(movi_i64, 1, 0, 1, IMPL64)
+DEF(mov_i64, 1, 1, 0, TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT)
+DEF(movi_i64, 1, 0, 1, TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT)
DEF(setcond_i64, 1, 2, 1, IMPL64)
DEF(movcond_i64, 1, 4, 1, IMPL64 | IMPL(TCG_TARGET_HAS_movcond_i64))
/* load/store */
diff --git a/tcg/tcg.c b/tcg/tcg.c
index e71f7a0975..0670affe2f 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -65,7 +65,7 @@
/* Forward declarations for functions declared in tcg-target.c and used here. */
static void tcg_target_init(TCGContext *s);
static void tcg_target_qemu_prologue(TCGContext *s);
-static void patch_reloc(uint8_t *code_ptr, int type,
+static void patch_reloc(tcg_insn_unit *code_ptr, int type,
intptr_t value, intptr_t addend);
/* The CIE and FDE header definitions will be common to all hosts. */
@@ -101,6 +101,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
const int *const_args);
static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
intptr_t arg2);
+static void tcg_out_call(TCGContext *s, tcg_insn_unit *target);
static int tcg_target_const_match(tcg_target_long val, TCGType type,
const TCGArgConstraint *arg_ct);
static void tcg_out_tb_init(TCGContext *s);
@@ -117,35 +118,87 @@ const size_t tcg_op_defs_max = ARRAY_SIZE(tcg_op_defs);
static TCGRegSet tcg_target_available_regs[2];
static TCGRegSet tcg_target_call_clobber_regs;
+#if TCG_TARGET_INSN_UNIT_SIZE == 1
static inline void tcg_out8(TCGContext *s, uint8_t v)
{
*s->code_ptr++ = v;
}
+static inline void tcg_patch8(tcg_insn_unit *p, uint8_t v)
+{
+ *p = v;
+}
+#endif
+
+#if TCG_TARGET_INSN_UNIT_SIZE <= 2
static inline void tcg_out16(TCGContext *s, uint16_t v)
{
- uint8_t *p = s->code_ptr;
- *(uint16_t *)p = v;
- s->code_ptr = p + 2;
+ if (TCG_TARGET_INSN_UNIT_SIZE == 2) {
+ *s->code_ptr++ = v;
+ } else {
+ tcg_insn_unit *p = s->code_ptr;
+ memcpy(p, &v, sizeof(v));
+ s->code_ptr = p + (2 / TCG_TARGET_INSN_UNIT_SIZE);
+ }
+}
+
+static inline void tcg_patch16(tcg_insn_unit *p, uint16_t v)
+{
+ if (TCG_TARGET_INSN_UNIT_SIZE == 2) {
+ *p = v;
+ } else {
+ memcpy(p, &v, sizeof(v));
+ }
}
+#endif
+#if TCG_TARGET_INSN_UNIT_SIZE <= 4
static inline void tcg_out32(TCGContext *s, uint32_t v)
{
- uint8_t *p = s->code_ptr;
- *(uint32_t *)p = v;
- s->code_ptr = p + 4;
+ if (TCG_TARGET_INSN_UNIT_SIZE == 4) {
+ *s->code_ptr++ = v;
+ } else {
+ tcg_insn_unit *p = s->code_ptr;
+ memcpy(p, &v, sizeof(v));
+ s->code_ptr = p + (4 / TCG_TARGET_INSN_UNIT_SIZE);
+ }
+}
+
+static inline void tcg_patch32(tcg_insn_unit *p, uint32_t v)
+{
+ if (TCG_TARGET_INSN_UNIT_SIZE == 4) {
+ *p = v;
+ } else {
+ memcpy(p, &v, sizeof(v));
+ }
}
+#endif
+#if TCG_TARGET_INSN_UNIT_SIZE <= 8
static inline void tcg_out64(TCGContext *s, uint64_t v)
{
- uint8_t *p = s->code_ptr;
- *(uint64_t *)p = v;
- s->code_ptr = p + 8;
+ if (TCG_TARGET_INSN_UNIT_SIZE == 8) {
+ *s->code_ptr++ = v;
+ } else {
+ tcg_insn_unit *p = s->code_ptr;
+ memcpy(p, &v, sizeof(v));
+ s->code_ptr = p + (8 / TCG_TARGET_INSN_UNIT_SIZE);
+ }
+}
+
+static inline void tcg_patch64(tcg_insn_unit *p, uint64_t v)
+{
+ if (TCG_TARGET_INSN_UNIT_SIZE == 8) {
+ *p = v;
+ } else {
+ memcpy(p, &v, sizeof(v));
+ }
}
+#endif
/* label relocation processing */
-static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
+static void tcg_out_reloc(TCGContext *s, tcg_insn_unit *code_ptr, int type,
int label_index, intptr_t addend)
{
TCGLabel *l;
@@ -168,23 +221,20 @@ static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
}
}
-static void tcg_out_label(TCGContext *s, int label_index, void *ptr)
+static void tcg_out_label(TCGContext *s, int label_index, tcg_insn_unit *ptr)
{
- TCGLabel *l;
- TCGRelocation *r;
+ TCGLabel *l = &s->labels[label_index];
intptr_t value = (intptr_t)ptr;
+ TCGRelocation *r;
- l = &s->labels[label_index];
- if (l->has_value) {
- tcg_abort();
- }
- r = l->u.first_reloc;
- while (r != NULL) {
+ assert(!l->has_value);
+
+ for (r = l->u.first_reloc; r != NULL; r = r->next) {
patch_reloc(r->ptr, r->type, value, r->addend);
- r = r->next;
}
+
l->has_value = 1;
- l->u.value = value;
+ l->u.value_ptr = ptr;
}
int gen_new_label(void)
@@ -339,7 +389,7 @@ void tcg_prologue_init(TCGContext *s)
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
- size_t size = s->code_ptr - s->code_buf;
+ size_t size = tcg_current_code_size(s);
qemu_log("PROLOGUE: [size=%zu]\n", size);
log_disas(s->code_buf, size);
qemu_log("\n");
@@ -656,7 +706,7 @@ int tcg_check_temp_count(void)
/* Note: we convert the 64 bit args to 32 bit and do some alignment
and endian swap. Maybe it would be better to do the alignment
and endian swap in tcg_reg_alloc_call(). */
-void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
+void tcg_gen_callN(TCGContext *s, void *func, unsigned int flags,
int sizemask, TCGArg ret, int nargs, TCGArg *args)
{
int i;
@@ -783,11 +833,10 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
*s->gen_opparam_ptr++ = args[i];
real_args++;
}
- *s->gen_opparam_ptr++ = GET_TCGV_PTR(func);
-
+ *s->gen_opparam_ptr++ = (uintptr_t)func;
*s->gen_opparam_ptr++ = flags;
- *nparam = (nb_rets << 16) | (real_args + 1);
+ *nparam = (nb_rets << 16) | real_args;
/* total parameters, needed to go backward in the instruction stream */
*s->gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
@@ -1194,49 +1243,21 @@ void tcg_dump_ops(TCGContext *s)
nb_iargs = arg & 0xffff;
nb_cargs = def->nb_cargs;
- qemu_log(" %s ", def->name);
-
- /* function name */
- qemu_log("%s",
- tcg_get_arg_str_idx(s, buf, sizeof(buf),
- args[nb_oargs + nb_iargs - 1]));
- /* flags */
- qemu_log(",$0x%" TCG_PRIlx, args[nb_oargs + nb_iargs]);
- /* nb out args */
- qemu_log(",$%d", nb_oargs);
- for(i = 0; i < nb_oargs; i++) {
- qemu_log(",");
- qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
+ /* function name, flags, out args */
+ qemu_log(" %s %s,$0x%" TCG_PRIlx ",$%d", def->name,
+ tcg_find_helper(s, args[nb_oargs + nb_iargs]),
+ args[nb_oargs + nb_iargs + 1], nb_oargs);
+ for (i = 0; i < nb_oargs; i++) {
+ qemu_log(",%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
args[i]));
}
- for(i = 0; i < (nb_iargs - 1); i++) {
- qemu_log(",");
- if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
- qemu_log("<dummy>");
- } else {
- qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
- args[nb_oargs + i]));
- }
- }
- } else if (c == INDEX_op_movi_i32 || c == INDEX_op_movi_i64) {
- tcg_target_ulong val;
- const char *name;
-
- nb_oargs = def->nb_oargs;
- nb_iargs = def->nb_iargs;
- nb_cargs = def->nb_cargs;
- qemu_log(" %s %s,$", def->name,
- tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
- val = args[1];
- name = tcg_find_helper(s, val);
- if (name) {
- qemu_log("%s", name);
- } else {
- if (c == INDEX_op_movi_i32) {
- qemu_log("0x%x", (uint32_t)val);
- } else {
- qemu_log("0x%" PRIx64 , (uint64_t)val);
+ for (i = 0; i < nb_iargs; i++) {
+ TCGArg arg = args[nb_oargs + i];
+ const char *t = "<dummy>";
+ if (arg != TCG_CALL_DUMMY_ARG) {
+ t = tcg_get_arg_str_idx(s, buf, sizeof(buf), arg);
}
+ qemu_log(",%s", t);
}
} else {
qemu_log(" %s ", def->name);
@@ -1499,9 +1520,9 @@ static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps,
temporaries are removed. */
static void tcg_liveness_analysis(TCGContext *s)
{
- int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
+ int i, op_index, nb_args, nb_iargs, nb_oargs, nb_ops;
TCGOpcode op, op_new, op_new2;
- TCGArg *args;
+ TCGArg *args, arg;
const TCGOpDef *def;
uint8_t *dead_temps, *mem_temps;
uint16_t dead_args;
@@ -1531,15 +1552,15 @@ static void tcg_liveness_analysis(TCGContext *s)
nb_args = args[-1];
args -= nb_args;
- nb_iargs = args[0] & 0xffff;
- nb_oargs = args[0] >> 16;
- args++;
- call_flags = args[nb_oargs + nb_iargs];
+ arg = *args++;
+ nb_iargs = arg & 0xffff;
+ nb_oargs = arg >> 16;
+ call_flags = args[nb_oargs + nb_iargs + 1];
/* pure functions can be removed if their result is not
used */
if (call_flags & TCG_CALL_NO_SIDE_EFFECTS) {
- for(i = 0; i < nb_oargs; i++) {
+ for (i = 0; i < nb_oargs; i++) {
arg = args[i];
if (!dead_temps[arg] || mem_temps[arg]) {
goto do_not_remove_call;
@@ -1553,7 +1574,7 @@ static void tcg_liveness_analysis(TCGContext *s)
/* output args are dead */
dead_args = 0;
sync_args = 0;
- for(i = 0; i < nb_oargs; i++) {
+ for (i = 0; i < nb_oargs; i++) {
arg = args[i];
if (dead_temps[arg]) {
dead_args |= (1 << i);
@@ -1576,7 +1597,7 @@ static void tcg_liveness_analysis(TCGContext *s)
}
/* input args are live */
- for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
+ for (i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
arg = args[i];
if (arg != TCG_CALL_DUMMY_ARG) {
if (dead_temps[arg]) {
@@ -2075,13 +2096,12 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
{
TCGRegSet allocated_regs;
TCGTemp *ts, *ots;
- const TCGArgConstraint *arg_ct, *oarg_ct;
+ TCGType type;
tcg_regset_set(allocated_regs, s->reserved_regs);
ots = &s->temps[args[0]];
ts = &s->temps[args[1]];
- oarg_ct = &def->args_ct[0];
- arg_ct = &def->args_ct[1];
+ type = ots->type;
/* If the source value is not in a register, and we're going to be
forced to have it in a register in order to perform the copy,
@@ -2089,12 +2109,13 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
we don't have to reload SOURCE the next time it is used. */
if (((NEED_SYNC_ARG(0) || ots->fixed_reg) && ts->val_type != TEMP_VAL_REG)
|| ts->val_type == TEMP_VAL_MEM) {
- ts->reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
+ ts->reg = tcg_reg_alloc(s, tcg_target_available_regs[type],
+ allocated_regs);
if (ts->val_type == TEMP_VAL_MEM) {
- tcg_out_ld(s, ts->type, ts->reg, ts->mem_reg, ts->mem_offset);
+ tcg_out_ld(s, type, ts->reg, ts->mem_reg, ts->mem_offset);
ts->mem_coherent = 1;
} else if (ts->val_type == TEMP_VAL_CONST) {
- tcg_out_movi(s, ts->type, ts->reg, ts->val);
+ tcg_out_movi(s, type, ts->reg, ts->val);
}
s->reg_to_temp[ts->reg] = args[1];
ts->val_type = TEMP_VAL_REG;
@@ -2109,7 +2130,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
if (!ots->mem_allocated) {
temp_allocate_frame(s, args[0]);
}
- tcg_out_st(s, ots->type, ts->reg, ots->mem_reg, ots->mem_offset);
+ tcg_out_st(s, type, ts->reg, ots->mem_reg, ots->mem_offset);
if (IS_DEAD_ARG(1)) {
temp_dead(s, args[1]);
}
@@ -2137,9 +2158,10 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
/* When allocating a new register, make sure to not spill the
input one. */
tcg_regset_set_reg(allocated_regs, ts->reg);
- ots->reg = tcg_reg_alloc(s, oarg_ct->u.regs, allocated_regs);
+ ots->reg = tcg_reg_alloc(s, tcg_target_available_regs[type],
+ allocated_regs);
}
- tcg_out_mov(s, ots->type, ots->reg, ts->reg);
+ tcg_out_mov(s, type, ots->reg, ts->reg);
}
ots->val_type = TEMP_VAL_REG;
ots->mem_coherent = 0;
@@ -2323,26 +2345,27 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
uint16_t dead_args, uint8_t sync_args)
{
int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
- TCGArg arg, func_arg;
+ TCGArg arg;
TCGTemp *ts;
intptr_t stack_offset;
size_t call_stack_size;
- uintptr_t func_addr;
- int const_func_arg, allocate_args;
+ tcg_insn_unit *func_addr;
+ int allocate_args;
TCGRegSet allocated_regs;
- const TCGArgConstraint *arg_ct;
arg = *args++;
nb_oargs = arg >> 16;
nb_iargs = arg & 0xffff;
- nb_params = nb_iargs - 1;
+ nb_params = nb_iargs;
- flags = args[nb_oargs + nb_iargs];
+ func_addr = (tcg_insn_unit *)(intptr_t)args[nb_oargs + nb_iargs];
+ flags = args[nb_oargs + nb_iargs + 1];
nb_regs = ARRAY_SIZE(tcg_target_call_iarg_regs);
- if (nb_regs > nb_params)
+ if (nb_regs > nb_params) {
nb_regs = nb_params;
+ }
/* assign stack slots first */
call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
@@ -2410,40 +2433,6 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
}
}
- /* assign function address */
- func_arg = args[nb_oargs + nb_iargs - 1];
- arg_ct = &def->args_ct[0];
- ts = &s->temps[func_arg];
- func_addr = ts->val;
- const_func_arg = 0;
- if (ts->val_type == TEMP_VAL_MEM) {
- reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
- tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
- func_arg = reg;
- tcg_regset_set_reg(allocated_regs, reg);
- } else if (ts->val_type == TEMP_VAL_REG) {
- reg = ts->reg;
- if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
- reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
- tcg_out_mov(s, ts->type, reg, ts->reg);
- }
- func_arg = reg;
- tcg_regset_set_reg(allocated_regs, reg);
- } else if (ts->val_type == TEMP_VAL_CONST) {
- if (tcg_target_const_match(func_addr, ts->type, arg_ct)) {
- const_func_arg = 1;
- func_arg = func_addr;
- } else {
- reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
- tcg_out_movi(s, ts->type, reg, func_addr);
- func_arg = reg;
- tcg_regset_set_reg(allocated_regs, reg);
- }
- } else {
- tcg_abort();
- }
-
-
/* mark dead temporaries and free the associated registers */
for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
if (IS_DEAD_ARG(i)) {
@@ -2468,7 +2457,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
save_globals(s, allocated_regs);
}
- tcg_out_op(s, opc, &func_arg, &const_func_arg);
+ tcg_out_call(s, func_addr);
/* assign output registers and emit moves if needed */
for(i = 0; i < nb_oargs; i++) {
@@ -2518,7 +2507,8 @@ static void dump_op_count(void)
#endif
-static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
+static inline int tcg_gen_code_common(TCGContext *s,
+ tcg_insn_unit *gen_code_buf,
long search_pc)
{
TCGOpcode opc;
@@ -2633,7 +2623,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
}
args += def->nb_args;
next:
- if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
+ if (search_pc >= 0 && search_pc < tcg_current_code_size(s)) {
return op_index;
}
op_index++;
@@ -2647,7 +2637,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
return -1;
}
-int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
+int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf)
{
#ifdef CONFIG_PROFILER
{
@@ -2666,16 +2656,17 @@ int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
tcg_gen_code_common(s, gen_code_buf, -1);
/* flush instruction cache */
- flush_icache_range((uintptr_t)gen_code_buf, (uintptr_t)s->code_ptr);
+ flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr);
- return s->code_ptr - gen_code_buf;
+ return tcg_current_code_size(s);
}
/* Return the index of the micro operation such as the pc after is <
offset bytes from the start of the TB. The contents of gen_code_buf must
not be changed, though writing the same values is ok.
Return -1 if not found. */
-int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
+int tcg_gen_code_search_pc(TCGContext *s, tcg_insn_unit *gen_code_buf,
+ long offset)
{
return tcg_gen_code_common(s, gen_code_buf, offset);
}
diff --git a/tcg/tcg.h b/tcg/tcg.h
index a6a2d06080..fbc93101cf 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -146,10 +146,25 @@ typedef enum TCGOpcode {
#define tcg_regset_andnot(d, a, b) (d) = (a) & ~(b)
#define tcg_regset_not(d, a) (d) = ~(a)
+#ifndef TCG_TARGET_INSN_UNIT_SIZE
+# error "Missing TCG_TARGET_INSN_UNIT_SIZE"
+#elif TCG_TARGET_INSN_UNIT_SIZE == 1
+typedef uint8_t tcg_insn_unit;
+#elif TCG_TARGET_INSN_UNIT_SIZE == 2
+typedef uint16_t tcg_insn_unit;
+#elif TCG_TARGET_INSN_UNIT_SIZE == 4
+typedef uint32_t tcg_insn_unit;
+#elif TCG_TARGET_INSN_UNIT_SIZE == 8
+typedef uint64_t tcg_insn_unit;
+#else
+/* The port better have done this. */
+#endif
+
+
typedef struct TCGRelocation {
struct TCGRelocation *next;
int type;
- uint8_t *ptr;
+ tcg_insn_unit *ptr;
intptr_t addend;
} TCGRelocation;
@@ -157,6 +172,7 @@ typedef struct TCGLabel {
int has_value;
union {
uintptr_t value;
+ tcg_insn_unit *value_ptr;
TCGRelocation *first_reloc;
} u;
} TCGLabel;
@@ -464,7 +480,7 @@ struct TCGContext {
int nb_temps;
/* goto_tb support */
- uint8_t *code_buf;
+ tcg_insn_unit *code_buf;
uintptr_t *tb_next;
uint16_t *tb_next_offset;
uint16_t *tb_jmp_offset; /* != NULL if USE_DIRECT_JUMP */
@@ -485,7 +501,7 @@ struct TCGContext {
intptr_t frame_end;
int frame_reg;
- uint8_t *code_ptr;
+ tcg_insn_unit *code_ptr;
TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */
TCGTempSet free_temps[TCG_TYPE_COUNT * 2];
@@ -524,14 +540,17 @@ struct TCGContext {
uint16_t gen_opc_icount[OPC_BUF_SIZE];
uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
- /* Code generation */
+ /* Code generation. Note that we specifically do not use tcg_insn_unit
+ here, because there's too much arithmetic throughout that relies
+ on addition and subtraction working on bytes. Rely on the GCC
+ extension that allows arithmetic on void*. */
int code_gen_max_blocks;
- uint8_t *code_gen_prologue;
- uint8_t *code_gen_buffer;
+ void *code_gen_prologue;
+ void *code_gen_buffer;
size_t code_gen_buffer_size;
/* threshold to flush the translated code buffer */
size_t code_gen_buffer_max_size;
- uint8_t *code_gen_ptr;
+ void *code_gen_ptr;
TBContext tb_ctx;
@@ -566,8 +585,9 @@ void tcg_context_init(TCGContext *s);
void tcg_prologue_init(TCGContext *s);
void tcg_func_start(TCGContext *s);
-int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf);
-int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset);
+int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf);
+int tcg_gen_code_search_pc(TCGContext *s, tcg_insn_unit *gen_code_buf,
+ long offset);
void tcg_set_frame(TCGContext *s, int reg, intptr_t start, intptr_t size);
@@ -705,7 +725,7 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs);
#define tcg_temp_free_ptr(T) tcg_temp_free_i64(TCGV_PTR_TO_NAT(T))
#endif
-void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
+void tcg_gen_callN(TCGContext *s, void *func, unsigned int flags,
int sizemask, TCGArg ret, int nargs, TCGArg *args);
void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
@@ -724,6 +744,51 @@ TCGv_i32 tcg_const_local_i32(int32_t val);
TCGv_i64 tcg_const_local_i64(int64_t val);
/**
+ * tcg_ptr_byte_diff
+ * @a, @b: addresses to be differenced
+ *
+ * There are many places within the TCG backends where we need a byte
+ * difference between two pointers. While this can be accomplished
+ * with local casting, it's easy to get wrong -- especially if one is
+ * concerned with the signedness of the result.
+ *
+ * This version relies on GCC's void pointer arithmetic to get the
+ * correct result.
+ */
+
+static inline ptrdiff_t tcg_ptr_byte_diff(void *a, void *b)
+{
+ return a - b;
+}
+
+/**
+ * tcg_pcrel_diff
+ * @s: the tcg context
+ * @target: address of the target
+ *
+ * Produce a pc-relative difference, from the current code_ptr
+ * to the destination address.
+ */
+
+static inline ptrdiff_t tcg_pcrel_diff(TCGContext *s, void *target)
+{
+ return tcg_ptr_byte_diff(target, s->code_ptr);
+}
+
+/**
+ * tcg_current_code_size
+ * @s: the tcg context
+ *
+ * Compute the current code size within the translation block.
+ * This is used to fill in qemu's data structures for goto_tb.
+ */
+
+static inline size_t tcg_current_code_size(TCGContext *s)
+{
+ return tcg_ptr_byte_diff(s->code_ptr, s->code_buf);
+}
+
+/**
* tcg_qemu_tb_exec:
* @env: CPUArchState * for the CPU
* @tb_ptr: address of generated code for the TB to execute
diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c
index 47c0b85d95..9b39231c15 100644
--- a/tcg/tci/tcg-target.c
+++ b/tcg/tci/tcg-target.c
@@ -59,12 +59,8 @@
static const TCGTargetOpDef tcg_target_op_defs[] = {
{ INDEX_op_exit_tb, { NULL } },
{ INDEX_op_goto_tb, { NULL } },
- { INDEX_op_call, { RI } },
{ INDEX_op_br, { NULL } },
- { INDEX_op_mov_i32, { R, R } },
- { INDEX_op_movi_i32, { R } },
-
{ INDEX_op_ld8u_i32, { R, R } },
{ INDEX_op_ld8s_i32, { R, R } },
{ INDEX_op_ld16u_i32, { R, R } },
@@ -141,9 +137,6 @@ static const TCGTargetOpDef tcg_target_op_defs[] = {
#endif
#if TCG_TARGET_REG_BITS == 64
- { INDEX_op_mov_i64, { R, R } },
- { INDEX_op_movi_i64, { R } },
-
{ INDEX_op_ld8u_i64, { R, R } },
{ INDEX_op_ld8s_i64, { R, R } },
{ INDEX_op_ld16u_i64, { R, R } },
@@ -371,14 +364,18 @@ static const char *const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
};
#endif
-static void patch_reloc(uint8_t *code_ptr, int type,
+static void patch_reloc(tcg_insn_unit *code_ptr, int type,
intptr_t value, intptr_t addend)
{
/* tcg_out_reloc always uses the same type, addend. */
assert(type == sizeof(tcg_target_long));
assert(addend == 0);
assert(value != 0);
- *(tcg_target_long *)code_ptr = value;
+ if (TCG_TARGET_REG_BITS == 32) {
+ tcg_patch32(code_ptr, value);
+ } else {
+ tcg_patch64(code_ptr, value);
+ }
}
/* Parse target specific constraints. */
@@ -413,8 +410,11 @@ void tci_disas(uint8_t opc)
/* Write value (native size). */
static void tcg_out_i(TCGContext *s, tcg_target_ulong v)
{
- *(tcg_target_ulong *)s->code_ptr = v;
- s->code_ptr += sizeof(tcg_target_ulong);
+ if (TCG_TARGET_REG_BITS == 32) {
+ tcg_out32(s, v);
+ } else {
+ tcg_out64(s, v);
+ }
}
/* Write opcode. */
@@ -542,6 +542,11 @@ static void tcg_out_movi(TCGContext *s, TCGType type,
old_code_ptr[1] = s->code_ptr - old_code_ptr;
}
+static inline void tcg_out_call(TCGContext *s, tcg_insn_unit *arg)
+{
+ tcg_out_ri(s, 1, (uintptr_t)arg);
+}
+
static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
const int *const_args)
{
@@ -557,21 +562,18 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
if (s->tb_jmp_offset) {
/* Direct jump method. */
assert(args[0] < ARRAY_SIZE(s->tb_jmp_offset));
- s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
+ s->tb_jmp_offset[args[0]] = tcg_current_code_size(s);
tcg_out32(s, 0);
} else {
/* Indirect jump method. */
TODO();
}
assert(args[0] < ARRAY_SIZE(s->tb_next_offset));
- s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
+ s->tb_next_offset[args[0]] = tcg_current_code_size(s);
break;
case INDEX_op_br:
tci_out_label(s, args[0]);
break;
- case INDEX_op_call:
- tcg_out_ri(s, const_args[0], args[0]);
- break;
case INDEX_op_setcond_i32:
tcg_out_r(s, args[0]);
tcg_out_r(s, args[1]);
@@ -596,9 +598,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
tcg_out8(s, args[3]); /* condition */
break;
#endif
- case INDEX_op_movi_i32:
- TODO(); /* Handled by tcg_out_movi? */
- break;
case INDEX_op_ld8u_i32:
case INDEX_op_ld8s_i32:
case INDEX_op_ld16u_i32:
@@ -654,10 +653,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
break;
#if TCG_TARGET_REG_BITS == 64
- case INDEX_op_mov_i64:
- case INDEX_op_movi_i64:
- TODO();
- break;
case INDEX_op_add_i64:
case INDEX_op_sub_i64:
case INDEX_op_mul_i64:
@@ -825,11 +820,12 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
tcg_out_i(s, *args);
#endif
break;
- case INDEX_op_end:
- TODO();
- break;
+ case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
+ case INDEX_op_mov_i64:
+ case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
+ case INDEX_op_movi_i64:
+ case INDEX_op_call: /* Always emitted via tcg_out_call. */
default:
- fprintf(stderr, "Missing: %s\n", tcg_op_defs[opc].name);
tcg_abort();
}
old_code_ptr[1] = s->code_ptr - old_code_ptr;
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
index 37719e875c..0be5acdb81 100644
--- a/tcg/tci/tcg-target.h
+++ b/tcg/tci/tcg-target.h
@@ -43,6 +43,7 @@
#include "config-host.h"
#define TCG_TARGET_INTERPRETER 1
+#define TCG_TARGET_INSN_UNIT_SIZE 1
#if UINTPTR_MAX == UINT32_MAX
# define TCG_TARGET_REG_BITS 32
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
index 073dc7a2d3..c4af131a66 100755
--- a/tests/qemu-iotests/051
+++ b/tests/qemu-iotests/051
@@ -233,6 +233,10 @@ echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG",
$QEMU_IO -c "read -P 0x22 0 4k" "$TEST_IMG" | _filter_qemu_io
+echo -e 'qemu-io ide0-hd0 "write -P 0x33 0 4k"\ncommit ide0-hd0' | run_qemu -drive file="$TEST_IMG",snapshot=on | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0x33 0 4k" "$TEST_IMG" | _filter_qemu_io
+
# success, all done
echo "*** done"
rm -f $seq.full
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
index 01b0384472..31e329e893 100644
--- a/tests/qemu-iotests/051.out
+++ b/tests/qemu-iotests/051.out
@@ -358,4 +358,14 @@ wrote 4096/4096 bytes at offset 0
read 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x3qemu-io ide0-hd0 "write -P 0x33qemu-io ide0-hd0 "write -P 0x33 qemu-io ide0-hd0 "write -P 0x33 0qemu-io ide0-hd0 "write -P 0x33 0 qemu-io ide0-hd0 "write -P 0x33 0 4qemu-io ide0-hd0 "write -P 0x33 0 4kqemu-io ide0-hd0 "write -P 0x33 0 4k"
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) ccocomcommcommicommitcommit commit icommit idcommit idecommit ide0commit ide0-commit ide0-hcommit ide0-hdcommit ide0-hd0
+(qemu) qququiquit
+
+read 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
*** done
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
index ca5aa16ff7..26a2fd3e0e 100755
--- a/tests/qemu-iotests/059
+++ b/tests/qemu-iotests/059
@@ -104,6 +104,13 @@ truncate -s 10M $TEST_IMG
_img_info
echo
+echo "=== Converting to streamOptimized from image with small cluster size==="
+TEST_IMG="$TEST_IMG.qcow2" IMGFMT=qcow2 IMGOPTS="cluster_size=4096" _make_test_img 1G
+$QEMU_IO -c "write -P 0xa 0 512" "$TEST_IMG.qcow2" | _filter_qemu_io
+$QEMU_IO -c "write -P 0xb 10240 512" "$TEST_IMG.qcow2" | _filter_qemu_io
+$QEMU_IMG convert -f qcow2 -O vmdk -o subformat=streamOptimized "$TEST_IMG.qcow2" "$TEST_IMG" 2>&1
+
+echo
echo "=== Testing version 3 ==="
_use_sample_img iotest-version3.vmdk.bz2
_img_info
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
index 3371c867bb..eba0dedda0 100644
--- a/tests/qemu-iotests/059.out
+++ b/tests/qemu-iotests/059.out
@@ -2046,10 +2046,18 @@ RW 12582912 VMFS "dummy.IMGFMT" 1
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=107374182400
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': File truncated, expecting at least 13172736 bytes
+=== Converting to streamOptimized from image with small cluster size===
+Formatting 'TEST_DIR/t.vmdk.IMGFMT', fmt=IMGFMT size=1073741824
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 10240
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
=== Testing version 3 ===
image: TEST_DIR/iotest-version3.IMGFMT
file format: IMGFMT
virtual size: 1.0G (1073741824 bytes)
+cluster_size: 65536
=== Testing 4TB monolithicFlat creation and IO ===
Formatting 'TEST_DIR/iotest-version3.IMGFMT', fmt=IMGFMT size=4398046511104
diff --git a/tests/qemu-iotests/085 b/tests/qemu-iotests/085
index 33c8dc410a..56cd6f89b7 100755
--- a/tests/qemu-iotests/085
+++ b/tests/qemu-iotests/085
@@ -30,10 +30,6 @@ echo "QA output created by $seq"
here=`pwd`
status=1 # failure is the default!
-qemu_pid=
-
-QMP_IN="${TEST_DIR}/qmp-in-$$"
-QMP_OUT="${TEST_DIR}/qmp-out-$$"
snapshot_virt0="snapshot-v0.qcow2"
snapshot_virt1="snapshot-v1.qcow2"
@@ -42,10 +38,7 @@ MAX_SNAPSHOTS=10
_cleanup()
{
- kill -KILL ${qemu_pid}
- wait ${qemu_pid} 2>/dev/null # silent kill
-
- rm -f "${QMP_IN}" "${QMP_OUT}"
+ _cleanup_qemu
for i in $(seq 1 ${MAX_SNAPSHOTS})
do
rm -f "${TEST_DIR}/${i}-${snapshot_virt0}"
@@ -59,43 +52,12 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
# get standard environment, filters and checks
. ./common.rc
. ./common.filter
+. ./common.qemu
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
-# Wait for expected QMP response from QEMU. Will time out
-# after 10 seconds, which counts as failure.
-#
-# $1 is the string to expect
-#
-# If $silent is set to anything but an empty string, then
-# response is not echoed out.
-function timed_wait_for()
-{
- while read -t 10 resp <&5
- do
- if [ "${silent}" == "" ]; then
- echo "${resp}" | _filter_testdir | _filter_qemu
- fi
- grep -q "${1}" < <(echo ${resp})
- if [ $? -eq 0 ]; then
- return
- fi
- done
- echo "Timeout waiting for ${1}"
- exit 1 # Timeout means the test failed
-}
-
-# Sends QMP command to QEMU, and waits for the expected response
-#
-# ${1}: String of the QMP command to send
-# ${2}: String that the QEMU response should contain
-function send_qmp_cmd()
-{
- echo "${1}" >&6
- timed_wait_for "${2}"
-}
# ${1}: unique identifier for the snapshot filename
function create_single_snapshot()
@@ -104,7 +66,7 @@ function create_single_snapshot()
'arguments': { 'device': 'virtio0',
'snapshot-file':'"${TEST_DIR}/${1}-${snapshot_virt0}"',
'format': 'qcow2' } }"
- send_qmp_cmd "${cmd}" "return"
+ _send_qemu_cmd $h "${cmd}" "return"
}
# ${1}: unique identifier for the snapshot filename
@@ -120,14 +82,11 @@ function create_group_snapshot()
'snapshot-file': '"${TEST_DIR}/${1}-${snapshot_virt1}"' } } ]
} }"
- send_qmp_cmd "${cmd}" "return"
+ _send_qemu_cmd $h "${cmd}" "return"
}
size=128M
-mkfifo "${QMP_IN}"
-mkfifo "${QMP_OUT}"
-
_make_test_img $size
mv "${TEST_IMG}" "${TEST_IMG}.orig"
_make_test_img $size
@@ -136,23 +95,15 @@ echo
echo === Running QEMU ===
echo
-"${QEMU}" -nographic -monitor none -serial none -qmp stdio\
- -drive file="${TEST_IMG}.orig",if=virtio\
- -drive file="${TEST_IMG}",if=virtio 2>&1 >"${QMP_OUT}" <"${QMP_IN}"&
-qemu_pid=$!
-
-# redirect fifos to file descriptors, to keep from blocking
-exec 5<"${QMP_OUT}"
-exec 6>"${QMP_IN}"
-
-# Don't print response, since it has version information in it
-silent=yes timed_wait_for "capabilities"
+qemu_comm_method="qmp"
+_launch_qemu -drive file="${TEST_IMG}.orig",if=virtio -drive file="${TEST_IMG}",if=virtio
+h=$QEMU_HANDLE
echo
echo === Sending capabilities ===
echo
-send_qmp_cmd "{ 'execute': 'qmp_capabilities' }" "return"
+_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" "return"
echo
echo === Create a single snapshot on virtio0 ===
@@ -165,16 +116,16 @@ echo
echo === Invalid command - missing device and nodename ===
echo
-send_qmp_cmd "{ 'execute': 'blockdev-snapshot-sync',
- 'arguments': { 'snapshot-file':'"${TEST_DIR}"/1-${snapshot_virt0}',
+_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot-sync',
+ 'arguments': { 'snapshot-file':'"${TEST_DIR}/1-${snapshot_virt0}"',
'format': 'qcow2' } }" "error"
echo
echo === Invalid command - missing snapshot-file ===
echo
-send_qmp_cmd "{ 'execute': 'blockdev-snapshot-sync',
- 'arguments': { 'device': 'virtio0',
+_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot-sync',
+ 'arguments': { 'device': 'virtio0',
'format': 'qcow2' } }" "error"
echo
echo
diff --git a/tests/qemu-iotests/091 b/tests/qemu-iotests/091
new file mode 100755
index 0000000000..384b3ace54
--- /dev/null
+++ b/tests/qemu-iotests/091
@@ -0,0 +1,105 @@
+#!/bin/bash
+#
+# Live migration test
+#
+# Performs a migration from one VM to another via monitor commands
+#
+# Copyright (C) 2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=jcody@redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+status=1 # failure is the default!
+
+MIG_FIFO="${TEST_DIR}/migrate"
+
+_cleanup()
+{
+ rm -f "${MIG_FIFO}"
+ _cleanup_qemu
+ _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.qemu
+
+_supported_fmt qcow2
+_supported_proto file
+_supported_os Linux
+
+size=1G
+
+_make_test_img $size
+
+mkfifo "${MIG_FIFO}"
+
+echo
+echo === Starting QEMU VM1 ===
+echo
+
+qemu_comm_method="monitor"
+_launch_qemu -drive file="${TEST_IMG}",cache=none,id=disk
+h1=$QEMU_HANDLE
+
+echo
+echo === Starting QEMU VM2 ===
+echo
+_launch_qemu -drive file="${TEST_IMG}",cache=none,id=disk \
+ -incoming "exec: cat '${MIG_FIFO}'"
+h2=$QEMU_HANDLE
+
+echo
+echo === VM 1: Migrate from VM1 to VM2 ===
+echo
+
+silent=yes
+_send_qemu_cmd $h1 'qemu-io disk "write -P 0x22 0 4M"' "(qemu)"
+echo "vm1: qemu-io disk write complete"
+_send_qemu_cmd $h1 "migrate \"exec: cat > '${MIG_FIFO}'\"" "(qemu)"
+echo "vm1: live migration started"
+qemu_cmd_repeat=20 _send_qemu_cmd $h1 "info migrate" "completed"
+echo "vm1: live migration completed"
+
+echo
+echo === VM 2: Post-migration, write to disk, verify running ===
+echo
+
+_send_qemu_cmd $h2 'qemu-io disk "write 4M 1M"' "(qemu)"
+echo "vm2: qemu-io disk write complete"
+qemu_cmd_repeat=20 _send_qemu_cmd $h2 "info status" "running"
+echo "vm2: qemu process running successfully"
+
+echo "vm2: flush io, and quit"
+_send_qemu_cmd $h2 'qemu-io disk flush' "(qemu)"
+_send_qemu_cmd $h2 'quit' ""
+
+echo "Check image pattern"
+${QEMU_IO} -c "read -P 0x22 0 4M" "${TEST_IMG}" | _filter_testdir | _filter_qemu_io
+
+echo "Running 'qemu-img check -r all \$TEST_IMG'"
+"${QEMU_IMG}" check -r all "${TEST_IMG}" 2>&1 | _filter_testdir | _filter_qemu
+
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/091.out b/tests/qemu-iotests/091.out
new file mode 100644
index 0000000000..a2e0122966
--- /dev/null
+++ b/tests/qemu-iotests/091.out
@@ -0,0 +1,28 @@
+QA output created by 091
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+
+=== Starting QEMU VM1 ===
+
+
+=== Starting QEMU VM2 ===
+
+
+=== VM 1: Migrate from VM1 to VM2 ===
+
+vm1: qemu-io disk write complete
+vm1: live migration started
+vm1: live migration completed
+
+=== VM 2: Post-migration, write to disk, verify running ===
+
+vm2: qemu-io disk write complete
+vm2: qemu process running successfully
+vm2: flush io, and quit
+Check image pattern
+read 4194304/4194304 bytes at offset 0
+4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Running 'qemu-img check -r all $TEST_IMG'
+No errors were found on the image.
+80/16384 = 0.49% allocated, 0.00% fragmented, 0.00% compressed clusters
+Image end offset: 5570560
+*** done
diff --git a/tests/qemu-iotests/common.qemu b/tests/qemu-iotests/common.qemu
new file mode 100644
index 0000000000..918af3102c
--- /dev/null
+++ b/tests/qemu-iotests/common.qemu
@@ -0,0 +1,200 @@
+#!/bin/bash
+#
+# This allows for launching of multiple QEMU instances, with independent
+# communication possible to each instance.
+#
+# Each instance can choose, at launch, to use either the QMP or the
+# HMP (monitor) interface.
+#
+# All instances are cleaned up via _cleanup_qemu, including killing the
+# running qemu instance.
+#
+# Copyright (C) 2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+QEMU_COMM_TIMEOUT=10
+
+QEMU_FIFO_IN="${TEST_DIR}/qmp-in-$$"
+QEMU_FIFO_OUT="${TEST_DIR}/qmp-out-$$"
+
+QEMU_PID=
+_QEMU_HANDLE=0
+QEMU_HANDLE=0
+
+# If bash version is >= 4.1, these will be overwritten and dynamic
+# file descriptor values assigned.
+_out_fd=3
+_in_fd=4
+
+# Wait for expected QMP response from QEMU. Will time out
+# after 10 seconds, which counts as failure.
+#
+# Override QEMU_COMM_TIMEOUT for a timeout different than the
+# default 10 seconds
+#
+# $1: The handle to use
+# $2+ All remaining arguments comprise the string to search for
+# in the response.
+#
+# If $silent is set to anything but an empty string, then
+# response is not echoed out.
+function _timed_wait_for()
+{
+ local h=${1}
+ shift
+
+ QEMU_STATUS[$h]=0
+ while read -t ${QEMU_COMM_TIMEOUT} resp <&${QEMU_OUT[$h]}
+ do
+ if [ -z "${silent}" ]; then
+ echo "${resp}" | _filter_testdir | _filter_qemu \
+ | _filter_qemu_io | _filter_qmp
+ fi
+ grep -q "${*}" < <(echo ${resp})
+ if [ $? -eq 0 ]; then
+ return
+ fi
+ done
+ QEMU_STATUS[$h]=-1
+ if [ -z "${qemu_error_no_exit}" ]; then
+ echo "Timeout waiting for ${*} on handle ${h}"
+ exit 1 # Timeout means the test failed
+ fi
+}
+
+
+# Sends QMP or HMP command to QEMU, and waits for the expected response
+#
+# $1: QEMU handle to use
+# $2: String of the QMP command to send
+# ${@: -1} (Last string passed)
+# String that the QEMU response should contain. If it is a null
+# string, do not wait for a response
+#
+# Set qemu_cmd_repeat to the number of times to repeat the cmd
+# until either timeout, or a response. If it is not set, or <=0,
+# then the command is only sent once.
+#
+# If $qemu_error_no_exit is set, then even if the expected response
+# is not seen, we will not exit. $QEMU_STATUS[$1] will be set it -1 in
+# that case.
+function _send_qemu_cmd()
+{
+ local h=${1}
+ local count=1
+ local cmd=
+ local use_error=${qemu_error_no_exit}
+ shift
+
+ if [ ${qemu_cmd_repeat} -gt 0 ] 2>/dev/null; then
+ count=${qemu_cmd_repeat}
+ use_error="no"
+ fi
+ # This array element extraction is done to accomodate pathnames with spaces
+ cmd=${@: 1:${#@}-1}
+ shift $(($# - 1))
+
+ while [ ${count} -gt 0 ]
+ do
+ echo "${cmd}" >&${QEMU_IN[${h}]}
+ if [ -n "${1}" ]; then
+ qemu_error_no_exit=${use_error} _timed_wait_for ${h} "${1}"
+ if [ ${QEMU_STATUS[$h]} -eq 0 ]; then
+ return
+ fi
+ fi
+ let count--;
+ done
+ if [ ${QEMU_STATUS[$h]} -ne 0 ] && [ -z "${qemu_error_no_exit}" ]; then
+ echo "Timeout waiting for ${1} on handle ${h}"
+ exit 1 #Timeout means the test failed
+ fi
+}
+
+
+# Launch a QEMU process.
+#
+# Input parameters:
+# $qemu_comm_method: set this variable to 'monitor' (case insensitive)
+# to use the QEMU HMP monitor for communication.
+# Otherwise, the default of QMP is used.
+# Returns:
+# $QEMU_HANDLE: set to a handle value to communicate with this QEMU instance.
+#
+function _launch_qemu()
+{
+ local comm=
+ local fifo_out=
+ local fifo_in=
+
+ if (shopt -s nocasematch; [[ "${qemu_comm_method}" == "monitor" ]])
+ then
+ comm="-monitor stdio"
+ else
+ local qemu_comm_method="qmp"
+ comm="-monitor none -qmp stdio"
+ fi
+
+ fifo_out=${QEMU_FIFO_OUT}_${_QEMU_HANDLE}
+ fifo_in=${QEMU_FIFO_IN}_${_QEMU_HANDLE}
+ mkfifo "${fifo_out}"
+ mkfifo "${fifo_in}"
+
+ "${QEMU}" -nographic -serial none ${comm} -machine accel=qtest "${@}" 2>&1 \
+ >"${fifo_out}" \
+ <"${fifo_in}" &
+ QEMU_PID[${_QEMU_HANDLE}]=$!
+
+ if [[ "${BASH_VERSINFO[0]}" -ge "5" ||
+ ("${BASH_VERSINFO[0]}" -ge "4" && "${BASH_VERSINFO[1]}" -ge "1") ]]
+ then
+ # bash >= 4.1 required for automatic fd
+ exec {_out_fd}<"${fifo_out}"
+ exec {_in_fd}>"${fifo_in}"
+ else
+ let _out_fd++
+ let _in_fd++
+ eval "exec ${_out_fd}<'${fifo_out}'"
+ eval "exec ${_in_fd}>'${fifo_in}'"
+ fi
+
+ QEMU_OUT[${_QEMU_HANDLE}]=${_out_fd}
+ QEMU_IN[${_QEMU_HANDLE}]=${_in_fd}
+ QEMU_STATUS[${_QEMU_HANDLE}]=0
+
+ if [ "${qemu_comm_method}" == "qmp" ]
+ then
+ # Don't print response, since it has version information in it
+ silent=yes _timed_wait_for ${_QEMU_HANDLE} "capabilities"
+ fi
+ QEMU_HANDLE=${_QEMU_HANDLE}
+ let _QEMU_HANDLE++
+}
+
+
+# Silenty kills the QEMU process
+function _cleanup_qemu()
+{
+ # QEMU_PID[], QEMU_IN[], QEMU_OUT[] all use same indices
+ for i in "${!QEMU_OUT[@]}"
+ do
+ kill -KILL ${QEMU_PID[$i]} 2>/dev/null
+ wait ${QEMU_PID[$i]} 2>/dev/null # silent kill
+ rm -f "${QEMU_FIFO_IN}_${i}" "${QEMU_FIFO_OUT}_${i}"
+ eval "exec ${QEMU_IN[$i]}<&-" # close file descriptors
+ eval "exec ${QEMU_OUT[$i]}<&-"
+ done
+}
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index ae096638b8..cd3e4d2c27 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -96,3 +96,4 @@
087 rw auto
088 rw auto
090 rw auto quick
+091 rw auto
diff --git a/translate-all.c b/translate-all.c
index 5759974d42..5549a85ed5 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -143,7 +143,7 @@ void cpu_gen_init(void)
int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_size_ptr)
{
TCGContext *s = &tcg_ctx;
- uint8_t *gen_code_buf;
+ tcg_insn_unit *gen_code_buf;
int gen_code_size;
#ifdef CONFIG_PROFILER
int64_t ti;
@@ -186,8 +186,8 @@ int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_size_ptr
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
- qemu_log("OUT: [size=%d]\n", *gen_code_size_ptr);
- log_disas(tb->tc_ptr, *gen_code_size_ptr);
+ qemu_log("OUT: [size=%d]\n", gen_code_size);
+ log_disas(tb->tc_ptr, gen_code_size);
qemu_log("\n");
qemu_log_flush();
}
@@ -235,7 +235,8 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
s->tb_jmp_offset = NULL;
s->tb_next = tb->tb_next;
#endif
- j = tcg_gen_code_search_pc(s, (uint8_t *)tc_ptr, searched_pc - tc_ptr);
+ j = tcg_gen_code_search_pc(s, (tcg_insn_unit *)tc_ptr,
+ searched_pc - tc_ptr);
if (j < 0)
return -1;
/* now find start of instruction before */
@@ -944,7 +945,6 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
{
CPUArchState *env = cpu->env_ptr;
TranslationBlock *tb;
- uint8_t *tc_ptr;
tb_page_addr_t phys_pc, phys_page2;
target_ulong virt_page2;
int code_gen_size;
@@ -959,8 +959,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
/* Don't forget to invalidate previous TB info. */
tcg_ctx.tb_ctx.tb_invalidated_flag = 1;
}
- tc_ptr = tcg_ctx.code_gen_ptr;
- tb->tc_ptr = tc_ptr;
+ tb->tc_ptr = tcg_ctx.code_gen_ptr;
tb->cs_base = cs_base;
tb->flags = flags;
tb->cflags = cflags;
diff --git a/ui/Makefile.objs b/ui/Makefile.objs
index 6f2294efda..4af420bfa8 100644
--- a/ui/Makefile.objs
+++ b/ui/Makefile.objs
@@ -17,4 +17,4 @@ common-obj-$(CONFIG_GTK) += gtk.o x_keymap.o
$(obj)/sdl.o $(obj)/sdl_zoom.o $(obj)/sdl2.o: QEMU_CFLAGS += $(SDL_CFLAGS)
-$(obj)/gtk.o: QEMU_CFLAGS += $(GTK_CFLAGS) $(VTE_CFLAGS)
+gtk.o-cflags := $(GTK_CFLAGS) $(VTE_CFLAGS)
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index 93f7d351d3..69552f7ec3 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -238,3 +238,115 @@ char *qemu_get_exec_dir(void)
{
return g_strdup(exec_dir);
}
+
+/*
+ * g_poll has a problem on Windows when using
+ * timeouts < 10ms, in glib/gpoll.c:
+ *
+ * // If not, and we have a significant timeout, poll again with
+ * // timeout then. Note that this will return indication for only
+ * // one event, or only for messages. We ignore timeouts less than
+ * // ten milliseconds as they are mostly pointless on Windows, the
+ * // MsgWaitForMultipleObjectsEx() call will timeout right away
+ * // anyway.
+ *
+ * if (retval == 0 && (timeout == INFINITE || timeout >= 10))
+ * retval = poll_rest (poll_msgs, handles, nhandles, fds, nfds, timeout);
+ *
+ * So whenever g_poll is called with timeout < 10ms it does
+ * a quick poll instead of wait, this causes significant performance
+ * degradation of QEMU, thus we should use WaitForMultipleObjectsEx
+ * directly
+ */
+gint g_poll_fixed(GPollFD *fds, guint nfds, gint timeout)
+{
+ guint i;
+ HANDLE handles[MAXIMUM_WAIT_OBJECTS];
+ gint nhandles = 0;
+ int num_completed = 0;
+
+ for (i = 0; i < nfds; i++) {
+ gint j;
+
+ if (fds[i].fd <= 0) {
+ continue;
+ }
+
+ /* don't add same handle several times
+ */
+ for (j = 0; j < nhandles; j++) {
+ if (handles[j] == (HANDLE)fds[i].fd) {
+ break;
+ }
+ }
+
+ if (j == nhandles) {
+ if (nhandles == MAXIMUM_WAIT_OBJECTS) {
+ fprintf(stderr, "Too many handles to wait for!\n");
+ break;
+ } else {
+ handles[nhandles++] = (HANDLE)fds[i].fd;
+ }
+ }
+ }
+
+ for (i = 0; i < nfds; ++i) {
+ fds[i].revents = 0;
+ }
+
+ if (timeout == -1) {
+ timeout = INFINITE;
+ }
+
+ if (nhandles == 0) {
+ if (timeout == INFINITE) {
+ return -1;
+ } else {
+ SleepEx(timeout, TRUE);
+ return 0;
+ }
+ }
+
+ while (1) {
+ DWORD res;
+ gint j;
+
+ res = WaitForMultipleObjectsEx(nhandles, handles, FALSE,
+ timeout, TRUE);
+
+ if (res == WAIT_FAILED) {
+ for (i = 0; i < nfds; ++i) {
+ fds[i].revents = 0;
+ }
+
+ return -1;
+ } else if ((res == WAIT_TIMEOUT) || (res == WAIT_IO_COMPLETION) ||
+ ((int)res < (int)WAIT_OBJECT_0) ||
+ (res >= (WAIT_OBJECT_0 + nhandles))) {
+ break;
+ }
+
+ for (i = 0; i < nfds; ++i) {
+ if (handles[res - WAIT_OBJECT_0] == (HANDLE)fds[i].fd) {
+ fds[i].revents = fds[i].events;
+ }
+ }
+
+ ++num_completed;
+
+ if (nhandles <= 1) {
+ break;
+ }
+
+ /* poll the rest of the handles
+ */
+ for (j = res - WAIT_OBJECT_0 + 1; j < nhandles; j++) {
+ handles[j - 1] = handles[j];
+ }
+ --nhandles;
+
+ timeout = 0;
+ }
+
+ return num_completed;
+}
diff --git a/vl.c b/vl.c
index 73e06610b0..709d8cda8d 100644
--- a/vl.c
+++ b/vl.c
@@ -3024,7 +3024,6 @@ int main(int argc, char **argv, char **envp)
runstate_init();
- init_clocks();
rtc_clock = QEMU_CLOCK_HOST;
qemu_init_auxval(envp);