summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS2
-rw-r--r--accel/tcg/cpu-exec.c6
-rw-r--r--accel/tcg/tcg-runtime.c5
-rwxr-xr-xconfigure2
-rw-r--r--dump.c7
-rw-r--r--fsdev/file-op-9p.h36
-rw-r--r--fsdev/qemu-fsdev.c4
-rw-r--r--hw/9pfs/9p-handle.c54
-rw-r--r--hw/9pfs/9p-local.c36
-rw-r--r--hw/9pfs/9p-proxy.c30
-rw-r--r--hw/9pfs/9p-synth.c2
-rw-r--r--hw/9pfs/9p-xattr.h5
-rw-r--r--hw/9pfs/9p.c22
-rw-r--r--hw/9pfs/9p.h14
-rw-r--r--hw/9pfs/virtio-9p-device.c62
-rw-r--r--hw/9pfs/xen-9p-backend.c2
-rw-r--r--hw/misc/vmcoreinfo.c3
-rw-r--r--include/exec/gen-icount.h9
-rw-r--r--include/exec/helper-gen.h11
-rw-r--r--include/exec/helper-head.h2
-rw-r--r--include/exec/helper-proto.h5
-rw-r--r--include/exec/helper-tcg.h7
-rw-r--r--include/qemu/queue.h5
-rw-r--r--linux-user/main.c7
-rw-r--r--linux-user/signal.c7
-rw-r--r--qemu-doc.texi8
-rw-r--r--scripts/coccinelle/cpu_restore_state.cocci19
-rw-r--r--scripts/dump-guest-memory.py3
-rw-r--r--target/alpha/mem_helper.c13
-rw-r--r--target/alpha/translate.c22
-rw-r--r--target/arm/op_helper.c18
-rw-r--r--target/arm/translate-a64.c37
-rw-r--r--target/arm/translate.c31
-rw-r--r--target/arm/translate.h10
-rw-r--r--target/cris/translate.c4
-rw-r--r--target/hppa/translate.c63
-rw-r--r--target/i386/svm_helper.c4
-rw-r--r--target/i386/translate.c13
-rw-r--r--target/lm32/op_helper.c7
-rw-r--r--target/lm32/translate.c2
-rw-r--r--target/m68k/cpu.c20
-rw-r--r--target/m68k/cpu.h84
-rw-r--r--target/m68k/gdbstub.c2
-rw-r--r--target/m68k/helper.c99
-rw-r--r--target/m68k/helper.h11
-rw-r--r--target/m68k/monitor.c1
-rw-r--r--target/m68k/op_helper.c345
-rw-r--r--target/m68k/translate.c511
-rw-r--r--target/microblaze/op_helper.c7
-rw-r--r--target/microblaze/translate.c4
-rw-r--r--target/mips/translate.c2
-rw-r--r--target/moxie/helper.c5
-rw-r--r--target/nios2/mmu.c7
-rw-r--r--target/nios2/translate.c6
-rw-r--r--target/openrisc/mmu_helper.c6
-rw-r--r--target/ppc/translate.c2
-rw-r--r--target/s390x/translate.c42
-rw-r--r--target/sh4/translate.c4
-rw-r--r--target/sparc/translate.c2
-rw-r--r--target/tilegx/translate.c10
-rw-r--r--target/tricore/op_helper.c13
-rw-r--r--target/unicore32/op_helper.c7
-rw-r--r--target/unicore32/translate.c4
-rw-r--r--tcg/optimize.c20
-rw-r--r--tcg/tcg-op.c24
-rw-r--r--tcg/tcg-op.h4
-rw-r--r--tcg/tcg.c149
-rw-r--r--tcg/tcg.h60
-rw-r--r--tcg/tci.c12
-rw-r--r--tcg/tci/tcg-target.inc.c6
-rw-r--r--tests/virtio-9p-test.c33
71 files changed, 1417 insertions, 684 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 73a5555735..bc2d3a4ef1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1083,13 +1083,11 @@ F: include/hw/virtio/
F: tests/virtio-balloon-test.c
virtio-9p
-M: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
M: Greg Kurz <groug@kaod.org>
S: Supported
F: hw/9pfs/
F: fsdev/
F: tests/virtio-9p-test.c
-T: git git://github.com/kvaneesh/QEMU.git
T: git git://github.com/gkurz/qemu.git 9p-next
virtio-blk
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index 4452cd9856..280200f737 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -146,8 +146,10 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb)
uint8_t *tb_ptr = itb->tc.ptr;
qemu_log_mask_and_addr(CPU_LOG_EXEC, itb->pc,
- "Trace %p [%d: " TARGET_FMT_lx "] %s\n",
- itb->tc.ptr, cpu->cpu_index, itb->pc,
+ "Trace %d: %p ["
+ TARGET_FMT_lx "/" TARGET_FMT_lx "/%#x] %s\n",
+ cpu->cpu_index, itb->tc.ptr,
+ itb->cs_base, itb->pc, itb->flags,
lookup_symbol(itb->pc));
#if defined(DEBUG_DISAS)
diff --git a/accel/tcg/tcg-runtime.c b/accel/tcg/tcg-runtime.c
index 4172ffda82..d0d4484406 100644
--- a/accel/tcg/tcg-runtime.c
+++ b/accel/tcg/tcg-runtime.c
@@ -156,8 +156,9 @@ void *HELPER(lookup_tb_ptr)(CPUArchState *env)
return tcg_ctx->code_gen_epilogue;
}
qemu_log_mask_and_addr(CPU_LOG_EXEC, pc,
- "Chain %p [%d: " TARGET_FMT_lx "] %s\n",
- tb->tc.ptr, cpu->cpu_index, pc,
+ "Chain %d: %p ["
+ TARGET_FMT_lx "/" TARGET_FMT_lx "/%#x] %s\n",
+ cpu->cpu_index, tb->tc.ptr, cs_base, pc, flags,
lookup_symbol(pc));
return tb->tc.ptr;
}
diff --git a/configure b/configure
index 56f9716609..6a040821c6 100755
--- a/configure
+++ b/configure
@@ -5076,7 +5076,7 @@ fi
#################################################
# Check to see if we have the Hypervisor framework
-if [ "$darwin" == "yes" ] ; then
+if [ "$darwin" = "yes" ] ; then
cat > $TMPC << EOF
#include <Hypervisor/hv.h>
int main() { return 0;}
diff --git a/dump.c b/dump.c
index d4a8c942eb..e9dfed060a 100644
--- a/dump.c
+++ b/dump.c
@@ -788,12 +788,7 @@ static bool note_name_equal(DumpState *s,
get_note_sizes(s, note, &head_size, &name_size, NULL);
head_size = ROUND_UP(head_size, 4);
- if (name_size != len ||
- memcmp(note + head_size, "VMCOREINFO", len)) {
- return false;
- }
-
- return true;
+ return name_size == len && memcmp(note + head_size, name, len) == 0;
}
/* write common header, sub header and elf note to vmcore */
diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 474c79d003..3fa062b39f 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -22,22 +22,19 @@
#define SM_LOCAL_MODE_BITS 0600
#define SM_LOCAL_DIR_MODE_BITS 0700
-typedef struct FsCred
-{
+typedef struct FsCred {
uid_t fc_uid;
gid_t fc_gid;
mode_t fc_mode;
dev_t fc_rdev;
} FsCred;
-struct xattr_operations;
-struct FsContext;
-struct V9fsPath;
+typedef struct FsContext FsContext;
+typedef struct V9fsPath V9fsPath;
-typedef struct extended_ops {
- int (*get_st_gen)(struct FsContext *, struct V9fsPath *,
- mode_t, uint64_t *);
-} extended_ops;
+typedef struct ExtendedOps {
+ int (*get_st_gen)(FsContext *, V9fsPath *, mode_t, uint64_t *);
+} ExtendedOps;
/* export flags */
#define V9FS_IMMEDIATE_WRITEOUT 0x00000001
@@ -67,6 +64,8 @@ typedef struct extended_ops {
typedef struct FileOperations FileOperations;
+typedef struct XattrOperations XattrOperations;
+
/*
* Structure to store the various fsdev's passed through command line.
*/
@@ -80,24 +79,23 @@ typedef struct FsDriverEntry {
mode_t dmode;
} FsDriverEntry;
-typedef struct FsContext
-{
+struct FsContext {
uid_t uid;
char *fs_root;
int export_flags;
- struct xattr_operations **xops;
- struct extended_ops exops;
+ XattrOperations **xops;
+ ExtendedOps exops;
FsThrottle *fst;
/* fs driver specific data */
void *private;
mode_t fmode;
mode_t dmode;
-} FsContext;
+};
-typedef struct V9fsPath {
+struct V9fsPath {
uint16_t size;
char *data;
-} V9fsPath;
+};
typedef union V9fsFidOpenState V9fsFidOpenState;
@@ -105,9 +103,9 @@ void cred_init(FsCred *);
struct FileOperations
{
- int (*parse_opts)(QemuOpts *, struct FsDriverEntry *);
- int (*init)(struct FsContext *);
- void (*cleanup)(struct FsContext *);
+ int (*parse_opts)(QemuOpts *, FsDriverEntry *, Error **errp);
+ int (*init)(FsContext *, Error **errp);
+ void (*cleanup)(FsContext *);
int (*lstat)(FsContext *, V9fsPath *, struct stat *);
ssize_t (*readlink)(FsContext *, V9fsPath *, char *, size_t);
int (*chmod)(FsContext *, V9fsPath *, FsCred *);
diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
index 266e442b87..941e309657 100644
--- a/fsdev/qemu-fsdev.c
+++ b/fsdev/qemu-fsdev.c
@@ -37,6 +37,7 @@ int qemu_fsdev_add(QemuOpts *opts)
const char *fsdriver = qemu_opt_get(opts, "fsdriver");
const char *writeout = qemu_opt_get(opts, "writeout");
bool ro = qemu_opt_get_bool(opts, "readonly", 0);
+ Error *local_err = NULL;
if (!fsdev_id) {
error_report("fsdev: No id specified");
@@ -74,7 +75,8 @@ int qemu_fsdev_add(QemuOpts *opts)
}
if (fsle->fse.ops->parse_opts) {
- if (fsle->fse.ops->parse_opts(opts, &fsle->fse)) {
+ if (fsle->fse.ops->parse_opts(opts, &fsle->fse, &local_err)) {
+ error_report_err(local_err);
g_free(fsle->fse.fsdev_id);
g_free(fsle);
return -1;
diff --git a/hw/9pfs/9p-handle.c b/hw/9pfs/9p-handle.c
index 9875f1894c..c1681d3c8a 100644
--- a/hw/9pfs/9p-handle.c
+++ b/hw/9pfs/9p-handle.c
@@ -41,10 +41,10 @@
#define BTRFS_SUPER_MAGIC 0x9123683E
#endif
-struct handle_data {
+typedef struct HandleData {
int mountfd;
int handle_bytes;
-};
+} HandleData;
static inline int name_to_handle(int dirfd, const char *name,
struct file_handle *fh, int *mnt_id, int flags)
@@ -79,7 +79,7 @@ static int handle_lstat(FsContext *fs_ctx, V9fsPath *fs_path,
struct stat *stbuf)
{
int fd, ret;
- struct handle_data *data = (struct handle_data *)fs_ctx->private;
+ HandleData *data = (HandleData *) fs_ctx->private;
fd = open_by_handle(data->mountfd, fs_path->data, O_PATH);
if (fd < 0) {
@@ -94,7 +94,7 @@ static ssize_t handle_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
char *buf, size_t bufsz)
{
int fd, ret;
- struct handle_data *data = (struct handle_data *)fs_ctx->private;
+ HandleData *data = (HandleData *) fs_ctx->private;
fd = open_by_handle(data->mountfd, fs_path->data, O_PATH);
if (fd < 0) {
@@ -118,7 +118,7 @@ static int handle_closedir(FsContext *ctx, V9fsFidOpenState *fs)
static int handle_open(FsContext *ctx, V9fsPath *fs_path,
int flags, V9fsFidOpenState *fs)
{
- struct handle_data *data = (struct handle_data *)ctx->private;
+ HandleData *data = (HandleData *) ctx->private;
fs->fd = open_by_handle(data->mountfd, fs_path->data, flags);
return fs->fd;
@@ -207,7 +207,7 @@ static ssize_t handle_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
static int handle_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
{
int fd, ret;
- struct handle_data *data = (struct handle_data *)fs_ctx->private;
+ HandleData *data = (HandleData *) fs_ctx->private;
fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
if (fd < 0) {
@@ -222,7 +222,7 @@ static int handle_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
const char *name, FsCred *credp)
{
int dirfd, ret;
- struct handle_data *data = (struct handle_data *)fs_ctx->private;
+ HandleData *data = (HandleData *) fs_ctx->private;
dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
if (dirfd < 0) {
@@ -240,7 +240,7 @@ static int handle_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
const char *name, FsCred *credp)
{
int dirfd, ret;
- struct handle_data *data = (struct handle_data *)fs_ctx->private;
+ HandleData *data = (HandleData *) fs_ctx->private;
dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
if (dirfd < 0) {
@@ -272,7 +272,7 @@ static int handle_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
{
int ret;
int dirfd, fd;
- struct handle_data *data = (struct handle_data *)fs_ctx->private;
+ HandleData *data = (HandleData *) fs_ctx->private;
dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
if (dirfd < 0) {
@@ -297,7 +297,7 @@ static int handle_symlink(FsContext *fs_ctx, const char *oldpath,
V9fsPath *dir_path, const char *name, FsCred *credp)
{
int fd, dirfd, ret;
- struct handle_data *data = (struct handle_data *)fs_ctx->private;
+ HandleData *data = (HandleData *) fs_ctx->private;
dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
if (dirfd < 0) {
@@ -322,7 +322,7 @@ static int handle_link(FsContext *ctx, V9fsPath *oldpath,
V9fsPath *dirpath, const char *name)
{
int oldfd, newdirfd, ret;
- struct handle_data *data = (struct handle_data *)ctx->private;
+ HandleData *data = (HandleData *) ctx->private;
oldfd = open_by_handle(data->mountfd, oldpath->data, O_PATH);
if (oldfd < 0) {
@@ -342,7 +342,7 @@ static int handle_link(FsContext *ctx, V9fsPath *oldpath,
static int handle_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
{
int fd, ret;
- struct handle_data *data = (struct handle_data *)ctx->private;
+ HandleData *data = (HandleData *) ctx->private;
fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK | O_WRONLY);
if (fd < 0) {
@@ -363,7 +363,7 @@ static int handle_rename(FsContext *ctx, const char *oldpath,
static int handle_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
{
int fd, ret;
- struct handle_data *data = (struct handle_data *)fs_ctx->private;
+ HandleData *data = (HandleData *) fs_ctx->private;
fd = open_by_handle(data->mountfd, fs_path->data, O_PATH);
if (fd < 0) {
@@ -379,7 +379,7 @@ static int handle_utimensat(FsContext *ctx, V9fsPath *fs_path,
{
int ret;
int fd;
- struct handle_data *data = (struct handle_data *)ctx->private;
+ HandleData *data = (HandleData *) ctx->private;
fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
if (fd < 0) {
@@ -418,7 +418,7 @@ static int handle_statfs(FsContext *ctx, V9fsPath *fs_path,
struct statfs *stbuf)
{
int fd, ret;
- struct handle_data *data = (struct handle_data *)ctx->private;
+ HandleData *data = (HandleData *) ctx->private;
fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
if (fd < 0) {
@@ -433,7 +433,7 @@ static ssize_t handle_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
const char *name, void *value, size_t size)
{
int fd, ret;
- struct handle_data *data = (struct handle_data *)ctx->private;
+ HandleData *data = (HandleData *) ctx->private;
fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
if (fd < 0) {
@@ -448,7 +448,7 @@ static ssize_t handle_llistxattr(FsContext *ctx, V9fsPath *fs_path,
void *value, size_t size)
{
int fd, ret;
- struct handle_data *data = (struct handle_data *)ctx->private;
+ HandleData *data = (HandleData *) ctx->private;
fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
if (fd < 0) {
@@ -463,7 +463,7 @@ static int handle_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
void *value, size_t size, int flags)
{
int fd, ret;
- struct handle_data *data = (struct handle_data *)ctx->private;
+ HandleData *data = (HandleData *) ctx->private;
fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
if (fd < 0) {
@@ -478,7 +478,7 @@ static int handle_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
const char *name)
{
int fd, ret;
- struct handle_data *data = (struct handle_data *)ctx->private;
+ HandleData *data = (HandleData *) ctx->private;
fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
if (fd < 0) {
@@ -495,7 +495,7 @@ static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
char *buffer;
struct file_handle *fh;
int dirfd, ret, mnt_id;
- struct handle_data *data = (struct handle_data *)ctx->private;
+ HandleData *data = (HandleData *) ctx->private;
/* "." and ".." are not allowed */
if (!strcmp(name, ".") || !strcmp(name, "..")) {
@@ -536,7 +536,7 @@ static int handle_renameat(FsContext *ctx, V9fsPath *olddir,
const char *new_name)
{
int olddirfd, newdirfd, ret;
- struct handle_data *data = (struct handle_data *)ctx->private;
+ HandleData *data = (HandleData *) ctx->private;
olddirfd = open_by_handle(data->mountfd, olddir->data, O_PATH);
if (olddirfd < 0) {
@@ -557,7 +557,7 @@ static int handle_unlinkat(FsContext *ctx, V9fsPath *dir,
const char *name, int flags)
{
int dirfd, ret;
- struct handle_data *data = (struct handle_data *)ctx->private;
+ HandleData *data = (HandleData *) ctx->private;
int rflags;
dirfd = open_by_handle(data->mountfd, dir->data, O_PATH);
@@ -604,12 +604,12 @@ static int handle_ioc_getversion(FsContext *ctx, V9fsPath *path,
#endif
}
-static int handle_init(FsContext *ctx)
+static int handle_init(FsContext *ctx, Error **errp)
{
int ret, mnt_id;
struct statfs stbuf;
struct file_handle fh;
- struct handle_data *data = g_malloc(sizeof(struct handle_data));
+ HandleData *data = g_malloc(sizeof(HandleData));
data->mountfd = open(ctx->fs_root, O_DIRECTORY);
if (data->mountfd < 0) {
@@ -646,17 +646,19 @@ out:
static void handle_cleanup(FsContext *ctx)
{
- struct handle_data *data = ctx->private;
+ HandleData *data = ctx->private;
close(data->mountfd);
g_free(data);
}
-static int handle_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
+static int handle_parse_opts(QemuOpts *opts, FsDriverEntry *fse, Error **errp)
{
const char *sec_model = qemu_opt_get(opts, "security_model");
const char *path = qemu_opt_get(opts, "path");
+ warn_report("handle backend is deprecated");
+
if (sec_model) {
error_report("Invalid argument security_model specified with handle fsdriver");
return -1;
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index e51af87309..b25c185ff0 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -1400,13 +1400,14 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path,
#endif
}
-static int local_init(FsContext *ctx)
+static int local_init(FsContext *ctx, Error **errp)
{
struct statfs stbuf;
LocalData *data = g_malloc(sizeof(*data));
data->mountfd = open(ctx->fs_root, O_DIRECTORY | O_RDONLY);
if (data->mountfd == -1) {
+ error_setg_errno(errp, errno, "failed to open '%s'", ctx->fs_root);
goto err;
}
@@ -1459,16 +1460,21 @@ static void local_cleanup(FsContext *ctx)
g_free(data);
}
-static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
+static void error_append_security_model_hint(Error **errp)
+{
+ error_append_hint(errp, "Valid options are: security_model="
+ "[passthrough|mapped-xattr|mapped-file|none]\n");
+}
+
+static int local_parse_opts(QemuOpts *opts, FsDriverEntry *fse, Error **errp)
{
const char *sec_model = qemu_opt_get(opts, "security_model");
const char *path = qemu_opt_get(opts, "path");
- Error *err = NULL;
+ Error *local_err = NULL;
if (!sec_model) {
- error_report("Security model not specified, local fs needs security model");
- error_printf("valid options are:"
- "\tsecurity_model=[passthrough|mapped-xattr|mapped-file|none]\n");
+ error_setg(errp, "security_model property not set");
+ error_append_security_model_hint(errp);
return -1;
}
@@ -1482,20 +1488,20 @@ static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
} else if (!strcmp(sec_model, "mapped-file")) {
fse->export_flags |= V9FS_SM_MAPPED_FILE;
} else {
- error_report("Invalid security model %s specified", sec_model);
- error_printf("valid options are:"
- "\t[passthrough|mapped-xattr|mapped-file|none]\n");
+ error_setg(errp, "invalid security_model property '%s'", sec_model);
+ error_append_security_model_hint(errp);
return -1;
}
if (!path) {
- error_report("fsdev: No path specified");
+ error_setg(errp, "path property not set");
return -1;
}
- fsdev_throttle_parse_opts(opts, &fse->fst, &err);
- if (err) {
- error_reportf_err(err, "Throttle configuration is not valid: ");
+ fsdev_throttle_parse_opts(opts, &fse->fst, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ error_prepend(errp, "invalid throttle configuration: ");
return -1;
}
@@ -1507,11 +1513,11 @@ static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
qemu_opt_get_number(opts, "dmode", SM_LOCAL_DIR_MODE_BITS) & 0777;
} else {
if (qemu_opt_find(opts, "fmode")) {
- error_report("fmode is only valid for mapped 9p modes");
+ error_setg(errp, "fmode is only valid for mapped security modes");
return -1;
}
if (qemu_opt_find(opts, "dmode")) {
- error_report("dmode is only valid for mapped 9p modes");
+ error_setg(errp, "dmode is only valid for mapped security modes");
return -1;
}
}
diff --git a/hw/9pfs/9p-proxy.c b/hw/9pfs/9p-proxy.c
index 28b20a7c3d..f030c6a428 100644
--- a/hw/9pfs/9p-proxy.c
+++ b/hw/9pfs/9p-proxy.c
@@ -1083,25 +1083,25 @@ static int proxy_ioc_getversion(FsContext *fs_ctx, V9fsPath *path,
return err;
}
-static int connect_namedsocket(const char *path)
+static int connect_namedsocket(const char *path, Error **errp)
{
int sockfd, size;
struct sockaddr_un helper;
if (strlen(path) >= sizeof(helper.sun_path)) {
- error_report("Socket name too long");
+ error_setg(errp, "socket name too long");
return -1;
}
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sockfd < 0) {
- error_report("Failed to create socket: %s", strerror(errno));
+ error_setg_errno(errp, errno, "failed to create client socket");
return -1;
}
strcpy(helper.sun_path, path);
helper.sun_family = AF_UNIX;
size = strlen(helper.sun_path) + sizeof(helper.sun_family);
if (connect(sockfd, (struct sockaddr *)&helper, size) < 0) {
- error_report("Failed to connect to %s: %s", path, strerror(errno));
+ error_setg_errno(errp, errno, "failed to connect to '%s'", path);
close(sockfd);
return -1;
}
@@ -1111,17 +1111,27 @@ static int connect_namedsocket(const char *path)
return sockfd;
}
-static int proxy_parse_opts(QemuOpts *opts, struct FsDriverEntry *fs)
+static void error_append_socket_sockfd_hint(Error **errp)
+{
+ error_append_hint(errp, "Either specify socket=/some/path where /some/path"
+ " points to a listening AF_UNIX socket or sock_fd=fd"
+ " where fd is a file descriptor to a connected AF_UNIX"
+ " socket\n");
+}
+
+static int proxy_parse_opts(QemuOpts *opts, FsDriverEntry *fs, Error **errp)
{
const char *socket = qemu_opt_get(opts, "socket");
const char *sock_fd = qemu_opt_get(opts, "sock_fd");
if (!socket && !sock_fd) {
- error_report("Must specify either socket or sock_fd");
+ error_setg(errp, "both socket and sock_fd properties are missing");
+ error_append_socket_sockfd_hint(errp);
return -1;
}
if (socket && sock_fd) {
- error_report("Both socket and sock_fd options specified");
+ error_setg(errp, "both socket and sock_fd properties are set");
+ error_append_socket_sockfd_hint(errp);
return -1;
}
if (socket) {
@@ -1134,17 +1144,17 @@ static int proxy_parse_opts(QemuOpts *opts, struct FsDriverEntry *fs)
return 0;
}
-static int proxy_init(FsContext *ctx)
+static int proxy_init(FsContext *ctx, Error **errp)
{
V9fsProxy *proxy = g_malloc(sizeof(V9fsProxy));
int sock_id;
if (ctx->export_flags & V9FS_PROXY_SOCK_NAME) {
- sock_id = connect_namedsocket(ctx->fs_root);
+ sock_id = connect_namedsocket(ctx->fs_root, errp);
} else {
sock_id = atoi(ctx->fs_root);
if (sock_id < 0) {
- error_report("Socket descriptor not initialized");
+ error_setg(errp, "socket descriptor not initialized");
}
}
if (sock_id < 0) {
diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c
index df0a8de08a..8f255e91c0 100644
--- a/hw/9pfs/9p-synth.c
+++ b/hw/9pfs/9p-synth.c
@@ -514,7 +514,7 @@ static int synth_unlinkat(FsContext *ctx, V9fsPath *dir,
return -1;
}
-static int synth_init(FsContext *ctx)
+static int synth_init(FsContext *ctx, Error **errp)
{
QLIST_INIT(&synth_root.child);
qemu_mutex_init(&synth_mutex);
diff --git a/hw/9pfs/9p-xattr.h b/hw/9pfs/9p-xattr.h
index 0d83996575..35bcd24f77 100644
--- a/hw/9pfs/9p-xattr.h
+++ b/hw/9pfs/9p-xattr.h
@@ -16,8 +16,7 @@
#include "qemu/xattr.h"
-typedef struct xattr_operations
-{
+struct XattrOperations {
const char *name;
ssize_t (*getxattr)(FsContext *ctx, const char *path,
const char *name, void *value, size_t size);
@@ -27,7 +26,7 @@ typedef struct xattr_operations
void *value, size_t size, int flags);
int (*removexattr)(FsContext *ctx,
const char *path, const char *name);
-} XattrOperations;
+};
ssize_t local_getxattr_nofollow(FsContext *ctx, const char *path,
const char *name, void *value, size_t size);
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 52d46632fe..909a611394 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -41,7 +41,7 @@ enum {
Oappend = 0x80,
};
-ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
+static ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
{
ssize_t ret;
va_list ap;
@@ -53,7 +53,7 @@ ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
return ret;
}
-ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
+static ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
{
ssize_t ret;
va_list ap;
@@ -99,10 +99,10 @@ static int omode_to_uflags(int8_t mode)
return ret;
}
-struct dotl_openflag_map {
+typedef struct DotlOpenflagMap {
int dotl_flag;
int open_flag;
-};
+} DotlOpenflagMap;
static int dotl_to_open_flags(int flags)
{
@@ -113,7 +113,7 @@ static int dotl_to_open_flags(int flags)
*/
int oflags = flags & O_ACCMODE;
- struct dotl_openflag_map dotl_oflag_map[] = {
+ DotlOpenflagMap dotl_oflag_map[] = {
{ P9_DOTL_CREATE, O_CREAT },
{ P9_DOTL_EXCL, O_EXCL },
{ P9_DOTL_NOCTTY , O_NOCTTY },
@@ -3473,14 +3473,12 @@ void pdu_submit(V9fsPDU *pdu, P9MsgHeader *hdr)
if (pdu->id >= ARRAY_SIZE(pdu_co_handlers) ||
(pdu_co_handlers[pdu->id] == NULL)) {
handler = v9fs_op_not_supp;
+ } else if (is_ro_export(&s->ctx) && !is_read_only_op(pdu)) {
+ handler = v9fs_fs_ro;
} else {
handler = pdu_co_handlers[pdu->id];
}
- if (is_ro_export(&s->ctx) && !is_read_only_op(pdu)) {
- handler = v9fs_fs_ro;
- }
-
qemu_co_queue_init(&pdu->complete);
co = qemu_coroutine_create(handler, pdu);
qemu_coroutine_enter(co);
@@ -3544,9 +3542,9 @@ int v9fs_device_realize_common(V9fsState *s, Error **errp)
s->fid_list = NULL;
qemu_co_rwlock_init(&s->rename_lock);
- if (s->ops->init(&s->ctx) < 0) {
- error_setg(errp, "9pfs Failed to initialize fs-driver with id:%s"
- " and export path:%s", s->fsconf.fsdev_id, s->ctx.fs_root);
+ if (s->ops->init(&s->ctx, errp) < 0) {
+ error_prepend(errp, "cannot initialize fsdev '%s': ",
+ s->fsconf.fsdev_id);
goto out;
}
diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
index cdfc4f4ce7..ffe658ab89 100644
--- a/hw/9pfs/9p.h
+++ b/hw/9pfs/9p.h
@@ -94,10 +94,10 @@ enum {
P9_QTFILE = 0x00,
};
-enum p9_proto_version {
+typedef enum P9ProtoVersion {
V9FS_PROTO_2000U = 0x01,
V9FS_PROTO_2000L = 0x02,
-};
+} P9ProtoVersion;
#define P9_NOTAG UINT16_MAX
#define P9_NOFID UINT32_MAX
@@ -118,6 +118,7 @@ static inline char *rpath(FsContext *ctx, const char *path)
typedef struct V9fsPDU V9fsPDU;
typedef struct V9fsState V9fsState;
+typedef struct V9fsTransport V9fsTransport;
typedef struct {
uint32_t size_le;
@@ -238,10 +239,10 @@ struct V9fsState
FileOperations *ops;
FsContext ctx;
char *tag;
- enum p9_proto_version proto_version;
+ P9ProtoVersion proto_version;
int32_t msize;
V9fsPDU pdus[MAX_REQ];
- const struct V9fsTransport *transport;
+ const V9fsTransport *transport;
/*
* lock ensuring atomic path update
* on rename.
@@ -348,8 +349,6 @@ int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath,
int v9fs_device_realize_common(V9fsState *s, Error **errp);
void v9fs_device_unrealize_common(V9fsState *s, Error **errp);
-ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...);
-ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...);
V9fsPDU *pdu_alloc(V9fsState *s);
void pdu_free(V9fsPDU *pdu);
void pdu_submit(V9fsPDU *pdu, P9MsgHeader *hdr);
@@ -367,8 +366,7 @@ struct V9fsTransport {
void (*push_and_notify)(V9fsPDU *pdu);
};
-static inline int v9fs_register_transport(V9fsState *s,
- const struct V9fsTransport *t)
+static inline int v9fs_register_transport(V9fsState *s, const V9fsTransport *t)
{
assert(!s->transport);
s->transport = t;
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 62650b0a6b..43f4e53f33 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -20,8 +20,6 @@
#include "hw/virtio/virtio-access.h"
#include "qemu/iov.h"
-static const struct V9fsTransport virtio_9p_transport;
-
static void virtio_9p_push_and_notify(V9fsPDU *pdu)
{
V9fsState *s = pdu->s;
@@ -104,35 +102,6 @@ static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
g_free(cfg);
}
-static void virtio_9p_device_realize(DeviceState *dev, Error **errp)
-{
- VirtIODevice *vdev = VIRTIO_DEVICE(dev);
- V9fsVirtioState *v = VIRTIO_9P(dev);
- V9fsState *s = &v->state;
-
- if (v9fs_device_realize_common(s, errp)) {
- goto out;
- }
-
- v->config_size = sizeof(struct virtio_9p_config) + strlen(s->fsconf.tag);
- virtio_init(vdev, "virtio-9p", VIRTIO_ID_9P, v->config_size);
- v->vq = virtio_add_queue(vdev, MAX_REQ, handle_9p_output);
- v9fs_register_transport(s, &virtio_9p_transport);
-
-out:
- return;
-}
-
-static void virtio_9p_device_unrealize(DeviceState *dev, Error **errp)
-{
- VirtIODevice *vdev = VIRTIO_DEVICE(dev);
- V9fsVirtioState *v = VIRTIO_9P(dev);
- V9fsState *s = &v->state;
-
- virtio_cleanup(vdev);
- v9fs_device_unrealize_common(s, errp);
-}
-
static void virtio_9p_reset(VirtIODevice *vdev)
{
V9fsVirtioState *v = (V9fsVirtioState *)vdev;
@@ -215,7 +184,7 @@ static void virtio_init_out_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov,
*pniov = elem->out_num;
}
-static const struct V9fsTransport virtio_9p_transport = {
+static const V9fsTransport virtio_9p_transport = {
.pdu_vmarshal = virtio_pdu_vmarshal,
.pdu_vunmarshal = virtio_pdu_vunmarshal,
.init_in_iov_from_pdu = virtio_init_in_iov_from_pdu,
@@ -223,6 +192,35 @@ static const struct V9fsTransport virtio_9p_transport = {
.push_and_notify = virtio_9p_push_and_notify,
};
+static void virtio_9p_device_realize(DeviceState *dev, Error **errp)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ V9fsVirtioState *v = VIRTIO_9P(dev);
+ V9fsState *s = &v->state;
+
+ if (v9fs_device_realize_common(s, errp)) {
+ goto out;
+ }
+
+ v->config_size = sizeof(struct virtio_9p_config) + strlen(s->fsconf.tag);
+ virtio_init(vdev, "virtio-9p", VIRTIO_ID_9P, v->config_size);
+ v->vq = virtio_add_queue(vdev, MAX_REQ, handle_9p_output);
+ v9fs_register_transport(s, &virtio_9p_transport);
+
+out:
+ return;
+}
+
+static void virtio_9p_device_unrealize(DeviceState *dev, Error **errp)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ V9fsVirtioState *v = VIRTIO_9P(dev);
+ V9fsState *s = &v->state;
+
+ virtio_cleanup(vdev);
+ v9fs_device_unrealize_common(s, errp);
+}
+
/* virtio-9p device */
static const VMStateDescription vmstate_virtio_9p = {
diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c
index ee87f08926..df2a4100bf 100644
--- a/hw/9pfs/xen-9p-backend.c
+++ b/hw/9pfs/xen-9p-backend.c
@@ -233,7 +233,7 @@ static void xen_9pfs_push_and_notify(V9fsPDU *pdu)
qemu_bh_schedule(ring->bh);
}
-static const struct V9fsTransport xen_9p_transport = {
+static const V9fsTransport xen_9p_transport = {
.pdu_vmarshal = xen_9pfs_pdu_vmarshal,
.pdu_vunmarshal = xen_9pfs_pdu_vunmarshal,
.init_in_iov_from_pdu = xen_9pfs_init_in_iov_from_pdu,
diff --git a/hw/misc/vmcoreinfo.c b/hw/misc/vmcoreinfo.c
index 31db57ab44..a2805527cb 100644
--- a/hw/misc/vmcoreinfo.c
+++ b/hw/misc/vmcoreinfo.c
@@ -35,6 +35,8 @@ static void vmcoreinfo_realize(DeviceState *dev, Error **errp)
{
VMCoreInfoState *s = VMCOREINFO(dev);
FWCfgState *fw_cfg = fw_cfg_find();
+ /* for gdb script dump-guest-memory.py */
+ static VMCoreInfoState * volatile vmcoreinfo_state G_GNUC_UNUSED;
/* Given that this function is executing, there is at least one VMCOREINFO
* device. Check if there are several.
@@ -56,6 +58,7 @@ static void vmcoreinfo_realize(DeviceState *dev, Error **errp)
&s->vmcoreinfo, sizeof(s->vmcoreinfo), false);
qemu_register_reset(vmcoreinfo_reset, dev);
+ vmcoreinfo_state = s;
}
static const VMStateDescription vmstate_vmcoreinfo = {
diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h
index 049bba86e9..54aaa61d65 100644
--- a/include/exec/gen-icount.h
+++ b/include/exec/gen-icount.h
@@ -5,7 +5,7 @@
/* Helpers for instruction counting code generation. */
-static int icount_start_insn_idx;
+static TCGOp *icount_start_insn;
static inline void gen_tb_start(TranslationBlock *tb)
{
@@ -26,8 +26,8 @@ static inline void gen_tb_start(TranslationBlock *tb)
/* We emit a movi with a dummy immediate argument. Keep the insn index
* of the movi so that we later (when we know the actual insn count)
* can update the immediate argument with the actual insn count. */
- icount_start_insn_idx = tcg_op_buf_count();
tcg_gen_movi_i32(imm, 0xdeadbeef);
+ icount_start_insn = tcg_last_op();
tcg_gen_sub_i32(count, count, imm);
tcg_temp_free_i32(imm);
@@ -48,14 +48,11 @@ static inline void gen_tb_end(TranslationBlock *tb, int num_insns)
if (tb_cflags(tb) & CF_USE_ICOUNT) {
/* Update the num_insn immediate parameter now that we know
* the actual insn count. */
- tcg_set_insn_param(icount_start_insn_idx, 1, num_insns);
+ tcg_set_insn_param(icount_start_insn, 1, num_insns);
}
gen_set_label(tcg_ctx->exitreq_label);
tcg_gen_exit_tb((uintptr_t)tb + TB_EXIT_REQUESTED);
-
- /* Terminate the linked list. */
- tcg_ctx->gen_op_buf[tcg_ctx->gen_op_buf[0].prev].next = 0;
}
static inline void gen_io_start(void)
diff --git a/include/exec/helper-gen.h b/include/exec/helper-gen.h
index 15204ab961..22381a1708 100644
--- a/include/exec/helper-gen.h
+++ b/include/exec/helper-gen.h
@@ -56,6 +56,16 @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
tcg_gen_callN(HELPER(name), dh_retvar(ret), 5, args); \
}
+#define DEF_HELPER_FLAGS_6(name, flags, ret, t1, t2, t3, t4, t5, t6) \
+static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
+ dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
+ dh_arg_decl(t4, 4), dh_arg_decl(t5, 5), dh_arg_decl(t6, 6)) \
+{ \
+ TCGTemp *args[6] = { dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
+ dh_arg(t4, 4), dh_arg(t5, 5), dh_arg(t6, 6) }; \
+ tcg_gen_callN(HELPER(name), dh_retvar(ret), 6, args); \
+}
+
#include "helper.h"
#include "trace/generated-helpers.h"
#include "trace/generated-helpers-wrappers.h"
@@ -67,6 +77,7 @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
#undef DEF_HELPER_FLAGS_3
#undef DEF_HELPER_FLAGS_4
#undef DEF_HELPER_FLAGS_5
+#undef DEF_HELPER_FLAGS_6
#undef GEN_HELPER
#endif /* HELPER_GEN_H */
diff --git a/include/exec/helper-head.h b/include/exec/helper-head.h
index 639eefdbc0..e1fd08f2ba 100644
--- a/include/exec/helper-head.h
+++ b/include/exec/helper-head.h
@@ -125,6 +125,8 @@
DEF_HELPER_FLAGS_4(name, 0, ret, t1, t2, t3, t4)
#define DEF_HELPER_5(name, ret, t1, t2, t3, t4, t5) \
DEF_HELPER_FLAGS_5(name, 0, ret, t1, t2, t3, t4, t5)
+#define DEF_HELPER_6(name, ret, t1, t2, t3, t4, t5, t6) \
+ DEF_HELPER_FLAGS_6(name, 0, ret, t1, t2, t3, t4, t5, t6)
/* MAX_OPC_PARAM_IARGS must be set to n if last entry is DEF_HELPER_FLAGS_n. */
diff --git a/include/exec/helper-proto.h b/include/exec/helper-proto.h
index 954bef85ce..74943edb13 100644
--- a/include/exec/helper-proto.h
+++ b/include/exec/helper-proto.h
@@ -26,6 +26,10 @@ dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
dh_ctype(t4), dh_ctype(t5));
+#define DEF_HELPER_FLAGS_6(name, flags, ret, t1, t2, t3, t4, t5, t6) \
+dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
+ dh_ctype(t4), dh_ctype(t5), dh_ctype(t6));
+
#include "helper.h"
#include "trace/generated-helpers.h"
#include "tcg-runtime.h"
@@ -36,5 +40,6 @@ dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
#undef DEF_HELPER_FLAGS_3
#undef DEF_HELPER_FLAGS_4
#undef DEF_HELPER_FLAGS_5
+#undef DEF_HELPER_FLAGS_6
#endif /* HELPER_PROTO_H */
diff --git a/include/exec/helper-tcg.h b/include/exec/helper-tcg.h
index b0c5bafa99..b3bdb0c399 100644
--- a/include/exec/helper-tcg.h
+++ b/include/exec/helper-tcg.h
@@ -39,6 +39,12 @@
| dh_sizemask(t2, 2) | dh_sizemask(t3, 3) | dh_sizemask(t4, 4) \
| dh_sizemask(t5, 5) },
+#define DEF_HELPER_FLAGS_6(NAME, FLAGS, ret, t1, t2, t3, t4, t5, t6) \
+ { .func = HELPER(NAME), .name = str(NAME), .flags = FLAGS, \
+ .sizemask = dh_sizemask(ret, 0) | dh_sizemask(t1, 1) \
+ | dh_sizemask(t2, 2) | dh_sizemask(t3, 3) | dh_sizemask(t4, 4) \
+ | dh_sizemask(t5, 5) | dh_sizemask(t6, 6) },
+
#include "helper.h"
#include "trace/generated-helpers.h"
#include "tcg-runtime.h"
@@ -50,5 +56,6 @@
#undef DEF_HELPER_FLAGS_3
#undef DEF_HELPER_FLAGS_4
#undef DEF_HELPER_FLAGS_5
+#undef DEF_HELPER_FLAGS_6
#endif /* HELPER_TCG_H */
diff --git a/include/qemu/queue.h b/include/qemu/queue.h
index 35292c3155..aa270d2b38 100644
--- a/include/qemu/queue.h
+++ b/include/qemu/queue.h
@@ -425,6 +425,11 @@ struct { \
(var); \
(var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
+#define QTAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, prev_var) \
+ for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \
+ (var) && ((prev_var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)), 1); \
+ (var) = (prev_var))
+
/*
* Tail queue access methods.
*/
diff --git a/linux-user/main.c b/linux-user/main.c
index 71696ed33d..99a551b04f 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2985,6 +2985,13 @@ void cpu_loop(CPUM68KState *env)
info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
+ case EXCP_CHK:
+ info.si_signo = TARGET_SIGFPE;
+ info.si_errno = 0;
+ info.si_code = TARGET_FPE_INTOVF;
+ info._sifields._sigfault._addr = env->pc;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ break;
case EXCP_DIV0:
info.si_signo = TARGET_SIGFPE;
info.si_errno = 0;
diff --git a/linux-user/signal.c b/linux-user/signal.c
index dae14d4a89..74fa03f96d 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -5612,13 +5612,14 @@ struct target_rt_sigframe
static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
abi_ulong mask)
{
+ uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
__put_user(mask, &sc->sc_mask);
__put_user(env->aregs[7], &sc->sc_usp);
__put_user(env->dregs[0], &sc->sc_d0);
__put_user(env->dregs[1], &sc->sc_d1);
__put_user(env->aregs[0], &sc->sc_a0);
__put_user(env->aregs[1], &sc->sc_a1);
- __put_user(env->sr, &sc->sc_sr);
+ __put_user(sr, &sc->sc_sr);
__put_user(env->pc, &sc->sc_pc);
}
@@ -5634,7 +5635,7 @@ restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
__get_user(env->aregs[1], &sc->sc_a1);
__get_user(env->pc, &sc->sc_pc);
__get_user(temp, &sc->sc_sr);
- env->sr = (env->sr & 0xff00) | (temp & 0xff);
+ cpu_m68k_set_ccr(env, temp);
}
/*
@@ -5726,7 +5727,7 @@ static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
CPUM68KState *env)
{
target_greg_t *gregs = uc->tuc_mcontext.gregs;
- uint32_t sr = cpu_m68k_get_ccr(env);
+ uint32_t sr = (env->sr & 0xff00) | cpu_m68k_get_ccr(env);
__put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version);
__put_user(env->dregs[0], &gregs[0]);
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 8d0c809ad5..9d0159832e 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -2725,6 +2725,14 @@ default channel subsystem image for guests that do not support multiple
channel subsystems, all devices can be put into the default channel
subsystem image.
+@subsection -fsdev handle (since 2.12.0)
+
+The ``handle'' fsdev backend does not support symlinks and causes the 9p
+filesystem in the guest to fail a fair amount of tests from the PJD POSIX
+filesystem test suite. Also it requires the CAP_DAC_READ_SEARCH capability,
+which is not the recommended way to run QEMU. This backend should not be
+used and it will be removed with no replacement.
+
@section qemu-img command line arguments
@subsection convert -s (since 2.0.0)
diff --git a/scripts/coccinelle/cpu_restore_state.cocci b/scripts/coccinelle/cpu_restore_state.cocci
new file mode 100644
index 0000000000..61bc749d14
--- /dev/null
+++ b/scripts/coccinelle/cpu_restore_state.cocci
@@ -0,0 +1,19 @@
+// Remove unneeded tests before calling cpu_restore_state
+//
+// spatch --macro-file scripts/cocci-macro-file.h \
+// --sp-file ./scripts/coccinelle/cpu_restore_state.cocci \
+// --keep-comments --in-place --use-gitgrep --dir target
+@@
+expression A;
+expression C;
+@@
+-if (A) {
+ cpu_restore_state(C, A);
+-}
+@@
+expression A;
+expression C;
+@@
+- cpu_restore_state(C, A);
+- cpu_loop_exit(C);
++ cpu_loop_exit_restore(C, A);
diff --git a/scripts/dump-guest-memory.py b/scripts/dump-guest-memory.py
index 1af26c1a45..09bec92b50 100644
--- a/scripts/dump-guest-memory.py
+++ b/scripts/dump-guest-memory.py
@@ -546,8 +546,7 @@ shape and this command should mostly work."""
return None
def add_vmcoreinfo(self):
- vmci = '(VMCoreInfoState *)' + \
- 'object_resolve_path_type("", "vmcoreinfo", 0)'
+ vmci = 'vmcoreinfo_realize::vmcoreinfo_state'
if not gdb.parse_and_eval("%s" % vmci) \
or not gdb.parse_and_eval("(%s)->has_vmcoreinfo" % vmci):
return
diff --git a/target/alpha/mem_helper.c b/target/alpha/mem_helper.c
index 3c06baa93a..430eea470b 100644
--- a/target/alpha/mem_helper.c
+++ b/target/alpha/mem_helper.c
@@ -34,9 +34,7 @@ void alpha_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
uint64_t pc;
uint32_t insn;
- if (retaddr) {
- cpu_restore_state(cs, retaddr);
- }
+ cpu_restore_state(cs, retaddr);
pc = env->pc;
insn = cpu_ldl_code(env, pc);
@@ -58,9 +56,7 @@ void alpha_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
AlphaCPU *cpu = ALPHA_CPU(cs);
CPUAlphaState *env = &cpu->env;
- if (retaddr) {
- cpu_restore_state(cs, retaddr);
- }
+ cpu_restore_state(cs, retaddr);
env->trap_arg0 = addr;
env->trap_arg1 = access_type == MMU_DATA_STORE ? 1 : 0;
@@ -80,11 +76,8 @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type,
ret = alpha_cpu_handle_mmu_fault(cs, addr, access_type, mmu_idx);
if (unlikely(ret != 0)) {
- if (retaddr) {
- cpu_restore_state(cs, retaddr);
- }
/* Exception index and error code are already set */
- cpu_loop_exit(cs);
+ cpu_loop_exit_restore(cs, retaddr);
}
}
#endif /* CONFIG_USER_ONLY */
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index 629f35ec8e..73a1b5e63e 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -156,7 +156,7 @@ void alpha_translate_init(void)
static TCGv load_zero(DisasContext *ctx)
{
- if (TCGV_IS_UNUSED_I64(ctx->zero)) {
+ if (!ctx->zero) {
ctx->zero = tcg_const_i64(0);
}
return ctx->zero;
@@ -164,7 +164,7 @@ static TCGv load_zero(DisasContext *ctx)
static TCGv dest_sink(DisasContext *ctx)
{
- if (TCGV_IS_UNUSED_I64(ctx->sink)) {
+ if (!ctx->sink) {
ctx->sink = tcg_temp_new();
}
return ctx->sink;
@@ -172,18 +172,18 @@ static TCGv dest_sink(DisasContext *ctx)
static void free_context_temps(DisasContext *ctx)
{
- if (!TCGV_IS_UNUSED_I64(ctx->sink)) {
+ if (ctx->sink) {
tcg_gen_discard_i64(ctx->sink);
tcg_temp_free(ctx->sink);
- TCGV_UNUSED_I64(ctx->sink);
+ ctx->sink = NULL;
}
- if (!TCGV_IS_UNUSED_I64(ctx->zero)) {
+ if (ctx->zero) {
tcg_temp_free(ctx->zero);
- TCGV_UNUSED_I64(ctx->zero);
+ ctx->zero = NULL;
}
- if (!TCGV_IS_UNUSED_I64(ctx->lit)) {
+ if (ctx->lit) {
tcg_temp_free(ctx->lit);
- TCGV_UNUSED_I64(ctx->lit);
+ ctx->lit = NULL;
}
}
@@ -2948,9 +2948,9 @@ static int alpha_tr_init_disas_context(DisasContextBase *dcbase,
/* Similarly for flush-to-zero. */
ctx->tb_ftz = -1;
- TCGV_UNUSED_I64(ctx->zero);
- TCGV_UNUSED_I64(ctx->sink);
- TCGV_UNUSED_I64(ctx->lit);
+ ctx->zero = NULL;
+ ctx->sink = NULL;
+ ctx->lit = NULL;
/* Bound the number of insns to execute to those left on the page. */
if (in_superpage(ctx, ctx->base.pc_first)) {
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index c2bb4f3a43..b36206343d 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -182,10 +182,8 @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type,
if (unlikely(ret)) {
ARMCPU *cpu = ARM_CPU(cs);
- if (retaddr) {
- /* now we have a real cpu fault */
- cpu_restore_state(cs, retaddr);
- }
+ /* now we have a real cpu fault */
+ cpu_restore_state(cs, retaddr);
deliver_fault(cpu, addr, access_type, mmu_idx, &fi);
}
@@ -199,10 +197,8 @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
ARMCPU *cpu = ARM_CPU(cs);
ARMMMUFaultInfo fi = {};
- if (retaddr) {
- /* now we have a real cpu fault */
- cpu_restore_state(cs, retaddr);
- }
+ /* now we have a real cpu fault */
+ cpu_restore_state(cs, retaddr);
fi.type = ARMFault_Alignment;
deliver_fault(cpu, vaddr, access_type, mmu_idx, &fi);
@@ -221,10 +217,8 @@ void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
ARMCPU *cpu = ARM_CPU(cs);
ARMMMUFaultInfo fi = {};
- if (retaddr) {
- /* now we have a real cpu fault */
- cpu_restore_state(cs, retaddr);
- }
+ /* now we have a real cpu fault */
+ cpu_restore_state(cs, retaddr);
/* The EA bit in syndromes and fault status registers is an
* IMPDEF classification of external aborts. ARM implementations
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 625ef2dfd2..ba94f7d045 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -405,10 +405,7 @@ static void unallocated_encoding(DisasContext *s)
static void init_tmp_a64_array(DisasContext *s)
{
#ifdef CONFIG_DEBUG_TCG
- int i;
- for (i = 0; i < ARRAY_SIZE(s->tmp_a64); i++) {
- TCGV_UNUSED_I64(s->tmp_a64[i]);
- }
+ memset(s->tmp_a64, 0, sizeof(s->tmp_a64));
#endif
s->tmp_a64_count = 0;
}
@@ -6276,7 +6273,7 @@ static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
return;
}
- TCGV_UNUSED_PTR(fpst);
+ fpst = NULL;
break;
case 0xc: /* FMAXNMP */
case 0xd: /* FADDP */
@@ -6371,7 +6368,7 @@ static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
tcg_temp_free_i32(tcg_res);
}
- if (!TCGV_IS_UNUSED_PTR(fpst)) {
+ if (fpst) {
tcg_temp_free_ptr(fpst);
}
}
@@ -6387,7 +6384,7 @@ static void handle_shri_with_rndacc(TCGv_i64 tcg_res, TCGv_i64 tcg_src,
bool is_u, int size, int shift)
{
bool extended_result = false;
- bool round = !TCGV_IS_UNUSED_I64(tcg_rnd);
+ bool round = tcg_rnd != NULL;
int ext_lshift = 0;
TCGv_i64 tcg_src_hi;
@@ -6533,7 +6530,7 @@ static void handle_scalar_simd_shri(DisasContext *s,
uint64_t round_const = 1ULL << (shift - 1);
tcg_round = tcg_const_i64(round_const);
} else {
- TCGV_UNUSED_I64(tcg_round);
+ tcg_round = NULL;
}
tcg_rn = read_fp_dreg(s, rn);
@@ -6649,7 +6646,7 @@ static void handle_vec_simd_sqshrn(DisasContext *s, bool is_scalar, bool is_q,
uint64_t round_const = 1ULL << (shift - 1);
tcg_round = tcg_const_i64(round_const);
} else {
- TCGV_UNUSED_I64(tcg_round);
+ tcg_round = NULL;
}
for (i = 0; i < elements; i++) {
@@ -8239,8 +8236,8 @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
tcg_fpstatus = get_fpstatus_ptr();
} else {
- TCGV_UNUSED_I32(tcg_rmode);
- TCGV_UNUSED_PTR(tcg_fpstatus);
+ tcg_rmode = NULL;
+ tcg_fpstatus = NULL;
}
if (size == 3) {
@@ -8360,7 +8357,7 @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
uint64_t round_const = 1ULL << (shift - 1);
tcg_round = tcg_const_i64(round_const);
} else {
- TCGV_UNUSED_I64(tcg_round);
+ tcg_round = NULL;
}
for (i = 0; i < elements; i++) {
@@ -8502,7 +8499,7 @@ static void handle_vec_simd_shrn(DisasContext *s, bool is_q,
uint64_t round_const = 1ULL << (shift - 1);
tcg_round = tcg_const_i64(round_const);
} else {
- TCGV_UNUSED_I64(tcg_round);
+ tcg_round = NULL;
}
for (i = 0; i < elements; i++) {
@@ -9168,7 +9165,7 @@ static void handle_simd_3same_pair(DisasContext *s, int is_q, int u, int opcode,
if (opcode >= 0x58) {
fpst = get_fpstatus_ptr();
} else {
- TCGV_UNUSED_PTR(fpst);
+ fpst = NULL;
}
if (!fp_access_check(s)) {
@@ -9305,7 +9302,7 @@ static void handle_simd_3same_pair(DisasContext *s, int is_q, int u, int opcode,
}
}
- if (!TCGV_IS_UNUSED_PTR(fpst)) {
+ if (fpst) {
tcg_temp_free_ptr(fpst);
}
}
@@ -10226,13 +10223,13 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
if (need_fpstatus) {
tcg_fpstatus = get_fpstatus_ptr();
} else {
- TCGV_UNUSED_PTR(tcg_fpstatus);
+ tcg_fpstatus = NULL;
}
if (need_rmode) {
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
} else {
- TCGV_UNUSED_I32(tcg_rmode);
+ tcg_rmode = NULL;
}
if (size == 3) {
@@ -10593,7 +10590,7 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
if (is_fp) {
fpst = get_fpstatus_ptr();
} else {
- TCGV_UNUSED_PTR(fpst);
+ fpst = NULL;
}
if (size == 3) {
@@ -10917,7 +10914,7 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
}
}
- if (!TCGV_IS_UNUSED_PTR(fpst)) {
+ if (fpst) {
tcg_temp_free_ptr(fpst);
}
}
@@ -11293,8 +11290,8 @@ static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
{
DisasContext *dc = container_of(dcbase, DisasContext, base);
- dc->insn_start_idx = tcg_op_buf_count();
tcg_gen_insn_start(dc->pc, 0, 0);
+ dc->insn_start = tcg_last_op();
}
static bool aarch64_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
diff --git a/target/arm/translate.c b/target/arm/translate.c
index e15192d5d6..c690658493 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -2169,8 +2169,8 @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
tmp3 = tcg_const_i32((insn & 1) << 5);
break;
default:
- TCGV_UNUSED_I32(tmp2);
- TCGV_UNUSED_I32(tmp3);
+ tmp2 = NULL;
+ tmp3 = NULL;
}
gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
tcg_temp_free_i32(tmp3);
@@ -4939,7 +4939,7 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
}
} else /* size == 0 */ {
if (load) {
- TCGV_UNUSED_I32(tmp2);
+ tmp2 = NULL;
for (n = 0; n < 4; n++) {
tmp = tcg_temp_new_i32();
gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
@@ -6643,11 +6643,11 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
tmp = neon_load_reg(rn, 1);
neon_store_scratch(2, tmp);
}
- TCGV_UNUSED_I32(tmp3);
+ tmp3 = NULL;
for (pass = 0; pass < 2; pass++) {
if (src1_wide) {
neon_load_reg64(cpu_V0, rn + pass);
- TCGV_UNUSED_I32(tmp);
+ tmp = NULL;
} else {
if (pass == 1 && rd == rn) {
tmp = neon_load_scratch(2);
@@ -6660,7 +6660,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
}
if (src2_wide) {
neon_load_reg64(cpu_V1, rm + pass);
- TCGV_UNUSED_I32(tmp2);
+ tmp2 = NULL;
} else {
if (pass == 1 && rd == rm) {
tmp2 = neon_load_scratch(2);
@@ -7078,7 +7078,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
if (rm & 1) {
return 1;
}
- TCGV_UNUSED_I32(tmp2);
+ tmp2 = NULL;
for (pass = 0; pass < 2; pass++) {
neon_load_reg64(cpu_V0, rm + pass);
tmp = tcg_temp_new_i32();
@@ -7217,7 +7217,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
if (neon_2rm_is_float_op(op)) {
tcg_gen_ld_f32(cpu_F0s, cpu_env,
neon_reg_offset(rm, pass));
- TCGV_UNUSED_I32(tmp);
+ tmp = NULL;
} else {
tmp = neon_load_reg(rm, pass);
}
@@ -8666,7 +8666,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
rn = (insn >> 16) & 0xf;
tmp = load_reg(s, rn);
} else {
- TCGV_UNUSED_I32(tmp);
+ tmp = NULL;
}
rd = (insn >> 12) & 0xf;
switch(op1) {
@@ -9505,7 +9505,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
/* compute total size */
loaded_base = 0;
- TCGV_UNUSED_I32(loaded_var);
+ loaded_var = NULL;
n = 0;
for(i=0;i<16;i++) {
if (insn & (1 << i))
@@ -10074,7 +10074,7 @@ static int disas_thumb2_insn(DisasContext *s, uint32_t insn)
tcg_gen_addi_i32(addr, addr, -offset);
}
- TCGV_UNUSED_I32(loaded_var);
+ loaded_var = NULL;
for (i = 0; i < 16; i++) {
if ((insn & (1 << i)) == 0)
continue;
@@ -11355,7 +11355,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
} else if (op != 0xf) { /* mvn doesn't read its first operand */
tmp = load_reg(s, rd);
} else {
- TCGV_UNUSED_I32(tmp);
+ tmp = NULL;
}
tmp2 = load_reg(s, rm);
@@ -11686,7 +11686,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
tcg_gen_addi_i32(addr, addr, 4);
}
}
- TCGV_UNUSED_I32(tmp);
+ tmp = NULL;
if (insn & (1 << 8)) {
if (insn & (1 << 11)) {
/* pop pc */
@@ -11831,8 +11831,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
case 12:
{
/* load/store multiple */
- TCGv_i32 loaded_var;
- TCGV_UNUSED_I32(loaded_var);
+ TCGv_i32 loaded_var = NULL;
rn = (insn >> 8) & 0x7;
addr = load_reg(s, rn);
for (i = 0; i < 8; i++) {
@@ -12097,10 +12096,10 @@ static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
{
DisasContext *dc = container_of(dcbase, DisasContext, base);
- dc->insn_start_idx = tcg_op_buf_count();
tcg_gen_insn_start(dc->pc,
(dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
0);
+ dc->insn_start = tcg_last_op();
}
static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
diff --git a/target/arm/translate.h b/target/arm/translate.h
index 410ba79c0d..cd7313ace7 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -66,8 +66,8 @@ typedef struct DisasContext {
bool ss_same_el;
/* Bottom two bits of XScale c15_cpar coprocessor access control reg */
int c15_cpar;
- /* TCG op index of the current insn_start. */
- int insn_start_idx;
+ /* TCG op of the current insn_start. */
+ TCGOp *insn_start;
#define TMP_A64_MAX 16
int tmp_a64_count;
TCGv_i64 tmp_a64[TMP_A64_MAX];
@@ -117,9 +117,9 @@ static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
syn >>= ARM_INSN_START_WORD2_SHIFT;
/* We check and clear insn_start_idx to catch multiple updates. */
- assert(s->insn_start_idx != 0);
- tcg_set_insn_param(s->insn_start_idx, 2, syn);
- s->insn_start_idx = 0;
+ assert(s->insn_start != NULL);
+ tcg_set_insn_param(s->insn_start, 2, syn);
+ s->insn_start = NULL;
}
/* is_jmp field values */
diff --git a/target/cris/translate.c b/target/cris/translate.c
index 2831419845..f51a731db9 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -2603,7 +2603,7 @@ static int dec_movem_mr(CPUCRISState *env, DisasContext *dc)
tcg_gen_addi_tl(addr, cpu_R[dc->op1], i * 8);
gen_load(dc, tmp32, addr, 4, 0);
} else {
- TCGV_UNUSED(tmp32);
+ tmp32 = NULL;
}
tcg_temp_free(addr);
@@ -3297,8 +3297,6 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
qemu_log("--------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, dc->pc - pc_start);
- qemu_log("\nisize=%d osize=%d\n",
- dc->pc - pc_start, tcg_op_buf_count());
qemu_log_unlock();
}
#endif
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 53aa1f88c4..31d9a2a31b 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -125,7 +125,7 @@ void hppa_translate_init(void)
int i;
- TCGV_UNUSED(cpu_gr[0]);
+ cpu_gr[0] = NULL;
for (i = 1; i < 32; i++) {
cpu_gr[i] = tcg_global_mem_new(cpu_env,
offsetof(CPUHPPAState, gr[i]),
@@ -140,28 +140,31 @@ void hppa_translate_init(void)
static DisasCond cond_make_f(void)
{
- DisasCond r = { .c = TCG_COND_NEVER };
- TCGV_UNUSED(r.a0);
- TCGV_UNUSED(r.a1);
- return r;
+ return (DisasCond){
+ .c = TCG_COND_NEVER,
+ .a0 = NULL,
+ .a1 = NULL,
+ };
}
static DisasCond cond_make_n(void)
{
- DisasCond r = { .c = TCG_COND_NE, .a0_is_n = true, .a1_is_0 = true };
- r.a0 = cpu_psw_n;
- TCGV_UNUSED(r.a1);
- return r;
+ return (DisasCond){
+ .c = TCG_COND_NE,
+ .a0 = cpu_psw_n,
+ .a0_is_n = true,
+ .a1 = NULL,
+ .a1_is_0 = true
+ };
}
static DisasCond cond_make_0(TCGCond c, TCGv a0)
{
- DisasCond r = { .c = c, .a1_is_0 = true };
+ DisasCond r = { .c = c, .a1 = NULL, .a1_is_0 = true };
assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS);
r.a0 = tcg_temp_new();
tcg_gen_mov_tl(r.a0, a0);
- TCGV_UNUSED(r.a1);
return r;
}
@@ -199,8 +202,8 @@ static void cond_free(DisasCond *cond)
}
cond->a0_is_n = false;
cond->a1_is_0 = false;
- TCGV_UNUSED(cond->a0);
- TCGV_UNUSED(cond->a1);
+ cond->a0 = NULL;
+ cond->a1 = NULL;
/* fallthru */
case TCG_COND_ALWAYS:
cond->c = TCG_COND_NEVER;
@@ -716,9 +719,8 @@ static DisasCond do_sed_cond(unsigned orig, TCGv res)
static DisasCond do_unit_cond(unsigned cf, TCGv res, TCGv in1, TCGv in2)
{
DisasCond cond;
- TCGv tmp, cb;
+ TCGv tmp, cb = NULL;
- TCGV_UNUSED(cb);
if (cf & 8) {
/* Since we want to test lots of carry-out bits all at once, do not
* do our normal thing and compute carry-in of bit B+1 since that
@@ -826,8 +828,8 @@ static DisasJumpType do_add(DisasContext *ctx, unsigned rt, TCGv in1, TCGv in2,
DisasCond cond;
dest = tcg_temp_new();
- TCGV_UNUSED(cb);
- TCGV_UNUSED(cb_msb);
+ cb = NULL;
+ cb_msb = NULL;
if (shift) {
tmp = get_temp(ctx);
@@ -856,7 +858,7 @@ static DisasJumpType do_add(DisasContext *ctx, unsigned rt, TCGv in1, TCGv in2,
}
/* Compute signed overflow if required. */
- TCGV_UNUSED(sv);
+ sv = NULL;
if (is_tsv || c == 6) {
sv = do_add_sv(ctx, dest, in1, in2);
if (is_tsv) {
@@ -919,7 +921,7 @@ static DisasJumpType do_sub(DisasContext *ctx, unsigned rt, TCGv in1, TCGv in2,
tcg_temp_free(zero);
/* Compute signed overflow if required. */
- TCGV_UNUSED(sv);
+ sv = NULL;
if (is_tsv || c == 6) {
sv = do_sub_sv(ctx, dest, in1, in2);
if (is_tsv) {
@@ -965,7 +967,7 @@ static DisasJumpType do_cmpclr(DisasContext *ctx, unsigned rt, TCGv in1,
tcg_gen_sub_tl(dest, in1, in2);
/* Compute signed overflow if required. */
- TCGV_UNUSED(sv);
+ sv = NULL;
if ((cf >> 1) == 6) {
sv = do_sub_sv(ctx, dest, in1, in2);
}
@@ -2070,8 +2072,7 @@ static DisasJumpType trans_ds(DisasContext *ctx, uint32_t insn,
/* Install the new nullification. */
if (cf) {
- TCGv sv;
- TCGV_UNUSED(sv);
+ TCGv sv = NULL;
if (cf >> 1 == 6) {
/* ??? The lshift is supposed to contribute to overflow. */
sv = do_add_sv(ctx, dest, add1, add2);
@@ -2542,7 +2543,7 @@ static DisasJumpType trans_cmpb(DisasContext *ctx, uint32_t insn,
tcg_gen_sub_tl(dest, in1, in2);
- TCGV_UNUSED(sv);
+ sv = NULL;
if (c == 6) {
sv = do_sub_sv(ctx, dest, in1, in2);
}
@@ -2571,8 +2572,8 @@ static DisasJumpType trans_addb(DisasContext *ctx, uint32_t insn,
}
in2 = load_gpr(ctx, r);
dest = dest_gpr(ctx, r);
- TCGV_UNUSED(sv);
- TCGV_UNUSED(cb_msb);
+ sv = NULL;
+ cb_msb = NULL;
switch (c) {
default:
@@ -3732,18 +3733,16 @@ static int hppa_tr_init_disas_context(DisasContextBase *dcbase,
{
DisasContext *ctx = container_of(dcbase, DisasContext, base);
TranslationBlock *tb = ctx->base.tb;
- int i, bound;
+ int bound;
ctx->cs = cs;
ctx->iaoq_f = tb->pc;
ctx->iaoq_b = tb->cs_base;
ctx->iaoq_n = -1;
- TCGV_UNUSED(ctx->iaoq_n_var);
+ ctx->iaoq_n_var = NULL;
ctx->ntemps = 0;
- for (i = 0; i < ARRAY_SIZE(ctx->temps); ++i) {
- TCGV_UNUSED(ctx->temps[i]);
- }
+ memset(ctx->temps, 0, sizeof(ctx->temps));
bound = -(tb->pc | TARGET_PAGE_MASK) / 4;
return MIN(max_insns, bound);
@@ -3804,7 +3803,7 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
tcg_gen_addi_tl(ctx->iaoq_n_var, cpu_iaoq_b, 4);
} else {
ctx->iaoq_n = ctx->iaoq_b + 4;
- TCGV_UNUSED(ctx->iaoq_n_var);
+ ctx->iaoq_n_var = NULL;
}
if (unlikely(ctx->null_cond.c == TCG_COND_ALWAYS)) {
@@ -3819,7 +3818,7 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
/* Free any temporaries allocated. */
for (i = 0, n = ctx->ntemps; i < n; ++i) {
tcg_temp_free(ctx->temps[i]);
- TCGV_UNUSED(ctx->temps[i]);
+ ctx->temps[i] = NULL;
}
ctx->ntemps = 0;
diff --git a/target/i386/svm_helper.c b/target/i386/svm_helper.c
index f479239875..303106981c 100644
--- a/target/i386/svm_helper.c
+++ b/target/i386/svm_helper.c
@@ -584,9 +584,7 @@ void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1,
{
CPUState *cs = CPU(x86_env_get_cpu(env));
- if (retaddr) {
- cpu_restore_state(cs, retaddr);
- }
+ cpu_restore_state(cs, retaddr);
qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016"
PRIx64 ", " TARGET_FMT_lx ")!\n",
diff --git a/target/i386/translate.c b/target/i386/translate.c
index 23d7eec964..0135415d92 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -689,7 +689,7 @@ static void gen_compute_eflags(DisasContext *s)
return;
}
- TCGV_UNUSED(zero);
+ zero = NULL;
dst = cpu_cc_dst;
src1 = cpu_cc_src;
src2 = cpu_cc_src2;
@@ -2050,9 +2050,8 @@ static AddressParts gen_lea_modrm_0(CPUX86State *env, DisasContext *s,
/* Compute the address, with a minimum number of TCG ops. */
static TCGv gen_lea_modrm_1(AddressParts a)
{
- TCGv ea;
+ TCGv ea = NULL;
- TCGV_UNUSED(ea);
if (a.index >= 0) {
if (a.scale == 0) {
ea = cpu_regs[a.index];
@@ -2067,7 +2066,7 @@ static TCGv gen_lea_modrm_1(AddressParts a)
} else if (a.base >= 0) {
ea = cpu_regs[a.base];
}
- if (TCGV_IS_UNUSED(ea)) {
+ if (!ea) {
tcg_gen_movi_tl(cpu_A0, a.disp);
ea = cpu_A0;
} else if (a.disp != 0) {
@@ -3951,7 +3950,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
/* Re-use the carry-out from a previous round. */
- TCGV_UNUSED(carry_in);
+ carry_in = NULL;
carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
switch (s->cc_op) {
case CC_OP_ADCX:
@@ -3979,7 +3978,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
break;
}
/* If we can't reuse carry-out, get it out of EFLAGS. */
- if (TCGV_IS_UNUSED(carry_in)) {
+ if (!carry_in) {
if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
gen_compute_eflags(s);
}
@@ -7673,7 +7672,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
tcg_gen_mov_tl(a0, cpu_A0);
} else {
gen_op_mov_v_reg(ot, t0, rm);
- TCGV_UNUSED(a0);
+ a0 = NULL;
}
gen_op_mov_v_reg(ot, t1, reg);
tcg_gen_andi_tl(cpu_tmp0, t0, 3);
diff --git a/target/lm32/op_helper.c b/target/lm32/op_helper.c
index 2177c8ad12..30f670eee8 100644
--- a/target/lm32/op_helper.c
+++ b/target/lm32/op_helper.c
@@ -151,11 +151,8 @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type,
ret = lm32_cpu_handle_mmu_fault(cs, addr, access_type, mmu_idx);
if (unlikely(ret)) {
- if (retaddr) {
- /* now we have a real cpu fault */
- cpu_restore_state(cs, retaddr);
- }
- cpu_loop_exit(cs);
+ /* now we have a real cpu fault */
+ cpu_loop_exit_restore(cs, retaddr);
}
}
#endif
diff --git a/target/lm32/translate.c b/target/lm32/translate.c
index b8b2b13e36..2e1c5e6d01 100644
--- a/target/lm32/translate.c
+++ b/target/lm32/translate.c
@@ -1156,8 +1156,6 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
qemu_log_lock();
qemu_log("\n");
log_target_disas(cs, pc_start, dc->pc - pc_start);
- qemu_log("\nisize=%d osize=%d\n",
- dc->pc - pc_start, tcg_op_buf_count());
qemu_log_unlock();
}
#endif
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index 0a3dd83548..03126ba543 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -55,17 +55,17 @@ static void m68k_cpu_reset(CPUState *s)
mcc->parent_reset(s);
memset(env, 0, offsetof(CPUM68KState, end_reset_fields));
-#if !defined(CONFIG_USER_ONLY)
- env->sr = 0x2700;
+#ifdef CONFIG_SOFTMMU
+ cpu_m68k_set_sr(env, SR_S | SR_I);
+#else
+ cpu_m68k_set_sr(env, 0);
#endif
- m68k_switch_sp(env);
for (i = 0; i < 8; i++) {
env->fregs[i].d = nan;
}
cpu_m68k_set_fpcr(env, 0);
env->fpsr = 0;
- cpu_m68k_set_ccr(env, 0);
/* TODO: We should set PC from the interrupt vector. */
env->pc = 0;
}
@@ -134,9 +134,18 @@ static void m68020_cpu_initfn(Object *obj)
m68k_set_feature(env, M68K_FEATURE_CAS);
m68k_set_feature(env, M68K_FEATURE_BKPT);
m68k_set_feature(env, M68K_FEATURE_RTD);
+ m68k_set_feature(env, M68K_FEATURE_CHK2);
}
#define m68030_cpu_initfn m68020_cpu_initfn
-#define m68040_cpu_initfn m68020_cpu_initfn
+
+static void m68040_cpu_initfn(Object *obj)
+{
+ M68kCPU *cpu = M68K_CPU(obj);
+ CPUM68KState *env = &cpu->env;
+
+ m68020_cpu_initfn(obj);
+ m68k_set_feature(env, M68K_FEATURE_M68040);
+}
static void m68060_cpu_initfn(Object *obj)
{
@@ -156,6 +165,7 @@ static void m68060_cpu_initfn(Object *obj)
m68k_set_feature(env, M68K_FEATURE_CAS);
m68k_set_feature(env, M68K_FEATURE_BKPT);
m68k_set_feature(env, M68K_FEATURE_RTD);
+ m68k_set_feature(env, M68K_FEATURE_CHK2);
}
static void m5208_cpu_initfn(Object *obj)
diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h
index 5d03764eab..2985b039e1 100644
--- a/target/m68k/cpu.h
+++ b/target/m68k/cpu.h
@@ -45,6 +45,8 @@
#define EXCP_ADDRESS 3 /* Address error. */
#define EXCP_ILLEGAL 4 /* Illegal instruction. */
#define EXCP_DIV0 5 /* Divide by zero */
+#define EXCP_CHK 6 /* CHK, CHK2 Instructions */
+#define EXCP_TRAPCC 7 /* FTRAPcc, TRAPcc, TRAPV Instructions */
#define EXCP_PRIVILEGE 8 /* Privilege violation. */
#define EXCP_TRACE 9
#define EXCP_LINEA 10 /* Unimplemented line-A (MAC) opcode. */
@@ -53,6 +55,9 @@
#define EXCP_DEBEGBP 13 /* Breakpoint debug interrupt. */
#define EXCP_FORMAT 14 /* RTE format error. */
#define EXCP_UNINITIALIZED 15
+#define EXCP_SPURIOUS 24 /* Spurious interrupt */
+#define EXCP_INT_LEVEL_1 25 /* Level 1 Interrupt autovector */
+#define EXCP_INT_LEVEL_7 31 /* Level 7 Interrupt autovector */
#define EXCP_TRAP0 32 /* User trap #0. */
#define EXCP_TRAP15 47 /* User trap #15. */
#define EXCP_FP_BSUN 48 /* Branch Set on Unordered */
@@ -63,6 +68,9 @@
#define EXCP_FP_OVFL 53 /* Overflow */
#define EXCP_FP_SNAN 54 /* Signaling Not-A-Number */
#define EXCP_FP_UNIMP 55 /* Unimplemented Data type */
+#define EXCP_MMU_CONF 56 /* MMU Configuration Error */
+#define EXCP_MMU_ILLEGAL 57 /* MMU Illegal Operation Error */
+#define EXCP_MMU_ACCESS 58 /* MMU Access Level Violation Error */
#define EXCP_UNSUPPORTED 61
#define EXCP_RTE 0x100
@@ -81,7 +89,7 @@ typedef struct CPUM68KState {
/* SSP and USP. The current_sp is stored in aregs[7], the other here. */
int current_sp;
- uint32_t sp[2];
+ uint32_t sp[3];
/* Condition flags. */
uint32_t cc_op;
@@ -170,6 +178,7 @@ int cpu_m68k_signal_handler(int host_signum, void *pinfo,
void *puc);
uint32_t cpu_m68k_get_ccr(CPUM68KState *env);
void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t);
+void cpu_m68k_set_sr(CPUM68KState *env, uint32_t);
void cpu_m68k_set_fpcr(CPUM68KState *env, uint32_t val);
@@ -210,10 +219,79 @@ typedef enum {
#define SR_I 0x0700
#define SR_M 0x1000
#define SR_S 0x2000
-#define SR_T 0x8000
+#define SR_T_SHIFT 14
+#define SR_T 0xc000
#define M68K_SSP 0
#define M68K_USP 1
+#define M68K_ISP 2
+
+/* m68k Control Registers */
+
+/* ColdFire */
+/* Memory Management Control Registers */
+#define M68K_CR_ASID 0x003
+#define M68K_CR_ACR0 0x004
+#define M68K_CR_ACR1 0x005
+#define M68K_CR_ACR2 0x006
+#define M68K_CR_ACR3 0x007
+#define M68K_CR_MMUBAR 0x008
+
+/* Processor Miscellaneous Registers */
+#define M68K_CR_PC 0x80F
+
+/* Local Memory and Module Control Registers */
+#define M68K_CR_ROMBAR0 0xC00
+#define M68K_CR_ROMBAR1 0xC01
+#define M68K_CR_RAMBAR0 0xC04
+#define M68K_CR_RAMBAR1 0xC05
+#define M68K_CR_MPCR 0xC0C
+#define M68K_CR_EDRAMBAR 0xC0D
+#define M68K_CR_SECMBAR 0xC0E
+#define M68K_CR_MBAR 0xC0F
+
+/* Local Memory Address Permutation Control Registers */
+#define M68K_CR_PCR1U0 0xD02
+#define M68K_CR_PCR1L0 0xD03
+#define M68K_CR_PCR2U0 0xD04
+#define M68K_CR_PCR2L0 0xD05
+#define M68K_CR_PCR3U0 0xD06
+#define M68K_CR_PCR3L0 0xD07
+#define M68K_CR_PCR1U1 0xD0A
+#define M68K_CR_PCR1L1 0xD0B
+#define M68K_CR_PCR2U1 0xD0C
+#define M68K_CR_PCR2L1 0xD0D
+#define M68K_CR_PCR3U1 0xD0E
+#define M68K_CR_PCR3L1 0xD0F
+
+/* MC680x0 */
+/* MC680[1234]0/CPU32 */
+#define M68K_CR_SFC 0x000
+#define M68K_CR_DFC 0x001
+#define M68K_CR_USP 0x800
+#define M68K_CR_VBR 0x801 /* + Coldfire */
+
+/* MC680[234]0 */
+#define M68K_CR_CACR 0x002 /* + Coldfire */
+#define M68K_CR_CAAR 0x802 /* MC68020 and MC68030 only */
+#define M68K_CR_MSP 0x803
+#define M68K_CR_ISP 0x804
+
+/* MC68040/MC68LC040 */
+#define M68K_CR_TC 0x003
+#define M68K_CR_ITT0 0x004
+#define M68K_CR_ITT1 0x005
+#define M68K_CR_DTT0 0x006
+#define M68K_CR_DTT1 0x007
+#define M68K_CR_MMUSR 0x805
+#define M68K_CR_URP 0x806
+#define M68K_CR_SRP 0x807
+
+/* MC68EC040 */
+#define M68K_CR_IACR0 0x004
+#define M68K_CR_IACR1 0x005
+#define M68K_CR_DACR0 0x006
+#define M68K_CR_DACR1 0x007
#define M68K_FPIAR_SHIFT 0
#define M68K_FPIAR (1 << M68K_FPIAR_SHIFT)
@@ -296,6 +374,8 @@ enum m68k_features {
M68K_FEATURE_CAS,
M68K_FEATURE_BKPT,
M68K_FEATURE_RTD,
+ M68K_FEATURE_CHK2,
+ M68K_FEATURE_M68040, /* instructions specific to MC68040 */
};
static inline int m68k_feature(CPUM68KState *env, int feature)
diff --git a/target/m68k/gdbstub.c b/target/m68k/gdbstub.c
index c7f44c9bb3..99e5be8132 100644
--- a/target/m68k/gdbstub.c
+++ b/target/m68k/gdbstub.c
@@ -63,7 +63,7 @@ int m68k_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
} else {
switch (n) {
case 16:
- env->sr = tmp;
+ cpu_m68k_set_sr(env, tmp);
break;
case 17:
env->pc = tmp;
diff --git a/target/m68k/helper.c b/target/m68k/helper.c
index 7e50ff5871..a999389e9a 100644
--- a/target/m68k/helper.c
+++ b/target/m68k/helper.c
@@ -171,28 +171,84 @@ void m68k_cpu_init_gdb(M68kCPU *cpu)
/* TODO: Add [E]MAC registers. */
}
-void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
+void HELPER(cf_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val)
{
M68kCPU *cpu = m68k_env_get_cpu(env);
switch (reg) {
- case 0x02: /* CACR */
+ case M68K_CR_CACR:
env->cacr = val;
m68k_switch_sp(env);
break;
- case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
+ case M68K_CR_ACR0:
+ case M68K_CR_ACR1:
+ case M68K_CR_ACR2:
+ case M68K_CR_ACR3:
/* TODO: Implement Access Control Registers. */
break;
- case 0x801: /* VBR */
+ case M68K_CR_VBR:
env->vbr = val;
break;
/* TODO: Implement control registers. */
default:
- cpu_abort(CPU(cpu), "Unimplemented control register write 0x%x = 0x%x\n",
+ cpu_abort(CPU(cpu),
+ "Unimplemented control register write 0x%x = 0x%x\n",
reg, val);
}
}
+void HELPER(m68k_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val)
+{
+ M68kCPU *cpu = m68k_env_get_cpu(env);
+
+ switch (reg) {
+ /* MC680[1234]0 */
+ case M68K_CR_VBR:
+ env->vbr = val;
+ return;
+ /* MC680[234]0 */
+ case M68K_CR_CACR:
+ env->cacr = val;
+ m68k_switch_sp(env);
+ return;
+ /* MC680[34]0 */
+ case M68K_CR_USP:
+ env->sp[M68K_USP] = val;
+ return;
+ case M68K_CR_MSP:
+ env->sp[M68K_SSP] = val;
+ return;
+ case M68K_CR_ISP:
+ env->sp[M68K_ISP] = val;
+ return;
+ }
+ cpu_abort(CPU(cpu), "Unimplemented control register write 0x%x = 0x%x\n",
+ reg, val);
+}
+
+uint32_t HELPER(m68k_movec_from)(CPUM68KState *env, uint32_t reg)
+{
+ M68kCPU *cpu = m68k_env_get_cpu(env);
+
+ switch (reg) {
+ /* MC680[1234]0 */
+ case M68K_CR_VBR:
+ return env->vbr;
+ /* MC680[234]0 */
+ case M68K_CR_CACR:
+ return env->cacr;
+ /* MC680[34]0 */
+ case M68K_CR_USP:
+ return env->sp[M68K_USP];
+ case M68K_CR_MSP:
+ return env->sp[M68K_SSP];
+ case M68K_CR_ISP:
+ return env->sp[M68K_ISP];
+ }
+ cpu_abort(CPU(cpu), "Unimplemented control register read 0x%x\n",
+ reg);
+}
+
void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
{
uint32_t acc;
@@ -232,8 +288,20 @@ void m68k_switch_sp(CPUM68KState *env)
int new_sp;
env->sp[env->current_sp] = env->aregs[7];
- new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
- ? M68K_SSP : M68K_USP;
+ if (m68k_feature(env, M68K_FEATURE_M68000)) {
+ if (env->sr & SR_S) {
+ if (env->sr & SR_M) {
+ new_sp = M68K_SSP;
+ } else {
+ new_sp = M68K_ISP;
+ }
+ } else {
+ new_sp = M68K_USP;
+ }
+ } else {
+ new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
+ ? M68K_SSP : M68K_USP;
+ }
env->aregs[7] = env->sp[new_sp];
env->current_sp = new_sp;
}
@@ -316,13 +384,17 @@ uint32_t HELPER(sats)(uint32_t val, uint32_t v)
return val;
}
-void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
+void cpu_m68k_set_sr(CPUM68KState *env, uint32_t sr)
{
- env->sr = val & 0xffe0;
- cpu_m68k_set_ccr(env, val);
+ env->sr = sr & 0xffe0;
+ cpu_m68k_set_ccr(env, sr);
m68k_switch_sp(env);
}
+void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
+{
+ cpu_m68k_set_sr(env, val);
+}
/* MAC unit. */
/* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
@@ -707,3 +779,10 @@ void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
res |= (uint64_t)(val & 0xffff0000) << 16;
env->macc[acc + 1] = res;
}
+
+#if defined(CONFIG_SOFTMMU)
+void HELPER(reset)(CPUM68KState *env)
+{
+ /* FIXME: reset all except CPU */
+}
+#endif
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index eebe52dae5..57f210aa14 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -8,7 +8,9 @@ DEF_HELPER_4(divsl, void, env, int, int, s32)
DEF_HELPER_4(divull, void, env, int, int, i32)
DEF_HELPER_4(divsll, void, env, int, int, s32)
DEF_HELPER_2(set_sr, void, env, i32)
-DEF_HELPER_3(movec, void, env, i32, i32)
+DEF_HELPER_3(cf_movec_to, void, env, i32, i32)
+DEF_HELPER_3(m68k_movec_to, void, env, i32, i32)
+DEF_HELPER_2(m68k_movec_from, i32, env, i32)
DEF_HELPER_4(cas2w, void, env, i32, i32, i32)
DEF_HELPER_4(cas2l, void, env, i32, i32, i32)
DEF_HELPER_4(cas2l_parallel, void, env, i32, i32, i32)
@@ -94,3 +96,10 @@ DEF_HELPER_FLAGS_4(bfchg_mem, TCG_CALL_NO_WG, i32, env, i32, s32, i32)
DEF_HELPER_FLAGS_4(bfclr_mem, TCG_CALL_NO_WG, i32, env, i32, s32, i32)
DEF_HELPER_FLAGS_4(bfset_mem, TCG_CALL_NO_WG, i32, env, i32, s32, i32)
DEF_HELPER_FLAGS_4(bfffo_mem, TCG_CALL_NO_WG, i64, env, i32, s32, i32)
+
+DEF_HELPER_3(chk, void, env, s32, s32)
+DEF_HELPER_4(chk2, void, env, s32, s32, s32)
+
+#if defined(CONFIG_SOFTMMU)
+DEF_HELPER_FLAGS_1(reset, TCG_CALL_NO_RWG, void, env)
+#endif
diff --git a/target/m68k/monitor.c b/target/m68k/monitor.c
index 5605323a81..52781e85f0 100644
--- a/target/m68k/monitor.c
+++ b/target/m68k/monitor.c
@@ -30,6 +30,7 @@ static const MonitorDef monitor_defs[] = {
{ "sr", offsetof(CPUM68KState, sr) },
{ "ssp", offsetof(CPUM68KState, sp[0]) },
{ "usp", offsetof(CPUM68KState, sp[1]) },
+ { "isp", offsetof(CPUM68KState, sp[2]) },
{ NULL },
};
diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c
index 63089511cb..c61ca9392f 100644
--- a/target/m68k/op_helper.c
+++ b/target/m68k/op_helper.c
@@ -46,15 +46,12 @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type,
ret = m68k_cpu_handle_mmu_fault(cs, addr, access_type, mmu_idx);
if (unlikely(ret)) {
- if (retaddr) {
- /* now we have a real cpu fault */
- cpu_restore_state(cs, retaddr);
- }
- cpu_loop_exit(cs);
+ /* now we have a real cpu fault */
+ cpu_loop_exit_restore(cs, retaddr);
}
}
-static void do_rte(CPUM68KState *env)
+static void cf_rte(CPUM68KState *env)
{
uint32_t sp;
uint32_t fmt;
@@ -65,13 +62,158 @@ static void do_rte(CPUM68KState *env)
sp |= (fmt >> 28) & 3;
env->aregs[7] = sp + 8;
- helper_set_sr(env, fmt);
+ cpu_m68k_set_sr(env, fmt);
}
-static void do_interrupt_all(CPUM68KState *env, int is_hw)
+static void m68k_rte(CPUM68KState *env)
+{
+ uint32_t sp;
+ uint16_t fmt;
+ uint16_t sr;
+
+ sp = env->aregs[7];
+throwaway:
+ sr = cpu_lduw_kernel(env, sp);
+ sp += 2;
+ env->pc = cpu_ldl_kernel(env, sp);
+ sp += 4;
+ if (m68k_feature(env, M68K_FEATURE_QUAD_MULDIV)) {
+ /* all except 68000 */
+ fmt = cpu_lduw_kernel(env, sp);
+ sp += 2;
+ switch (fmt >> 12) {
+ case 0:
+ break;
+ case 1:
+ env->aregs[7] = sp;
+ cpu_m68k_set_sr(env, sr);
+ goto throwaway;
+ case 2:
+ case 3:
+ sp += 4;
+ break;
+ case 4:
+ sp += 8;
+ break;
+ case 7:
+ sp += 52;
+ break;
+ }
+ }
+ env->aregs[7] = sp;
+ cpu_m68k_set_sr(env, sr);
+}
+
+static const char *m68k_exception_name(int index)
+{
+ switch (index) {
+ case EXCP_ACCESS:
+ return "Access Fault";
+ case EXCP_ADDRESS:
+ return "Address Error";
+ case EXCP_ILLEGAL:
+ return "Illegal Instruction";
+ case EXCP_DIV0:
+ return "Divide by Zero";
+ case EXCP_CHK:
+ return "CHK/CHK2";
+ case EXCP_TRAPCC:
+ return "FTRAPcc, TRAPcc, TRAPV";
+ case EXCP_PRIVILEGE:
+ return "Privilege Violation";
+ case EXCP_TRACE:
+ return "Trace";
+ case EXCP_LINEA:
+ return "A-Line";
+ case EXCP_LINEF:
+ return "F-Line";
+ case EXCP_DEBEGBP: /* 68020/030 only */
+ return "Copro Protocol Violation";
+ case EXCP_FORMAT:
+ return "Format Error";
+ case EXCP_UNINITIALIZED:
+ return "Unitialized Interruot";
+ case EXCP_SPURIOUS:
+ return "Spurious Interrupt";
+ case EXCP_INT_LEVEL_1:
+ return "Level 1 Interrupt";
+ case EXCP_INT_LEVEL_1 + 1:
+ return "Level 2 Interrupt";
+ case EXCP_INT_LEVEL_1 + 2:
+ return "Level 3 Interrupt";
+ case EXCP_INT_LEVEL_1 + 3:
+ return "Level 4 Interrupt";
+ case EXCP_INT_LEVEL_1 + 4:
+ return "Level 5 Interrupt";
+ case EXCP_INT_LEVEL_1 + 5:
+ return "Level 6 Interrupt";
+ case EXCP_INT_LEVEL_1 + 6:
+ return "Level 7 Interrupt";
+ case EXCP_TRAP0:
+ return "TRAP #0";
+ case EXCP_TRAP0 + 1:
+ return "TRAP #1";
+ case EXCP_TRAP0 + 2:
+ return "TRAP #2";
+ case EXCP_TRAP0 + 3:
+ return "TRAP #3";
+ case EXCP_TRAP0 + 4:
+ return "TRAP #4";
+ case EXCP_TRAP0 + 5:
+ return "TRAP #5";
+ case EXCP_TRAP0 + 6:
+ return "TRAP #6";
+ case EXCP_TRAP0 + 7:
+ return "TRAP #7";
+ case EXCP_TRAP0 + 8:
+ return "TRAP #8";
+ case EXCP_TRAP0 + 9:
+ return "TRAP #9";
+ case EXCP_TRAP0 + 10:
+ return "TRAP #10";
+ case EXCP_TRAP0 + 11:
+ return "TRAP #11";
+ case EXCP_TRAP0 + 12:
+ return "TRAP #12";
+ case EXCP_TRAP0 + 13:
+ return "TRAP #13";
+ case EXCP_TRAP0 + 14:
+ return "TRAP #14";
+ case EXCP_TRAP0 + 15:
+ return "TRAP #15";
+ case EXCP_FP_BSUN:
+ return "FP Branch/Set on unordered condition";
+ case EXCP_FP_INEX:
+ return "FP Inexact Result";
+ case EXCP_FP_DZ:
+ return "FP Divide by Zero";
+ case EXCP_FP_UNFL:
+ return "FP Underflow";
+ case EXCP_FP_OPERR:
+ return "FP Operand Error";
+ case EXCP_FP_OVFL:
+ return "FP Overflow";
+ case EXCP_FP_SNAN:
+ return "FP Signaling NAN";
+ case EXCP_FP_UNIMP:
+ return "FP Unimplemented Data Type";
+ case EXCP_MMU_CONF: /* 68030/68851 only */
+ return "MMU Configuration Error";
+ case EXCP_MMU_ILLEGAL: /* 68851 only */
+ return "MMU Illegal Operation";
+ case EXCP_MMU_ACCESS: /* 68851 only */
+ return "MMU Access Level Violation";
+ case 64 ... 255:
+ return "User Defined Vector";
+ }
+ return "Unassigned";
+}
+
+static void cf_interrupt_all(CPUM68KState *env, int is_hw)
{
CPUState *cs = CPU(m68k_env_get_cpu(env));
uint32_t sp;
+ uint32_t sr;
uint32_t fmt;
uint32_t retaddr;
uint32_t vector;
@@ -83,7 +225,7 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
switch (cs->exception_index) {
case EXCP_RTE:
/* Return from an exception. */
- do_rte(env);
+ cf_rte(env);
return;
case EXCP_HALT_INSN:
if (semihosting_enabled()
@@ -109,10 +251,17 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
vector = cs->exception_index << 2;
+ sr = env->sr | cpu_m68k_get_ccr(env);
+ if (qemu_loglevel_mask(CPU_LOG_INT)) {
+ static int count;
+ qemu_log("INT %6d: %s(%#x) pc=%08x sp=%08x sr=%04x\n",
+ ++count, m68k_exception_name(cs->exception_index),
+ vector, env->pc, env->aregs[7], sr);
+ }
+
fmt |= 0x40000000;
fmt |= vector << 16;
- fmt |= env->sr;
- fmt |= cpu_m68k_get_ccr(env);
+ fmt |= sr;
env->sr |= SR_S;
if (is_hw) {
@@ -134,6 +283,119 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
env->pc = cpu_ldl_kernel(env, env->vbr + vector);
}
+static inline void do_stack_frame(CPUM68KState *env, uint32_t *sp,
+ uint16_t format, uint16_t sr,
+ uint32_t addr, uint32_t retaddr)
+{
+ CPUState *cs = CPU(m68k_env_get_cpu(env));
+ switch (format) {
+ case 4:
+ *sp -= 4;
+ cpu_stl_kernel(env, *sp, env->pc);
+ *sp -= 4;
+ cpu_stl_kernel(env, *sp, addr);
+ break;
+ case 3:
+ case 2:
+ *sp -= 4;
+ cpu_stl_kernel(env, *sp, addr);
+ break;
+ }
+ *sp -= 2;
+ cpu_stw_kernel(env, *sp, (format << 12) + (cs->exception_index << 2));
+ *sp -= 4;
+ cpu_stl_kernel(env, *sp, retaddr);
+ *sp -= 2;
+ cpu_stw_kernel(env, *sp, sr);
+}
+
+static void m68k_interrupt_all(CPUM68KState *env, int is_hw)
+{
+ CPUState *cs = CPU(m68k_env_get_cpu(env));
+ uint32_t sp;
+ uint32_t retaddr;
+ uint32_t vector;
+ uint16_t sr, oldsr;
+
+ retaddr = env->pc;
+
+ if (!is_hw) {
+ switch (cs->exception_index) {
+ case EXCP_RTE:
+ /* Return from an exception. */
+ m68k_rte(env);
+ return;
+ case EXCP_TRAP0 ... EXCP_TRAP15:
+ /* Move the PC after the trap instruction. */
+ retaddr += 2;
+ break;
+ }
+ }
+
+ vector = cs->exception_index << 2;
+
+ sr = env->sr | cpu_m68k_get_ccr(env);
+ if (qemu_loglevel_mask(CPU_LOG_INT)) {
+ static int count;
+ qemu_log("INT %6d: %s(%#x) pc=%08x sp=%08x sr=%04x\n",
+ ++count, m68k_exception_name(cs->exception_index),
+ vector, env->pc, env->aregs[7], sr);
+ }
+
+ /*
+ * MC68040UM/AD, chapter 9.3.10
+ */
+
+ /* "the processor first make an internal copy" */
+ oldsr = sr;
+ /* "set the mode to supervisor" */
+ sr |= SR_S;
+ /* "suppress tracing" */
+ sr &= ~SR_T;
+ /* "sets the processor interrupt mask" */
+ if (is_hw) {
+ sr |= (env->sr & ~SR_I) | (env->pending_level << SR_I_SHIFT);
+ }
+ cpu_m68k_set_sr(env, sr);
+ sp = env->aregs[7];
+
+ sp &= ~1;
+ if (cs->exception_index == EXCP_ADDRESS) {
+ do_stack_frame(env, &sp, 2, oldsr, 0, retaddr);
+ } else if (cs->exception_index == EXCP_ILLEGAL ||
+ cs->exception_index == EXCP_DIV0 ||
+ cs->exception_index == EXCP_CHK ||
+ cs->exception_index == EXCP_TRAPCC ||
+ cs->exception_index == EXCP_TRACE) {
+ /* FIXME: addr is not only env->pc */
+ do_stack_frame(env, &sp, 2, oldsr, env->pc, retaddr);
+ } else if (is_hw && oldsr & SR_M &&
+ cs->exception_index >= EXCP_SPURIOUS &&
+ cs->exception_index <= EXCP_INT_LEVEL_7) {
+ do_stack_frame(env, &sp, 0, oldsr, 0, retaddr);
+ oldsr = sr;
+ env->aregs[7] = sp;
+ cpu_m68k_set_sr(env, sr &= ~SR_M);
+ sp = env->aregs[7] & ~1;
+ do_stack_frame(env, &sp, 1, oldsr, 0, retaddr);
+ } else {
+ do_stack_frame(env, &sp, 0, oldsr, 0, retaddr);
+ }
+
+ env->aregs[7] = sp;
+ /* Jump to vector. */
+ env->pc = cpu_ldl_kernel(env, env->vbr + vector);
+}
+
+static void do_interrupt_all(CPUM68KState *env, int is_hw)
+{
+ if (m68k_feature(env, M68K_FEATURE_M68000)) {
+ m68k_interrupt_all(env, is_hw);
+ return;
+ }
+ cf_interrupt_all(env, is_hw);
+}
+
void m68k_cpu_do_interrupt(CPUState *cs)
{
M68kCPU *cpu = M68K_CPU(cs);
@@ -682,3 +944,64 @@ uint64_t HELPER(bfffo_mem)(CPUM68KState *env, uint32_t addr,
is already zero. */
return n | ffo;
}
+
+void HELPER(chk)(CPUM68KState *env, int32_t val, int32_t ub)
+{
+ /* From the specs:
+ * X: Not affected, C,V,Z: Undefined,
+ * N: Set if val < 0; cleared if val > ub, undefined otherwise
+ * We implement here values found from a real MC68040:
+ * X,V,Z: Not affected
+ * N: Set if val < 0; cleared if val >= 0
+ * C: if 0 <= ub: set if val < 0 or val > ub, cleared otherwise
+ * if 0 > ub: set if val > ub and val < 0, cleared otherwise
+ */
+ env->cc_n = val;
+ env->cc_c = 0 <= ub ? val < 0 || val > ub : val > ub && val < 0;
+
+ if (val < 0 || val > ub) {
+ CPUState *cs = CPU(m68k_env_get_cpu(env));
+
+ /* Recover PC and CC_OP for the beginning of the insn. */
+ cpu_restore_state(cs, GETPC());
+
+ /* flags have been modified by gen_flush_flags() */
+ env->cc_op = CC_OP_FLAGS;
+ /* Adjust PC to end of the insn. */
+ env->pc += 2;
+
+ cs->exception_index = EXCP_CHK;
+ cpu_loop_exit(cs);
+ }
+}
+
+void HELPER(chk2)(CPUM68KState *env, int32_t val, int32_t lb, int32_t ub)
+{
+ /* From the specs:
+ * X: Not affected, N,V: Undefined,
+ * Z: Set if val is equal to lb or ub
+ * C: Set if val < lb or val > ub, cleared otherwise
+ * We implement here values found from a real MC68040:
+ * X,N,V: Not affected
+ * Z: Set if val is equal to lb or ub
+ * C: if lb <= ub: set if val < lb or val > ub, cleared otherwise
+ * if lb > ub: set if val > ub and val < lb, cleared otherwise
+ */
+ env->cc_z = val != lb && val != ub;
+ env->cc_c = lb <= ub ? val < lb || val > ub : val > ub && val < lb;
+
+ if (env->cc_c) {
+ CPUState *cs = CPU(m68k_env_get_cpu(env));
+
+ /* Recover PC and CC_OP for the beginning of the insn. */
+ cpu_restore_state(cs, GETPC());
+
+ /* flags have been modified by gen_flush_flags() */
+ env->cc_op = CC_OP_FLAGS;
+ /* Adjust PC to end of the insn. */
+ env->pc += 4;
+
+ cs->exception_index = EXCP_CHK;
+ cpu_loop_exit(cs);
+ }
+}
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index bbda7399ec..f0e86a73d4 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -270,7 +270,6 @@ static void gen_raise_exception(int nr)
static void gen_exception(DisasContext *s, uint32_t where, int nr)
{
- update_cc_op(s);
gen_jmp_im(s, where);
gen_raise_exception(nr);
}
@@ -1510,12 +1509,12 @@ DISAS_INSN(dbcc)
DISAS_INSN(undef_mac)
{
- gen_exception(s, s->pc - 2, EXCP_LINEA);
+ gen_exception(s, s->insn_pc, EXCP_LINEA);
}
DISAS_INSN(undef_fpu)
{
- gen_exception(s, s->pc - 2, EXCP_LINEF);
+ gen_exception(s, s->insn_pc, EXCP_LINEF);
}
DISAS_INSN(undef)
@@ -1524,8 +1523,8 @@ DISAS_INSN(undef)
for the 680x0 series, as well as those that are implemented
but actually illegal for CPU32 or pre-68020. */
qemu_log_mask(LOG_UNIMP, "Illegal instruction: %04x @ %08x",
- insn, s->pc - 2);
- gen_exception(s, s->pc - 2, EXCP_UNSUPPORTED);
+ insn, s->insn_pc);
+ gen_exception(s, s->insn_pc, EXCP_UNSUPPORTED);
}
DISAS_INSN(mulw)
@@ -2132,6 +2131,68 @@ DISAS_INSN(bitop_im)
}
}
+static TCGv gen_get_ccr(DisasContext *s)
+{
+ TCGv dest;
+
+ update_cc_op(s);
+ dest = tcg_temp_new();
+ gen_helper_get_ccr(dest, cpu_env);
+ return dest;
+}
+
+static TCGv gen_get_sr(DisasContext *s)
+{
+ TCGv ccr;
+ TCGv sr;
+
+ ccr = gen_get_ccr(s);
+ sr = tcg_temp_new();
+ tcg_gen_andi_i32(sr, QREG_SR, 0xffe0);
+ tcg_gen_or_i32(sr, sr, ccr);
+ return sr;
+}
+
+static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
+{
+ if (ccr_only) {
+ tcg_gen_movi_i32(QREG_CC_C, val & CCF_C ? 1 : 0);
+ tcg_gen_movi_i32(QREG_CC_V, val & CCF_V ? -1 : 0);
+ tcg_gen_movi_i32(QREG_CC_Z, val & CCF_Z ? 0 : 1);
+ tcg_gen_movi_i32(QREG_CC_N, val & CCF_N ? -1 : 0);
+ tcg_gen_movi_i32(QREG_CC_X, val & CCF_X ? 1 : 0);
+ } else {
+ TCGv sr = tcg_const_i32(val);
+ gen_helper_set_sr(cpu_env, sr);
+ tcg_temp_free(sr);
+ }
+ set_cc_op(s, CC_OP_FLAGS);
+}
+
+static void gen_set_sr(DisasContext *s, TCGv val, int ccr_only)
+{
+ if (ccr_only) {
+ gen_helper_set_ccr(cpu_env, val);
+ } else {
+ gen_helper_set_sr(cpu_env, val);
+ }
+ set_cc_op(s, CC_OP_FLAGS);
+}
+
+static void gen_move_to_sr(CPUM68KState *env, DisasContext *s, uint16_t insn,
+ bool ccr_only)
+{
+ if ((insn & 0x3f) == 0x3c) {
+ uint16_t val;
+ val = read_im16(env, s);
+ gen_set_sr_im(s, val, ccr_only);
+ } else {
+ TCGv src;
+ SRC_EA(env, src, OS_WORD, 0, NULL);
+ gen_set_sr(s, src, ccr_only);
+ }
+}
+
DISAS_INSN(arith_im)
{
int op;
@@ -2140,6 +2201,7 @@ DISAS_INSN(arith_im)
TCGv dest;
TCGv addr;
int opsize;
+ bool with_SR = ((insn & 0x3f) == 0x3c);
op = (insn >> 9) & 7;
opsize = insn_opsize(insn);
@@ -2156,32 +2218,73 @@ DISAS_INSN(arith_im)
default:
abort();
}
- SRC_EA(env, src1, opsize, 1, (op == 6) ? NULL : &addr);
+
+ if (with_SR) {
+ /* SR/CCR can only be used with andi/eori/ori */
+ if (op == 2 || op == 3 || op == 6) {
+ disas_undef(env, s, insn);
+ return;
+ }
+ switch (opsize) {
+ case OS_BYTE:
+ src1 = gen_get_ccr(s);
+ break;
+ case OS_WORD:
+ if (IS_USER(s)) {
+ gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
+ return;
+ }
+ src1 = gen_get_sr(s);
+ break;
+ case OS_LONG:
+ disas_undef(env, s, insn);
+ return;
+ }
+ } else {
+ SRC_EA(env, src1, opsize, 1, (op == 6) ? NULL : &addr);
+ }
dest = tcg_temp_new();
switch (op) {
case 0: /* ori */
tcg_gen_or_i32(dest, src1, im);
- gen_logic_cc(s, dest, opsize);
+ if (with_SR) {
+ gen_set_sr(s, dest, opsize == OS_BYTE);
+ } else {
+ DEST_EA(env, insn, opsize, dest, &addr);
+ gen_logic_cc(s, dest, opsize);
+ }
break;
case 1: /* andi */
tcg_gen_and_i32(dest, src1, im);
- gen_logic_cc(s, dest, opsize);
+ if (with_SR) {
+ gen_set_sr(s, dest, opsize == OS_BYTE);
+ } else {
+ DEST_EA(env, insn, opsize, dest, &addr);
+ gen_logic_cc(s, dest, opsize);
+ }
break;
case 2: /* subi */
tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, src1, im);
tcg_gen_sub_i32(dest, src1, im);
gen_update_cc_add(dest, im, opsize);
set_cc_op(s, CC_OP_SUBB + opsize);
+ DEST_EA(env, insn, opsize, dest, &addr);
break;
case 3: /* addi */
tcg_gen_add_i32(dest, src1, im);
gen_update_cc_add(dest, im, opsize);
tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, im);
set_cc_op(s, CC_OP_ADDB + opsize);
+ DEST_EA(env, insn, opsize, dest, &addr);
break;
case 5: /* eori */
tcg_gen_xor_i32(dest, src1, im);
- gen_logic_cc(s, dest, opsize);
+ if (with_SR) {
+ gen_set_sr(s, dest, opsize == OS_BYTE);
+ } else {
+ DEST_EA(env, insn, opsize, dest, &addr);
+ gen_logic_cc(s, dest, opsize);
+ }
break;
case 6: /* cmpi */
gen_update_cc_cmp(s, src1, im, opsize);
@@ -2190,9 +2293,6 @@ DISAS_INSN(arith_im)
abort();
}
tcg_temp_free(im);
- if (op != 6) {
- DEST_EA(env, insn, opsize, dest, &addr);
- }
tcg_temp_free(dest);
}
@@ -2475,17 +2575,6 @@ DISAS_INSN(clr)
tcg_temp_free(zero);
}
-static TCGv gen_get_ccr(DisasContext *s)
-{
- TCGv dest;
-
- gen_flush_flags(s);
- update_cc_op(s);
- dest = tcg_temp_new();
- gen_helper_get_ccr(dest, cpu_env);
- return dest;
-}
-
DISAS_INSN(move_from_ccr)
{
TCGv ccr;
@@ -2512,43 +2601,9 @@ DISAS_INSN(neg)
tcg_temp_free(dest);
}
-static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
-{
- if (ccr_only) {
- tcg_gen_movi_i32(QREG_CC_C, val & CCF_C ? 1 : 0);
- tcg_gen_movi_i32(QREG_CC_V, val & CCF_V ? -1 : 0);
- tcg_gen_movi_i32(QREG_CC_Z, val & CCF_Z ? 0 : 1);
- tcg_gen_movi_i32(QREG_CC_N, val & CCF_N ? -1 : 0);
- tcg_gen_movi_i32(QREG_CC_X, val & CCF_X ? 1 : 0);
- } else {
- gen_helper_set_sr(cpu_env, tcg_const_i32(val));
- }
- set_cc_op(s, CC_OP_FLAGS);
-}
-
-static void gen_set_sr(CPUM68KState *env, DisasContext *s, uint16_t insn,
- int ccr_only)
-{
- if ((insn & 0x38) == 0) {
- if (ccr_only) {
- gen_helper_set_ccr(cpu_env, DREG(insn, 0));
- } else {
- gen_helper_set_sr(cpu_env, DREG(insn, 0));
- }
- set_cc_op(s, CC_OP_FLAGS);
- } else if ((insn & 0x3f) == 0x3c) {
- uint16_t val;
- val = read_im16(env, s);
- gen_set_sr_im(s, val, ccr_only);
- } else {
- disas_undef(env, s, insn);
- }
-}
-
-
DISAS_INSN(move_to_ccr)
{
- gen_set_sr(env, s, insn, 1);
+ gen_move_to_sr(env, s, insn, true);
}
DISAS_INSN(not)
@@ -2585,7 +2640,7 @@ DISAS_INSN(swap)
DISAS_INSN(bkpt)
{
- gen_exception(s, s->pc - 2, EXCP_DEBUG);
+ gen_exception(s, s->insn_pc, EXCP_DEBUG);
}
DISAS_INSN(pea)
@@ -2638,7 +2693,7 @@ DISAS_INSN(pulse)
DISAS_INSN(illegal)
{
- gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
+ gen_exception(s, s->insn_pc, EXCP_ILLEGAL);
}
/* ??? This should be atomic. */
@@ -2668,7 +2723,7 @@ DISAS_INSN(mull)
if (ext & 0x400) {
if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) {
- gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
+ gen_exception(s, s->insn_pc, EXCP_UNSUPPORTED);
return;
}
@@ -2764,6 +2819,18 @@ DISAS_INSN(unlk)
tcg_temp_free(src);
}
+#if defined(CONFIG_SOFTMMU)
+DISAS_INSN(reset)
+{
+ if (IS_USER(s)) {
+ gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
+ return;
+ }
+
+ gen_helper_reset(cpu_env);
+}
+#endif
+
DISAS_INSN(nop)
{
}
@@ -2897,6 +2964,7 @@ DISAS_INSN(branch)
gen_jmp_tb(s, 0, s->pc);
} else {
/* Unconditional branch. */
+ update_cc_op(s);
gen_jmp_tb(s, 0, base + offset);
}
}
@@ -3948,8 +4016,8 @@ DISAS_INSN(bfop_reg)
int ofs = extract32(ext, 6, 5); /* big bit-endian */
TCGv mask, tofs, tlen;
- TCGV_UNUSED(tofs);
- TCGV_UNUSED(tlen);
+ tofs = NULL;
+ tlen = NULL;
if ((insn & 0x0f00) == 0x0d00) { /* bfffo */
tofs = tcg_temp_new();
tlen = tcg_temp_new();
@@ -3965,7 +4033,7 @@ DISAS_INSN(bfop_reg)
}
tcg_gen_andi_i32(QREG_CC_N, QREG_CC_N, ~maski);
mask = tcg_const_i32(ror32(maski, ofs));
- if (!TCGV_IS_UNUSED(tofs)) {
+ if (tofs) {
tcg_gen_movi_i32(tofs, ofs);
tcg_gen_movi_i32(tlen, len);
}
@@ -3977,13 +4045,13 @@ DISAS_INSN(bfop_reg)
tcg_gen_andi_i32(tmp, tmp, 31);
mask = tcg_const_i32(0x7fffffffu);
tcg_gen_shr_i32(mask, mask, tmp);
- if (!TCGV_IS_UNUSED(tlen)) {
+ if (tlen) {
tcg_gen_addi_i32(tlen, tmp, 1);
}
} else {
/* Immediate width */
mask = tcg_const_i32(0x7fffffffu >> (len - 1));
- if (!TCGV_IS_UNUSED(tlen)) {
+ if (tlen) {
tcg_gen_movi_i32(tlen, len);
}
}
@@ -3993,7 +4061,7 @@ DISAS_INSN(bfop_reg)
tcg_gen_rotl_i32(QREG_CC_N, src, tmp);
tcg_gen_andc_i32(QREG_CC_N, QREG_CC_N, mask);
tcg_gen_rotr_i32(mask, mask, tmp);
- if (!TCGV_IS_UNUSED(tofs)) {
+ if (tofs) {
tcg_gen_mov_i32(tofs, tmp);
}
} else {
@@ -4001,7 +4069,7 @@ DISAS_INSN(bfop_reg)
tcg_gen_rotli_i32(QREG_CC_N, src, ofs);
tcg_gen_andc_i32(QREG_CC_N, QREG_CC_N, mask);
tcg_gen_rotri_i32(mask, mask, ofs);
- if (!TCGV_IS_UNUSED(tofs)) {
+ if (tofs) {
tcg_gen_movi_i32(tofs, ofs);
}
}
@@ -4204,16 +4272,148 @@ DISAS_INSN(ff1)
gen_helper_ff1(reg, reg);
}
-static TCGv gen_get_sr(DisasContext *s)
+DISAS_INSN(chk)
{
- TCGv ccr;
- TCGv sr;
+ TCGv src, reg;
+ int opsize;
- ccr = gen_get_ccr(s);
- sr = tcg_temp_new();
- tcg_gen_andi_i32(sr, QREG_SR, 0xffe0);
- tcg_gen_or_i32(sr, sr, ccr);
- return sr;
+ switch ((insn >> 7) & 3) {
+ case 3:
+ opsize = OS_WORD;
+ break;
+ case 2:
+ if (m68k_feature(env, M68K_FEATURE_CHK2)) {
+ opsize = OS_LONG;
+ break;
+ }
+ /* fallthru */
+ default:
+ gen_exception(s, s->insn_pc, EXCP_ILLEGAL);
+ return;
+ }
+ SRC_EA(env, src, opsize, 1, NULL);
+ reg = gen_extend(DREG(insn, 9), opsize, 1);
+
+ gen_flush_flags(s);
+ gen_helper_chk(cpu_env, reg, src);
+}
+
+DISAS_INSN(chk2)
+{
+ uint16_t ext;
+ TCGv addr1, addr2, bound1, bound2, reg;
+ int opsize;
+
+ switch ((insn >> 9) & 3) {
+ case 0:
+ opsize = OS_BYTE;
+ break;
+ case 1:
+ opsize = OS_WORD;
+ break;
+ case 2:
+ opsize = OS_LONG;
+ break;
+ default:
+ gen_exception(s, s->insn_pc, EXCP_ILLEGAL);
+ return;
+ }
+
+ ext = read_im16(env, s);
+ if ((ext & 0x0800) == 0) {
+ gen_exception(s, s->insn_pc, EXCP_ILLEGAL);
+ return;
+ }
+
+ addr1 = gen_lea(env, s, insn, OS_UNSIZED);
+ addr2 = tcg_temp_new();
+ tcg_gen_addi_i32(addr2, addr1, opsize_bytes(opsize));
+
+ bound1 = gen_load(s, opsize, addr1, 1);
+ tcg_temp_free(addr1);
+ bound2 = gen_load(s, opsize, addr2, 1);
+ tcg_temp_free(addr2);
+
+ reg = tcg_temp_new();
+ if (ext & 0x8000) {
+ tcg_gen_mov_i32(reg, AREG(ext, 12));
+ } else {
+ gen_ext(reg, DREG(ext, 12), opsize, 1);
+ }
+
+ gen_flush_flags(s);
+ gen_helper_chk2(cpu_env, reg, bound1, bound2);
+ tcg_temp_free(reg);
+}
+
+static void m68k_copy_line(TCGv dst, TCGv src, int index)
+{
+ TCGv addr;
+ TCGv_i64 t0, t1;
+
+ addr = tcg_temp_new();
+
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+
+ tcg_gen_andi_i32(addr, src, ~15);
+ tcg_gen_qemu_ld64(t0, addr, index);
+ tcg_gen_addi_i32(addr, addr, 8);
+ tcg_gen_qemu_ld64(t1, addr, index);
+
+ tcg_gen_andi_i32(addr, dst, ~15);
+ tcg_gen_qemu_st64(t0, addr, index);
+ tcg_gen_addi_i32(addr, addr, 8);
+ tcg_gen_qemu_st64(t1, addr, index);
+
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
+ tcg_temp_free(addr);
+}
+
+DISAS_INSN(move16_reg)
+{
+ int index = IS_USER(s);
+ TCGv tmp;
+ uint16_t ext;
+
+ ext = read_im16(env, s);
+ if ((ext & (1 << 15)) == 0) {
+ gen_exception(s, s->insn_pc, EXCP_ILLEGAL);
+ }
+
+ m68k_copy_line(AREG(ext, 12), AREG(insn, 0), index);
+
+ /* Ax can be Ay, so save Ay before incrementing Ax */
+ tmp = tcg_temp_new();
+ tcg_gen_mov_i32(tmp, AREG(ext, 12));
+ tcg_gen_addi_i32(AREG(insn, 0), AREG(insn, 0), 16);
+ tcg_gen_addi_i32(AREG(ext, 12), tmp, 16);
+ tcg_temp_free(tmp);
+}
+
+DISAS_INSN(move16_mem)
+{
+ int index = IS_USER(s);
+ TCGv reg, addr;
+
+ reg = AREG(insn, 0);
+ addr = tcg_const_i32(read_im32(env, s));
+
+ if ((insn >> 3) & 1) {
+ /* MOVE16 (xxx).L, (Ay) */
+ m68k_copy_line(reg, addr, index);
+ } else {
+ /* MOVE16 (Ay), (xxx).L */
+ m68k_copy_line(addr, reg, index);
+ }
+
+ tcg_temp_free(addr);
+
+ if (((insn >> 3) & 2) == 0) {
+ /* (Ay)+ */
+ tcg_gen_addi_i32(reg, reg, 16);
+ }
}
DISAS_INSN(strldsr)
@@ -4241,27 +4441,28 @@ DISAS_INSN(move_from_sr)
TCGv sr;
if (IS_USER(s) && !m68k_feature(env, M68K_FEATURE_M68000)) {
- gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
+ gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
return;
}
sr = gen_get_sr(s);
DEST_EA(env, insn, OS_WORD, sr, NULL);
}
+#if defined(CONFIG_SOFTMMU)
DISAS_INSN(move_to_sr)
{
if (IS_USER(s)) {
- gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
+ gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
return;
}
- gen_set_sr(env, s, insn, 0);
+ gen_move_to_sr(env, s, insn, false);
gen_lookup_tb(s);
}
DISAS_INSN(move_from_usp)
{
if (IS_USER(s)) {
- gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
+ gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
return;
}
tcg_gen_ld_i32(AREG(insn, 0), cpu_env,
@@ -4271,7 +4472,7 @@ DISAS_INSN(move_from_usp)
DISAS_INSN(move_to_usp)
{
if (IS_USER(s)) {
- gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
+ gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
return;
}
tcg_gen_st_i32(AREG(insn, 0), cpu_env,
@@ -4280,6 +4481,11 @@ DISAS_INSN(move_to_usp)
DISAS_INSN(halt)
{
+ if (IS_USER(s)) {
+ gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
+ return;
+ }
+
gen_exception(s, s->pc, EXCP_HALT_INSN);
}
@@ -4288,7 +4494,7 @@ DISAS_INSN(stop)
uint16_t ext;
if (IS_USER(s)) {
- gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
+ gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
return;
}
@@ -4302,19 +4508,19 @@ DISAS_INSN(stop)
DISAS_INSN(rte)
{
if (IS_USER(s)) {
- gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
+ gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
return;
}
- gen_exception(s, s->pc - 2, EXCP_RTE);
+ gen_exception(s, s->insn_pc, EXCP_RTE);
}
-DISAS_INSN(movec)
+DISAS_INSN(cf_movec)
{
uint16_t ext;
TCGv reg;
if (IS_USER(s)) {
- gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
+ gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
return;
}
@@ -4325,14 +4531,39 @@ DISAS_INSN(movec)
} else {
reg = DREG(ext, 12);
}
- gen_helper_movec(cpu_env, tcg_const_i32(ext & 0xfff), reg);
+ gen_helper_cf_movec_to(cpu_env, tcg_const_i32(ext & 0xfff), reg);
+ gen_lookup_tb(s);
+}
+
+DISAS_INSN(m68k_movec)
+{
+ uint16_t ext;
+ TCGv reg;
+
+ if (IS_USER(s)) {
+ gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
+ return;
+ }
+
+ ext = read_im16(env, s);
+
+ if (ext & 0x8000) {
+ reg = AREG(ext, 12);
+ } else {
+ reg = DREG(ext, 12);
+ }
+ if (insn & 1) {
+ gen_helper_m68k_movec_to(cpu_env, tcg_const_i32(ext & 0xfff), reg);
+ } else {
+ gen_helper_m68k_movec_from(reg, cpu_env, tcg_const_i32(ext & 0xfff));
+ }
gen_lookup_tb(s);
}
DISAS_INSN(intouch)
{
if (IS_USER(s)) {
- gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
+ gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
return;
}
/* ICache fetch. Implement as no-op. */
@@ -4341,15 +4572,33 @@ DISAS_INSN(intouch)
DISAS_INSN(cpushl)
{
if (IS_USER(s)) {
- gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
+ gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
return;
}
/* Cache push/invalidate. Implement as no-op. */
}
+DISAS_INSN(cpush)
+{
+ if (IS_USER(s)) {
+ gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
+ return;
+ }
+ /* Cache push/invalidate. Implement as no-op. */
+}
+
+DISAS_INSN(cinv)
+{
+ if (IS_USER(s)) {
+ gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
+ return;
+ }
+ /* Invalidate cache line. Implement as no-op. */
+}
+
DISAS_INSN(wddata)
{
- gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
+ gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
}
DISAS_INSN(wdebug)
@@ -4357,16 +4606,17 @@ DISAS_INSN(wdebug)
M68kCPU *cpu = m68k_env_get_cpu(env);
if (IS_USER(s)) {
- gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
+ gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
return;
}
/* TODO: Implement wdebug. */
cpu_abort(CPU(cpu), "WDEBUG not implemented");
}
+#endif
DISAS_INSN(trap)
{
- gen_exception(s, s->pc - 2, EXCP_TRAP0 + (insn & 0xf));
+ gen_exception(s, s->insn_pc, EXCP_TRAP0 + (insn & 0xf));
}
static void gen_load_fcr(DisasContext *s, TCGv res, int reg)
@@ -4875,6 +5125,7 @@ static void gen_fjmpcc(DisasContext *s, int cond, TCGLabel *l1)
DisasCompare c;
gen_fcc_cond(&c, s, cond);
+ update_cc_op(s);
tcg_gen_brcond_i32(c.tcond, c.v1, c.v2, l1);
free_cond(&c);
}
@@ -4919,21 +5170,40 @@ DISAS_INSN(fscc)
tcg_temp_free(tmp);
}
+#if defined(CONFIG_SOFTMMU)
DISAS_INSN(frestore)
{
- M68kCPU *cpu = m68k_env_get_cpu(env);
+ TCGv addr;
- /* TODO: Implement frestore. */
- cpu_abort(CPU(cpu), "FRESTORE not implemented");
+ if (IS_USER(s)) {
+ gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
+ return;
+ }
+ if (m68k_feature(s->env, M68K_FEATURE_M68040)) {
+ SRC_EA(env, addr, OS_LONG, 0, NULL);
+ /* FIXME: check the state frame */
+ } else {
+ disas_undef(env, s, insn);
+ }
}
DISAS_INSN(fsave)
{
- M68kCPU *cpu = m68k_env_get_cpu(env);
+ if (IS_USER(s)) {
+ gen_exception(s, s->insn_pc, EXCP_PRIVILEGE);
+ return;
+ }
- /* TODO: Implement fsave. */
- cpu_abort(CPU(cpu), "FSAVE not implemented");
+ if (m68k_feature(s->env, M68K_FEATURE_M68040)) {
+ /* always write IDLE */
+ TCGv idle = tcg_const_i32(0x41000000);
+ DEST_EA(env, insn, OS_LONG, idle, NULL);
+ tcg_temp_free(idle);
+ } else {
+ disas_undef(env, s, insn);
+ }
}
+#endif
static inline TCGv gen_mac_extract_word(DisasContext *s, TCGv val, int upper)
{
@@ -5306,7 +5576,7 @@ void register_m68k_insns (CPUM68KState *env)
BASE(undef, 0000, 0000);
INSN(arith_im, 0080, fff8, CF_ISA_A);
INSN(arith_im, 0000, ff00, M68000);
- INSN(undef, 00c0, ffc0, M68000);
+ INSN(chk2, 00c0, f9c0, CHK2);
INSN(bitrev, 00c0, fff8, CF_ISA_APLUSC);
BASE(bitop_reg, 0100, f1c0);
BASE(bitop_reg, 0140, f1c0);
@@ -5339,6 +5609,7 @@ void register_m68k_insns (CPUM68KState *env)
BASE(move, 1000, f000);
BASE(move, 2000, f000);
BASE(move, 3000, f000);
+ INSN(chk, 4000, f040, M68000);
INSN(strldsr, 40e7, ffff, CF_ISA_APLUSC);
INSN(negx, 4080, fff8, CF_ISA_A);
INSN(negx, 4000, ff00, M68000);
@@ -5356,8 +5627,9 @@ void register_m68k_insns (CPUM68KState *env)
BASE(move_to_ccr, 44c0, ffc0);
INSN(not, 4680, fff8, CF_ISA_A);
INSN(not, 4600, ff00, M68000);
- INSN(undef, 46c0, ffc0, M68000);
- INSN(move_to_sr, 46c0, ffc0, CF_ISA_A);
+#if defined(CONFIG_SOFTMMU)
+ BASE(move_to_sr, 46c0, ffc0);
+#endif
INSN(nbcd, 4800, ffc0, M68000);
INSN(linkl, 4808, fff8, M68000);
BASE(pea, 4840, ffc0);
@@ -5372,7 +5644,9 @@ void register_m68k_insns (CPUM68KState *env)
BASE(tst, 4a00, ff00);
INSN(tas, 4ac0, ffc0, CF_ISA_B);
INSN(tas, 4ac0, ffc0, M68000);
+#if defined(CONFIG_SOFTMMU)
INSN(halt, 4ac8, ffff, CF_ISA_A);
+#endif
INSN(pulse, 4acc, ffff, CF_ISA_A);
BASE(illegal, 4afc, ffff);
INSN(mull, 4c00, ffc0, CF_ISA_A);
@@ -5383,14 +5657,18 @@ void register_m68k_insns (CPUM68KState *env)
BASE(trap, 4e40, fff0);
BASE(link, 4e50, fff8);
BASE(unlk, 4e58, fff8);
+#if defined(CONFIG_SOFTMMU)
INSN(move_to_usp, 4e60, fff8, USP);
INSN(move_from_usp, 4e68, fff8, USP);
- BASE(nop, 4e71, ffff);
+ INSN(reset, 4e70, ffff, M68000);
BASE(stop, 4e72, ffff);
BASE(rte, 4e73, ffff);
+ INSN(cf_movec, 4e7b, ffff, CF_ISA_A);
+ INSN(m68k_movec, 4e7a, fffe, M68000);
+#endif
+ BASE(nop, 4e71, ffff);
INSN(rtd, 4e74, ffff, RTD);
BASE(rts, 4e75, ffff);
- INSN(movec, 4e7b, ffff, CF_ISA_A);
BASE(jump, 4e80, ffc0);
BASE(jump, 4ec0, ffc0);
INSN(addsubq, 5000, f080, M68000);
@@ -5494,17 +5772,23 @@ void register_m68k_insns (CPUM68KState *env)
BASE(undef_fpu, f000, f000);
INSN(fpu, f200, ffc0, CF_FPU);
INSN(fbcc, f280, ffc0, CF_FPU);
- INSN(frestore, f340, ffc0, CF_FPU);
- INSN(fsave, f300, ffc0, CF_FPU);
INSN(fpu, f200, ffc0, FPU);
INSN(fscc, f240, ffc0, FPU);
INSN(fbcc, f280, ff80, FPU);
+#if defined(CONFIG_SOFTMMU)
+ INSN(frestore, f340, ffc0, CF_FPU);
+ INSN(fsave, f300, ffc0, CF_FPU);
INSN(frestore, f340, ffc0, FPU);
INSN(fsave, f300, ffc0, FPU);
INSN(intouch, f340, ffc0, CF_ISA_A);
INSN(cpushl, f428, ff38, CF_ISA_A);
+ INSN(cpush, f420, ff20, M68040);
+ INSN(cinv, f400, ff20, M68040);
INSN(wddata, fb00, ff00, CF_ISA_A);
INSN(wdebug, fbc0, ffc0, CF_ISA_A);
+#endif
+ INSN(move16_mem, f600, ffe0, M68040);
+ INSN(move16_reg, f620, fff8, M68040);
#undef INSN
}
@@ -5652,9 +5936,12 @@ void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
}
cpu_fprintf (f, "PC = %08x ", env->pc);
sr = env->sr | cpu_m68k_get_ccr(env);
- cpu_fprintf(f, "SR = %04x %c%c%c%c%c ", sr, (sr & CCF_X) ? 'X' : '-',
- (sr & CCF_N) ? 'N' : '-', (sr & CCF_Z) ? 'Z' : '-',
- (sr & CCF_V) ? 'V' : '-', (sr & CCF_C) ? 'C' : '-');
+ cpu_fprintf(f, "SR = %04x T:%x I:%x %c%c %c%c%c%c%c\n",
+ sr, (sr & SR_T) >> SR_T_SHIFT, (sr & SR_I) >> SR_I_SHIFT,
+ (sr & SR_S) ? 'S' : 'U', (sr & SR_M) ? '%' : 'I',
+ (sr & CCF_X) ? 'X' : '-', (sr & CCF_N) ? 'N' : '-',
+ (sr & CCF_Z) ? 'Z' : '-', (sr & CCF_V) ? 'V' : '-',
+ (sr & CCF_C) ? 'C' : '-');
cpu_fprintf(f, "FPSR = %08x %c%c%c%c ", env->fpsr,
(env->fpsr & FPSR_CC_A) ? 'A' : '-',
(env->fpsr & FPSR_CC_I) ? 'I' : '-',
@@ -5687,6 +5974,14 @@ void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf(f, "RP ");
break;
}
+ cpu_fprintf(f, "\n");
+#ifdef CONFIG_SOFTMMU
+ cpu_fprintf(f, "%sA7(MSP) = %08x %sA7(USP) = %08x %sA7(ISP) = %08x\n",
+ env->current_sp == M68K_SSP ? "->" : " ", env->sp[M68K_SSP],
+ env->current_sp == M68K_USP ? "->" : " ", env->sp[M68K_USP],
+ env->current_sp == M68K_ISP ? "->" : " ", env->sp[M68K_ISP]);
+ cpu_fprintf(f, "VBR = 0x%08x\n", env->vbr);
+#endif
}
void restore_state_to_opc(CPUM68KState *env, TranslationBlock *tb,
diff --git a/target/microblaze/op_helper.c b/target/microblaze/op_helper.c
index 1e07e21c1c..4cf51568df 100644
--- a/target/microblaze/op_helper.c
+++ b/target/microblaze/op_helper.c
@@ -40,11 +40,8 @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type,
ret = mb_cpu_handle_mmu_fault(cs, addr, access_type, mmu_idx);
if (unlikely(ret)) {
- if (retaddr) {
- /* now we have a real cpu fault */
- cpu_restore_state(cs, retaddr);
- }
- cpu_loop_exit(cs);
+ /* now we have a real cpu fault */
+ cpu_loop_exit_restore(cs, retaddr);
}
}
#endif
diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
index e7b5597c46..7628b0e25b 100644
--- a/target/microblaze/translate.c
+++ b/target/microblaze/translate.c
@@ -1808,11 +1808,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
&& qemu_log_in_addr_range(pc_start)) {
qemu_log_lock();
qemu_log("--------------\n");
-#if DISAS_GNU
log_target_disas(cs, pc_start, dc->pc - pc_start);
-#endif
- qemu_log("\nisize=%d osize=%d\n",
- dc->pc - pc_start, tcg_op_buf_count());
qemu_log_unlock();
}
#endif
diff --git a/target/mips/translate.c b/target/mips/translate.c
index b022f840c9..d05ee67e63 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -20453,7 +20453,7 @@ void mips_tcg_init(void)
{
int i;
- TCGV_UNUSED(cpu_gpr[0]);
+ cpu_gpr[0] = NULL;
for (i = 1; i < 32; i++)
cpu_gpr[i] = tcg_global_mem_new(cpu_env,
offsetof(CPUMIPSState, active_tc.gpr[i]),
diff --git a/target/moxie/helper.c b/target/moxie/helper.c
index 330299f5a7..6890ffd71c 100644
--- a/target/moxie/helper.c
+++ b/target/moxie/helper.c
@@ -36,11 +36,8 @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type,
ret = moxie_cpu_handle_mmu_fault(cs, addr, access_type, mmu_idx);
if (unlikely(ret)) {
- if (retaddr) {
- cpu_restore_state(cs, retaddr);
- }
+ cpu_loop_exit_restore(cs, retaddr);
}
- cpu_loop_exit(cs);
}
void helper_raise_exception(CPUMoxieState *env, int ex)
diff --git a/target/nios2/mmu.c b/target/nios2/mmu.c
index fe9298af50..0cd8647510 100644
--- a/target/nios2/mmu.c
+++ b/target/nios2/mmu.c
@@ -42,11 +42,8 @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type,
ret = nios2_cpu_handle_mmu_fault(cs, addr, access_type, mmu_idx);
if (unlikely(ret)) {
- if (retaddr) {
- /* now we have a real cpu fault */
- cpu_restore_state(cs, retaddr);
- }
- cpu_loop_exit(cs);
+ /* now we have a real cpu fault */
+ cpu_loop_exit_restore(cs, retaddr);
}
}
diff --git a/target/nios2/translate.c b/target/nios2/translate.c
index 51a54ff760..cb8624e8d2 100644
--- a/target/nios2/translate.c
+++ b/target/nios2/translate.c
@@ -125,7 +125,7 @@ static uint8_t get_opxcode(uint32_t code)
static TCGv load_zero(DisasContext *dc)
{
- if (TCGV_IS_UNUSED_I32(dc->zero)) {
+ if (!dc->zero) {
dc->zero = tcg_const_i32(0);
}
return dc->zero;
@@ -755,12 +755,12 @@ static void handle_instruction(DisasContext *dc, CPUNios2State *env)
goto illegal_op;
}
- TCGV_UNUSED_I32(dc->zero);
+ dc->zero = NULL;
instr = &i_type_instructions[op];
instr->handler(dc, code, instr->flags);
- if (!TCGV_IS_UNUSED_I32(dc->zero)) {
+ if (dc->zero) {
tcg_temp_free(dc->zero);
}
diff --git a/target/openrisc/mmu_helper.c b/target/openrisc/mmu_helper.c
index a44d0aa51a..a3e182c42d 100644
--- a/target/openrisc/mmu_helper.c
+++ b/target/openrisc/mmu_helper.c
@@ -33,12 +33,8 @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type,
ret = openrisc_cpu_handle_mmu_fault(cs, addr, access_type, mmu_idx);
if (ret) {
- if (retaddr) {
- /* now we have a real cpu fault. */
- cpu_restore_state(cs, retaddr);
- }
/* Raise Exception. */
- cpu_loop_exit(cs);
+ cpu_loop_exit_restore(cs, retaddr);
}
}
#endif
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 4075fc8589..0ef21cce33 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -3495,7 +3495,7 @@ static void gen_bcond(DisasContext *ctx, int type)
else
tcg_gen_mov_tl(target, cpu_lr);
} else {
- TCGV_UNUSED(target);
+ target = NULL;
}
if (LK(ctx->opcode))
gen_setlr(ctx, ctx->nip);
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index eede2ed157..ac55886792 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -434,11 +434,9 @@ static void set_cc_static(DisasContext *s)
/* calculates cc into cc_op */
static void gen_op_calc_cc(DisasContext *s)
{
- TCGv_i32 local_cc_op;
- TCGv_i64 dummy;
+ TCGv_i32 local_cc_op = NULL;
+ TCGv_i64 dummy = NULL;
- TCGV_UNUSED_I32(local_cc_op);
- TCGV_UNUSED_I64(dummy);
switch (s->cc_op) {
default:
dummy = tcg_const_i64(0);
@@ -528,10 +526,10 @@ static void gen_op_calc_cc(DisasContext *s)
tcg_abort();
}
- if (!TCGV_IS_UNUSED_I32(local_cc_op)) {
+ if (local_cc_op) {
tcg_temp_free_i32(local_cc_op);
}
- if (!TCGV_IS_UNUSED_I64(dummy)) {
+ if (dummy) {
tcg_temp_free_i64(dummy);
}
@@ -1189,7 +1187,7 @@ static ExitStatus help_branch(DisasContext *s, DisasCompare *c,
goto egress;
}
} else {
- if (TCGV_IS_UNUSED_I64(cdest)) {
+ if (!cdest) {
/* E.g. bcr %r0 -> no branch. */
ret = NO_EXIT;
goto egress;
@@ -1451,7 +1449,7 @@ static ExitStatus op_ni(DisasContext *s, DisasOps *o)
static ExitStatus op_bas(DisasContext *s, DisasOps *o)
{
tcg_gen_movi_i64(o->out, pc_to_link_info(s, s->next_pc));
- if (!TCGV_IS_UNUSED_I64(o->in2)) {
+ if (o->in2) {
tcg_gen_mov_i64(psw_addr, o->in2);
per_branch(s, false);
return EXIT_PC_UPDATED;
@@ -3031,7 +3029,7 @@ static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
{
o->out = o->in2;
o->g_out = o->g_in2;
- TCGV_UNUSED_I64(o->in2);
+ o->in2 = NULL;
o->g_in2 = false;
return NO_EXIT;
}
@@ -3043,7 +3041,7 @@ static ExitStatus op_mov2e(DisasContext *s, DisasOps *o)
o->out = o->in2;
o->g_out = o->g_in2;
- TCGV_UNUSED_I64(o->in2);
+ o->in2 = NULL;
o->g_in2 = false;
switch (s->tb->flags & FLAG_MASK_ASC) {
@@ -3077,8 +3075,8 @@ static ExitStatus op_movx(DisasContext *s, DisasOps *o)
o->out2 = o->in2;
o->g_out = o->g_in1;
o->g_out2 = o->g_in2;
- TCGV_UNUSED_I64(o->in1);
- TCGV_UNUSED_I64(o->in2);
+ o->in1 = NULL;
+ o->in2 = NULL;
o->g_in1 = o->g_in2 = false;
return NO_EXIT;
}
@@ -5945,11 +5943,11 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
s->insn = insn;
s->fields = &f;
o.g_out = o.g_out2 = o.g_in1 = o.g_in2 = false;
- TCGV_UNUSED_I64(o.out);
- TCGV_UNUSED_I64(o.out2);
- TCGV_UNUSED_I64(o.in1);
- TCGV_UNUSED_I64(o.in2);
- TCGV_UNUSED_I64(o.addr1);
+ o.out = NULL;
+ o.out2 = NULL;
+ o.in1 = NULL;
+ o.in2 = NULL;
+ o.addr1 = NULL;
/* Implement the instruction. */
if (insn->help_in1) {
@@ -5972,19 +5970,19 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
}
/* Free any temporaries created by the helpers. */
- if (!TCGV_IS_UNUSED_I64(o.out) && !o.g_out) {
+ if (o.out && !o.g_out) {
tcg_temp_free_i64(o.out);
}
- if (!TCGV_IS_UNUSED_I64(o.out2) && !o.g_out2) {
+ if (o.out2 && !o.g_out2) {
tcg_temp_free_i64(o.out2);
}
- if (!TCGV_IS_UNUSED_I64(o.in1) && !o.g_in1) {
+ if (o.in1 && !o.g_in1) {
tcg_temp_free_i64(o.in1);
}
- if (!TCGV_IS_UNUSED_I64(o.in2) && !o.g_in2) {
+ if (o.in2 && !o.g_in2) {
tcg_temp_free_i64(o.in2);
}
- if (!TCGV_IS_UNUSED_I64(o.addr1)) {
+ if (o.addr1) {
tcg_temp_free_i64(o.addr1);
}
diff --git a/target/sh4/translate.c b/target/sh4/translate.c
index 038663cc05..012156b97b 100644
--- a/target/sh4/translate.c
+++ b/target/sh4/translate.c
@@ -1940,7 +1940,7 @@ static int decode_gusa(DisasContext *ctx, CPUSH4State *env, int *pmax_insns)
op_dst = op_src = op_opc = -1;
mt_dst = -1;
st_src = st_mop = -1;
- TCGV_UNUSED(op_arg);
+ op_arg = NULL;
i = 0;
#define NEXT_INSN \
@@ -2228,7 +2228,7 @@ static int decode_gusa(DisasContext *ctx, CPUSH4State *env, int *pmax_insns)
}
/* If op_src is not a valid register, then op_arg was a constant. */
- if (op_src < 0 && !TCGV_IS_UNUSED(op_arg)) {
+ if (op_src < 0 && op_arg) {
tcg_temp_free_i32(op_arg);
}
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index 849a02aebd..71e0853e43 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -5922,7 +5922,7 @@ void sparc_tcg_init(void)
*rtl[i].ptr = tcg_global_mem_new(cpu_env, rtl[i].off, rtl[i].name);
}
- TCGV_UNUSED(cpu_regs[0]);
+ cpu_regs[0] = NULL;
for (i = 1; i < 8; ++i) {
cpu_regs[i] = tcg_global_mem_new(cpu_env,
offsetof(CPUSPARCState, gregs[i]),
diff --git a/target/tilegx/translate.c b/target/tilegx/translate.c
index d55549dabc..d63bf5bba3 100644
--- a/target/tilegx/translate.c
+++ b/target/tilegx/translate.c
@@ -143,7 +143,7 @@ static bool check_gr(DisasContext *dc, uint8_t reg)
static TCGv load_zero(DisasContext *dc)
{
- if (TCGV_IS_UNUSED_I64(dc->zero)) {
+ if (!dc->zero) {
dc->zero = tcg_const_i64(0);
}
return dc->zero;
@@ -2324,7 +2324,7 @@ static void translate_one_bundle(DisasContext *dc, uint64_t bundle)
for (i = 0; i < ARRAY_SIZE(dc->wb); i++) {
DisasContextTemp *wb = &dc->wb[i];
wb->reg = TILEGX_R_NOREG;
- TCGV_UNUSED_I64(wb->val);
+ wb->val = NULL;
}
dc->num_wb = 0;
@@ -2384,9 +2384,9 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
dc->exit_tb = false;
dc->atomic_excp = TILEGX_EXCP_NONE;
dc->jmp.cond = TCG_COND_NEVER;
- TCGV_UNUSED_I64(dc->jmp.dest);
- TCGV_UNUSED_I64(dc->jmp.val1);
- TCGV_UNUSED_I64(dc->zero);
+ dc->jmp.dest = NULL;
+ dc->jmp.val1 = NULL;
+ dc->zero = NULL;
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log_lock();
diff --git a/target/tricore/op_helper.c b/target/tricore/op_helper.c
index 7af202c8c0..40ed229486 100644
--- a/target/tricore/op_helper.c
+++ b/target/tricore/op_helper.c
@@ -31,9 +31,7 @@ raise_exception_sync_internal(CPUTriCoreState *env, uint32_t class, int tin,
{
CPUState *cs = CPU(tricore_env_get_cpu(env));
/* in case we come from a helper-call we need to restore the PC */
- if (pc) {
- cpu_restore_state(cs, pc);
- }
+ cpu_restore_state(cs, pc);
/* Tin is loaded into d[15] */
env->gpr_d[15] = tin;
@@ -2804,13 +2802,8 @@ static inline void QEMU_NORETURN do_raise_exception_err(CPUTriCoreState *env,
CPUState *cs = CPU(tricore_env_get_cpu(env));
cs->exception_index = exception;
env->error_code = error_code;
-
- if (pc) {
- /* now we have a real cpu fault */
- cpu_restore_state(cs, pc);
- }
-
- cpu_loop_exit(cs);
+ /* now we have a real cpu fault */
+ cpu_loop_exit_restore(cs, pc);
}
void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type,
diff --git a/target/unicore32/op_helper.c b/target/unicore32/op_helper.c
index 0872c29faa..8788642a7f 100644
--- a/target/unicore32/op_helper.c
+++ b/target/unicore32/op_helper.c
@@ -251,11 +251,8 @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type,
ret = uc32_cpu_handle_mmu_fault(cs, addr, access_type, mmu_idx);
if (unlikely(ret)) {
- if (retaddr) {
- /* now we have a real cpu fault */
- cpu_restore_state(cs, retaddr);
- }
- cpu_loop_exit(cs);
+ /* now we have a real cpu fault */
+ cpu_loop_exit_restore(cs, retaddr);
}
}
#endif
diff --git a/target/unicore32/translate.c b/target/unicore32/translate.c
index 384aa86027..5b51f2166d 100644
--- a/target/unicore32/translate.c
+++ b/target/unicore32/translate.c
@@ -1230,7 +1230,7 @@ static void do_datap(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
if (UCOP_OPCODES != 0x0f && UCOP_OPCODES != 0x0d) {
tmp = load_reg(s, UCOP_REG_N);
} else {
- TCGV_UNUSED(tmp);
+ tmp = NULL;
}
switch (UCOP_OPCODES) {
@@ -1652,7 +1652,7 @@ static void do_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn)
/* compute total size */
loaded_base = 0;
- TCGV_UNUSED(loaded_var);
+ loaded_var = NULL;
n = 0;
for (i = 0; i < 6; i++) {
if (UCOP_SET(i)) {
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 438321c6cc..2cbbeefd53 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -602,8 +602,8 @@ static bool swap_commutative2(TCGArg *p1, TCGArg *p2)
/* Propagate constants and copies, fold constant expressions. */
void tcg_optimize(TCGContext *s)
{
- int oi, oi_next, nb_temps, nb_globals;
- TCGOp *prev_mb = NULL;
+ int nb_temps, nb_globals;
+ TCGOp *op, *op_next, *prev_mb = NULL;
struct tcg_temp_info *infos;
TCGTempSet temps_used;
@@ -617,22 +617,18 @@ void tcg_optimize(TCGContext *s)
bitmap_zero(temps_used.l, nb_temps);
infos = tcg_malloc(sizeof(struct tcg_temp_info) * nb_temps);
- for (oi = s->gen_op_buf[0].next; oi != 0; oi = oi_next) {
+ QTAILQ_FOREACH_SAFE(op, &s->ops, link, op_next) {
tcg_target_ulong mask, partmask, affected;
int nb_oargs, nb_iargs, i;
TCGArg tmp;
-
- TCGOp * const op = &s->gen_op_buf[oi];
TCGOpcode opc = op->opc;
const TCGOpDef *def = &tcg_op_defs[opc];
- oi_next = op->next;
-
/* Count the arguments, and initialize the temps that are
going to be used */
if (opc == INDEX_op_call) {
- nb_oargs = op->callo;
- nb_iargs = op->calli;
+ nb_oargs = TCGOP_CALLO(op);
+ nb_iargs = TCGOP_CALLI(op);
for (i = 0; i < nb_oargs + nb_iargs; i++) {
TCGTemp *ts = arg_temp(op->args[i]);
if (ts) {
@@ -1261,9 +1257,6 @@ void tcg_optimize(TCGContext *s)
rh = op->args[1];
tcg_opt_gen_movi(s, op, rl, (int32_t)a);
tcg_opt_gen_movi(s, op2, rh, (int32_t)(a >> 32));
-
- /* We've done all we need to do with the movi. Skip it. */
- oi_next = op2->next;
break;
}
goto do_default;
@@ -1280,9 +1273,6 @@ void tcg_optimize(TCGContext *s)
rh = op->args[1];
tcg_opt_gen_movi(s, op, rl, (int32_t)r);
tcg_opt_gen_movi(s, op2, rh, (int32_t)(r >> 32));
-
- /* We've done all we need to do with the movi. Skip it. */
- oi_next = op2->next;
break;
}
goto do_default;
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
index 3cad30b1f2..0c509bfe46 100644
--- a/tcg/tcg-op.c
+++ b/tcg/tcg-op.c
@@ -42,30 +42,6 @@ extern TCGv_i32 TCGV_HIGH_link_error(TCGv_i64);
#define TCGV_HIGH TCGV_HIGH_link_error
#endif
-/* Note that this is optimized for sequential allocation during translate.
- Up to and including filling in the forward link immediately. We'll do
- proper termination of the end of the list after we finish translation. */
-
-static inline TCGOp *tcg_emit_op(TCGOpcode opc)
-{
- TCGContext *ctx = tcg_ctx;
- int oi = ctx->gen_next_op_idx;
- int ni = oi + 1;
- int pi = oi - 1;
- TCGOp *op = &ctx->gen_op_buf[oi];
-
- tcg_debug_assert(oi < OPC_BUF_SIZE);
- ctx->gen_op_buf[0].prev = oi;
- ctx->gen_next_op_idx = ni;
-
- memset(op, 0, offsetof(TCGOp, args));
- op->opc = opc;
- op->prev = pi;
- op->next = ni;
-
- return op;
-}
-
void tcg_gen_op1(TCGOpcode opc, TCGArg a1)
{
TCGOp *op = tcg_emit_op(opc);
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index 3129159907..ca07b32b65 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -807,8 +807,6 @@ void tcg_gen_lookup_and_goto_ptr(void);
#define tcg_global_mem_new tcg_global_mem_new_i32
#define tcg_temp_local_new() tcg_temp_local_new_i32()
#define tcg_temp_free tcg_temp_free_i32
-#define TCGV_UNUSED(x) TCGV_UNUSED_I32(x)
-#define TCGV_IS_UNUSED(x) TCGV_IS_UNUSED_I32(x)
#define tcg_gen_qemu_ld_tl tcg_gen_qemu_ld_i32
#define tcg_gen_qemu_st_tl tcg_gen_qemu_st_i32
#else
@@ -817,8 +815,6 @@ void tcg_gen_lookup_and_goto_ptr(void);
#define tcg_global_mem_new tcg_global_mem_new_i64
#define tcg_temp_local_new() tcg_temp_local_new_i64()
#define tcg_temp_free tcg_temp_free_i64
-#define TCGV_UNUSED(x) TCGV_UNUSED_I64(x)
-#define TCGV_IS_UNUSED(x) TCGV_IS_UNUSED_I64(x)
#define tcg_gen_qemu_ld_tl tcg_gen_qemu_ld_i64
#define tcg_gen_qemu_st_tl tcg_gen_qemu_st_i64
#endif
diff --git a/tcg/tcg.c b/tcg/tcg.c
index c22f1c4441..93caa0be93 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -862,9 +862,8 @@ void tcg_func_start(TCGContext *s)
s->goto_tb_issue_mask = 0;
#endif
- s->gen_op_buf[0].next = 1;
- s->gen_op_buf[0].prev = 0;
- s->gen_next_op_idx = 1;
+ QTAILQ_INIT(&s->ops);
+ QTAILQ_INIT(&s->free_ops);
}
static inline TCGTemp *tcg_temp_alloc(TCGContext *s)
@@ -1339,7 +1338,6 @@ bool tcg_op_supported(TCGOpcode op)
and endian swap in tcg_reg_alloc_call(). */
void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
{
- TCGContext *s = tcg_ctx;
int i, real_args, nb_rets, pi;
unsigned sizemask, flags;
TCGHelperInfo *info;
@@ -1358,8 +1356,8 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
TCGv_i64 retl, reth;
TCGTemp *split_args[MAX_OPC_PARAM];
- TCGV_UNUSED_I64(retl);
- TCGV_UNUSED_I64(reth);
+ retl = NULL;
+ reth = NULL;
if (sizemask != 0) {
for (i = real_args = 0; i < nargs; ++i) {
int is_64bit = sizemask & (1 << (i+1)*2);
@@ -1395,17 +1393,7 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
}
#endif /* TCG_TARGET_EXTEND_ARGS */
- i = s->gen_next_op_idx;
- tcg_debug_assert(i < OPC_BUF_SIZE);
- s->gen_op_buf[0].prev = i;
- s->gen_next_op_idx = i + 1;
- op = &s->gen_op_buf[i];
-
- /* Set links for sequential allocation during translation. */
- memset(op, 0, offsetof(TCGOp, args));
- op->opc = INDEX_op_call;
- op->prev = i - 1;
- op->next = i + 1;
+ op = tcg_emit_op(INDEX_op_call);
pi = 0;
if (ret != NULL) {
@@ -1442,7 +1430,7 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
} else {
nb_rets = 0;
}
- op->callo = nb_rets;
+ TCGOP_CALLO(op) = nb_rets;
real_args = 0;
for (i = 0; i < nargs; i++) {
@@ -1481,10 +1469,10 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
}
op->args[pi++] = (uintptr_t)func;
op->args[pi++] = flags;
- op->calli = real_args;
+ TCGOP_CALLI(op) = real_args;
/* Make sure the fields didn't overflow. */
- tcg_debug_assert(op->calli == real_args);
+ tcg_debug_assert(TCGOP_CALLI(op) == real_args);
tcg_debug_assert(pi <= ARRAY_SIZE(op->args));
#if defined(__sparc__) && !defined(__arch64__) \
@@ -1622,20 +1610,18 @@ void tcg_dump_ops(TCGContext *s)
{
char buf[128];
TCGOp *op;
- int oi;
- for (oi = s->gen_op_buf[0].next; oi != 0; oi = op->next) {
+ QTAILQ_FOREACH(op, &s->ops, link) {
int i, k, nb_oargs, nb_iargs, nb_cargs;
const TCGOpDef *def;
TCGOpcode c;
int col = 0;
- op = &s->gen_op_buf[oi];
c = op->opc;
def = &tcg_op_defs[c];
if (c == INDEX_op_insn_start) {
- col += qemu_log("%s ----", oi != s->gen_op_buf[0].next ? "\n" : "");
+ col += qemu_log("\n ----");
for (i = 0; i < TARGET_INSN_START_WORDS; ++i) {
target_ulong a;
@@ -1648,8 +1634,8 @@ void tcg_dump_ops(TCGContext *s)
}
} else if (c == INDEX_op_call) {
/* variable number of arguments */
- nb_oargs = op->callo;
- nb_iargs = op->calli;
+ nb_oargs = TCGOP_CALLO(op);
+ nb_iargs = TCGOP_CALLI(op);
nb_cargs = def->nb_cargs;
/* function name, flags, out args */
@@ -1898,65 +1884,51 @@ static void process_op_defs(TCGContext *s)
void tcg_op_remove(TCGContext *s, TCGOp *op)
{
- int next = op->next;
- int prev = op->prev;
-
- /* We should never attempt to remove the list terminator. */
- tcg_debug_assert(op != &s->gen_op_buf[0]);
-
- s->gen_op_buf[next].prev = prev;
- s->gen_op_buf[prev].next = next;
-
- memset(op, 0, sizeof(*op));
+ QTAILQ_REMOVE(&s->ops, op, link);
+ QTAILQ_INSERT_TAIL(&s->free_ops, op, link);
#ifdef CONFIG_PROFILER
atomic_set(&s->prof.del_op_count, s->prof.del_op_count + 1);
#endif
}
-TCGOp *tcg_op_insert_before(TCGContext *s, TCGOp *old_op,
- TCGOpcode opc, int nargs)
+static TCGOp *tcg_op_alloc(TCGOpcode opc)
{
- int oi = s->gen_next_op_idx;
- int prev = old_op->prev;
- int next = old_op - s->gen_op_buf;
- TCGOp *new_op;
+ TCGContext *s = tcg_ctx;
+ TCGOp *op;
- tcg_debug_assert(oi < OPC_BUF_SIZE);
- s->gen_next_op_idx = oi + 1;
+ if (likely(QTAILQ_EMPTY(&s->free_ops))) {
+ op = tcg_malloc(sizeof(TCGOp));
+ } else {
+ op = QTAILQ_FIRST(&s->free_ops);
+ QTAILQ_REMOVE(&s->free_ops, op, link);
+ }
+ memset(op, 0, offsetof(TCGOp, link));
+ op->opc = opc;
- new_op = &s->gen_op_buf[oi];
- *new_op = (TCGOp){
- .opc = opc,
- .prev = prev,
- .next = next
- };
- s->gen_op_buf[prev].next = oi;
- old_op->prev = oi;
+ return op;
+}
+
+TCGOp *tcg_emit_op(TCGOpcode opc)
+{
+ TCGOp *op = tcg_op_alloc(opc);
+ QTAILQ_INSERT_TAIL(&tcg_ctx->ops, op, link);
+ return op;
+}
+TCGOp *tcg_op_insert_before(TCGContext *s, TCGOp *old_op,
+ TCGOpcode opc, int nargs)
+{
+ TCGOp *new_op = tcg_op_alloc(opc);
+ QTAILQ_INSERT_BEFORE(old_op, new_op, link);
return new_op;
}
TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *old_op,
TCGOpcode opc, int nargs)
{
- int oi = s->gen_next_op_idx;
- int prev = old_op - s->gen_op_buf;
- int next = old_op->next;
- TCGOp *new_op;
-
- tcg_debug_assert(oi < OPC_BUF_SIZE);
- s->gen_next_op_idx = oi + 1;
-
- new_op = &s->gen_op_buf[oi];
- *new_op = (TCGOp){
- .opc = opc,
- .prev = prev,
- .next = next
- };
- s->gen_op_buf[next].prev = oi;
- old_op->next = oi;
-
+ TCGOp *new_op = tcg_op_alloc(opc);
+ QTAILQ_INSERT_AFTER(&s->ops, old_op, new_op, link);
return new_op;
}
@@ -2006,30 +1978,26 @@ static void tcg_la_bb_end(TCGContext *s)
static void liveness_pass_1(TCGContext *s)
{
int nb_globals = s->nb_globals;
- int oi, oi_prev;
+ TCGOp *op, *op_prev;
tcg_la_func_end(s);
- for (oi = s->gen_op_buf[0].prev; oi != 0; oi = oi_prev) {
+ QTAILQ_FOREACH_REVERSE_SAFE(op, &s->ops, TCGOpHead, link, op_prev) {
int i, nb_iargs, nb_oargs;
TCGOpcode opc_new, opc_new2;
bool have_opc_new2;
TCGLifeData arg_life = 0;
TCGTemp *arg_ts;
-
- TCGOp * const op = &s->gen_op_buf[oi];
TCGOpcode opc = op->opc;
const TCGOpDef *def = &tcg_op_defs[opc];
- oi_prev = op->prev;
-
switch (opc) {
case INDEX_op_call:
{
int call_flags;
- nb_oargs = op->callo;
- nb_iargs = op->calli;
+ nb_oargs = TCGOP_CALLO(op);
+ nb_iargs = TCGOP_CALLI(op);
call_flags = op->args[nb_oargs + nb_iargs + 1];
/* pure functions can be removed if their result is unused */
@@ -2233,8 +2201,9 @@ static void liveness_pass_1(TCGContext *s)
static bool liveness_pass_2(TCGContext *s)
{
int nb_globals = s->nb_globals;
- int nb_temps, i, oi, oi_next;
+ int nb_temps, i;
bool changes = false;
+ TCGOp *op, *op_next;
/* Create a temporary for each indirect global. */
for (i = 0; i < nb_globals; ++i) {
@@ -2256,19 +2225,16 @@ static bool liveness_pass_2(TCGContext *s)
its->state = TS_DEAD;
}
- for (oi = s->gen_op_buf[0].next; oi != 0; oi = oi_next) {
- TCGOp *op = &s->gen_op_buf[oi];
+ QTAILQ_FOREACH_SAFE(op, &s->ops, link, op_next) {
TCGOpcode opc = op->opc;
const TCGOpDef *def = &tcg_op_defs[opc];
TCGLifeData arg_life = op->life;
int nb_iargs, nb_oargs, call_flags;
TCGTemp *arg_ts, *dir_ts;
- oi_next = op->next;
-
if (opc == INDEX_op_call) {
- nb_oargs = op->callo;
- nb_iargs = op->calli;
+ nb_oargs = TCGOP_CALLO(op);
+ nb_iargs = TCGOP_CALLI(op);
call_flags = op->args[nb_oargs + nb_iargs + 1];
} else {
nb_iargs = def->nb_iargs;
@@ -2949,8 +2915,8 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
static void tcg_reg_alloc_call(TCGContext *s, TCGOp *op)
{
- const int nb_oargs = op->callo;
- const int nb_iargs = op->calli;
+ const int nb_oargs = TCGOP_CALLO(op);
+ const int nb_iargs = TCGOP_CALLI(op);
const TCGLifeData arg_life = op->life;
int flags, nb_regs, i;
TCGReg reg;
@@ -3168,13 +3134,16 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
#ifdef CONFIG_PROFILER
TCGProfile *prof = &s->prof;
#endif
- int i, oi, oi_next, num_insns;
+ int i, num_insns;
+ TCGOp *op;
#ifdef CONFIG_PROFILER
{
int n;
- n = s->gen_op_buf[0].prev + 1;
+ QTAILQ_FOREACH(op, &s->ops, link) {
+ n++;
+ }
atomic_set(&prof->op_count, prof->op_count + n);
if (n > prof->op_count_max) {
atomic_set(&prof->op_count_max, n);
@@ -3260,11 +3229,9 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
#endif
num_insns = -1;
- for (oi = s->gen_op_buf[0].next; oi != 0; oi = oi_next) {
- TCGOp * const op = &s->gen_op_buf[oi];
+ QTAILQ_FOREACH(op, &s->ops, link) {
TCGOpcode opc = op->opc;
- oi_next = op->next;
#ifdef CONFIG_PROFILER
atomic_set(&prof->table_op_count[opc], prof->table_op_count[opc] + 1);
#endif
diff --git a/tcg/tcg.h b/tcg/tcg.h
index cb7b329876..2ce497cebf 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -29,6 +29,7 @@
#include "cpu.h"
#include "exec/tb-context.h"
#include "qemu/bitops.h"
+#include "qemu/queue.h"
#include "tcg-mo.h"
#include "tcg-target.h"
@@ -40,7 +41,7 @@
#else
#define MAX_OPC_PARAM_PER_ARG 1
#endif
-#define MAX_OPC_PARAM_IARGS 5
+#define MAX_OPC_PARAM_IARGS 6
#define MAX_OPC_PARAM_OARGS 1
#define MAX_OPC_PARAM_ARGS (MAX_OPC_PARAM_IARGS + MAX_OPC_PARAM_OARGS)
@@ -48,8 +49,6 @@
* and up to 4 + N parameters on 64-bit archs
* (N = number of input arguments + output arguments). */
#define MAX_OPC_PARAM (4 + (MAX_OPC_PARAM_PER_ARG * MAX_OPC_PARAM_ARGS))
-#define OPC_BUF_SIZE 640
-#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
#define CPU_TEMP_BUF_NLONGS 128
@@ -428,15 +427,6 @@ typedef TCGv_ptr TCGv_env;
#error Unhandled TARGET_LONG_BITS value
#endif
-/* See the comment before tcgv_i32_temp. */
-#define TCGV_UNUSED_I32(x) (x = (TCGv_i32)NULL)
-#define TCGV_UNUSED_I64(x) (x = (TCGv_i64)NULL)
-#define TCGV_UNUSED_PTR(x) (x = (TCGv_ptr)NULL)
-
-#define TCGV_IS_UNUSED_I32(x) ((x) == (TCGv_i32)NULL)
-#define TCGV_IS_UNUSED_I64(x) ((x) == (TCGv_i64)NULL)
-#define TCGV_IS_UNUSED_PTR(x) ((x) == (TCGv_ptr)NULL)
-
/* call flags */
/* Helper does not read globals (either directly or through an exception). It
implies TCG_CALL_NO_WRITE_GLOBALS. */
@@ -498,6 +488,12 @@ static inline TCGCond tcg_unsigned_cond(TCGCond c)
return c & 2 ? (TCGCond)(c ^ 6) : c;
}
+/* Create a "signed" version of an "unsigned" comparison. */
+static inline TCGCond tcg_signed_cond(TCGCond c)
+{
+ return c & 4 ? (TCGCond)(c ^ 6) : c;
+}
+
/* Must a comparison be considered unsigned? */
static inline bool is_unsigned_cond(TCGCond c)
{
@@ -576,28 +572,25 @@ typedef uint16_t TCGLifeData;
typedef struct TCGOp {
TCGOpcode opc : 8; /* 8 */
- /* The number of out and in parameter for a call. */
- unsigned calli : 4; /* 12 */
- unsigned callo : 2; /* 14 */
- unsigned : 2; /* 16 */
-
- /* Index of the prev/next op, or 0 for the end of the list. */
- unsigned prev : 16; /* 32 */
- unsigned next : 16; /* 48 */
+ /* Parameters for this opcode. See below. */
+ unsigned param1 : 4; /* 12 */
+ unsigned param2 : 4; /* 16 */
/* Lifetime data of the operands. */
- unsigned life : 16; /* 64 */
+ unsigned life : 16; /* 32 */
+
+ /* Next and previous opcodes. */
+ QTAILQ_ENTRY(TCGOp) link;
/* Arguments for the opcode. */
TCGArg args[MAX_OPC_PARAM];
} TCGOp;
-/* Make sure that we don't expand the structure without noticing. */
-QEMU_BUILD_BUG_ON(sizeof(TCGOp) != 8 + sizeof(TCGArg) * MAX_OPC_PARAM);
+#define TCGOP_CALLI(X) (X)->param1
+#define TCGOP_CALLO(X) (X)->param2
/* Make sure operands fit in the bitfields above. */
QEMU_BUILD_BUG_ON(NB_OPS > (1 << 8));
-QEMU_BUILD_BUG_ON(OPC_BUF_SIZE > (1 << 16));
typedef struct TCGProfile {
int64_t tb_count1;
@@ -651,8 +644,6 @@ struct TCGContext {
int goto_tb_issue_mask;
#endif
- int gen_next_op_idx;
-
/* 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
@@ -683,12 +674,12 @@ struct TCGContext {
TCGTempSet free_temps[TCG_TYPE_COUNT * 2];
TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */
+ QTAILQ_HEAD(TCGOpHead, TCGOp) ops, free_ops;
+
/* Tells which temporary holds a given register.
It does not take into account fixed registers */
TCGTemp *reg_to_temp[TCG_TARGET_NB_REGS];
- TCGOp gen_op_buf[OPC_BUF_SIZE];
-
uint16_t gen_insn_end_off[TCG_MAX_INSNS];
target_ulong gen_insn_data[TCG_MAX_INSNS][TARGET_INSN_START_WORDS];
};
@@ -778,21 +769,21 @@ static inline TCGv_i32 TCGV_HIGH(TCGv_i64 t)
}
#endif
-static inline void tcg_set_insn_param(int op_idx, int arg, TCGArg v)
+static inline void tcg_set_insn_param(TCGOp *op, int arg, TCGArg v)
{
- tcg_ctx->gen_op_buf[op_idx].args[arg] = v;
+ op->args[arg] = v;
}
-/* The number of opcodes emitted so far. */
-static inline int tcg_op_buf_count(void)
+/* The last op that was emitted. */
+static inline TCGOp *tcg_last_op(void)
{
- return tcg_ctx->gen_next_op_idx;
+ return QTAILQ_LAST(&tcg_ctx->ops, TCGOpHead);
}
/* Test for whether to terminate the TB for using too many opcodes. */
static inline bool tcg_op_buf_full(void)
{
- return tcg_op_buf_count() >= OPC_MAX_SIZE;
+ return false;
}
/* pool based memory allocation */
@@ -976,6 +967,7 @@ bool tcg_op_supported(TCGOpcode op);
void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args);
+TCGOp *tcg_emit_op(TCGOpcode opc);
void tcg_op_remove(TCGContext *s, TCGOp *op);
TCGOp *tcg_op_insert_before(TCGContext *s, TCGOp *op, TCGOpcode opc, int narg);
TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *op, TCGOpcode opc, int narg);
diff --git a/tcg/tci.c b/tcg/tci.c
index 63f2cd54ab..33edca1903 100644
--- a/tcg/tci.c
+++ b/tcg/tci.c
@@ -40,7 +40,7 @@
tcg_abort(); \
} while (0)
-#if MAX_OPC_PARAM_IARGS != 5
+#if MAX_OPC_PARAM_IARGS != 6
# error Fix needed, number of supported input arguments changed!
#endif
#if TCG_TARGET_REG_BITS == 32
@@ -48,11 +48,12 @@ typedef uint64_t (*helper_function)(tcg_target_ulong, tcg_target_ulong,
tcg_target_ulong, tcg_target_ulong,
tcg_target_ulong, tcg_target_ulong,
tcg_target_ulong, tcg_target_ulong,
+ tcg_target_ulong, tcg_target_ulong,
tcg_target_ulong, tcg_target_ulong);
#else
typedef uint64_t (*helper_function)(tcg_target_ulong, tcg_target_ulong,
tcg_target_ulong, tcg_target_ulong,
- tcg_target_ulong);
+ tcg_target_ulong, tcg_target_ulong);
#endif
static tcg_target_ulong tci_read_reg(const tcg_target_ulong *regs, TCGReg index)
@@ -520,7 +521,9 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
tci_read_reg(regs, TCG_REG_R7),
tci_read_reg(regs, TCG_REG_R8),
tci_read_reg(regs, TCG_REG_R9),
- tci_read_reg(regs, TCG_REG_R10));
+ tci_read_reg(regs, TCG_REG_R10),
+ tci_read_reg(regs, TCG_REG_R11),
+ tci_read_reg(regs, TCG_REG_R12));
tci_write_reg(regs, TCG_REG_R0, tmp64);
tci_write_reg(regs, TCG_REG_R1, tmp64 >> 32);
#else
@@ -528,7 +531,8 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
tci_read_reg(regs, TCG_REG_R1),
tci_read_reg(regs, TCG_REG_R2),
tci_read_reg(regs, TCG_REG_R3),
- tci_read_reg(regs, TCG_REG_R5));
+ tci_read_reg(regs, TCG_REG_R5),
+ tci_read_reg(regs, TCG_REG_R6));
tci_write_reg(regs, TCG_REG_R0, tmp64);
#endif
break;
diff --git a/tcg/tci/tcg-target.inc.c b/tcg/tci/tcg-target.inc.c
index 913c3802a3..cc949bea85 100644
--- a/tcg/tci/tcg-target.inc.c
+++ b/tcg/tci/tcg-target.inc.c
@@ -292,7 +292,7 @@ static const int tcg_target_reg_alloc_order[] = {
#endif
};
-#if MAX_OPC_PARAM_IARGS != 5
+#if MAX_OPC_PARAM_IARGS != 6
# error Fix needed, number of supported input arguments changed!
#endif
@@ -305,14 +305,16 @@ static const int tcg_target_call_iarg_regs[] = {
TCG_REG_R4,
#endif
TCG_REG_R5,
+ TCG_REG_R6,
#if TCG_TARGET_REG_BITS == 32
/* 32 bit hosts need 2 * MAX_OPC_PARAM_IARGS registers. */
- TCG_REG_R6,
TCG_REG_R7,
#if TCG_TARGET_NB_REGS >= 16
TCG_REG_R8,
TCG_REG_R9,
TCG_REG_R10,
+ TCG_REG_R11,
+ TCG_REG_R12,
#else
# error Too few input registers available
#endif
diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index ad33d96387..00f00f7246 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -18,6 +18,8 @@
#include "standard-headers/linux/virtio_pci.h"
#include "hw/9pfs/9p.h"
+#define QVIRTIO_9P_TIMEOUT_US (10 * 1000 * 1000)
+
static const char mount_tag[] = "qtest";
typedef struct {
@@ -73,6 +75,9 @@ static QVirtIO9P *qvirtio_9p_pci_start(void)
qvirtio_set_driver(v9p->dev);
v9p->vq = qvirtqueue_setup(v9p->dev, v9p->qs->alloc, 0);
+
+ qvirtio_set_driver_ok(v9p->dev);
+
return v9p;
}
@@ -111,6 +116,7 @@ typedef struct {
/* No r_size, it is hardcoded to P9_MAX_SIZE */
size_t t_off;
size_t r_off;
+ uint32_t free_head;
} P9Req;
static void v9fs_memwrite(P9Req *req, const void *addr, size_t len)
@@ -124,11 +130,6 @@ static void v9fs_memskip(P9Req *req, size_t len)
req->r_off += len;
}
-static void v9fs_memrewind(P9Req *req, size_t len)
-{
- req->r_off -= len;
-}
-
static void v9fs_memread(P9Req *req, void *addr, size_t len)
{
memread(req->r_msg + req->r_off, addr, len);
@@ -227,12 +228,12 @@ static P9Req *v9fs_req_init(QVirtIO9P *v9p, uint32_t size, uint8_t id,
static void v9fs_req_send(P9Req *req)
{
QVirtIO9P *v9p = req->v9p;
- uint32_t free_head;
req->r_msg = guest_alloc(v9p->qs->alloc, P9_MAX_SIZE);
- free_head = qvirtqueue_add(v9p->vq, req->t_msg, req->t_size, false, true);
+ req->free_head = qvirtqueue_add(v9p->vq, req->t_msg, req->t_size, false,
+ true);
qvirtqueue_add(v9p->vq, req->r_msg, P9_MAX_SIZE, true, false);
- qvirtqueue_kick(v9p->dev, v9p->vq, free_head);
+ qvirtqueue_kick(v9p->dev, v9p->vq, req->free_head);
req->t_off = 0;
}
@@ -250,19 +251,13 @@ static void v9fs_req_recv(P9Req *req, uint8_t id)
{
QVirtIO9P *v9p = req->v9p;
P9Hdr hdr;
- int i;
- for (i = 0; i < 10; i++) {
- qvirtio_wait_queue_isr(v9p->dev, v9p->vq, 1000 * 1000);
+ qvirtio_wait_used_elem(v9p->dev, v9p->vq, req->free_head,
+ QVIRTIO_9P_TIMEOUT_US);
- v9fs_memread(req, &hdr, 7);
- hdr.size = ldl_le_p(&hdr.size);
- hdr.tag = lduw_le_p(&hdr.tag);
- if (hdr.size >= 7) {
- break;
- }
- v9fs_memrewind(req, 7);
- }
+ v9fs_memread(req, &hdr, 7);
+ hdr.size = ldl_le_p(&hdr.size);
+ hdr.tag = lduw_le_p(&hdr.tag);
g_assert_cmpint(hdr.size, >=, 7);
g_assert_cmpint(hdr.size, <=, P9_MAX_SIZE);