diff options
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; } @@ -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;} @@ -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 @@ -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 @@ -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); @@ -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); |