diff options
66 files changed, 2371 insertions, 1530 deletions
@@ -40,8 +40,8 @@ config-all-devices.mak: $(SUBDIR_DEVICES_MAK) -include config-all-devices.mak -build-all: config-host.h config-all-devices.h - $(call quiet-command, $(MAKE) $(SUBDIR_MAKEFLAGS) $(TOOLS) $(DOCS) recurse-all,) +build-all: config-host.h config-all-devices.h $(DOCS) $(TOOLS) + $(call quiet-command, $(MAKE) $(SUBDIR_MAKEFLAGS) recurse-all,) config-host.h: config-host.h-timestamp config-host.h-timestamp: config-host.mak diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 609eee189..30266786d 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -182,7 +182,6 @@ static int grow_refcount_table(BlockDriverState *bs, int min_size) qcow2_free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t)); return 0; fail: - qcow2_free_clusters(bs, table_offset, new_table_size2); qemu_free(new_table); return -EIO; } diff --git a/block/raw-posix.c b/block/raw-posix.c index 46e4aa965..121412bc8 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -175,6 +175,10 @@ static int raw_open_common(BlockDriverState *bs, const char *filename, #ifdef CONFIG_LINUX_AIO if ((bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) == (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) { + + /* We're falling back to POSIX AIO in some cases */ + paio_init(); + s->aio_ctx = laio_init(); if (!s->aio_ctx) { goto out_free_buf; diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c index 8ac14b795..7374912b1 100644 --- a/bsd-user/elfload.c +++ b/bsd-user/elfload.c @@ -126,6 +126,9 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i regs->rax = 0; regs->rsp = infop->start_stack; regs->rip = infop->entry; + if (bsd_type == target_freebsd) { + regs->rdi = infop->start_stack; + } } #else @@ -249,8 +252,13 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i #else if (personality(infop->personality) == PER_LINUX32) regs->u_regs[14] = infop->start_stack - 16 * 4; - else + else { regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS; + if (bsd_type == target_freebsd) { + regs->u_regs[8] = infop->start_stack; + regs->u_regs[11] = infop->start_stack; + } + } #endif } diff --git a/bsd-user/freebsd/strace.list b/bsd-user/freebsd/strace.list index f4ad052f7..1edf412c8 100644 --- a/bsd-user/freebsd/strace.list +++ b/bsd-user/freebsd/strace.list @@ -39,6 +39,7 @@ { TARGET_FREEBSD_NR_ftruncate, "ftruncate", NULL, NULL, NULL }, { TARGET_FREEBSD_NR_futimes, "futimes", NULL, NULL, NULL }, { TARGET_FREEBSD_NR_getdirentries, "getdirentries", NULL, NULL, NULL }, +{ TARGET_FREEBSD_NR_freebsd6_mmap, "freebsd6_mmap", NULL, NULL, NULL }, { TARGET_FREEBSD_NR_getegid, "getegid", "%s()", NULL, NULL }, { TARGET_FREEBSD_NR_geteuid, "geteuid", "%s()", NULL, NULL }, { TARGET_FREEBSD_NR_getfh, "getfh", NULL, NULL, NULL }, diff --git a/bsd-user/i386/syscall.h b/bsd-user/i386/syscall.h index cf53fba45..9b34c61bb 100644 --- a/bsd-user/i386/syscall.h +++ b/bsd-user/i386/syscall.h @@ -143,5 +143,19 @@ struct target_vm86plus_struct { struct target_vm86plus_info_struct vm86plus; }; +/* FreeBSD sysarch(2) */ +#define TARGET_FREEBSD_I386_GET_LDT 0 +#define TARGET_FREEBSD_I386_SET_LDT 1 + /* I386_IOPL */ +#define TARGET_FREEBSD_I386_GET_IOPERM 3 +#define TARGET_FREEBSD_I386_SET_IOPERM 4 + /* xxxxx */ +#define TARGET_FREEBSD_I386_VM86 6 +#define TARGET_FREEBSD_I386_GET_FSBASE 7 +#define TARGET_FREEBSD_I386_SET_FSBASE 8 +#define TARGET_FREEBSD_I386_GET_GSBASE 9 +#define TARGET_FREEBSD_I386_SET_GSBASE 10 + + #define UNAME_MACHINE "i386" diff --git a/bsd-user/main.c b/bsd-user/main.c index 1bba2b505..19b7f3a1f 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -46,6 +46,7 @@ int have_guest_base; static const char *interp_prefix = CONFIG_QEMU_PREFIX; const char *qemu_uname_release = CONFIG_UNAME_RELEASE; extern char **environ; +enum BSDType bsd_type; /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so we allocate a bigger stack. Need a better solution, for example @@ -168,7 +169,7 @@ static void set_idt(int n, unsigned int dpl) } #endif -void cpu_loop(CPUX86State *env, enum BSDType bsd_type) +void cpu_loop(CPUX86State *env) { int trapnr; abi_ulong pc; @@ -179,27 +180,90 @@ void cpu_loop(CPUX86State *env, enum BSDType bsd_type) switch(trapnr) { case 0x80: /* syscall from int $0x80 */ - env->regs[R_EAX] = do_openbsd_syscall(env, - env->regs[R_EAX], - env->regs[R_EBX], - env->regs[R_ECX], - env->regs[R_EDX], - env->regs[R_ESI], - env->regs[R_EDI], - env->regs[R_EBP]); + if (bsd_type == target_freebsd) { + abi_ulong params = (abi_ulong) env->regs[R_ESP] + + sizeof(int32_t); + int32_t syscall_nr = env->regs[R_EAX]; + int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8; + + if (syscall_nr == TARGET_FREEBSD_NR_syscall) { + get_user_s32(syscall_nr, params); + params += sizeof(int32_t); + } else if (syscall_nr == TARGET_FREEBSD_NR___syscall) { + get_user_s32(syscall_nr, params); + params += sizeof(int64_t); + } + get_user_s32(arg1, params); + params += sizeof(int32_t); + get_user_s32(arg2, params); + params += sizeof(int32_t); + get_user_s32(arg3, params); + params += sizeof(int32_t); + get_user_s32(arg4, params); + params += sizeof(int32_t); + get_user_s32(arg5, params); + params += sizeof(int32_t); + get_user_s32(arg6, params); + params += sizeof(int32_t); + get_user_s32(arg7, params); + params += sizeof(int32_t); + get_user_s32(arg8, params); + env->regs[R_EAX] = do_freebsd_syscall(env, + syscall_nr, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8); + } else { //if (bsd_type == target_openbsd) + env->regs[R_EAX] = do_openbsd_syscall(env, + env->regs[R_EAX], + env->regs[R_EBX], + env->regs[R_ECX], + env->regs[R_EDX], + env->regs[R_ESI], + env->regs[R_EDI], + env->regs[R_EBP]); + } + if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) { + env->regs[R_EAX] = -env->regs[R_EAX]; + env->eflags |= CC_C; + } else { + env->eflags &= ~CC_C; + } break; #ifndef TARGET_ABI32 case EXCP_SYSCALL: - /* linux syscall from syscall intruction */ - env->regs[R_EAX] = do_openbsd_syscall(env, - env->regs[R_EAX], - env->regs[R_EDI], - env->regs[R_ESI], - env->regs[R_EDX], - env->regs[10], - env->regs[8], - env->regs[9]); + /* syscall from syscall intruction */ + if (bsd_type == target_freebsd) + env->regs[R_EAX] = do_freebsd_syscall(env, + env->regs[R_EAX], + env->regs[R_EDI], + env->regs[R_ESI], + env->regs[R_EDX], + env->regs[R_ECX], + env->regs[8], + env->regs[9], 0, 0); + else { //if (bsd_type == target_openbsd) + env->regs[R_EAX] = do_openbsd_syscall(env, + env->regs[R_EAX], + env->regs[R_EDI], + env->regs[R_ESI], + env->regs[R_EDX], + env->regs[10], + env->regs[8], + env->regs[9]); + } env->eip = env->exception_next_eip; + if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) { + env->regs[R_EAX] = -env->regs[R_EAX]; + env->eflags |= CC_C; + } else { + env->eflags &= ~CC_C; + } break; #endif #if 0 @@ -446,7 +510,7 @@ static void flush_windows(CPUSPARCState *env) #endif } -void cpu_loop(CPUSPARCState *env, enum BSDType bsd_type) +void cpu_loop(CPUSPARCState *env) { int trapnr, ret, syscall_nr; //target_siginfo_t info; @@ -458,6 +522,10 @@ void cpu_loop(CPUSPARCState *env, enum BSDType bsd_type) #ifndef TARGET_SPARC64 case 0x80: #else + /* FreeBSD uses 0x141 for syscalls too */ + case 0x141: + if (bsd_type != target_freebsd) + goto badtrap; case 0x100: #endif syscall_nr = env->gregs[1]; @@ -465,7 +533,7 @@ void cpu_loop(CPUSPARCState *env, enum BSDType bsd_type) ret = do_freebsd_syscall(env, syscall_nr, env->regwptr[0], env->regwptr[1], env->regwptr[2], env->regwptr[3], - env->regwptr[4], env->regwptr[5]); + env->regwptr[4], env->regwptr[5], 0, 0); else if (bsd_type == target_netbsd) ret = do_netbsd_syscall(env, syscall_nr, env->regwptr[0], env->regwptr[1], @@ -482,6 +550,7 @@ void cpu_loop(CPUSPARCState *env, enum BSDType bsd_type) env->regwptr[4], env->regwptr[5]); } if ((unsigned int)ret >= (unsigned int)(-515)) { + ret = -ret; #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) env->xcc |= PSR_CARRY; #else @@ -587,6 +656,9 @@ void cpu_loop(CPUSPARCState *env, enum BSDType bsd_type) } break; default: +#ifdef TARGET_SPARC64 + badtrap: +#endif printf ("Unhandled trap: 0x%x\n", trapnr); cpu_dump_state(env, stderr, fprintf, 0); exit (1); @@ -668,7 +740,7 @@ int main(int argc, char **argv) int gdbstub_port = 0; char **target_environ, **wrk; envlist_t *envlist = NULL; - enum BSDType bsd_type = target_openbsd; + bsd_type = target_openbsd; if (argc <= 1) usage(); @@ -1033,7 +1105,7 @@ int main(int argc, char **argv) gdbserver_start (gdbstub_port); gdb_handlesig(env, 0); } - cpu_loop(env, bsd_type); + cpu_loop(env); /* never exits */ return 0; } diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h index 9f4cd1ba0..554ff8b0e 100644 --- a/bsd-user/qemu.h +++ b/bsd-user/qemu.h @@ -18,6 +18,7 @@ enum BSDType { target_netbsd, target_openbsd, }; +extern enum BSDType bsd_type; #include "syscall_defs.h" #include "syscall.h" @@ -130,7 +131,8 @@ abi_long do_brk(abi_ulong new_brk); void syscall_init(void); abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, - abi_long arg5, abi_long arg6); + abi_long arg5, abi_long arg6, abi_long arg7, + abi_long arg8); abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6); @@ -139,7 +141,7 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg5, abi_long arg6); void gemu_log(const char *fmt, ...) __attribute__((format(printf,1,2))); extern THREAD CPUState *thread_env; -void cpu_loop(CPUState *env, enum BSDType bsd_type); +void cpu_loop(CPUState *env); char *target_strerror(int err); int get_osversion(void); void fork_start(void); diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c index 3cff35765..eb1cdf21c 100644 --- a/bsd-user/syscall.c +++ b/bsd-user/syscall.c @@ -29,6 +29,8 @@ #include <sys/types.h> #include <sys/mman.h> #include <sys/syscall.h> +#include <sys/param.h> +#include <sys/sysctl.h> #include <signal.h> #include <utime.h> @@ -40,20 +42,283 @@ static abi_ulong target_brk; static abi_ulong target_original_brk; -#define get_errno(x) (x) +static inline abi_long get_errno(abi_long ret) +{ + if (ret == -1) + /* XXX need to translate host -> target errnos here */ + return -(errno); + else + return ret; +} + #define target_to_host_bitmask(x, tbl) (x) +static inline int is_error(abi_long ret) +{ + return (abi_ulong)ret >= (abi_ulong)(-4096); +} + void target_set_brk(abi_ulong new_brk) { target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk); } +/* do_obreak() must return target errnos. */ +static abi_long do_obreak(abi_ulong new_brk) +{ + abi_ulong brk_page; + abi_long mapped_addr; + int new_alloc_size; + + if (!new_brk) + return 0; + if (new_brk < target_original_brk) + return -TARGET_EINVAL; + + brk_page = HOST_PAGE_ALIGN(target_brk); + + /* If the new brk is less than this, set it and we're done... */ + if (new_brk < brk_page) { + target_brk = new_brk; + return 0; + } + + /* We need to allocate more memory after the brk... */ + new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1); + mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size, + PROT_READ|PROT_WRITE, + MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0)); + + if (!is_error(mapped_addr)) + target_brk = new_brk; + else + return mapped_addr; + + return 0; +} + +#if defined(TARGET_I386) +static abi_long do_freebsd_sysarch(CPUX86State *env, int op, abi_ulong parms) +{ + abi_long ret = 0; + abi_ulong val; + int idx; + + switch(op) { +#ifdef TARGET_ABI32 + case TARGET_FREEBSD_I386_SET_GSBASE: + case TARGET_FREEBSD_I386_SET_FSBASE: + if (op == TARGET_FREEBSD_I386_SET_GSBASE) +#else + case TARGET_FREEBSD_AMD64_SET_GSBASE: + case TARGET_FREEBSD_AMD64_SET_FSBASE: + if (op == TARGET_FREEBSD_AMD64_SET_GSBASE) +#endif + idx = R_GS; + else + idx = R_FS; + if (get_user(val, parms, abi_ulong)) + return -TARGET_EFAULT; + cpu_x86_load_seg(env, idx, 0); + env->segs[idx].base = val; + break; +#ifdef TARGET_ABI32 + case TARGET_FREEBSD_I386_GET_GSBASE: + case TARGET_FREEBSD_I386_GET_FSBASE: + if (op == TARGET_FREEBSD_I386_GET_GSBASE) +#else + case TARGET_FREEBSD_AMD64_GET_GSBASE: + case TARGET_FREEBSD_AMD64_GET_FSBASE: + if (op == TARGET_FREEBSD_AMD64_GET_GSBASE) +#endif + idx = R_GS; + else + idx = R_FS; + val = env->segs[idx].base; + if (put_user(val, parms, abi_ulong)) + return -TARGET_EFAULT; + break; + /* XXX handle the others... */ + default: + ret = -TARGET_EINVAL; + break; + } + return ret; +} +#endif + +#ifdef TARGET_SPARC +static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms) +{ + /* XXX handle + * TARGET_FREEBSD_SPARC_UTRAP_INSTALL, + * TARGET_FREEBSD_SPARC_SIGTRAMP_INSTALL + */ + return -TARGET_EINVAL; +} +#endif + +#ifdef __FreeBSD__ +/* + * XXX this uses the undocumented oidfmt interface to find the kind of + * a requested sysctl, see /sys/kern/kern_sysctl.c:sysctl_sysctl_oidfmt() + * (this is mostly copied from src/sbin/sysctl/sysctl.c) + */ +static int +oidfmt(int *oid, int len, char *fmt, uint32_t *kind) +{ + int qoid[CTL_MAXNAME+2]; + uint8_t buf[BUFSIZ]; + int i; + size_t j; + + qoid[0] = 0; + qoid[1] = 4; + memcpy(qoid + 2, oid, len * sizeof(int)); + + j = sizeof(buf); + i = sysctl(qoid, len + 2, buf, &j, 0, 0); + if (i) + return i; + + if (kind) + *kind = *(uint32_t *)buf; + + if (fmt) + strcpy(fmt, (char *)(buf + sizeof(uint32_t))); + return (0); +} + +/* + * try and convert sysctl return data for the target. + * XXX doesn't handle CTLTYPE_OPAQUE and CTLTYPE_STRUCT. + */ +static int sysctl_oldcvt(void *holdp, size_t holdlen, uint32_t kind) +{ + switch (kind & CTLTYPE) { + case CTLTYPE_INT: + case CTLTYPE_UINT: + *(uint32_t *)holdp = tswap32(*(uint32_t *)holdp); + break; +#ifdef TARGET_ABI32 + case CTLTYPE_LONG: + case CTLTYPE_ULONG: + *(uint32_t *)holdp = tswap32(*(long *)holdp); + break; +#else + case CTLTYPE_LONG: + *(uint64_t *)holdp = tswap64(*(long *)holdp); + case CTLTYPE_ULONG: + *(uint64_t *)holdp = tswap64(*(unsigned long *)holdp); + break; +#endif + case CTLTYPE_QUAD: + *(uint64_t *)holdp = tswap64(*(uint64_t *)holdp); + break; + case CTLTYPE_STRING: + break; + default: + /* XXX unhandled */ + return -1; + } + return 0; +} + +/* XXX this needs to be emulated on non-FreeBSD hosts... */ +static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong oldp, + abi_ulong oldlenp, abi_ulong newp, abi_ulong newlen) +{ + abi_long ret; + void *hnamep, *holdp, *hnewp = NULL; + size_t holdlen; + abi_ulong oldlen = 0; + int32_t *snamep = qemu_malloc(sizeof(int32_t) * namelen), *p, *q, i; + uint32_t kind = 0; + + if (oldlenp) + get_user_ual(oldlen, oldlenp); + if (!(hnamep = lock_user(VERIFY_READ, namep, namelen, 1))) + return -TARGET_EFAULT; + if (newp && !(hnewp = lock_user(VERIFY_READ, newp, newlen, 1))) + return -TARGET_EFAULT; + if (!(holdp = lock_user(VERIFY_WRITE, oldp, oldlen, 0))) + return -TARGET_EFAULT; + holdlen = oldlen; + for (p = hnamep, q = snamep, i = 0; i < namelen; p++, i++) + *q++ = tswap32(*p); + oidfmt(snamep, namelen, NULL, &kind); + /* XXX swap hnewp */ + ret = get_errno(sysctl(snamep, namelen, holdp, &holdlen, hnewp, newlen)); + if (!ret) + sysctl_oldcvt(holdp, holdlen, kind); + put_user_ual(holdlen, oldlenp); + unlock_user(hnamep, namep, 0); + unlock_user(holdp, oldp, holdlen); + if (hnewp) + unlock_user(hnewp, newp, 0); + qemu_free(snamep); + return ret; +} +#endif + +/* FIXME + * lock_iovec()/unlock_iovec() have a return code of 0 for success where + * other lock functions have a return code of 0 for failure. + */ +static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr, + int count, int copy) +{ + struct target_iovec *target_vec; + abi_ulong base; + int i; + + target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1); + if (!target_vec) + return -TARGET_EFAULT; + for(i = 0;i < count; i++) { + base = tswapl(target_vec[i].iov_base); + vec[i].iov_len = tswapl(target_vec[i].iov_len); + if (vec[i].iov_len != 0) { + vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy); + /* Don't check lock_user return value. We must call writev even + if a element has invalid base address. */ + } else { + /* zero length pointer is ignored */ + vec[i].iov_base = NULL; + } + } + unlock_user (target_vec, target_addr, 0); + return 0; +} + +static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr, + int count, int copy) +{ + struct target_iovec *target_vec; + abi_ulong base; + int i; + + target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1); + if (!target_vec) + return -TARGET_EFAULT; + for(i = 0;i < count; i++) { + if (target_vec[i].iov_base) { + base = tswapl(target_vec[i].iov_base); + unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0); + } + } + unlock_user (target_vec, target_addr, 0); + + return 0; +} + /* do_syscall() should always have a single exit point at the end so that actions, such as logging of syscall results, can be performed. All errnos that do_syscall() returns must be -TARGET_<errcode>. */ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, - abi_long arg5, abi_long arg6) + abi_long arg5, abi_long arg6, abi_long arg7, + abi_long arg8) { abi_long ret; void *p; @@ -86,6 +351,18 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = get_errno(write(arg1, p, arg3)); unlock_user(p, arg2, 0); break; + case TARGET_FREEBSD_NR_writev: + { + int count = arg3; + struct iovec *vec; + + vec = alloca(count * sizeof(struct iovec)); + if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0) + goto efault; + ret = get_errno(writev(arg1, vec, count)); + unlock_iovec(vec, arg2, count, 0); + } + break; case TARGET_FREEBSD_NR_open: if (!(p = lock_user_string(arg1))) goto efault; @@ -103,12 +380,23 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_FREEBSD_NR_mprotect: ret = get_errno(target_mprotect(arg1, arg2, arg3)); break; + case TARGET_FREEBSD_NR_break: + ret = do_obreak(arg1); + break; +#ifdef __FreeBSD__ + case TARGET_FREEBSD_NR___sysctl: + ret = do_freebsd_sysctl(arg1, arg2, arg3, arg4, arg5, arg6); + break; +#endif + case TARGET_FREEBSD_NR_sysarch: + ret = do_freebsd_sysarch(cpu_env, arg1, arg2); + break; case TARGET_FREEBSD_NR_syscall: case TARGET_FREEBSD_NR___syscall: - ret = do_freebsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0); + ret = do_freebsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,arg7,arg8,0); break; default: - ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); + ret = get_errno(syscall(num, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)); break; } fail: diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h index 4a658631b..207ddeecb 100644 --- a/bsd-user/syscall_defs.h +++ b/bsd-user/syscall_defs.h @@ -106,3 +106,9 @@ #include "freebsd/syscall_nr.h" #include "netbsd/syscall_nr.h" #include "openbsd/syscall_nr.h" + +struct target_iovec { + abi_long iov_base; /* Starting address */ + abi_long iov_len; /* Number of bytes */ +}; + diff --git a/bsd-user/x86_64/syscall.h b/bsd-user/x86_64/syscall.h index 2a8d696bf..5f71b7cdc 100644 --- a/bsd-user/x86_64/syscall.h +++ b/bsd-user/x86_64/syscall.h @@ -90,6 +90,24 @@ struct target_msqid64_ds { abi_ulong __unused5; }; +/* FreeBSD sysarch(2) */ +#define TARGET_FREEBSD_I386_GET_LDT 0 +#define TARGET_FREEBSD_I386_SET_LDT 1 + /* I386_IOPL */ +#define TARGET_FREEBSD_I386_GET_IOPERM 3 +#define TARGET_FREEBSD_I386_SET_IOPERM 4 + /* xxxxx */ +#define TARGET_FREEBSD_I386_GET_FSBASE 7 +#define TARGET_FREEBSD_I386_SET_FSBASE 8 +#define TARGET_FREEBSD_I386_GET_GSBASE 9 +#define TARGET_FREEBSD_I386_SET_GSBASE 10 + +#define TARGET_FREEBSD_AMD64_GET_FSBASE 128 +#define TARGET_FREEBSD_AMD64_SET_FSBASE 129 +#define TARGET_FREEBSD_AMD64_GET_GSBASE 130 +#define TARGET_FREEBSD_AMD64_SET_GSBASE 131 + + #define UNAME_MACHINE "x86_64" #define TARGET_ARCH_SET_GS 0x1001 @@ -1707,6 +1707,36 @@ if compile_prog "" "" ; then eventfd=yes fi +# check for fallocate +fallocate=no +cat > $TMPC << EOF +#include <fcntl.h> + +int main(void) +{ + fallocate(0, 0, 0, 0); + return 0; +} +EOF +if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then + fallocate=yes +fi + +# check for dup3 +dup3=no +cat > $TMPC << EOF +#include <unistd.h> + +int main(void) +{ + dup3(0, 0, 0); + return 0; +} +EOF +if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then + dup3=yes +fi + # Check if tools are available to build documentation. if test "$docs" != "no" ; then if test -x "`which texi2html 2>/dev/null`" -a \ @@ -1805,6 +1835,23 @@ if compile_prog "" "" ; then fi ########################################## +# check if the compiler understands attribute warn_unused_result +# +# This could be smarter, but gcc -Werror does not error out even when warning +# about attribute warn_unused_result + +gcc_attribute_warn_unused_result=no +cat > $TMPC << EOF +#if defined(__GNUC__) && (__GNUC__ < 4) && defined(__GNUC_MINOR__) && (__GNUC__ < 4) +#error gcc 3.3 or older +#endif +int main(void) { return 0;} +EOF +if compile_prog "" ""; then + gcc_attribute_warn_unused_result=yes +fi + +########################################## # check if we have fdatasync fdatasync=no @@ -2106,6 +2153,12 @@ fi if test "$eventfd" = "yes" ; then echo "CONFIG_EVENTFD=y" >> $config_host_mak fi +if test "$fallocate" = "yes" ; then + echo "CONFIG_FALLOCATE=y" >> $config_host_mak +fi +if test "$dup3" = "yes" ; then + echo "CONFIG_DUP3=y" >> $config_host_mak +fi if test "$inotify" = "yes" ; then echo "CONFIG_INOTIFY=y" >> $config_host_mak fi @@ -2153,6 +2206,9 @@ fi if test "$need_offsetof" = "yes" ; then echo "CONFIG_NEED_OFFSETOF=y" >> $config_host_mak fi +if test "$gcc_attribute_warn_unused_result" = "yes" ; then + echo "CONFIG_GCC_ATTRIBUTE_WARN_UNUSED_RESULT=y" >> $config_host_mak +fi if test "$fdatasync" = "yes" ; then echo "CONFIG_FDATASYNC=y" >> $config_host_mak fi diff --git a/cpu-exec.c b/cpu-exec.c index 8550617af..675e4ccbe 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -813,6 +813,20 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, # define TRAP_sig(context) ((context)->uc_mcontext->es.trapno) # define ERROR_sig(context) ((context)->uc_mcontext->es.err) # define MASK_sig(context) ((context)->uc_sigmask) +#elif defined (__NetBSD__) +# include <ucontext.h> + +# define EIP_sig(context) ((context)->uc_mcontext.__gregs[_REG_EIP]) +# define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO]) +# define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR]) +# define MASK_sig(context) ((context)->uc_sigmask) +#elif defined (__FreeBSD__) || defined(__DragonFly__) +# include <ucontext.h> + +# define EIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext.mc_eip)) +# define TRAP_sig(context) ((context)->uc_mcontext.mc_trapno) +# define ERROR_sig(context) ((context)->uc_mcontext.mc_err) +# define MASK_sig(context) ((context)->uc_sigmask) #elif defined(__OpenBSD__) # define EIP_sig(context) ((context)->sc_eip) # define TRAP_sig(context) ((context)->sc_trapno) @@ -829,7 +843,9 @@ int cpu_signal_handler(int host_signum, void *pinfo, void *puc) { siginfo_t *info = pinfo; -#if defined(__OpenBSD__) +#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__) + ucontext_t *uc = puc; +#elif defined(__OpenBSD__) struct sigcontext *uc = puc; #else struct ucontext *uc = puc; @@ -863,6 +879,13 @@ int cpu_signal_handler(int host_signum, void *pinfo, #define TRAP_sig(context) ((context)->sc_trapno) #define ERROR_sig(context) ((context)->sc_err) #define MASK_sig(context) ((context)->sc_mask) +#elif defined (__FreeBSD__) || defined(__DragonFly__) +#include <ucontext.h> + +#define PC_sig(context) (*((unsigned long*)&(context)->uc_mcontext.mc_rip)) +#define TRAP_sig(context) ((context)->uc_mcontext.mc_trapno) +#define ERROR_sig(context) ((context)->uc_mcontext.mc_err) +#define MASK_sig(context) ((context)->uc_sigmask) #else #define PC_sig(context) ((context)->uc_mcontext.gregs[REG_RIP]) #define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO]) @@ -875,7 +898,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, { siginfo_t *info = pinfo; unsigned long pc; -#ifdef __NetBSD__ +#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__) ucontext_t *uc = puc; #elif defined(__OpenBSD__) struct sigcontext *uc = puc; @@ -2448,7 +2448,7 @@ static void gdb_chr_receive(void *opaque, const uint8_t *buf, int size) static void gdb_chr_event(void *opaque, int event) { switch (event) { - case CHR_EVENT_RESET: + case CHR_EVENT_OPENED: vm_stop(EXCP_INTERRUPT); gdb_has_xml = 0; break; diff --git a/gen-icount.h b/gen-icount.h index 01face23b..3268f720a 100644 --- a/gen-icount.h +++ b/gen-icount.h @@ -11,14 +11,7 @@ static inline void gen_icount_start(void) return; icount_label = gen_new_label(); - /* FIXME: This generates lousy code. We can't use tcg_new_temp because - count needs to live over the conditional branch. To workaround this - we allow the target to supply a convenient register temporary. */ -#ifndef ICOUNT_TEMP count = tcg_temp_local_new_i32(); -#else - count = ICOUNT_TEMP; -#endif tcg_gen_ld_i32(count, cpu_env, offsetof(CPUState, icount_decr.u32)); /* This is a horrid hack to allow fixing up the value later. */ icount_arg = gen_opparam_ptr + 1; @@ -26,9 +19,7 @@ static inline void gen_icount_start(void) tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, icount_label); tcg_gen_st16_i32(count, cpu_env, offsetof(CPUState, icount_decr.u16.low)); -#ifndef ICOUNT_TEMP tcg_temp_free_i32(count); -#endif } static void gen_icount_end(TranslationBlock *tb, int num_insns) @@ -475,7 +475,7 @@ static void baum_send_event(CharDriverState *chr, int event) switch (event) { case CHR_EVENT_BREAK: break; - case CHR_EVENT_RESET: + case CHR_EVENT_OPENED: /* Reset state */ baum->in_buf_used = 0; break; diff --git a/hw/cs4231.c b/hw/cs4231.c index 843f86ed6..e161f19e2 100644 --- a/hw/cs4231.c +++ b/hw/cs4231.c @@ -22,7 +22,6 @@ * THE SOFTWARE. */ -#include "sun4m.h" #include "sysbus.h" /* debug CS4231 */ @@ -54,9 +53,9 @@ typedef struct CSState { #define DPRINTF(fmt, ...) #endif -static void cs_reset(void *opaque) +static void cs_reset(DeviceState *d) { - CSState *s = opaque; + CSState *s = container_of(d, CSState, busdev.qdev); memset(s->regs, 0, CS_REGS * 4); memset(s->dregs, 0, CS_DREGS); @@ -118,8 +117,9 @@ static void cs_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) case 2: // Read only break; case 4: - if (val & 1) - cs_reset(s); + if (val & 1) { + cs_reset(&s->busdev.qdev); + } val &= 0x7f; s->regs[saddr] = val; break; @@ -141,31 +141,17 @@ static CPUWriteMemoryFunc * const cs_mem_write[3] = { cs_mem_writel, }; -static void cs_save(QEMUFile *f, void *opaque) -{ - CSState *s = opaque; - unsigned int i; - - for (i = 0; i < CS_REGS; i++) - qemu_put_be32s(f, &s->regs[i]); - - qemu_put_buffer(f, s->dregs, CS_DREGS); -} - -static int cs_load(QEMUFile *f, void *opaque, int version_id) -{ - CSState *s = opaque; - unsigned int i; - - if (version_id > 1) - return -EINVAL; - - for (i = 0; i < CS_REGS; i++) - qemu_get_be32s(f, &s->regs[i]); - - qemu_get_buffer(f, s->dregs, CS_DREGS); - return 0; -} +static const VMStateDescription vmstate_cs4231 = { + .name ="cs4231", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField []) { + VMSTATE_UINT32_ARRAY(regs, CSState, CS_REGS), + VMSTATE_UINT8_ARRAY(dregs, CSState, CS_DREGS), + VMSTATE_END_OF_LIST() + } +}; static int cs4231_init1(SysBusDevice *dev) { @@ -176,9 +162,7 @@ static int cs4231_init1(SysBusDevice *dev) sysbus_init_mmio(dev, CS_SIZE, io); sysbus_init_irq(dev, &s->irq); - register_savevm("cs4231", -1, 1, cs_save, cs_load, s); - qemu_register_reset(cs_reset, s); - cs_reset(s); + cs_reset(&s->busdev.qdev); return 0; } @@ -186,6 +170,8 @@ static SysBusDeviceInfo cs4231_info = { .init = cs4231_init1, .qdev.name = "SUNW,CS4231", .qdev.size = sizeof(CSState), + .qdev.vmsd = &vmstate_cs4231, + .qdev.reset = cs_reset, .qdev.props = (Property[]) { {.name = NULL} } diff --git a/hw/eccmemctl.c b/hw/eccmemctl.c index 12c386b05..2110dc65e 100644 --- a/hw/eccmemctl.c +++ b/hw/eccmemctl.c @@ -22,7 +22,6 @@ * THE SOFTWARE. */ -#include "sun4m.h" #include "sysbus.h" //#define DEBUG_ECC @@ -38,6 +37,10 @@ * MCC (version 0, implementation 0) SS-600MP * EMC (version 0, implementation 1) SS-10 * SMC (version 0, implementation 2) SS-10SX and SS-20 + * + * Chipset docs: + * "Sun-4M System Architecture (revision 2.0) by Chuck Narad", 950-1373-01, + * http://mediacast.sun.com/users/Barton808/media/Sun4M_SystemArchitecture_edited2.pdf */ #define ECC_MCC 0x00000000 @@ -276,9 +279,9 @@ static const VMStateDescription vmstate_ecc = { } }; -static void ecc_reset(void *opaque) +static void ecc_reset(DeviceState *d) { - ECCState *s = opaque; + ECCState *s = container_of(d, ECCState, busdev.qdev); if (s->version == ECC_MCC) s->regs[ECC_MER] &= ECC_MER_REU; @@ -310,9 +313,8 @@ static int ecc_init1(SysBusDevice *dev) ecc_diag_mem_write, s); sysbus_init_mmio(dev, ECC_DIAG_SIZE, ecc_io_memory); } - vmstate_register(-1, &vmstate_ecc, s); - qemu_register_reset(ecc_reset, s); - ecc_reset(s); + ecc_reset(&s->busdev.qdev); + return 0; } @@ -320,6 +322,8 @@ static SysBusDeviceInfo ecc_info = { .init = ecc_init1, .qdev.name = "eccmemctl", .qdev.size = sizeof(ECCState), + .qdev.vmsd = &vmstate_ecc, + .qdev.reset = ecc_reset, .qdev.props = (Property[]) { DEFINE_PROP_HEX32("version", ECCState, version, -1), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/eepro100.c b/hw/eepro100.c index 62207da10..ef7d131e4 100644 --- a/hw/eepro100.c +++ b/hw/eepro100.c @@ -626,26 +626,11 @@ static void dump_statistics(EEPRO100State * s) //~ missing("CU dump statistical counters"); } -static void eepro100_cu_command(EEPRO100State * s, uint8_t val) +static void action_command(EEPRO100State *s) { - eepro100_tx_t tx; - uint32_t cb_address; - switch (val) { - case CU_NOP: - /* No operation. */ - break; - case CU_START: - if (get_cu_state(s) != cu_idle) { - /* Intel documentation says that CU must be idle for the CU - * start command. Intel driver for Linux also starts the CU - * from suspended state. */ - logout("CU state is %u, should be %u\n", get_cu_state(s), cu_idle); - //~ assert(!"wrong CU state"); - } - set_cu_state(s, cu_active); - s->cu_offset = s->pointer; - next_command: - cb_address = s->cu_base + s->cu_offset; + for (;;) { + uint32_t cb_address = s->cu_base + s->cu_offset; + eepro100_tx_t tx; cpu_physical_memory_read(cb_address, (uint8_t *) & tx, sizeof(tx)); uint16_t status = le16_to_cpu(tx.status); uint16_t command = le16_to_cpu(tx.command); @@ -787,17 +772,38 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val) /* CU becomes idle. Terminate command loop. */ set_cu_state(s, cu_idle); eepro100_cna_interrupt(s); + break; } else if (bit_s) { - /* CU becomes suspended. */ + /* CU becomes suspended. Terminate command loop. */ set_cu_state(s, cu_suspended); eepro100_cna_interrupt(s); + break; } else { /* More entries in list. */ TRACE(OTHER, logout("CU list with at least one more entry\n")); - goto next_command; } - TRACE(OTHER, logout("CU list empty\n")); - /* List is empty. Now CU is idle or suspended. */ + } + TRACE(OTHER, logout("CU list empty\n")); + /* List is empty. Now CU is idle or suspended. */ +} + +static void eepro100_cu_command(EEPRO100State * s, uint8_t val) +{ + switch (val) { + case CU_NOP: + /* No operation. */ + break; + case CU_START: + if (get_cu_state(s) != cu_idle) { + /* Intel documentation says that CU must be idle for the CU + * start command. Intel driver for Linux also starts the CU + * from suspended state. */ + logout("CU state is %u, should be %u\n", get_cu_state(s), cu_idle); + //~ assert(!"wrong CU state"); + } + set_cu_state(s, cu_active); + s->cu_offset = s->pointer; + action_command(s); break; case CU_RESUME: if (get_cu_state(s) != cu_suspended) { @@ -810,7 +816,7 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val) if (get_cu_state(s) == cu_suspended) { TRACE(OTHER, logout("CU resuming\n")); set_cu_state(s, cu_active); - goto next_command; + action_command(s); } break; case CU_STATSADDR: @@ -38,6 +38,10 @@ //#define DEBUG_MOUSE /* + * Chipset docs: + * "Z80C30/Z85C30/Z80230/Z85230/Z85233 SCC/ESCC User Manual", + * http://www.zilog.com/docs/serial/scc_escc_um.pdf + * * On Sparc32 this is the serial port, mouse and keyboard part of chip STP2001 * (Slave I/O), also produced as NCR89C105. See * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt @@ -113,6 +117,7 @@ typedef struct ChannelState { int e0_mode, led_mode, caps_lock_mode, num_lock_mode; int disabled; int clock; + uint32_t vmstate_dummy; } ChannelState; struct SerialState { @@ -326,9 +331,10 @@ static void escc_reset_chn(ChannelState *s) clear_queue(s); } -static void escc_reset(void *opaque) +static void escc_reset(DeviceState *d) { - SerialState *s = opaque; + SerialState *s = container_of(d, SerialState, busdev.qdev); + escc_reset_chn(&s->chn[0]); escc_reset_chn(&s->chn[1]); } @@ -547,7 +553,7 @@ static void escc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) escc_reset_chn(&serial->chn[1]); return; case MINTR_RST_ALL: - escc_reset(serial); + escc_reset(&serial->busdev.qdev); return; } break; @@ -666,64 +672,37 @@ static CPUWriteMemoryFunc * const escc_mem_write[3] = { NULL, }; -static void escc_save_chn(QEMUFile *f, ChannelState *s) -{ - uint32_t tmp = 0; - - qemu_put_be32s(f, &tmp); /* unused, was IRQ. */ - qemu_put_be32s(f, &s->reg); - qemu_put_be32s(f, &s->rxint); - qemu_put_be32s(f, &s->txint); - qemu_put_be32s(f, &s->rxint_under_svc); - qemu_put_be32s(f, &s->txint_under_svc); - qemu_put_8s(f, &s->rx); - qemu_put_8s(f, &s->tx); - qemu_put_buffer(f, s->wregs, SERIAL_REGS); - qemu_put_buffer(f, s->rregs, SERIAL_REGS); -} - -static void escc_save(QEMUFile *f, void *opaque) -{ - SerialState *s = opaque; - - escc_save_chn(f, &s->chn[0]); - escc_save_chn(f, &s->chn[1]); -} - -static int escc_load_chn(QEMUFile *f, ChannelState *s, int version_id) -{ - uint32_t tmp; - - if (version_id > 2) - return -EINVAL; - - qemu_get_be32s(f, &tmp); /* unused */ - qemu_get_be32s(f, &s->reg); - qemu_get_be32s(f, &s->rxint); - qemu_get_be32s(f, &s->txint); - if (version_id >= 2) { - qemu_get_be32s(f, &s->rxint_under_svc); - qemu_get_be32s(f, &s->txint_under_svc); +static const VMStateDescription vmstate_escc_chn = { + .name ="escc_chn", + .version_id = 2, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField []) { + VMSTATE_UINT32(vmstate_dummy, ChannelState), + VMSTATE_UINT32(reg, ChannelState), + VMSTATE_UINT32(rxint, ChannelState), + VMSTATE_UINT32(txint, ChannelState), + VMSTATE_UINT32(rxint_under_svc, ChannelState), + VMSTATE_UINT32(txint_under_svc, ChannelState), + VMSTATE_UINT8(rx, ChannelState), + VMSTATE_UINT8(tx, ChannelState), + VMSTATE_BUFFER(wregs, ChannelState), + VMSTATE_BUFFER(rregs, ChannelState), + VMSTATE_END_OF_LIST() } - qemu_get_8s(f, &s->rx); - qemu_get_8s(f, &s->tx); - qemu_get_buffer(f, s->wregs, SERIAL_REGS); - qemu_get_buffer(f, s->rregs, SERIAL_REGS); - return 0; -} - -static int escc_load(QEMUFile *f, void *opaque, int version_id) -{ - SerialState *s = opaque; - int ret; - - ret = escc_load_chn(f, &s->chn[0], version_id); - if (ret != 0) - return ret; - ret = escc_load_chn(f, &s->chn[1], version_id); - return ret; +}; -} +static const VMStateDescription vmstate_escc = { + .name ="escc", + .version_id = 2, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField []) { + VMSTATE_STRUCT_ARRAY(chn, SerialState, 2, 2, vmstate_escc_chn, + ChannelState), + VMSTATE_END_OF_LIST() + } +}; int escc_init(target_phys_addr_t base, qemu_irq irqA, qemu_irq irqB, CharDriverState *chrA, CharDriverState *chrB, @@ -942,9 +921,8 @@ static int escc_init1(SysBusDevice *dev) if (s->chn[1].type == kbd) { qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]); } - register_savevm("escc", -1, 2, escc_save, escc_load, s); - qemu_register_reset(escc_reset, s); - escc_reset(s); + escc_reset(&s->busdev.qdev); + return 0; } @@ -952,6 +930,8 @@ static SysBusDeviceInfo escc_info = { .init = escc_init1, .qdev.name = "escc", .qdev.size = sizeof(SerialState), + .qdev.vmsd = &vmstate_escc, + .qdev.reset = escc_reset, .qdev.props = (Property[]) { DEFINE_PROP_UINT32("frequency", SerialState, frequency, 0), DEFINE_PROP_UINT32("it_shift", SerialState, it_shift, 0), @@ -417,9 +417,9 @@ static void handle_ti(ESPState *s) } } -static void esp_reset(void *opaque) +static void esp_reset(DeviceState *d) { - ESPState *s = opaque; + ESPState *s = container_of(d, ESPState, busdev.qdev); memset(s->rregs, 0, ESP_REGS); memset(s->wregs, 0, ESP_REGS); @@ -526,7 +526,7 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) break; case CMD_RESET: DPRINTF("Chip reset (%2.2x)\n", val); - esp_reset(s); + esp_reset(&s->busdev.qdev); break; case CMD_BUSRESET: DPRINTF("Bus reset (%2.2x)\n", val); @@ -665,10 +665,7 @@ static int esp_init1(SysBusDevice *dev) esp_io_memory = cpu_register_io_memory(esp_mem_read, esp_mem_write, s); sysbus_init_mmio(dev, ESP_REGS << s->it_shift, esp_io_memory); - esp_reset(s); - - vmstate_register(-1, &vmstate_esp, s); - qemu_register_reset(esp_reset, s); + esp_reset(&s->busdev.qdev); qdev_init_gpio_in(&dev->qdev, parent_esp_reset, 1); @@ -677,9 +674,20 @@ static int esp_init1(SysBusDevice *dev) return 0; } +static SysBusDeviceInfo esp_info = { + .init = esp_init1, + .qdev.name = "esp", + .qdev.size = sizeof(ESPState), + .qdev.vmsd = &vmstate_esp, + .qdev.reset = esp_reset, + .qdev.props = (Property[]) { + {.name = NULL} + } +}; + static void esp_register_devices(void) { - sysbus_register_dev("esp", sizeof(ESPState), esp_init1); + sysbus_register_withprop(&esp_info); } device_init(esp_register_devices) @@ -699,9 +699,18 @@ static const VMStateDescription vmstate_fdc = { } }; -static void fdctrl_external_reset(void *opaque) +static void fdctrl_external_reset_sysbus(DeviceState *d) { - fdctrl_t *s = opaque; + fdctrl_sysbus_t *sys = container_of(d, fdctrl_sysbus_t, busdev.qdev); + fdctrl_t *s = &sys->state; + + fdctrl_reset(s, 0); +} + +static void fdctrl_external_reset_isa(DeviceState *d) +{ + fdctrl_isabus_t *isa = container_of(d, fdctrl_isabus_t, busdev.qdev); + fdctrl_t *s = &isa->state; fdctrl_reset(s, 0); } @@ -1923,9 +1932,6 @@ static int fdctrl_init_common(fdctrl_t *fdctrl) DMA_register_channel(fdctrl->dma_chann, &fdctrl_transfer_handler, fdctrl); fdctrl_connect_drives(fdctrl); - fdctrl_external_reset(fdctrl); - vmstate_register(-1, &vmstate_fdc, fdctrl); - qemu_register_reset(fdctrl_external_reset, fdctrl); return 0; } @@ -1936,6 +1942,7 @@ static int isabus_fdc_init1(ISADevice *dev) int iobase = 0x3f0; int isairq = 6; int dma_chann = 2; + int ret; register_ioport_read(iobase + 0x01, 5, 1, &fdctrl_read_port, fdctrl); @@ -1948,13 +1955,18 @@ static int isabus_fdc_init1(ISADevice *dev) isa_init_irq(&isa->busdev, &fdctrl->irq, isairq); fdctrl->dma_chann = dma_chann; - return fdctrl_init_common(fdctrl); + ret = fdctrl_init_common(fdctrl); + fdctrl_external_reset_isa(&isa->busdev.qdev); + + return ret; } static int sysbus_fdc_init1(SysBusDevice *dev) { - fdctrl_t *fdctrl = &(FROM_SYSBUS(fdctrl_sysbus_t, dev)->state); + fdctrl_sysbus_t *sys = DO_UPCAST(fdctrl_sysbus_t, busdev, dev); + fdctrl_t *fdctrl = &sys->state; int io; + int ret; io = cpu_register_io_memory(fdctrl_mem_read, fdctrl_mem_write, fdctrl); sysbus_init_mmio(dev, 0x08, io); @@ -1962,7 +1974,10 @@ static int sysbus_fdc_init1(SysBusDevice *dev) qdev_init_gpio_in(&dev->qdev, fdctrl_handle_tc, 1); fdctrl->dma_chann = -1; - return fdctrl_init_common(fdctrl); + ret = fdctrl_init_common(fdctrl); + fdctrl_external_reset_sysbus(&sys->busdev.qdev); + + return ret; } static int sun4m_fdc_init1(SysBusDevice *dev) @@ -1984,6 +1999,8 @@ static ISADeviceInfo isa_fdc_info = { .init = isabus_fdc_init1, .qdev.name = "isa-fdc", .qdev.size = sizeof(fdctrl_isabus_t), + .qdev.vmsd = &vmstate_fdc, + .qdev.reset = fdctrl_external_reset_isa, .qdev.props = (Property[]) { DEFINE_PROP_DRIVE("driveA", fdctrl_isabus_t, state.drives[0].dinfo), DEFINE_PROP_DRIVE("driveB", fdctrl_isabus_t, state.drives[1].dinfo), @@ -1995,6 +2012,8 @@ static SysBusDeviceInfo sysbus_fdc_info = { .init = sysbus_fdc_init1, .qdev.name = "sysbus-fdc", .qdev.size = sizeof(fdctrl_sysbus_t), + .qdev.vmsd = &vmstate_fdc, + .qdev.reset = fdctrl_external_reset_sysbus, .qdev.props = (Property[]) { DEFINE_PROP_DRIVE("driveA", fdctrl_sysbus_t, state.drives[0].dinfo), DEFINE_PROP_DRIVE("driveB", fdctrl_sysbus_t, state.drives[1].dinfo), @@ -2006,6 +2025,8 @@ static SysBusDeviceInfo sun4m_fdc_info = { .init = sun4m_fdc_init1, .qdev.name = "SUNW,fdtwo", .qdev.size = sizeof(fdctrl_sysbus_t), + .qdev.vmsd = &vmstate_fdc, + .qdev.reset = fdctrl_external_reset_sysbus, .qdev.props = (Property[]) { DEFINE_PROP_DRIVE("drive", fdctrl_sysbus_t, state.drives[0].dinfo), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/iommu.c b/hw/iommu.c index 20da7ab96..e1022f6ec 100644 --- a/hw/iommu.c +++ b/hw/iommu.c @@ -340,9 +340,9 @@ static const VMStateDescription vmstate_iommu = { } }; -static void iommu_reset(void *opaque) +static void iommu_reset(DeviceState *d) { - IOMMUState *s = opaque; + IOMMUState *s = container_of(d, IOMMUState, busdev.qdev); memset(s->regs, 0, IOMMU_NREGS * 4); s->iostart = 0; @@ -363,9 +363,8 @@ static int iommu_init1(SysBusDevice *dev) io = cpu_register_io_memory(iommu_mem_read, iommu_mem_write, s); sysbus_init_mmio(dev, IOMMU_NREGS * sizeof(uint32_t), io); - vmstate_register(-1, &vmstate_iommu, s); - qemu_register_reset(iommu_reset, s); - iommu_reset(s); + iommu_reset(&s->busdev.qdev); + return 0; } @@ -373,6 +372,8 @@ static SysBusDeviceInfo iommu_info = { .init = iommu_init1, .qdev.name = "iommu", .qdev.size = sizeof(IOMMUState), + .qdev.vmsd = &vmstate_iommu, + .qdev.reset = iommu_reset, .qdev.props = (Property[]) { DEFINE_PROP_HEX32("version", IOMMUState, version, 0), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/m48t59.c b/hw/m48t59.c index d5a91aa5d..bb58419d2 100644 --- a/hw/m48t59.c +++ b/hw/m48t59.c @@ -618,10 +618,8 @@ static int m48t59_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static void m48t59_reset(void *opaque) +static void m48t59_reset_common(m48t59_t *NVRAM) { - m48t59_t *NVRAM = opaque; - NVRAM->addr = 0; NVRAM->lock = 0; if (NVRAM->alrm_timer != NULL) @@ -631,6 +629,22 @@ static void m48t59_reset(void *opaque) qemu_del_timer(NVRAM->wd_timer); } +static void m48t59_reset_isa(DeviceState *d) +{ + M48t59ISAState *isa = container_of(d, M48t59ISAState, busdev.qdev); + m48t59_t *NVRAM = &isa->state; + + m48t59_reset_common(NVRAM); +} + +static void m48t59_reset_sysbus(DeviceState *d) +{ + M48t59SysBusState *sys = container_of(d, M48t59SysBusState, busdev.qdev); + m48t59_t *NVRAM = &sys->state; + + m48t59_reset_common(NVRAM); +} + /* Initialisation routine */ m48t59_t *m48t59_init (qemu_irq IRQ, target_phys_addr_t mem_base, uint32_t io_base, uint16_t size, @@ -691,7 +705,6 @@ static void m48t59_init_common(m48t59_t *s) } qemu_get_timedate(&s->alarm, 0); - qemu_register_reset(m48t59_reset, s); register_savevm("m48t59", -1, 1, m48t59_save, m48t59_load, s); } @@ -725,6 +738,7 @@ static ISADeviceInfo m48t59_isa_info = { .init = m48t59_init_isa1, .qdev.name = "m48t59_isa", .qdev.size = sizeof(M48t59ISAState), + .qdev.reset = m48t59_reset_isa, .qdev.no_user = 1, .qdev.props = (Property[]) { DEFINE_PROP_UINT32("size", M48t59ISAState, state.size, -1), @@ -738,6 +752,7 @@ static SysBusDeviceInfo m48t59_info = { .init = m48t59_init1, .qdev.name = "m48t59", .qdev.size = sizeof(M48t59SysBusState), + .qdev.reset = m48t59_reset_sysbus, .qdev.props = (Property[]) { DEFINE_PROP_UINT32("size", M48t59SysBusState, state.size, -1), DEFINE_PROP_UINT32("type", M48t59SysBusState, state.type, -1), diff --git a/hw/ne2000-isa.c b/hw/ne2000-isa.c index e3467316e..abb9b97d5 100644 --- a/hw/ne2000-isa.c +++ b/hw/ne2000-isa.c @@ -38,13 +38,8 @@ typedef struct ISANE2000State { static void isa_ne2000_cleanup(VLANClientState *vc) { NE2000State *s = vc->opaque; - ISANE2000State *isa = container_of(s, ISANE2000State, ne2000); - unregister_savevm("ne2000", s); - - isa_unassign_ioport(isa->iobase, 16); - isa_unassign_ioport(isa->iobase + 0x10, 2); - isa_unassign_ioport(isa->iobase + 0x1f, 1); + s->vc = NULL; } static int isa_ne2000_initfn(ISADevice *dev) @@ -65,13 +60,14 @@ static int isa_ne2000_initfn(ISADevice *dev) isa_init_irq(dev, &s->irq, isa->isairq); - qdev_get_macaddr(&dev->qdev, s->macaddr); + qemu_macaddr_default_if_unset(&s->c.macaddr); ne2000_reset(s); - s->vc = qdev_get_vlan_client(&dev->qdev, + s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, s->c.vlan, s->c.peer, + dev->qdev.info->name, dev->qdev.id, ne2000_can_receive, ne2000_receive, NULL, - isa_ne2000_cleanup, s); - qemu_format_nic_info_str(s->vc, s->macaddr); + NULL, isa_ne2000_cleanup, s); + qemu_format_nic_info_str(s->vc, s->c.macaddr.a); register_savevm("ne2000", -1, 2, ne2000_save, ne2000_load, s); return 0; @@ -84,9 +80,9 @@ void isa_ne2000_init(int base, int irq, NICInfo *nd) qemu_check_nic_model(nd, "ne2k_isa"); dev = isa_create("ne2k_isa"); - dev->qdev.nd = nd; /* hack alert */ qdev_prop_set_uint32(&dev->qdev, "iobase", base); qdev_prop_set_uint32(&dev->qdev, "irq", irq); + qdev_set_nic_properties(&dev->qdev, nd); qdev_init_nofail(&dev->qdev); } @@ -97,6 +93,7 @@ static ISADeviceInfo ne2000_isa_info = { .qdev.props = (Property[]) { DEFINE_PROP_HEX32("iobase", ISANE2000State, iobase, 0x300), DEFINE_PROP_UINT32("irq", ISANE2000State, isairq, 9), + DEFINE_NIC_PROPERTIES(ISANE2000State, ne2000.c), DEFINE_PROP_END_OF_LIST(), }, }; diff --git a/hw/ne2000.c b/hw/ne2000.c index 87f1e59d8..7ce56ff84 100644 --- a/hw/ne2000.c +++ b/hw/ne2000.c @@ -126,7 +126,7 @@ void ne2000_reset(NE2000State *s) int i; s->isr = ENISR_RESET; - memcpy(s->mem, s->macaddr, 6); + memcpy(s->mem, &s->c.macaddr, 6); s->mem[14] = 0x57; s->mem[15] = 0x57; @@ -758,13 +758,13 @@ static int pci_ne2000_init(PCIDevice *pci_dev) PCI_ADDRESS_SPACE_IO, ne2000_map); s = &d->ne2000; s->irq = d->dev.irq[0]; - qdev_get_macaddr(&d->dev.qdev, s->macaddr); + qdev_get_macaddr(&d->dev.qdev, s->c.macaddr.a); ne2000_reset(s); s->vc = qdev_get_vlan_client(&d->dev.qdev, ne2000_can_receive, ne2000_receive, NULL, ne2000_cleanup, s); - qemu_format_nic_info_str(s->vc, s->macaddr); + qemu_format_nic_info_str(s->vc, s->c.macaddr.a); register_savevm("ne2000", -1, 3, pci_ne2000_save, pci_ne2000_load, d); return 0; diff --git a/hw/ne2000.h b/hw/ne2000.h index 92a2ddb41..78422465c 100644 --- a/hw/ne2000.h +++ b/hw/ne2000.h @@ -23,7 +23,7 @@ typedef struct NE2000State { uint8_t mult[8]; /* multicast mask array */ qemu_irq irq; VLANClientState *vc; - uint8_t macaddr[6]; + NICConf c; uint8_t mem[NE2000_MEM_SIZE]; } NE2000State; diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 5c627fae4..2d4eeecbe 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -1,4 +1,5 @@ #include "sysemu.h" +#include "net.h" #include "qdev.h" void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) @@ -193,6 +194,34 @@ PropertyInfo qdev_prop_hex64 = { .print = print_hex64, }; +/* --- string --- */ + +static int parse_string(DeviceState *dev, Property *prop, const char *str) +{ + char **ptr = qdev_get_prop_ptr(dev, prop); + + if (*ptr) + qemu_free(*ptr); + *ptr = qemu_strdup(str); + return 0; +} + +static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len) +{ + char **ptr = qdev_get_prop_ptr(dev, prop); + if (!*ptr) + return snprintf(dest, len, "<null>"); + return snprintf(dest, len, "\"%s\"", *ptr); +} + +PropertyInfo qdev_prop_string = { + .name = "string", + .type = PROP_TYPE_STRING, + .size = sizeof(char*), + .parse = parse_string, + .print = print_string, +}; + /* --- drive --- */ static int parse_drive(DeviceState *dev, Property *prop, const char *str) @@ -250,6 +279,71 @@ PropertyInfo qdev_prop_chr = { .print = print_chr, }; +/* --- netdev device --- */ + +static int parse_netdev(DeviceState *dev, Property *prop, const char *str) +{ + VLANClientState **ptr = qdev_get_prop_ptr(dev, prop); + + *ptr = qemu_find_netdev(str); + if (*ptr == NULL) + return -1; + return 0; +} + +static int print_netdev(DeviceState *dev, Property *prop, char *dest, size_t len) +{ + VLANClientState **ptr = qdev_get_prop_ptr(dev, prop); + + if (*ptr && (*ptr)->name) { + return snprintf(dest, len, "%s", (*ptr)->name); + } else { + return snprintf(dest, len, "<null>"); + } +} + +PropertyInfo qdev_prop_netdev = { + .name = "netdev", + .type = PROP_TYPE_NETDEV, + .size = sizeof(VLANClientState*), + .parse = parse_netdev, + .print = print_netdev, +}; + +/* --- vlan --- */ + +static int parse_vlan(DeviceState *dev, Property *prop, const char *str) +{ + VLANState **ptr = qdev_get_prop_ptr(dev, prop); + int id; + + if (sscanf(str, "%d", &id) != 1) + return -1; + *ptr = qemu_find_vlan(id, 1); + if (*ptr == NULL) + return -1; + return 0; +} + +static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len) +{ + VLANState **ptr = qdev_get_prop_ptr(dev, prop); + + if (*ptr) { + return snprintf(dest, len, "%d", (*ptr)->id); + } else { + return snprintf(dest, len, "<null>"); + } +} + +PropertyInfo qdev_prop_vlan = { + .name = "vlan", + .type = PROP_TYPE_VLAN, + .size = sizeof(VLANClientState*), + .parse = parse_vlan, + .print = print_vlan, +}; + /* --- pointer --- */ static int print_ptr(DeviceState *dev, Property *prop, char *dest, size_t len) @@ -274,7 +368,7 @@ PropertyInfo qdev_prop_ptr = { */ static int parse_mac(DeviceState *dev, Property *prop, const char *str) { - uint8_t *mac = qdev_get_prop_ptr(dev, prop); + MACAddr *mac = qdev_get_prop_ptr(dev, prop); int i, pos; char *p; @@ -283,26 +377,31 @@ static int parse_mac(DeviceState *dev, Property *prop, const char *str) return -1; if (!qemu_isxdigit(str[pos+1])) return -1; - if (i == 5 && str[pos+2] != '\0') - return -1; - if (str[pos+2] != ':' && str[pos+2] != '-') - return -1; - mac[i] = strtol(str+pos, &p, 16); + if (i == 5) { + if (str[pos+2] != '\0') + return -1; + } else { + if (str[pos+2] != ':' && str[pos+2] != '-') + return -1; + } + mac->a[i] = strtol(str+pos, &p, 16); } return 0; } static int print_mac(DeviceState *dev, Property *prop, char *dest, size_t len) { - uint8_t *mac = qdev_get_prop_ptr(dev, prop); + MACAddr *mac = qdev_get_prop_ptr(dev, prop); + return snprintf(dest, len, "%02x:%02x:%02x:%02x:%02x:%02x", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + mac->a[0], mac->a[1], mac->a[2], + mac->a[3], mac->a[4], mac->a[5]); } PropertyInfo qdev_prop_macaddr = { - .name = "mac-addr", + .name = "macaddr", .type = PROP_TYPE_MACADDR, - .size = 6, + .size = sizeof(MACAddr), .parse = parse_mac, .print = print_mac, }; @@ -454,6 +553,21 @@ void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *valu qdev_prop_set(dev, name, &value, PROP_TYPE_CHR); } +void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value) +{ + qdev_prop_set(dev, name, &value, PROP_TYPE_NETDEV); +} + +void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value) +{ + qdev_prop_set(dev, name, &value, PROP_TYPE_VLAN); +} + +void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value) +{ + qdev_prop_set(dev, name, value, PROP_TYPE_MACADDR); +} + void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value) { qdev_prop_set(dev, name, &value, PROP_TYPE_PTR); @@ -383,6 +383,15 @@ void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr) memcpy(macaddr, dev->nd->macaddr, 6); } +void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) +{ + qdev_prop_set_macaddr(dev, "mac", nd->macaddr); + if (nd->vlan) + qdev_prop_set_vlan(dev, "vlan", nd->vlan); + if (nd->netdev) + qdev_prop_set_netdev(dev, "netdev", nd->netdev); +} + static int next_block_unit[IF_COUNT]; /* Get a block device. This should only be used for single-drive devices @@ -79,6 +79,9 @@ enum PropertyType { PROP_TYPE_MACADDR, PROP_TYPE_DRIVE, PROP_TYPE_CHR, + PROP_TYPE_STRING, + PROP_TYPE_NETDEV, + PROP_TYPE_VLAN, PROP_TYPE_PTR, }; @@ -100,7 +103,7 @@ struct CompatProperty { DeviceState *qdev_create(BusState *bus, const char *name); DeviceState *qdev_device_add(QemuOpts *opts); -int qdev_init(DeviceState *dev) __attribute__((warn_unused_result)); +int qdev_init(DeviceState *dev) QEMU_WARN_UNUSED_RESULT; void qdev_init_nofail(DeviceState *dev); int qdev_unplug(DeviceState *dev); void qdev_free(DeviceState *dev); @@ -186,10 +189,13 @@ extern PropertyInfo qdev_prop_int32; extern PropertyInfo qdev_prop_uint64; extern PropertyInfo qdev_prop_hex32; extern PropertyInfo qdev_prop_hex64; +extern PropertyInfo qdev_prop_string; extern PropertyInfo qdev_prop_chr; extern PropertyInfo qdev_prop_ptr; extern PropertyInfo qdev_prop_macaddr; extern PropertyInfo qdev_prop_drive; +extern PropertyInfo qdev_prop_netdev; +extern PropertyInfo qdev_prop_vlan; extern PropertyInfo qdev_prop_pci_devfn; #define DEFINE_PROP(_name, _state, _field, _prop, _type) { \ @@ -227,10 +233,16 @@ extern PropertyInfo qdev_prop_pci_devfn; DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, void*) #define DEFINE_PROP_CHR(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharDriverState*) +#define DEFINE_PROP_STRING(_n, _s, _f) \ + DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*) +#define DEFINE_PROP_NETDEV(_n, _s, _f) \ + DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, VLANClientState*) +#define DEFINE_PROP_VLAN(_n, _s, _f) \ + DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, VLANState*) #define DEFINE_PROP_DRIVE(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_drive, DriveInfo*) #define DEFINE_PROP_MACADDR(_n, _s, _f) \ - DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, uint8_t[6]) + DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr) #define DEFINE_PROP_END_OF_LIST() \ {} @@ -245,7 +257,10 @@ void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value); void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value); void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value); void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value); +void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value); +void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value); void qdev_prop_set_drive(DeviceState *dev, const char *name, DriveInfo *value); +void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value); /* FIXME: Remove opaque pointer properties. */ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value); void qdev_prop_set_defaults(DeviceState *dev, Property *props); @@ -22,9 +22,6 @@ * THE SOFTWARE. */ -#include "hw.h" -#include "sun4m.h" -#include "console.h" #include "sysbus.h" //#define DEBUG_IRQ @@ -96,34 +93,20 @@ static CPUWriteMemoryFunc * const sbi_mem_write[3] = { sbi_mem_writel, }; -static void sbi_save(QEMUFile *f, void *opaque) -{ - SBIState *s = opaque; - unsigned int i; - - for (i = 0; i < MAX_CPUS; i++) { - qemu_put_be32s(f, &s->intreg_pending[i]); - } -} - -static int sbi_load(QEMUFile *f, void *opaque, int version_id) -{ - SBIState *s = opaque; - unsigned int i; - - if (version_id != 1) - return -EINVAL; - - for (i = 0; i < MAX_CPUS; i++) { - qemu_get_be32s(f, &s->intreg_pending[i]); +static const VMStateDescription vmstate_sbi = { + .name ="sbi", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField []) { + VMSTATE_UINT32_ARRAY(intreg_pending, SBIState, MAX_CPUS), + VMSTATE_END_OF_LIST() } +}; - return 0; -} - -static void sbi_reset(void *opaque) +static void sbi_reset(DeviceState *d) { - SBIState *s = opaque; + SBIState *s = container_of(d, SBIState, busdev.qdev); unsigned int i; for (i = 0; i < MAX_CPUS; i++) { @@ -145,9 +128,8 @@ static int sbi_init1(SysBusDevice *dev) sbi_io_memory = cpu_register_io_memory(sbi_mem_read, sbi_mem_write, s); sysbus_init_mmio(dev, SBI_SIZE, sbi_io_memory); - register_savevm("sbi", -1, 1, sbi_save, sbi_load, s); - qemu_register_reset(sbi_reset, s); - sbi_reset(s); + sbi_reset(&s->busdev.qdev); + return 0; } @@ -155,6 +137,8 @@ static SysBusDeviceInfo sbi_info = { .init = sbi_init1, .qdev.name = "sbi", .qdev.size = sizeof(SBIState), + .qdev.vmsd = &vmstate_sbi, + .qdev.reset = sbi_reset, }; static void sbi_register_devices(void) diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c index ab29ee294..9680392c6 100644 --- a/hw/slavio_intctl.c +++ b/hw/slavio_intctl.c @@ -409,9 +409,9 @@ static const VMStateDescription vmstate_intctl = { } }; -static void slavio_intctl_reset(void *opaque) +static void slavio_intctl_reset(DeviceState *d) { - SLAVIO_INTCTLState *s = opaque; + SLAVIO_INTCTLState *s = container_of(d, SLAVIO_INTCTLState, busdev.qdev); int i; for (i = 0; i < MAX_CPUS; i++) { @@ -446,9 +446,9 @@ static int slavio_intctl_init1(SysBusDevice *dev) s->slaves[i].cpu = i; s->slaves[i].master = s; } - vmstate_register(-1, &vmstate_intctl, s); - qemu_register_reset(slavio_intctl_reset, s); - slavio_intctl_reset(s); + + slavio_intctl_reset(&s->busdev.qdev); + return 0; } @@ -456,6 +456,8 @@ static SysBusDeviceInfo slavio_intctl_info = { .init = slavio_intctl_init1, .qdev.name = "slavio_intctl", .qdev.size = sizeof(SLAVIO_INTCTLState), + .qdev.vmsd = &vmstate_intctl, + .qdev.reset = slavio_intctl_reset, }; static void slavio_intctl_register_devices(void) diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c index ca95b1058..f5216b38f 100644 --- a/hw/slavio_misc.c +++ b/hw/slavio_misc.c @@ -22,7 +22,6 @@ * THE SOFTWARE. */ -#include "sun4m.h" #include "sysemu.h" #include "sysbus.h" @@ -88,9 +87,9 @@ static void slavio_misc_update_irq(void *opaque) } } -static void slavio_misc_reset(void *opaque) +static void slavio_misc_reset(DeviceState *d) { - MiscState *s = opaque; + MiscState *s = container_of(d, MiscState, busdev.qdev); // Diagnostic and system control registers not cleared in reset s->config = s->aux1 = s->aux2 = s->mctrl = 0; @@ -477,9 +476,8 @@ static int slavio_misc_init1(SysBusDevice *dev) qdev_init_gpio_in(&dev->qdev, slavio_set_power_fail, 1); - vmstate_register(-1, &vmstate_misc, s); - qemu_register_reset(slavio_misc_reset, s); - slavio_misc_reset(s); + slavio_misc_reset(&s->busdev.qdev); + return 0; } @@ -487,6 +485,8 @@ static SysBusDeviceInfo slavio_misc_info = { .init = slavio_misc_init1, .qdev.name = "slavio_misc", .qdev.size = sizeof(MiscState), + .qdev.vmsd = &vmstate_misc, + .qdev.reset = slavio_misc_reset, }; static SysBusDeviceInfo apc_info = { diff --git a/hw/slavio_timer.c b/hw/slavio_timer.c index b745a4b1a..b2f8aab04 100644 --- a/hw/slavio_timer.c +++ b/hw/slavio_timer.c @@ -362,9 +362,9 @@ static const VMStateDescription vmstate_slavio_timer = { } }; -static void slavio_timer_reset(void *opaque) +static void slavio_timer_reset(DeviceState *d) { - SLAVIO_TIMERState *s = opaque; + SLAVIO_TIMERState *s = container_of(d, SLAVIO_TIMERState, busdev.qdev); unsigned int i; CPUTimerState *curr_timer; @@ -411,9 +411,8 @@ static int slavio_timer_init1(SysBusDevice *dev) sysbus_init_irq(dev, &s->cputimer[i].irq); } - vmstate_register(-1, &vmstate_slavio_timer, s); - qemu_register_reset(slavio_timer_reset, s); - slavio_timer_reset(s); + slavio_timer_reset(&s->busdev.qdev); + return 0; } @@ -421,6 +420,8 @@ static SysBusDeviceInfo slavio_timer_info = { .init = slavio_timer_init1, .qdev.name = "slavio_timer", .qdev.size = sizeof(SLAVIO_TIMERState), + .qdev.vmsd = &vmstate_slavio_timer, + .qdev.reset = slavio_timer_reset, .qdev.props = (Property[]) { DEFINE_PROP_UINT32("num_cpus", SLAVIO_TIMERState, num_cpus, 0), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c index aca37706f..ff2faf963 100644 --- a/hw/sparc32_dma.c +++ b/hw/sparc32_dma.c @@ -214,9 +214,9 @@ static CPUWriteMemoryFunc * const dma_mem_write[3] = { dma_mem_writel, }; -static void dma_reset(void *opaque) +static void dma_reset(DeviceState *d) { - DMAState *s = opaque; + DMAState *s = container_of(d, DMAState, busdev.qdev); memset(s->dmaregs, 0, DMA_SIZE); s->dmaregs[0] = DMA_VER; @@ -243,11 +243,10 @@ static int sparc32_dma_init1(SysBusDevice *dev) dma_io_memory = cpu_register_io_memory(dma_mem_read, dma_mem_write, s); sysbus_init_mmio(dev, DMA_SIZE, dma_io_memory); - vmstate_register(-1, &vmstate_dma, s); - qemu_register_reset(dma_reset, s); - qdev_init_gpio_in(&dev->qdev, dma_set_irq, 1); qdev_init_gpio_out(&dev->qdev, &s->dev_reset, 1); + dma_reset(&s->busdev.qdev); + return 0; } @@ -255,6 +254,8 @@ static SysBusDeviceInfo sparc32_dma_info = { .init = sparc32_dma_init1, .qdev.name = "sparc32_dma", .qdev.size = sizeof(DMAState), + .qdev.vmsd = &vmstate_dma, + .qdev.reset = dma_reset, .qdev.props = (Property[]) { DEFINE_PROP_PTR("iommu_opaque", DMAState, iommu), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/sun4c_intctl.c b/hw/sun4c_intctl.c index c0211370a..dca471fbb 100644 --- a/hw/sun4c_intctl.c +++ b/hw/sun4c_intctl.c @@ -181,9 +181,9 @@ static const VMStateDescription vmstate_sun4c_intctl = { } }; -static void sun4c_intctl_reset(void *opaque) +static void sun4c_intctl_reset(DeviceState *d) { - Sun4c_INTCTLState *s = opaque; + Sun4c_INTCTLState *s = container_of(d, Sun4c_INTCTLState, busdev.qdev); s->reg = 1; s->pending = 0; @@ -203,9 +203,9 @@ static int sun4c_intctl_init1(SysBusDevice *dev) for (i = 0; i < MAX_PILS; i++) { sysbus_init_irq(dev, &s->cpu_irqs[i]); } - vmstate_register(-1, &vmstate_sun4c_intctl, s); - qemu_register_reset(sun4c_intctl_reset, s); - sun4c_intctl_reset(s); + + sun4c_intctl_reset(&s->busdev.qdev); + return 0; } @@ -213,6 +213,8 @@ static SysBusDeviceInfo sun4c_intctl_info = { .init = sun4c_intctl_init1, .qdev.name = "sun4c_intctl", .qdev.size = sizeof(Sun4c_INTCTLState), + .qdev.vmsd = &vmstate_sun4c_intctl, + .qdev.reset = sun4c_intctl_reset, }; static void sun4c_intctl_register_devices(void) diff --git a/hw/sun4u.c b/hw/sun4u.c index 20db986b7..0c7cea67d 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -337,9 +337,6 @@ void cpu_tick_set_limit(void *opaque, uint64_t limit) ptimer_set_limit(opaque, -limit, 0); } -static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc }; -static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 }; - static void ebus_mmio_mapfunc(PCIDevice *pci_dev, int region_num, uint32_t addr, uint32_t size, int type) { @@ -22,7 +22,6 @@ * THE SOFTWARE. */ -#include "sun4m.h" #include "console.h" #include "pixel_ops.h" #include "sysbus.h" diff --git a/hw/usb-serial.c b/hw/usb-serial.c index e2379c4d5..d02f6b286 100644 --- a/hw/usb-serial.c +++ b/hw/usb-serial.c @@ -516,7 +516,7 @@ static void usb_serial_event(void *opaque, int event) break; case CHR_EVENT_FOCUS: break; - case CHR_EVENT_RESET: + case CHR_EVENT_OPENED: usb_serial_reset(s); /* TODO: Reset USB port */ break; diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 62a3f2ac2..682a81398 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -330,11 +330,18 @@ enum ARM_HWCAP_ARM_FPA = 1 << 5, ARM_HWCAP_ARM_VFP = 1 << 6, ARM_HWCAP_ARM_EDSP = 1 << 7, + ARM_HWCAP_ARM_JAVA = 1 << 8, + ARM_HWCAP_ARM_IWMMXT = 1 << 9, + ARM_HWCAP_ARM_THUMBEE = 1 << 10, + ARM_HWCAP_ARM_NEON = 1 << 11, + ARM_HWCAP_ARM_VFPv3 = 1 << 12, + ARM_HWCAP_ARM_VFPv3D16 = 1 << 13, }; #define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF \ | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT \ - | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP) + | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP \ + | ARM_HWCAP_ARM_NEON | ARM_HWCAP_ARM_VFPv3 ) #endif diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 685cc7131..769e1bcb8 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -53,7 +53,10 @@ IOCTL(KIOCSOUND, 0, TYPE_INT) IOCTL(KDMKTONE, 0, TYPE_INT) + IOCTL(KDSETMODE, 0, TYPE_INT) IOCTL(KDGKBTYPE, IOC_R, MK_PTR(TYPE_CHAR)) + IOCTL(KDGKBMODE, IOC_R, MK_PTR(TYPE_INT)) + IOCTL(KDSKBMODE, 0, TYPE_INT) IOCTL(KDGKBENT, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_kbentry))) IOCTL(KDGKBSENT, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_kbsentry))) @@ -314,3 +317,14 @@ IOCTL(MTIOCTOP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_mtop))) IOCTL(MTIOCGET, IOC_R, MK_PTR(MK_STRUCT(STRUCT_mtget))) IOCTL(MTIOCPOS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_mtpos))) + + IOCTL(FBIOGET_FSCREENINFO, IOC_R, MK_PTR(MK_STRUCT(STRUCT_fb_fix_screeninfo))) + IOCTL(FBIOGET_VSCREENINFO, IOC_R, MK_PTR(MK_STRUCT(STRUCT_fb_var_screeninfo))) + IOCTL(FBIOPUT_VSCREENINFO, IOC_W, MK_PTR(MK_STRUCT(STRUCT_fb_var_screeninfo))) + + IOCTL(VT_OPENQRY, IOC_R, MK_PTR(TYPE_INT)) + IOCTL(VT_GETSTATE, IOC_R, MK_PTR(MK_STRUCT(STRUCT_vt_stat))) + IOCTL(VT_ACTIVATE, 0, TYPE_INT) + IOCTL(VT_WAITACTIVE, 0, TYPE_INT) + IOCTL(VT_LOCKSWITCH, 0, TYPE_INT) + IOCTL(VT_UNLOCKSWITCH, 0, TYPE_INT) diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c index 4091bdccc..2d778a2ce 100644 --- a/linux-user/linuxload.c +++ b/linux-user/linuxload.c @@ -96,7 +96,6 @@ static int prepare_binprm(struct linux_binprm *bprm) } } - memset(bprm->buf, 0, sizeof(bprm->buf)); retval = lseek(bprm->fd, 0L, SEEK_SET); if(retval >= 0) { retval = read(bprm->fd, bprm->buf, 128); diff --git a/linux-user/syscall.c b/linux-user/syscall.c index bf06d14fc..0254226a4 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -79,6 +79,8 @@ #include <linux/kd.h> #include <linux/mtio.h> #include <linux/fs.h> +#include <linux/fb.h> +#include <linux/vt.h> #include "linux_loop.h" #include "qemu.h" @@ -4461,12 +4463,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, p3 = lock_user_string(arg3); if (!p || !p2 || !p3) ret = -TARGET_EFAULT; - else + else { /* FIXME - arg5 should be locked, but it isn't clear how to * do that since it's not guaranteed to be a NULL-terminated * string. */ - ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5))); + if ( ! arg5 ) + ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, NULL)); + else + ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5))); + } unlock_user(p, arg1, 0); unlock_user(p2, arg2, 0); unlock_user(p3, arg3, 0); @@ -4746,6 +4752,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_dup2: ret = get_errno(dup2(arg1, arg2)); break; +#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3) + case TARGET_NR_dup3: + ret = get_errno(dup3(arg1, arg2, arg3)); + break; +#endif #ifdef TARGET_NR_getppid /* not on alpha */ case TARGET_NR_getppid: ret = get_errno(getppid()); @@ -5306,7 +5317,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, /* libc does special remapping of the return value of * sys_getpriority() so it's just easiest to call * sys_getpriority() directly rather than through libc. */ - ret = sys_getpriority(arg1, arg2); + ret = get_errno(sys_getpriority(arg1, arg2)); break; case TARGET_NR_setpriority: ret = get_errno(setpriority(arg1, arg2, arg3)); @@ -7013,6 +7024,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #endif #endif /* CONFIG_EVENTFD */ +#if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate) + case TARGET_NR_fallocate: + ret = get_errno(fallocate(arg1, arg2, arg3, arg4)); + break; +#endif default: unimplemented: gemu_log("qemu: Unsupported syscall: %d\n", num); diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index c018165bf..2d45753dd 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -660,6 +660,9 @@ struct target_pollfd { #define TARGET_KIOCSOUND 0x4B2F /* start sound generation (0 for off) */ #define TARGET_KDMKTONE 0x4B30 /* generate tone */ #define TARGET_KDGKBTYPE 0x4b33 +#define TARGET_KDSETMODE 0x4b3a +#define TARGET_KDGKBMODE 0x4b44 +#define TARGET_KDSKBMODE 0x4b45 #define TARGET_KDGKBENT 0x4B46 /* gets one entry in translation table */ #define TARGET_KDGKBSENT 0x4B48 /* gets one function key string entry */ @@ -874,6 +877,19 @@ struct target_pollfd { #define TARGET_LOOP_GET_STATUS64 0x4C05 #define TARGET_LOOP_CHANGE_FD 0x4C06 +/* fb ioctls */ +#define TARGET_FBIOGET_VSCREENINFO 0x4600 +#define TARGET_FBIOPUT_VSCREENINFO 0x4601 +#define TARGET_FBIOGET_FSCREENINFO 0x4602 + +/* vt ioctls */ +#define TARGET_VT_OPENQRY 0x5600 +#define TARGET_VT_GETSTATE 0x5603 +#define TARGET_VT_ACTIVATE 0x5606 +#define TARGET_VT_WAITACTIVE 0x5607 +#define TARGET_VT_LOCKSWITCH 0x560b +#define TARGET_VT_UNLOCKSWITCH 0x560c + /* from asm/termbits.h */ #define TARGET_NCC 8 @@ -1187,8 +1203,8 @@ struct __attribute__((__packed__)) target_stat64 { unsigned long long __pad0; long long st_size; int st_blksize; - long long st_blocks; /* Number 512-byte blocks allocated. */ unsigned int __pad1; + long long st_blocks; /* Number 512-byte blocks allocated. */ int target_st_atime; unsigned int target_st_atime_nsec; int target_st_mtime; diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index d3f3df91a..340dbd367 100644 --- a/linux-user/syscall_types.h +++ b/linux-user/syscall_types.h @@ -114,3 +114,54 @@ STRUCT(mtop, TYPE_SHORT, TYPE_INT) STRUCT(mtget, TYPE_LONG, TYPE_LONG, TYPE_LONG, TYPE_LONG, TYPE_LONG, TYPE_INT, TYPE_INT) STRUCT(mtpos, TYPE_LONG) + +STRUCT(fb_fix_screeninfo, + MK_ARRAY(TYPE_CHAR, 16), /* id */ + TYPE_ULONG, /* smem_start */ + TYPE_INT, /* smem_len */ + TYPE_INT, /* type */ + TYPE_INT, /* type_aux */ + TYPE_INT, /* visual */ + TYPE_SHORT, /* xpanstep */ + TYPE_SHORT, /* ypanstep */ + TYPE_SHORT, /* ywrapstep */ + TYPE_INT, /* line_length */ + TYPE_ULONG, /* mmio_start */ + TYPE_INT, /* mmio_len */ + TYPE_INT, /* accel */ + MK_ARRAY(TYPE_CHAR, 3)) /* reserved */ + +STRUCT(fb_var_screeninfo, + TYPE_INT, /* xres */ + TYPE_INT, /* yres */ + TYPE_INT, /* xres_virtual */ + TYPE_INT, /* yres_virtual */ + TYPE_INT, /* xoffset */ + TYPE_INT, /* yoffset */ + TYPE_INT, /* bits_per_pixel */ + TYPE_INT, /* grayscale */ + MK_ARRAY(TYPE_INT, 3), /* red */ + MK_ARRAY(TYPE_INT, 3), /* green */ + MK_ARRAY(TYPE_INT, 3), /* blue */ + MK_ARRAY(TYPE_INT, 3), /* transp */ + TYPE_INT, /* nonstd */ + TYPE_INT, /* activate */ + TYPE_INT, /* height */ + TYPE_INT, /* width */ + TYPE_INT, /* accel_flags */ + TYPE_INT, /* pixclock */ + TYPE_INT, /* left_margin */ + TYPE_INT, /* right_margin */ + TYPE_INT, /* upper_margin */ + TYPE_INT, /* lower_margin */ + TYPE_INT, /* hsync_len */ + TYPE_INT, /* vsync_len */ + TYPE_INT, /* sync */ + TYPE_INT, /* vmode */ + TYPE_INT, /* rotate */ + MK_ARRAY(TYPE_INT, 5)) /* reserved */ + +STRUCT(vt_stat, + TYPE_SHORT, /* v_active */ + TYPE_SHORT, /* v_signal */ + TYPE_SHORT) /* v_state */ @@ -3502,7 +3502,7 @@ static void monitor_event(void *opaque, int event) mon->mux_out = 1; break; - case CHR_EVENT_RESET: + case CHR_EVENT_OPENED: monitor_printf(mon, "QEMU %s monitor - type 'help' for more " "information\n", QEMU_VERSION); if (!mon->mux_out) { @@ -281,6 +281,21 @@ void qemu_format_nic_info_str(VLANClientState *vc, uint8_t macaddr[6]) macaddr[3], macaddr[4], macaddr[5]); } +void qemu_macaddr_default_if_unset(MACAddr *macaddr) +{ + static int index = 0; + static const MACAddr zero = { .a = { 0,0,0,0,0,0 } }; + + if (memcmp(macaddr, &zero, sizeof(zero)) != 0) + return; + macaddr->a[0] = 0x52; + macaddr->a[1] = 0x54; + macaddr->a[2] = 0x00; + macaddr->a[3] = 0x12; + macaddr->a[4] = 0x34; + macaddr->a[5] = 0x56 + index++; +} + static char *assign_name(VLANClientState *vc1, const char *model) { VLANState *vlan; @@ -2559,7 +2574,7 @@ VLANState *qemu_find_vlan(int id, int allocate) return vlan; } -static VLANClientState *qemu_find_netdev(const char *id) +VLANClientState *qemu_find_netdev(const char *id) { VLANClientState *vc; @@ -7,6 +7,23 @@ #include "qemu-option.h" #include "net-queue.h" +struct MACAddr { + uint8_t a[6]; +}; + +/* qdev nic properties */ + +typedef struct NICConf { + MACAddr macaddr; + VLANState *vlan; + VLANClientState *peer; +} NICConf; + +#define DEFINE_NIC_PROPERTIES(_state, _conf) \ + DEFINE_PROP_MACADDR("mac", _state, _conf.macaddr), \ + DEFINE_PROP_VLAN("vlan", _state, _conf.vlan), \ + DEFINE_PROP_NETDEV("netdev", _state, _conf.peer) + /* VLANs support */ typedef int (NetCanReceive)(VLANClientState *); @@ -46,6 +63,7 @@ struct VLANState { }; VLANState *qemu_find_vlan(int id, int allocate); +VLANClientState *qemu_find_netdev(const char *id); VLANClientState *qemu_new_vlan_client(VLANState *vlan, VLANClientState *peer, const char *model, @@ -69,6 +87,7 @@ ssize_t qemu_send_packet_async(VLANClientState *vc, const uint8_t *buf, void qemu_purge_queued_packets(VLANClientState *vc); void qemu_flush_queued_packets(VLANClientState *vc); void qemu_format_nic_info_str(VLANClientState *vc, uint8_t macaddr[6]); +void qemu_macaddr_default_if_unset(MACAddr *macaddr); int qemu_show_nic_models(const char *arg, const char *const *models); void qemu_check_nic_model(NICInfo *nd, const char *model); int qemu_find_nic_model(NICInfo *nd, const char * const *models, @@ -160,5 +179,6 @@ VLANClientState *qdev_get_vlan_client(DeviceState *dev, NetReceiveIOV *receive_iov, NetCleanup *cleanup, void *opaque); +void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd); #endif diff --git a/pc-bios/optionrom/multiboot.S b/pc-bios/optionrom/multiboot.S index 93beb51b6..e6cbefdc9 100644 --- a/pc-bios/optionrom/multiboot.S +++ b/pc-bios/optionrom/multiboot.S @@ -113,7 +113,10 @@ mmap_loop: /* entry size (mmap struct) & max buffer size (int15) */ movl $20, %ecx /* store entry size */ + /* old as(1) doesn't like this insn so emit the bytes instead: movl %ecx, %es:-4(%edi) + */ + .dc.b 0x26,0x67,0x66,0x89,0x4f,0xfc /* e820 */ movl $0x0000e820, %eax /* 'SMAP' magic */ diff --git a/qemu-char.c b/qemu-char.c index 8084a6785..0fd402c46 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -108,7 +108,6 @@ static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs = QTAILQ_HEAD_INITIALIZER(chardevs); -static int initial_reset_issued; static void qemu_chr_event(CharDriverState *s, int event) { @@ -120,14 +119,19 @@ static void qemu_chr_event(CharDriverState *s, int event) static void qemu_chr_reset_bh(void *opaque) { CharDriverState *s = opaque; - qemu_chr_event(s, CHR_EVENT_RESET); + + if (s->initial_reset_issued) { + qemu_chr_event(s, CHR_EVENT_OPENED); + } else { + s->initial_reset_issued = true; + } qemu_bh_delete(s->bh); s->bh = NULL; } void qemu_chr_reset(CharDriverState *s) { - if (s->bh == NULL && initial_reset_issued) { + if (s->bh == NULL) { s->bh = qemu_bh_new(qemu_chr_reset_bh, s); qemu_bh_schedule(s->bh); } @@ -137,8 +141,6 @@ void qemu_chr_initial_reset(void) { CharDriverState *chr; - initial_reset_issued = 1; - QTAILQ_FOREACH(chr, &chardevs, next) { qemu_chr_reset(chr); } diff --git a/qemu-char.h b/qemu-char.h index c0654bca2..409961d20 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -1,6 +1,7 @@ #ifndef QEMU_CHAR_H #define QEMU_CHAR_H +#include <stdbool.h> #include "qemu-common.h" #include "qemu-queue.h" #include "qemu-option.h" @@ -10,7 +11,7 @@ #define CHR_EVENT_BREAK 0 /* serial break char */ #define CHR_EVENT_FOCUS 1 /* focus to this terminal (modal input needed) */ -#define CHR_EVENT_RESET 2 /* new connection established */ +#define CHR_EVENT_OPENED 2 /* new connection established */ #define CHR_EVENT_MUX_IN 3 /* mux-focus was set to this terminal */ #define CHR_EVENT_MUX_OUT 4 /* mux-focus will move on */ #define CHR_EVENT_CLOSED 5 /* connection closed */ @@ -66,6 +67,7 @@ struct CharDriverState { QEMUBH *bh; char *label; char *filename; + bool initial_reset_issued; QTAILQ_ENTRY(CharDriverState) next; }; diff --git a/qemu-common.h b/qemu-common.h index 996ce571c..9497dc92e 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -3,6 +3,11 @@ #define QEMU_COMMON_H #define QEMU_NORETURN __attribute__ ((__noreturn__)) +#ifdef CONFIG_GCC_ATTRIBUTE_WARN_UNUSED_RESULT +#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#else +#define QEMU_WARN_UNUSED_RESULT +#endif /* Hack around the mess dyngen-exec.h causes: We need QEMU_NORETURN in files that cannot include the following headers without conflicts. This condition has @@ -180,6 +185,7 @@ typedef struct PixelFormat PixelFormat; typedef struct TextConsole TextConsole; typedef TextConsole QEMUConsole; typedef struct CharDriverState CharDriverState; +typedef struct MACAddr MACAddr; typedef struct VLANState VLANState; typedef struct VLANClientState VLANClientState; typedef struct QEMUFile QEMUFile; @@ -96,25 +96,37 @@ static BlockDriverState *bs_snapshots; #define SELF_ANNOUNCE_ROUNDS 5 -#define ETH_P_EXPERIMENTAL 0x01F1 /* just a number */ -//#define ETH_P_EXPERIMENTAL 0x0012 /* make it the size of the packet */ -#define EXPERIMENTAL_MAGIC 0xf1f23f4f -static int announce_self_create(uint8_t *buf, +#ifndef ETH_P_RARP +#define ETH_P_RARP 0x0835 +#endif +#define ARP_HTYPE_ETH 0x0001 +#define ARP_PTYPE_IP 0x0800 +#define ARP_OP_REQUEST_REV 0x3 + +static int announce_self_create(uint8_t *buf, uint8_t *mac_addr) { - uint32_t magic = EXPERIMENTAL_MAGIC; - uint16_t proto = htons(ETH_P_EXPERIMENTAL); + /* Ethernet header. */ + memset(buf, 0xff, 6); /* destination MAC addr */ + memcpy(buf + 6, mac_addr, 6); /* source MAC addr */ + *(uint16_t *)(buf + 12) = htons(ETH_P_RARP); /* ethertype */ - /* FIXME: should we send a different packet (arp/rarp/ping)? */ + /* RARP header. */ + *(uint16_t *)(buf + 14) = htons(ARP_HTYPE_ETH); /* hardware addr space */ + *(uint16_t *)(buf + 16) = htons(ARP_PTYPE_IP); /* protocol addr space */ + *(buf + 18) = 6; /* hardware addr length (ethernet) */ + *(buf + 19) = 4; /* protocol addr length (IPv4) */ + *(uint16_t *)(buf + 20) = htons(ARP_OP_REQUEST_REV); /* opcode */ + memcpy(buf + 22, mac_addr, 6); /* source hw addr */ + memset(buf + 28, 0x00, 4); /* source protocol addr */ + memcpy(buf + 32, mac_addr, 6); /* target hw addr */ + memset(buf + 38, 0x00, 4); /* target protocol addr */ - memset(buf, 0, 64); - memset(buf, 0xff, 6); /* h_dst */ - memcpy(buf + 6, mac_addr, 6); /* h_src */ - memcpy(buf + 12, &proto, 2); /* h_proto */ - memcpy(buf + 14, &magic, 4); /* magic */ + /* Padding to get up to 60 bytes (ethernet min packet size, minus FCS). */ + memset(buf + 42, 0x00, 18); - return 64; /* len */ + return 60; /* len (FCS will be added by hardware) */ } static void qemu_announce_self_once(void *opaque) @@ -122,7 +134,7 @@ static void qemu_announce_self_once(void *opaque) int i, len; VLANState *vlan; VLANClientState *vc; - uint8_t buf[256]; + uint8_t buf[60]; static int count = SELF_ANNOUNCE_ROUNDS; QEMUTimer *timer = *(QEMUTimer **)opaque; @@ -135,8 +147,10 @@ static void qemu_announce_self_once(void *opaque) qemu_send_packet_raw(vc, buf, len); } } - if (count--) { - qemu_mod_timer(timer, qemu_get_clock(rt_clock) + 100); + if (--count) { + /* delay 50ms, 150ms, 250ms, ... */ + qemu_mod_timer(timer, qemu_get_clock(rt_clock) + + 50 + (SELF_ANNOUNCE_ROUNDS - count - 1) * 100); } else { qemu_del_timer(timer); qemu_free_timer(timer); diff --git a/target-arm/exec.h b/target-arm/exec.h index 325c3ee27..e9848e1d8 100644 --- a/target-arm/exec.h +++ b/target-arm/exec.h @@ -20,8 +20,6 @@ #include "dyngen-exec.h" register struct CPUARMState *env asm(AREG0); -register uint32_t T0 asm(AREG1); -register uint32_t T1 asm(AREG2); #define M0 env->iwmmxt.val diff --git a/target-arm/helper.c b/target-arm/helper.c index 701629af3..5e10533f1 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -7,6 +7,7 @@ #include "gdbstub.h" #include "helpers.h" #include "qemu-common.h" +#include "host-utils.h" static uint32_t cortexa8_cp15_c0_c1[8] = { 0x1031, 0x11, 0x400, 0, 0x31100003, 0x20000000, 0x01202000, 0x11 }; @@ -233,7 +234,7 @@ static int vfp_gdb_set_reg(CPUState *env, uint8_t *buf, int reg) switch (reg - nregs) { case 0: env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf); return 4; case 1: env->vfp.xregs[ARM_VFP_FPSCR] = ldl_p(buf); return 4; - case 2: env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf); return 4; + case 2: env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30); return 4; } return 0; } @@ -394,16 +395,15 @@ uint32_t HELPER(uxtb16)(uint32_t x) uint32_t HELPER(clz)(uint32_t x) { - int count; - for (count = 32; x; count--) - x >>= 1; - return count; + return clz32(x); } int32_t HELPER(sdiv)(int32_t num, int32_t den) { if (den == 0) return 0; + if (num == INT_MIN && den == -1) + return INT_MIN; return num / den; } diff --git a/target-arm/helpers.h b/target-arm/helpers.h index 01175e157..4d07e0cea 100644 --- a/target-arm/helpers.h +++ b/target-arm/helpers.h @@ -151,7 +151,6 @@ DEF_HELPER_2(sbc_cc, i32, i32, i32) DEF_HELPER_2(shl, i32, i32, i32) DEF_HELPER_2(shr, i32, i32, i32) DEF_HELPER_2(sar, i32, i32, i32) -DEF_HELPER_2(ror, i32, i32, i32) DEF_HELPER_2(shl_cc, i32, i32, i32) DEF_HELPER_2(shr_cc, i32, i32, i32) DEF_HELPER_2(sar_cc, i32, i32, i32) @@ -338,12 +337,6 @@ DEF_HELPER_2(neon_qneg_s8, i32, env, i32) DEF_HELPER_2(neon_qneg_s16, i32, env, i32) DEF_HELPER_2(neon_qneg_s32, i32, env, i32) -DEF_HELPER_0(neon_trn_u8, void) -DEF_HELPER_0(neon_trn_u16, void) -DEF_HELPER_0(neon_unzip_u8, void) -DEF_HELPER_0(neon_zip_u8, void) -DEF_HELPER_0(neon_zip_u16, void) - DEF_HELPER_2(neon_min_f32, i32, i32, i32) DEF_HELPER_2(neon_max_f32, i32, i32, i32) DEF_HELPER_2(neon_abd_f32, i32, i32, i32) diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c index f32ecd6e2..5e6452b9d 100644 --- a/target-arm/neon_helper.c +++ b/target-arm/neon_helper.c @@ -392,7 +392,8 @@ NEON_VOP(abd_u32, neon_u32, 1) #define NEON_FN(dest, src1, src2) do { \ int8_t tmp; \ tmp = (int8_t)src2; \ - if (tmp >= sizeof(src1) * 8 || tmp <= -sizeof(src1) * 8) { \ + if (tmp >= (ssize_t)sizeof(src1) * 8 || \ + tmp <= -(ssize_t)sizeof(src1) * 8) { \ dest = 0; \ } else if (tmp < 0) { \ dest = src1 >> -tmp; \ @@ -420,9 +421,9 @@ uint64_t HELPER(neon_shl_u64)(uint64_t val, uint64_t shiftop) #define NEON_FN(dest, src1, src2) do { \ int8_t tmp; \ tmp = (int8_t)src2; \ - if (tmp >= sizeof(src1) * 8) { \ + if (tmp >= (ssize_t)sizeof(src1) * 8) { \ dest = 0; \ - } else if (tmp <= -sizeof(src1) * 8) { \ + } else if (tmp <= -(ssize_t)sizeof(src1) * 8) { \ dest = src1 >> (sizeof(src1) * 8 - 1); \ } else if (tmp < 0) { \ dest = src1 >> -tmp; \ @@ -453,11 +454,11 @@ uint64_t HELPER(neon_shl_s64)(uint64_t valop, uint64_t shiftop) #define NEON_FN(dest, src1, src2) do { \ int8_t tmp; \ tmp = (int8_t)src2; \ - if (tmp >= sizeof(src1) * 8) { \ + if (tmp >= (ssize_t)sizeof(src1) * 8) { \ dest = 0; \ - } else if (tmp < -sizeof(src1) * 8) { \ + } else if (tmp < -(ssize_t)sizeof(src1) * 8) { \ dest = src1 >> (sizeof(src1) * 8 - 1); \ - } else if (tmp == -sizeof(src1) * 8) { \ + } else if (tmp == -(ssize_t)sizeof(src1) * 8) { \ dest = src1 >> (tmp - 1); \ dest++; \ dest >>= 1; \ @@ -494,9 +495,10 @@ uint64_t HELPER(neon_rshl_s64)(uint64_t valop, uint64_t shiftop) #define NEON_FN(dest, src1, src2) do { \ int8_t tmp; \ tmp = (int8_t)src2; \ - if (tmp >= sizeof(src1) * 8 || tmp < -sizeof(src1) * 8) { \ + if (tmp >= (ssize_t)sizeof(src1) * 8 || \ + tmp < -(ssize_t)sizeof(src1) * 8) { \ dest = 0; \ - } else if (tmp == -sizeof(src1) * 8) { \ + } else if (tmp == -(ssize_t)sizeof(src1) * 8) { \ dest = src1 >> (tmp - 1); \ } else if (tmp < 0) { \ dest = (src1 + (1 << (-1 - tmp))) >> -tmp; \ @@ -528,14 +530,14 @@ uint64_t HELPER(neon_rshl_u64)(uint64_t val, uint64_t shiftop) #define NEON_FN(dest, src1, src2) do { \ int8_t tmp; \ tmp = (int8_t)src2; \ - if (tmp >= sizeof(src1) * 8) { \ + if (tmp >= (ssize_t)sizeof(src1) * 8) { \ if (src1) { \ SET_QC(); \ dest = ~0; \ } else { \ dest = 0; \ } \ - } else if (tmp <= -sizeof(src1) * 8) { \ + } else if (tmp <= -(ssize_t)sizeof(src1) * 8) { \ dest = 0; \ } else if (tmp < 0) { \ dest = src1 >> -tmp; \ @@ -579,11 +581,11 @@ uint64_t HELPER(neon_qshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop) #define NEON_FN(dest, src1, src2) do { \ int8_t tmp; \ tmp = (int8_t)src2; \ - if (tmp >= sizeof(src1) * 8) { \ + if (tmp >= (ssize_t)sizeof(src1) * 8) { \ if (src1) \ SET_QC(); \ dest = src1 >> 31; \ - } else if (tmp <= -sizeof(src1) * 8) { \ + } else if (tmp <= -(ssize_t)sizeof(src1) * 8) { \ dest = src1 >> 31; \ } else if (tmp < 0) { \ dest = src1 >> -tmp; \ diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index d4ae4ae7e..9b1a0143d 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -379,14 +379,6 @@ uint32_t HELPER(sar)(uint32_t x, uint32_t i) return (int32_t)x >> shift; } -uint32_t HELPER(ror)(uint32_t x, uint32_t i) -{ - int shift = i & 0xff; - if (shift == 0) - return x; - return (x >> shift) | (x << (32 - shift)); -} - uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i) { int shift = i & 0xff; @@ -495,61 +487,3 @@ uint64_t HELPER(neon_sub_saturate_u64)(uint64_t src1, uint64_t src2) } return res; } - -/* These need to return a pair of value, so still use T0/T1. */ -/* Transpose. Argument order is rather strange to avoid special casing - the tranlation code. - On input T0 = rm, T1 = rd. On output T0 = rd, T1 = rm */ -void HELPER(neon_trn_u8)(void) -{ - uint32_t rd; - uint32_t rm; - rd = ((T0 & 0x00ff00ff) << 8) | (T1 & 0x00ff00ff); - rm = ((T1 & 0xff00ff00) >> 8) | (T0 & 0xff00ff00); - T0 = rd; - T1 = rm; -} - -void HELPER(neon_trn_u16)(void) -{ - uint32_t rd; - uint32_t rm; - rd = (T0 << 16) | (T1 & 0xffff); - rm = (T1 >> 16) | (T0 & 0xffff0000); - T0 = rd; - T1 = rm; -} - -/* Worker routines for zip and unzip. */ -void HELPER(neon_unzip_u8)(void) -{ - uint32_t rd; - uint32_t rm; - rd = (T0 & 0xff) | ((T0 >> 8) & 0xff00) - | ((T1 << 16) & 0xff0000) | ((T1 << 8) & 0xff000000); - rm = ((T0 >> 8) & 0xff) | ((T0 >> 16) & 0xff00) - | ((T1 << 8) & 0xff0000) | (T1 & 0xff000000); - T0 = rd; - T1 = rm; -} - -void HELPER(neon_zip_u8)(void) -{ - uint32_t rd; - uint32_t rm; - rd = (T0 & 0xff) | ((T1 << 8) & 0xff00) - | ((T0 << 16) & 0xff0000) | ((T1 << 24) & 0xff000000); - rm = ((T0 >> 16) & 0xff) | ((T1 >> 8) & 0xff00) - | ((T0 >> 8) & 0xff0000) | (T1 & 0xff000000); - T0 = rd; - T1 = rm; -} - -void HELPER(neon_zip_u16)(void) -{ - uint32_t tmp; - - tmp = (T0 & 0xffff) | (T1 << 16); - T1 = (T1 & 0xffff0000) | (T0 >> 16); - T0 = tmp; -} diff --git a/target-arm/translate.c b/target-arm/translate.c index c1d0dcf16..57845662a 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -75,65 +75,49 @@ typedef struct DisasContext { static TCGv_ptr cpu_env; /* We reuse the same 64-bit temporaries for efficiency. */ static TCGv_i64 cpu_V0, cpu_V1, cpu_M0; +static TCGv_i32 cpu_R[16]; /* FIXME: These should be removed. */ -static TCGv cpu_T[2]; static TCGv cpu_F0s, cpu_F1s; static TCGv_i64 cpu_F0d, cpu_F1d; -#define ICOUNT_TEMP cpu_T[0] #include "gen-icount.h" +static const char *regnames[] = + { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" }; + /* initialize TCG globals. */ void arm_translate_init(void) { + int i; + cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); - cpu_T[0] = tcg_global_reg_new_i32(TCG_AREG1, "T0"); - cpu_T[1] = tcg_global_reg_new_i32(TCG_AREG2, "T1"); + for (i = 0; i < 16; i++) { + cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0, + offsetof(CPUState, regs[i]), + regnames[i]); + } #define GEN_HELPER 2 #include "helpers.h" } -/* The code generator doesn't like lots of temporaries, so maintain our own - cache for reuse within a function. */ -#define MAX_TEMPS 8 static int num_temps; -static TCGv temps[MAX_TEMPS]; /* Allocate a temporary variable. */ static TCGv_i32 new_tmp(void) { - TCGv tmp; - if (num_temps == MAX_TEMPS) - abort(); - - if (GET_TCGV_I32(temps[num_temps])) - return temps[num_temps++]; - - tmp = tcg_temp_new_i32(); - temps[num_temps++] = tmp; - return tmp; + num_temps++; + return tcg_temp_new_i32(); } /* Release a temporary variable. */ static void dead_tmp(TCGv tmp) { - int i; + tcg_temp_free(tmp); num_temps--; - i = num_temps; - if (TCGV_EQUAL(temps[i], tmp)) - return; - - /* Shuffle this temp to the last slot. */ - while (!TCGV_EQUAL(temps[i], tmp)) - i--; - while (i < num_temps) { - temps[i] = temps[i + 1]; - i++; - } - temps[i] = tmp; } static inline TCGv load_cpu_offset(int offset) @@ -166,7 +150,7 @@ static void load_reg_var(DisasContext *s, TCGv var, int reg) addr = (long)s->pc + 4; tcg_gen_movi_i32(var, addr); } else { - tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, regs[reg])); + tcg_gen_mov_i32(var, cpu_R[reg]); } } @@ -186,38 +170,10 @@ static void store_reg(DisasContext *s, int reg, TCGv var) tcg_gen_andi_i32(var, var, ~1); s->is_jmp = DISAS_JUMP; } - tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, regs[reg])); + tcg_gen_mov_i32(cpu_R[reg], var); dead_tmp(var); } - -/* Basic operations. */ -#define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1]) -#define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im) -#define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im) - -#define gen_op_addl_T1_im(im) tcg_gen_addi_i32(cpu_T[1], cpu_T[1], im) -#define gen_op_addl_T0_T1() tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1]) -#define gen_op_subl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[0], cpu_T[1]) -#define gen_op_rsbl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[1], cpu_T[0]) - -#define gen_op_addl_T0_T1_cc() gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1]) -#define gen_op_adcl_T0_T1_cc() gen_helper_adc_cc(cpu_T[0], cpu_T[0], cpu_T[1]) -#define gen_op_subl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[0], cpu_T[1]) -#define gen_op_sbcl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[0], cpu_T[1]) -#define gen_op_rsbl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[1], cpu_T[0]) - -#define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1]) -#define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1]) -#define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1]) -#define gen_op_notl_T0() tcg_gen_not_i32(cpu_T[0], cpu_T[0]) -#define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1]) -#define gen_op_logic_T0_cc() gen_logic_CC(cpu_T[0]); -#define gen_op_logic_T1_cc() gen_logic_CC(cpu_T[1]); - -#define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im) -#define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im) - /* Value extensions. */ #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var) #define gen_uxth(var) tcg_gen_ext16u_i32(var, var) @@ -227,9 +183,13 @@ static void store_reg(DisasContext *s, int reg, TCGv var) #define gen_sxtb16(var) gen_helper_sxtb16(var, var) #define gen_uxtb16(var) gen_helper_uxtb16(var, var) -#define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1]) -#define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask)) +static inline void gen_set_cpsr(TCGv var, uint32_t mask) +{ + TCGv tmp_mask = tcg_const_i32(mask); + gen_helper_cpsr_write(var, tmp_mask); + tcg_temp_free_i32(tmp_mask); +} /* Set NZCV flags from the high 4 bits of var. */ #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV) @@ -332,6 +292,7 @@ static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b) tcg_gen_extu_i32_i64(tmp2, b); dead_tmp(b); tcg_gen_mul_i64(tmp1, tmp1, tmp2); + tcg_temp_free_i64(tmp2); return tmp1; } @@ -345,23 +306,10 @@ static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b) tcg_gen_ext_i32_i64(tmp2, b); dead_tmp(b); tcg_gen_mul_i64(tmp1, tmp1, tmp2); + tcg_temp_free_i64(tmp2); return tmp1; } -/* Unsigned 32x32->64 multiply. */ -static void gen_op_mull_T0_T1(void) -{ - TCGv_i64 tmp1 = tcg_temp_new_i64(); - TCGv_i64 tmp2 = tcg_temp_new_i64(); - - tcg_gen_extu_i32_i64(tmp1, cpu_T[0]); - tcg_gen_extu_i32_i64(tmp2, cpu_T[1]); - tcg_gen_mul_i64(tmp1, tmp1, tmp2); - tcg_gen_trunc_i64_i32(cpu_T[0], tmp1); - tcg_gen_shri_i64(tmp1, tmp1, 32); - tcg_gen_trunc_i64_i32(cpu_T[1], tmp1); -} - /* Signed 32x32->64 multiply. */ static void gen_imull(TCGv a, TCGv b) { @@ -371,9 +319,11 @@ static void gen_imull(TCGv a, TCGv b) tcg_gen_ext_i32_i64(tmp1, a); tcg_gen_ext_i32_i64(tmp2, b); tcg_gen_mul_i64(tmp1, tmp1, tmp2); + tcg_temp_free_i64(tmp2); tcg_gen_trunc_i64_i32(a, tmp1); tcg_gen_shri_i64(tmp1, tmp1, 32); tcg_gen_trunc_i64_i32(b, tmp1); + tcg_temp_free_i64(tmp1); } /* Swap low and high halfwords. */ @@ -425,12 +375,12 @@ static inline void gen_logic_CC(TCGv var) } /* T0 += T1 + CF. */ -static void gen_adc_T0_T1(void) +static void gen_adc(TCGv t0, TCGv t1) { TCGv tmp; - gen_op_addl_T0_T1(); + tcg_gen_add_i32(t0, t0, t1); tmp = load_cpu_field(CF); - tcg_gen_add_i32(cpu_T[0], cpu_T[0], tmp); + tcg_gen_add_i32(t0, t0, tmp); dead_tmp(tmp); } @@ -455,42 +405,9 @@ static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1) dead_tmp(tmp); } -#define gen_sbc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[0], cpu_T[1]) -#define gen_rsc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[1], cpu_T[0]) - -/* T0 &= ~T1. Clobbers T1. */ -/* FIXME: Implement bic natively. */ -static inline void tcg_gen_bic_i32(TCGv dest, TCGv t0, TCGv t1) -{ - TCGv tmp = new_tmp(); - tcg_gen_not_i32(tmp, t1); - tcg_gen_and_i32(dest, t0, tmp); - dead_tmp(tmp); -} -static inline void gen_op_bicl_T0_T1(void) -{ - gen_op_notl_T1(); - gen_op_andl_T0_T1(); -} - /* FIXME: Implement this natively. */ #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1) -/* FIXME: Implement this natively. */ -static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i) -{ - TCGv tmp; - - if (i == 0) - return; - - tmp = new_tmp(); - tcg_gen_shri_i32(tmp, t1, i); - tcg_gen_shli_i32(t1, t1, 32 - i); - tcg_gen_or_i32(t0, t1, tmp); - dead_tmp(tmp); -} - static void shifter_out_im(TCGv var, int shift) { TCGv tmp = new_tmp(); @@ -542,7 +459,7 @@ static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags) if (shift != 0) { if (flags) shifter_out_im(var, shift - 1); - tcg_gen_rori_i32(var, var, shift); break; + tcg_gen_rotri_i32(var, var, shift); break; } else { TCGv tmp = load_cpu_field(CF); if (flags) @@ -570,7 +487,8 @@ static inline void gen_arm_shift_reg(TCGv var, int shiftop, case 0: gen_helper_shl(var, var, shift); break; case 1: gen_helper_shr(var, var, shift); break; case 2: gen_helper_sar(var, var, shift); break; - case 3: gen_helper_ror(var, var, shift); break; + case 3: tcg_gen_andi_i32(shift, shift, 0x1f); + tcg_gen_rotr_i32(var, var, shift); break; } } dead_tmp(shift); @@ -595,11 +513,13 @@ static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b) tmp = tcg_temp_new_ptr(); tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE)); PAS_OP(s) + tcg_temp_free_ptr(tmp); break; case 5: tmp = tcg_temp_new_ptr(); tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE)); PAS_OP(u) + tcg_temp_free_ptr(tmp); break; #undef gen_pas_helper #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b) @@ -640,11 +560,13 @@ static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b) tmp = tcg_temp_new_ptr(); tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE)); PAS_OP(s) + tcg_temp_free_ptr(tmp); break; case 4: tmp = tcg_temp_new_ptr(); tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE)); PAS_OP(u) + tcg_temp_free_ptr(tmp); break; #undef gen_pas_helper #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b) @@ -788,27 +710,22 @@ static inline void gen_bx_im(DisasContext *s, uint32_t addr) TCGv tmp; s->is_jmp = DISAS_UPDATE; - tmp = new_tmp(); if (s->thumb != (addr & 1)) { + tmp = new_tmp(); tcg_gen_movi_i32(tmp, addr & 1); tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb)); + dead_tmp(tmp); } - tcg_gen_movi_i32(tmp, addr & ~1); - tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[15])); - dead_tmp(tmp); + tcg_gen_movi_i32(cpu_R[15], addr & ~1); } /* Set PC and Thumb state from var. var is marked as dead. */ static inline void gen_bx(DisasContext *s, TCGv var) { - TCGv tmp; - s->is_jmp = DISAS_UPDATE; - tmp = new_tmp(); - tcg_gen_andi_i32(tmp, var, 1); - store_cpu_field(tmp, thumb); - tcg_gen_andi_i32(var, var, ~1); - store_cpu_field(var, regs[15]); + tcg_gen_andi_i32(cpu_R[15], var, ~1); + tcg_gen_andi_i32(var, var, 1); + store_cpu_field(var, thumb); } /* Variant of store_reg which uses branch&exchange logic when storing @@ -854,6 +771,12 @@ static inline TCGv gen_ld32(TCGv addr, int index) tcg_gen_qemu_ld32u(tmp, addr, index); return tmp; } +static inline TCGv_i64 gen_ld64(TCGv addr, int index) +{ + TCGv_i64 tmp = tcg_temp_new_i64(); + tcg_gen_qemu_ld64(tmp, addr, index); + return tmp; +} static inline void gen_st8(TCGv val, TCGv addr, int index) { tcg_gen_qemu_st8(val, addr, index); @@ -869,60 +792,21 @@ static inline void gen_st32(TCGv val, TCGv addr, int index) tcg_gen_qemu_st32(val, addr, index); dead_tmp(val); } - -static inline void gen_movl_T0_reg(DisasContext *s, int reg) -{ - load_reg_var(s, cpu_T[0], reg); -} - -static inline void gen_movl_T1_reg(DisasContext *s, int reg) +static inline void gen_st64(TCGv_i64 val, TCGv addr, int index) { - load_reg_var(s, cpu_T[1], reg); -} - -static inline void gen_movl_T2_reg(DisasContext *s, int reg) -{ - load_reg_var(s, cpu_T[2], reg); + tcg_gen_qemu_st64(val, addr, index); + tcg_temp_free_i64(val); } static inline void gen_set_pc_im(uint32_t val) { - TCGv tmp = new_tmp(); - tcg_gen_movi_i32(tmp, val); - store_cpu_field(tmp, regs[15]); -} - -static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t) -{ - TCGv tmp; - if (reg == 15) { - tmp = new_tmp(); - tcg_gen_andi_i32(tmp, cpu_T[t], ~1); - } else { - tmp = cpu_T[t]; - } - tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[reg])); - if (reg == 15) { - dead_tmp(tmp); - s->is_jmp = DISAS_JUMP; - } -} - -static inline void gen_movl_reg_T0(DisasContext *s, int reg) -{ - gen_movl_reg_TN(s, reg, 0); -} - -static inline void gen_movl_reg_T1(DisasContext *s, int reg) -{ - gen_movl_reg_TN(s, reg, 1); + tcg_gen_movi_i32(cpu_R[15], val); } /* Force a TB lookup after an instruction that changes the CPU state. */ static inline void gen_lookup_tb(DisasContext *s) { - gen_op_movl_T0_im(s->pc); - gen_movl_reg_T0(s, 15); + tcg_gen_movi_i32(cpu_R[15], s->pc & ~1); s->is_jmp = DISAS_UPDATE; } @@ -1097,10 +981,12 @@ static inline void gen_vfp_tosiz(int dp) #define VFP_GEN_FIX(name) \ static inline void gen_vfp_##name(int dp, int shift) \ { \ + TCGv tmp_shift = tcg_const_i32(shift); \ if (dp) \ - gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\ + gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, cpu_env);\ else \ - gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\ + gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, cpu_env);\ + tcg_temp_free_i32(tmp_shift); \ } VFP_GEN_FIX(tosh) VFP_GEN_FIX(tosl) @@ -1112,20 +998,20 @@ VFP_GEN_FIX(uhto) VFP_GEN_FIX(ulto) #undef VFP_GEN_FIX -static inline void gen_vfp_ld(DisasContext *s, int dp) +static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv addr) { if (dp) - tcg_gen_qemu_ld64(cpu_F0d, cpu_T[1], IS_USER(s)); + tcg_gen_qemu_ld64(cpu_F0d, addr, IS_USER(s)); else - tcg_gen_qemu_ld32u(cpu_F0s, cpu_T[1], IS_USER(s)); + tcg_gen_qemu_ld32u(cpu_F0s, addr, IS_USER(s)); } -static inline void gen_vfp_st(DisasContext *s, int dp) +static inline void gen_vfp_st(DisasContext *s, int dp, TCGv addr) { if (dp) - tcg_gen_qemu_st64(cpu_F0d, cpu_T[1], IS_USER(s)); + tcg_gen_qemu_st64(cpu_F0d, addr, IS_USER(s)); else - tcg_gen_qemu_st32(cpu_F0s, cpu_T[1], IS_USER(s)); + tcg_gen_qemu_st32(cpu_F0s, addr, IS_USER(s)); } static inline long @@ -1152,14 +1038,6 @@ neon_reg_offset (int reg, int n) return vfp_reg_offset(0, sreg); } -/* FIXME: Remove these. */ -#define neon_T0 cpu_T[0] -#define neon_T1 cpu_T[1] -#define NEON_GET_REG(T, reg, n) \ - tcg_gen_ld_i32(neon_##T, cpu_env, neon_reg_offset(reg, n)) -#define NEON_SET_REG(T, reg, n) \ - tcg_gen_st_i32(neon_##T, cpu_env, neon_reg_offset(reg, n)) - static TCGv neon_load_reg(int reg, int pass) { TCGv tmp = new_tmp(); @@ -1224,19 +1102,16 @@ static inline void iwmmxt_store_reg(TCGv_i64 var, int reg) tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg])); } -static inline void gen_op_iwmmxt_movl_wCx_T0(int reg) -{ - tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg])); -} - -static inline void gen_op_iwmmxt_movl_T0_wCx(int reg) +static inline TCGv iwmmxt_load_creg(int reg) { - tcg_gen_ld_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg])); + TCGv var = new_tmp(); + tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg])); + return var; } -static inline void gen_op_iwmmxt_movl_T1_wCx(int reg) +static inline void iwmmxt_store_creg(int reg, TCGv var) { - tcg_gen_ld_i32(cpu_T[1], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg])); + tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg])); } static inline void gen_op_iwmmxt_movq_wRn_M0(int rn) @@ -1349,55 +1224,6 @@ IWMMXT_OP_ENV(packsw) IWMMXT_OP_ENV(packsl) IWMMXT_OP_ENV(packsq) -static inline void gen_op_iwmmxt_muladdsl_M0_T0_T1(void) -{ - gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]); -} - -static inline void gen_op_iwmmxt_muladdsw_M0_T0_T1(void) -{ - gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]); -} - -static inline void gen_op_iwmmxt_muladdswl_M0_T0_T1(void) -{ - gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]); -} - -static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn) -{ - iwmmxt_load_reg(cpu_V1, rn); - gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, cpu_T[0]); -} - -static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift) -{ - TCGv tmp = tcg_const_i32(shift); - gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1], tmp); -} - -static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift) -{ - tcg_gen_shri_i64(cpu_M0, cpu_M0, shift); - tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0); - tcg_gen_ext8s_i32(cpu_T[0], cpu_T[0]); -} - -static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift) -{ - tcg_gen_shri_i64(cpu_M0, cpu_M0, shift); - tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0); - tcg_gen_ext16s_i32(cpu_T[0], cpu_T[0]); -} - -static inline void gen_op_iwmmxt_extru_T0_M0(int shift, uint32_t mask) -{ - tcg_gen_shri_i64(cpu_M0, cpu_M0, shift); - tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0); - if (mask != ~0u) - tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask); -} - static void gen_op_iwmmxt_set_mup(void) { TCGv tmp; @@ -1428,66 +1254,59 @@ static inline void gen_op_iwmmxt_addl_M0_wRn(int rn) tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1); } - -static void gen_iwmmxt_movl_T0_T1_wRn(int rn) -{ - iwmmxt_load_reg(cpu_V0, rn); - tcg_gen_trunc_i64_i32(cpu_T[0], cpu_V0); - tcg_gen_shri_i64(cpu_V0, cpu_V0, 32); - tcg_gen_trunc_i64_i32(cpu_T[1], cpu_V0); -} - -static void gen_iwmmxt_movl_wRn_T0_T1(int rn) -{ - tcg_gen_concat_i32_i64(cpu_V0, cpu_T[0], cpu_T[1]); - iwmmxt_store_reg(cpu_V0, rn); -} - -static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn) +static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest) { int rd; uint32_t offset; + TCGv tmp; rd = (insn >> 16) & 0xf; - gen_movl_T1_reg(s, rd); + tmp = load_reg(s, rd); offset = (insn & 0xff) << ((insn >> 7) & 2); if (insn & (1 << 24)) { /* Pre indexed */ if (insn & (1 << 23)) - gen_op_addl_T1_im(offset); + tcg_gen_addi_i32(tmp, tmp, offset); else - gen_op_addl_T1_im(-offset); - + tcg_gen_addi_i32(tmp, tmp, -offset); + tcg_gen_mov_i32(dest, tmp); if (insn & (1 << 21)) - gen_movl_reg_T1(s, rd); + store_reg(s, rd, tmp); + else + dead_tmp(tmp); } else if (insn & (1 << 21)) { /* Post indexed */ + tcg_gen_mov_i32(dest, tmp); if (insn & (1 << 23)) - gen_op_movl_T0_im(offset); + tcg_gen_addi_i32(tmp, tmp, offset); else - gen_op_movl_T0_im(- offset); - gen_op_addl_T0_T1(); - gen_movl_reg_T0(s, rd); + tcg_gen_addi_i32(tmp, tmp, -offset); + store_reg(s, rd, tmp); } else if (!(insn & (1 << 23))) return 1; return 0; } -static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask) +static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest) { int rd = (insn >> 0) & 0xf; + TCGv tmp; - if (insn & (1 << 8)) - if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) + if (insn & (1 << 8)) { + if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) { return 1; - else - gen_op_iwmmxt_movl_T0_wCx(rd); - else - gen_iwmmxt_movl_T0_T1_wRn(rd); - - gen_op_movl_T1_im(mask); - gen_op_andl_T0_T1(); + } else { + tmp = iwmmxt_load_creg(rd); + } + } else { + tmp = new_tmp(); + iwmmxt_load_reg(cpu_V0, rd); + tcg_gen_trunc_i64_i32(tmp, cpu_V0); + } + tcg_gen_andi_i32(tmp, tmp, mask); + tcg_gen_mov_i32(dest, tmp); + dead_tmp(tmp); return 0; } @@ -1497,7 +1316,8 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) { int rd, wrd; int rdhi, rdlo, rd0, rd1, i; - TCGv tmp; + TCGv addr; + TCGv tmp, tmp2, tmp3; if ((insn & 0x0e000e00) == 0x0c000000) { if ((insn & 0x0fe00ff0) == 0x0c400000) { @@ -1505,41 +1325,43 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) rdlo = (insn >> 12) & 0xf; rdhi = (insn >> 16) & 0xf; if (insn & ARM_CP_RW_BIT) { /* TMRRC */ - gen_iwmmxt_movl_T0_T1_wRn(wrd); - gen_movl_reg_T0(s, rdlo); - gen_movl_reg_T1(s, rdhi); + iwmmxt_load_reg(cpu_V0, wrd); + tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0); + tcg_gen_shri_i64(cpu_V0, cpu_V0, 32); + tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0); } else { /* TMCRR */ - gen_movl_T0_reg(s, rdlo); - gen_movl_T1_reg(s, rdhi); - gen_iwmmxt_movl_wRn_T0_T1(wrd); + tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]); + iwmmxt_store_reg(cpu_V0, wrd); gen_op_iwmmxt_set_mup(); } return 0; } wrd = (insn >> 12) & 0xf; - if (gen_iwmmxt_address(s, insn)) + addr = new_tmp(); + if (gen_iwmmxt_address(s, insn, addr)) { + dead_tmp(addr); return 1; + } if (insn & ARM_CP_RW_BIT) { if ((insn >> 28) == 0xf) { /* WLDRW wCx */ - tmp = gen_ld32(cpu_T[1], IS_USER(s)); - tcg_gen_mov_i32(cpu_T[0], tmp); - dead_tmp(tmp); - gen_op_iwmmxt_movl_wCx_T0(wrd); + tmp = new_tmp(); + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); + iwmmxt_store_creg(wrd, tmp); } else { i = 1; if (insn & (1 << 8)) { if (insn & (1 << 22)) { /* WLDRD */ - tcg_gen_qemu_ld64(cpu_M0, cpu_T[1], IS_USER(s)); + tcg_gen_qemu_ld64(cpu_M0, addr, IS_USER(s)); i = 0; } else { /* WLDRW wRd */ - tmp = gen_ld32(cpu_T[1], IS_USER(s)); + tmp = gen_ld32(addr, IS_USER(s)); } } else { if (insn & (1 << 22)) { /* WLDRH */ - tmp = gen_ld16u(cpu_T[1], IS_USER(s)); + tmp = gen_ld16u(addr, IS_USER(s)); } else { /* WLDRB */ - tmp = gen_ld8u(cpu_T[1], IS_USER(s)); + tmp = gen_ld8u(addr, IS_USER(s)); } } if (i) { @@ -1550,28 +1372,26 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) } } else { if ((insn >> 28) == 0xf) { /* WSTRW wCx */ - gen_op_iwmmxt_movl_T0_wCx(wrd); - tmp = new_tmp(); - tcg_gen_mov_i32(tmp, cpu_T[0]); - gen_st32(tmp, cpu_T[1], IS_USER(s)); + tmp = iwmmxt_load_creg(wrd); + gen_st32(tmp, addr, IS_USER(s)); } else { gen_op_iwmmxt_movq_M0_wRn(wrd); tmp = new_tmp(); if (insn & (1 << 8)) { if (insn & (1 << 22)) { /* WSTRD */ dead_tmp(tmp); - tcg_gen_qemu_st64(cpu_M0, cpu_T[1], IS_USER(s)); + tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s)); } else { /* WSTRW wRd */ tcg_gen_trunc_i64_i32(tmp, cpu_M0); - gen_st32(tmp, cpu_T[1], IS_USER(s)); + gen_st32(tmp, addr, IS_USER(s)); } } else { if (insn & (1 << 22)) { /* WSTRH */ tcg_gen_trunc_i64_i32(tmp, cpu_M0); - gen_st16(tmp, cpu_T[1], IS_USER(s)); + gen_st16(tmp, addr, IS_USER(s)); } else { /* WSTRB */ tcg_gen_trunc_i64_i32(tmp, cpu_M0); - gen_st8(tmp, cpu_T[1], IS_USER(s)); + gen_st8(tmp, addr, IS_USER(s)); } } } @@ -1607,18 +1427,19 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) gen_op_iwmmxt_set_cup(); /* Fall through. */ case ARM_IWMMXT_wCSSF: - gen_op_iwmmxt_movl_T0_wCx(wrd); - gen_movl_T1_reg(s, rd); - gen_op_bicl_T0_T1(); - gen_op_iwmmxt_movl_wCx_T0(wrd); + tmp = iwmmxt_load_creg(wrd); + tmp2 = load_reg(s, rd); + tcg_gen_andc_i32(tmp, tmp, tmp2); + dead_tmp(tmp2); + iwmmxt_store_creg(wrd, tmp); break; case ARM_IWMMXT_wCGR0: case ARM_IWMMXT_wCGR1: case ARM_IWMMXT_wCGR2: case ARM_IWMMXT_wCGR3: gen_op_iwmmxt_set_cup(); - gen_movl_reg_T0(s, rd); - gen_op_iwmmxt_movl_wCx_T0(wrd); + tmp = load_reg(s, rd); + iwmmxt_store_creg(wrd, tmp); break; default: return 1; @@ -1640,8 +1461,8 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) return 1; rd = (insn >> 12) & 0xf; wrd = (insn >> 16) & 0xf; - gen_op_iwmmxt_movl_T0_wCx(wrd); - gen_movl_reg_T0(s, rd); + tmp = iwmmxt_load_creg(wrd); + store_reg(s, rd, tmp); break; case 0x300: /* WANDN */ wrd = (insn >> 12) & 0xf; @@ -1818,131 +1639,145 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) rd0 = (insn >> 16) & 0xf; rd1 = (insn >> 0) & 0xf; gen_op_iwmmxt_movq_M0_wRn(rd0); - gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3)); - gen_op_movl_T1_im(7); - gen_op_andl_T0_T1(); - gen_op_iwmmxt_align_M0_T0_wRn(rd1); + tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3)); + tcg_gen_andi_i32(tmp, tmp, 7); + iwmmxt_load_reg(cpu_V1, rd1); + gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp); + dead_tmp(tmp); gen_op_iwmmxt_movq_wRn_M0(wrd); gen_op_iwmmxt_set_mup(); break; case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */ + if (((insn >> 6) & 3) == 3) + return 1; rd = (insn >> 12) & 0xf; wrd = (insn >> 16) & 0xf; - gen_movl_T0_reg(s, rd); + tmp = load_reg(s, rd); gen_op_iwmmxt_movq_M0_wRn(wrd); switch ((insn >> 6) & 3) { case 0: - gen_op_movl_T1_im(0xff); - gen_op_iwmmxt_insr_M0_T0_T1((insn & 7) << 3); + tmp2 = tcg_const_i32(0xff); + tmp3 = tcg_const_i32((insn & 7) << 3); break; case 1: - gen_op_movl_T1_im(0xffff); - gen_op_iwmmxt_insr_M0_T0_T1((insn & 3) << 4); + tmp2 = tcg_const_i32(0xffff); + tmp3 = tcg_const_i32((insn & 3) << 4); break; case 2: - gen_op_movl_T1_im(0xffffffff); - gen_op_iwmmxt_insr_M0_T0_T1((insn & 1) << 5); + tmp2 = tcg_const_i32(0xffffffff); + tmp3 = tcg_const_i32((insn & 1) << 5); break; - case 3: - return 1; + default: + TCGV_UNUSED(tmp2); + TCGV_UNUSED(tmp3); } + gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3); + tcg_temp_free(tmp3); + tcg_temp_free(tmp2); + dead_tmp(tmp); gen_op_iwmmxt_movq_wRn_M0(wrd); gen_op_iwmmxt_set_mup(); break; case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */ rd = (insn >> 12) & 0xf; wrd = (insn >> 16) & 0xf; - if (rd == 15) + if (rd == 15 || ((insn >> 22) & 3) == 3) return 1; gen_op_iwmmxt_movq_M0_wRn(wrd); + tmp = new_tmp(); switch ((insn >> 22) & 3) { case 0: - if (insn & 8) - gen_op_iwmmxt_extrsb_T0_M0((insn & 7) << 3); - else { - gen_op_iwmmxt_extru_T0_M0((insn & 7) << 3, 0xff); + tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3); + tcg_gen_trunc_i64_i32(tmp, cpu_M0); + if (insn & 8) { + tcg_gen_ext8s_i32(tmp, tmp); + } else { + tcg_gen_andi_i32(tmp, tmp, 0xff); } break; case 1: - if (insn & 8) - gen_op_iwmmxt_extrsw_T0_M0((insn & 3) << 4); - else { - gen_op_iwmmxt_extru_T0_M0((insn & 3) << 4, 0xffff); + tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4); + tcg_gen_trunc_i64_i32(tmp, cpu_M0); + if (insn & 8) { + tcg_gen_ext16s_i32(tmp, tmp); + } else { + tcg_gen_andi_i32(tmp, tmp, 0xffff); } break; case 2: - gen_op_iwmmxt_extru_T0_M0((insn & 1) << 5, ~0u); + tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5); + tcg_gen_trunc_i64_i32(tmp, cpu_M0); break; - case 3: - return 1; } - gen_movl_reg_T0(s, rd); + store_reg(s, rd, tmp); break; case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */ - if ((insn & 0x000ff008) != 0x0003f000) + if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3) return 1; - gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF); + tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF); switch ((insn >> 22) & 3) { case 0: - gen_op_shrl_T1_im(((insn & 7) << 2) + 0); + tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0); break; case 1: - gen_op_shrl_T1_im(((insn & 3) << 3) + 4); + tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4); break; case 2: - gen_op_shrl_T1_im(((insn & 1) << 4) + 12); + tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12); break; - case 3: - return 1; } - gen_op_shll_T1_im(28); - gen_set_nzcv(cpu_T[1]); + tcg_gen_shli_i32(tmp, tmp, 28); + gen_set_nzcv(tmp); + dead_tmp(tmp); break; case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */ + if (((insn >> 6) & 3) == 3) + return 1; rd = (insn >> 12) & 0xf; wrd = (insn >> 16) & 0xf; - gen_movl_T0_reg(s, rd); + tmp = load_reg(s, rd); switch ((insn >> 6) & 3) { case 0: - gen_helper_iwmmxt_bcstb(cpu_M0, cpu_T[0]); + gen_helper_iwmmxt_bcstb(cpu_M0, tmp); break; case 1: - gen_helper_iwmmxt_bcstw(cpu_M0, cpu_T[0]); + gen_helper_iwmmxt_bcstw(cpu_M0, tmp); break; case 2: - gen_helper_iwmmxt_bcstl(cpu_M0, cpu_T[0]); + gen_helper_iwmmxt_bcstl(cpu_M0, tmp); break; - case 3: - return 1; } + dead_tmp(tmp); gen_op_iwmmxt_movq_wRn_M0(wrd); gen_op_iwmmxt_set_mup(); break; case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */ - if ((insn & 0x000ff00f) != 0x0003f000) + if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3) return 1; - gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF); + tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF); + tmp2 = new_tmp(); + tcg_gen_mov_i32(tmp2, tmp); switch ((insn >> 22) & 3) { case 0: for (i = 0; i < 7; i ++) { - gen_op_shll_T1_im(4); - gen_op_andl_T0_T1(); + tcg_gen_shli_i32(tmp2, tmp2, 4); + tcg_gen_and_i32(tmp, tmp, tmp2); } break; case 1: for (i = 0; i < 3; i ++) { - gen_op_shll_T1_im(8); - gen_op_andl_T0_T1(); + tcg_gen_shli_i32(tmp2, tmp2, 8); + tcg_gen_and_i32(tmp, tmp, tmp2); } break; case 2: - gen_op_shll_T1_im(16); - gen_op_andl_T0_T1(); + tcg_gen_shli_i32(tmp2, tmp2, 16); + tcg_gen_and_i32(tmp, tmp, tmp2); break; - case 3: - return 1; } - gen_set_nzcv(cpu_T[0]); + gen_set_nzcv(tmp); + dead_tmp(tmp2); + dead_tmp(tmp); break; case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */ wrd = (insn >> 12) & 0xf; @@ -1965,51 +1800,52 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) gen_op_iwmmxt_set_mup(); break; case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */ - if ((insn & 0x000ff00f) != 0x0003f000) + if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3) return 1; - gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF); + tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF); + tmp2 = new_tmp(); + tcg_gen_mov_i32(tmp2, tmp); switch ((insn >> 22) & 3) { case 0: for (i = 0; i < 7; i ++) { - gen_op_shll_T1_im(4); - gen_op_orl_T0_T1(); + tcg_gen_shli_i32(tmp2, tmp2, 4); + tcg_gen_or_i32(tmp, tmp, tmp2); } break; case 1: for (i = 0; i < 3; i ++) { - gen_op_shll_T1_im(8); - gen_op_orl_T0_T1(); + tcg_gen_shli_i32(tmp2, tmp2, 8); + tcg_gen_or_i32(tmp, tmp, tmp2); } break; case 2: - gen_op_shll_T1_im(16); - gen_op_orl_T0_T1(); + tcg_gen_shli_i32(tmp2, tmp2, 16); + tcg_gen_or_i32(tmp, tmp, tmp2); break; - case 3: - return 1; } - gen_set_nzcv(cpu_T[0]); + gen_set_nzcv(tmp); + dead_tmp(tmp2); + dead_tmp(tmp); break; case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */ rd = (insn >> 12) & 0xf; rd0 = (insn >> 16) & 0xf; - if ((insn & 0xf) != 0) + if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3) return 1; gen_op_iwmmxt_movq_M0_wRn(rd0); + tmp = new_tmp(); switch ((insn >> 22) & 3) { case 0: - gen_helper_iwmmxt_msbb(cpu_T[0], cpu_M0); + gen_helper_iwmmxt_msbb(tmp, cpu_M0); break; case 1: - gen_helper_iwmmxt_msbw(cpu_T[0], cpu_M0); + gen_helper_iwmmxt_msbw(tmp, cpu_M0); break; case 2: - gen_helper_iwmmxt_msbl(cpu_T[0], cpu_M0); + gen_helper_iwmmxt_msbl(tmp, cpu_M0); break; - case 3: - return 1; } - gen_movl_reg_T0(s, rd); + store_reg(s, rd, tmp); break; case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */ case 0x906: case 0xb06: case 0xd06: case 0xf06: @@ -2107,100 +1943,120 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) break; case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */ case 0x214: case 0x614: case 0xa14: case 0xe14: + if (((insn >> 22) & 3) == 0) + return 1; wrd = (insn >> 12) & 0xf; rd0 = (insn >> 16) & 0xf; gen_op_iwmmxt_movq_M0_wRn(rd0); - if (gen_iwmmxt_shift(insn, 0xff)) + tmp = new_tmp(); + if (gen_iwmmxt_shift(insn, 0xff, tmp)) { + dead_tmp(tmp); return 1; + } switch ((insn >> 22) & 3) { - case 0: - return 1; case 1: - gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]); + gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp); break; case 2: - gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]); + gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp); break; case 3: - gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]); + gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp); break; } + dead_tmp(tmp); gen_op_iwmmxt_movq_wRn_M0(wrd); gen_op_iwmmxt_set_mup(); gen_op_iwmmxt_set_cup(); break; case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */ case 0x014: case 0x414: case 0x814: case 0xc14: + if (((insn >> 22) & 3) == 0) + return 1; wrd = (insn >> 12) & 0xf; rd0 = (insn >> 16) & 0xf; gen_op_iwmmxt_movq_M0_wRn(rd0); - if (gen_iwmmxt_shift(insn, 0xff)) + tmp = new_tmp(); + if (gen_iwmmxt_shift(insn, 0xff, tmp)) { + dead_tmp(tmp); return 1; + } switch ((insn >> 22) & 3) { - case 0: - return 1; case 1: - gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]); + gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp); break; case 2: - gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, cpu_T[0]); + gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp); break; case 3: - gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]); + gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp); break; } + dead_tmp(tmp); gen_op_iwmmxt_movq_wRn_M0(wrd); gen_op_iwmmxt_set_mup(); gen_op_iwmmxt_set_cup(); break; case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */ case 0x114: case 0x514: case 0x914: case 0xd14: + if (((insn >> 22) & 3) == 0) + return 1; wrd = (insn >> 12) & 0xf; rd0 = (insn >> 16) & 0xf; gen_op_iwmmxt_movq_M0_wRn(rd0); - if (gen_iwmmxt_shift(insn, 0xff)) + tmp = new_tmp(); + if (gen_iwmmxt_shift(insn, 0xff, tmp)) { + dead_tmp(tmp); return 1; + } switch ((insn >> 22) & 3) { - case 0: - return 1; case 1: - gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]); + gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp); break; case 2: - gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]); + gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp); break; case 3: - gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]); + gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp); break; } + dead_tmp(tmp); gen_op_iwmmxt_movq_wRn_M0(wrd); gen_op_iwmmxt_set_mup(); gen_op_iwmmxt_set_cup(); break; case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */ case 0x314: case 0x714: case 0xb14: case 0xf14: + if (((insn >> 22) & 3) == 0) + return 1; wrd = (insn >> 12) & 0xf; rd0 = (insn >> 16) & 0xf; gen_op_iwmmxt_movq_M0_wRn(rd0); + tmp = new_tmp(); switch ((insn >> 22) & 3) { - case 0: - return 1; case 1: - if (gen_iwmmxt_shift(insn, 0xf)) + if (gen_iwmmxt_shift(insn, 0xf, tmp)) { + dead_tmp(tmp); return 1; - gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]); + } + gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp); break; case 2: - if (gen_iwmmxt_shift(insn, 0x1f)) + if (gen_iwmmxt_shift(insn, 0x1f, tmp)) { + dead_tmp(tmp); return 1; - gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, cpu_T[0]); + } + gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp); break; case 3: - if (gen_iwmmxt_shift(insn, 0x3f)) + if (gen_iwmmxt_shift(insn, 0x3f, tmp)) { + dead_tmp(tmp); return 1; - gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]); + } + gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp); break; } + dead_tmp(tmp); gen_op_iwmmxt_movq_wRn_M0(wrd); gen_op_iwmmxt_set_mup(); gen_op_iwmmxt_set_cup(); @@ -2273,8 +2129,10 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) rd0 = (insn >> 16) & 0xf; rd1 = (insn >> 0) & 0xf; gen_op_iwmmxt_movq_M0_wRn(rd0); - gen_op_movl_T0_im((insn >> 20) & 3); - gen_op_iwmmxt_align_M0_T0_wRn(rd1); + tmp = tcg_const_i32((insn >> 20) & 3); + iwmmxt_load_reg(cpu_V1, rd1); + gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp); + tcg_temp_free(tmp); gen_op_iwmmxt_movq_wRn_M0(wrd); gen_op_iwmmxt_set_mup(); break; @@ -2328,8 +2186,9 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) wrd = (insn >> 12) & 0xf; rd0 = (insn >> 16) & 0xf; gen_op_iwmmxt_movq_M0_wRn(rd0); - gen_op_movl_T0_im(((insn >> 16) & 0xf0) | (insn & 0x0f)); - gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, cpu_T[0]); + tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f)); + gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp); + tcg_temp_free(tmp); gen_op_iwmmxt_movq_wRn_M0(wrd); gen_op_iwmmxt_set_mup(); gen_op_iwmmxt_set_cup(); @@ -2381,15 +2240,13 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) case 0x408: case 0x508: case 0x608: case 0x708: case 0x808: case 0x908: case 0xa08: case 0xb08: case 0xc08: case 0xd08: case 0xe08: case 0xf08: + if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0) + return 1; wrd = (insn >> 12) & 0xf; rd0 = (insn >> 16) & 0xf; rd1 = (insn >> 0) & 0xf; gen_op_iwmmxt_movq_M0_wRn(rd0); - if (!(insn & (1 << 20))) - return 1; switch ((insn >> 22) & 3) { - case 0: - return 1; case 1: if (insn & (1 << 21)) gen_op_iwmmxt_packsw_M0_wRn(rd1); @@ -2423,30 +2280,29 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) if (rd0 == 0xf || rd1 == 0xf) return 1; gen_op_iwmmxt_movq_M0_wRn(wrd); + tmp = load_reg(s, rd0); + tmp2 = load_reg(s, rd1); switch ((insn >> 16) & 0xf) { case 0x0: /* TMIA */ - gen_movl_T0_reg(s, rd0); - gen_movl_T1_reg(s, rd1); - gen_op_iwmmxt_muladdsl_M0_T0_T1(); + gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2); break; case 0x8: /* TMIAPH */ - gen_movl_T0_reg(s, rd0); - gen_movl_T1_reg(s, rd1); - gen_op_iwmmxt_muladdsw_M0_T0_T1(); + gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2); break; case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */ - gen_movl_T1_reg(s, rd0); if (insn & (1 << 16)) - gen_op_shrl_T1_im(16); - gen_op_movl_T0_T1(); - gen_movl_T1_reg(s, rd1); + tcg_gen_shri_i32(tmp, tmp, 16); if (insn & (1 << 17)) - gen_op_shrl_T1_im(16); - gen_op_iwmmxt_muladdswl_M0_T0_T1(); + tcg_gen_shri_i32(tmp2, tmp2, 16); + gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2); break; default: + dead_tmp(tmp2); + dead_tmp(tmp); return 1; } + dead_tmp(tmp2); + dead_tmp(tmp); gen_op_iwmmxt_movq_wRn_M0(wrd); gen_op_iwmmxt_set_mup(); break; @@ -2462,6 +2318,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn) { int acc, rd0, rd1, rdhi, rdlo; + TCGv tmp, tmp2; if ((insn & 0x0ff00f10) == 0x0e200010) { /* Multiply with Internal Accumulate Format */ @@ -2472,33 +2329,30 @@ static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn) if (acc != 0) return 1; + tmp = load_reg(s, rd0); + tmp2 = load_reg(s, rd1); switch ((insn >> 16) & 0xf) { case 0x0: /* MIA */ - gen_movl_T0_reg(s, rd0); - gen_movl_T1_reg(s, rd1); - gen_op_iwmmxt_muladdsl_M0_T0_T1(); + gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2); break; case 0x8: /* MIAPH */ - gen_movl_T0_reg(s, rd0); - gen_movl_T1_reg(s, rd1); - gen_op_iwmmxt_muladdsw_M0_T0_T1(); + gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2); break; case 0xc: /* MIABB */ case 0xd: /* MIABT */ case 0xe: /* MIATB */ case 0xf: /* MIATT */ - gen_movl_T1_reg(s, rd0); if (insn & (1 << 16)) - gen_op_shrl_T1_im(16); - gen_op_movl_T0_T1(); - gen_movl_T1_reg(s, rd1); + tcg_gen_shri_i32(tmp, tmp, 16); if (insn & (1 << 17)) - gen_op_shrl_T1_im(16); - gen_op_iwmmxt_muladdswl_M0_T0_T1(); + tcg_gen_shri_i32(tmp2, tmp2, 16); + gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2); break; default: return 1; } + dead_tmp(tmp2); + dead_tmp(tmp); gen_op_iwmmxt_movq_wRn_M0(acc); return 0; @@ -2514,15 +2368,14 @@ static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn) return 1; if (insn & ARM_CP_RW_BIT) { /* MRA */ - gen_iwmmxt_movl_T0_T1_wRn(acc); - gen_movl_reg_T0(s, rdlo); - gen_op_movl_T0_im((1 << (40 - 32)) - 1); - gen_op_andl_T0_T1(); - gen_movl_reg_T0(s, rdhi); + iwmmxt_load_reg(cpu_V0, acc); + tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0); + tcg_gen_shri_i64(cpu_V0, cpu_V0, 32); + tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0); + tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1); } else { /* MAR */ - gen_movl_T0_reg(s, rdlo); - gen_movl_T1_reg(s, rdhi); - gen_iwmmxt_movl_wRn_T0_T1(acc); + tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]); + iwmmxt_store_reg(cpu_V0, acc); } return 0; } @@ -2534,7 +2387,7 @@ static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn) instruction is not defined. */ static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn) { - TCGv tmp; + TCGv tmp, tmp2; uint32_t rd = (insn >> 12) & 0xf; uint32_t cp = (insn >> 8) & 0xf; if (IS_USER(s)) { @@ -2546,14 +2399,18 @@ static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn) return 1; gen_set_pc_im(s->pc); tmp = new_tmp(); - gen_helper_get_cp(tmp, cpu_env, tcg_const_i32(insn)); + tmp2 = tcg_const_i32(insn); + gen_helper_get_cp(tmp, cpu_env, tmp2); + tcg_temp_free(tmp2); store_reg(s, rd, tmp); } else { if (!env->cp[cp].cp_write) return 1; gen_set_pc_im(s->pc); tmp = load_reg(s, rd); - gen_helper_set_cp(cpu_env, tcg_const_i32(insn), tmp); + tmp2 = tcg_const_i32(insn); + gen_helper_set_cp(cpu_env, tmp2, tmp); + tcg_temp_free(tmp2); dead_tmp(tmp); } return 0; @@ -2584,7 +2441,7 @@ static int cp15_user_ok(uint32_t insn) static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn) { uint32_t rd; - TCGv tmp; + TCGv tmp, tmp2; /* M profile cores use memory mapped registers instead of cp15. */ if (arm_feature(env, ARM_FEATURE_M)) @@ -2613,9 +2470,10 @@ static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn) return 0; } rd = (insn >> 12) & 0xf; + tmp2 = tcg_const_i32(insn); if (insn & ARM_CP_RW_BIT) { tmp = new_tmp(); - gen_helper_get_cp15(tmp, cpu_env, tcg_const_i32(insn)); + gen_helper_get_cp15(tmp, cpu_env, tmp2); /* If the destination register is r15 then sets condition codes. */ if (rd != 15) store_reg(s, rd, tmp); @@ -2623,7 +2481,7 @@ static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn) dead_tmp(tmp); } else { tmp = load_reg(s, rd); - gen_helper_set_cp15(cpu_env, tcg_const_i32(insn), tmp); + gen_helper_set_cp15(cpu_env, tmp2, tmp); dead_tmp(tmp); /* Normally we would always end the TB here, but Linux * arch/arm/mach-pxa/sleep.S expects two instructions following @@ -2632,6 +2490,7 @@ static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn) (insn & 0x0fff0fff) != 0x0e010f10) gen_lookup_tb(s); } + tcg_temp_free_i32(tmp2); return 0; } @@ -2712,6 +2571,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) { uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask; int dp, veclen; + TCGv addr; TCGv tmp; TCGv tmp2; @@ -2904,6 +2764,9 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) case ARM_VFP_FPEXC: if (IS_USER(s)) return 1; + /* TODO: VFP subarchitecture support. + * For now, keep the EN bit only */ + tcg_gen_andi_i32(tmp, tmp, 1 << 30); store_cpu_field(tmp, vfp.xregs[rn]); gen_lookup_tb(s); break; @@ -3302,23 +3165,25 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) else rd = VFP_SREG_D(insn); if (s->thumb && rn == 15) { - gen_op_movl_T1_im(s->pc & ~2); + addr = new_tmp(); + tcg_gen_movi_i32(addr, s->pc & ~2); } else { - gen_movl_T1_reg(s, rn); + addr = load_reg(s, rn); } if ((insn & 0x01200000) == 0x01000000) { /* Single load/store */ offset = (insn & 0xff) << 2; if ((insn & (1 << 23)) == 0) offset = -offset; - gen_op_addl_T1_im(offset); + tcg_gen_addi_i32(addr, addr, offset); if (insn & (1 << 20)) { - gen_vfp_ld(s, dp); + gen_vfp_ld(s, dp, addr); gen_mov_vreg_F0(dp, rd); } else { gen_mov_F0_vreg(dp, rd); - gen_vfp_st(s, dp); + gen_vfp_st(s, dp, addr); } + dead_tmp(addr); } else { /* load/store multiple */ if (dp) @@ -3327,7 +3192,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) n = insn & 0xff; if (insn & (1 << 24)) /* pre-decrement */ - gen_op_addl_T1_im(-((insn & 0xff) << 2)); + tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2)); if (dp) offset = 8; @@ -3336,14 +3201,14 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) for (i = 0; i < n; i++) { if (insn & ARM_CP_RW_BIT) { /* load */ - gen_vfp_ld(s, dp); + gen_vfp_ld(s, dp, addr); gen_mov_vreg_F0(dp, rd + i); } else { /* store */ gen_mov_F0_vreg(dp, rd + i); - gen_vfp_st(s, dp); + gen_vfp_st(s, dp, addr); } - gen_op_addl_T1_im(offset); + tcg_gen_addi_i32(addr, addr, offset); } if (insn & (1 << 21)) { /* writeback */ @@ -3355,8 +3220,10 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) offset = 0; if (offset != 0) - gen_op_addl_T1_im(offset); - gen_movl_reg_T1(s, rn); + tcg_gen_addi_i32(addr, addr, offset); + store_reg(s, rn, addr); + } else { + dead_tmp(addr); } } } @@ -3438,8 +3305,8 @@ static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) { return mask; } -/* Returns nonzero if access to the PSR is not permitted. */ -static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr) +/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */ +static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0) { TCGv tmp; if (spsr) { @@ -3449,16 +3316,26 @@ static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr) tmp = load_cpu_field(spsr); tcg_gen_andi_i32(tmp, tmp, ~mask); - tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask); - tcg_gen_or_i32(tmp, tmp, cpu_T[0]); + tcg_gen_andi_i32(t0, t0, mask); + tcg_gen_or_i32(tmp, tmp, t0); store_cpu_field(tmp, spsr); } else { - gen_set_cpsr(cpu_T[0], mask); + gen_set_cpsr(t0, mask); } + dead_tmp(t0); gen_lookup_tb(s); return 0; } +/* Returns nonzero if access to the PSR is not permitted. */ +static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val) +{ + TCGv tmp; + tmp = new_tmp(); + tcg_gen_movi_i32(tmp, val); + return gen_set_psr(s, mask, spsr, tmp); +} + /* Generate an old-style exception return. Marks pc as dead. */ static void gen_exception_return(DisasContext *s, TCGv pc) { @@ -3505,31 +3382,25 @@ static void gen_nop_hint(DisasContext *s, int val) } } -/* These macros help make the code more readable when migrating from the - old dyngen helpers. They should probably be removed when - T0/T1 are removed. */ -#define CPU_T001 cpu_T[0], cpu_T[0], cpu_T[1] -#define CPU_T0E01 cpu_T[0], cpu_env, cpu_T[0], cpu_T[1] - #define CPU_V001 cpu_V0, cpu_V0, cpu_V1 -static inline int gen_neon_add(int size) +static inline int gen_neon_add(int size, TCGv t0, TCGv t1) { switch (size) { - case 0: gen_helper_neon_add_u8(CPU_T001); break; - case 1: gen_helper_neon_add_u16(CPU_T001); break; - case 2: gen_op_addl_T0_T1(); break; + case 0: gen_helper_neon_add_u8(t0, t0, t1); break; + case 1: gen_helper_neon_add_u16(t0, t0, t1); break; + case 2: tcg_gen_add_i32(t0, t0, t1); break; default: return 1; } return 0; } -static inline void gen_neon_rsb(int size) +static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1) { switch (size) { - case 0: gen_helper_neon_sub_u8(cpu_T[0], cpu_T[1], cpu_T[0]); break; - case 1: gen_helper_neon_sub_u16(cpu_T[0], cpu_T[1], cpu_T[0]); break; - case 2: gen_op_rsbl_T0_T1(); break; + case 0: gen_helper_neon_sub_u8(t0, t1, t0); break; + case 1: gen_helper_neon_sub_u16(t0, t1, t0); break; + case 2: tcg_gen_sub_i32(t0, t1, t0); break; default: return; } } @@ -3549,22 +3420,22 @@ static inline void gen_neon_rsb(int size) #define GEN_NEON_INTEGER_OP_ENV(name) do { \ switch ((size << 1) | u) { \ case 0: \ - gen_helper_neon_##name##_s8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \ + gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \ break; \ case 1: \ - gen_helper_neon_##name##_u8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \ + gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \ break; \ case 2: \ - gen_helper_neon_##name##_s16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \ + gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \ break; \ case 3: \ - gen_helper_neon_##name##_u16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \ + gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \ break; \ case 4: \ - gen_helper_neon_##name##_s32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \ + gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \ break; \ case 5: \ - gen_helper_neon_##name##_u32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \ + gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \ break; \ default: return 1; \ }} while (0) @@ -3572,93 +3443,207 @@ static inline void gen_neon_rsb(int size) #define GEN_NEON_INTEGER_OP(name) do { \ switch ((size << 1) | u) { \ case 0: \ - gen_helper_neon_##name##_s8(cpu_T[0], cpu_T[0], cpu_T[1]); \ + gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \ break; \ case 1: \ - gen_helper_neon_##name##_u8(cpu_T[0], cpu_T[0], cpu_T[1]); \ + gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \ break; \ case 2: \ - gen_helper_neon_##name##_s16(cpu_T[0], cpu_T[0], cpu_T[1]); \ + gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \ break; \ case 3: \ - gen_helper_neon_##name##_u16(cpu_T[0], cpu_T[0], cpu_T[1]); \ + gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \ break; \ case 4: \ - gen_helper_neon_##name##_s32(cpu_T[0], cpu_T[0], cpu_T[1]); \ + gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \ break; \ case 5: \ - gen_helper_neon_##name##_u32(cpu_T[0], cpu_T[0], cpu_T[1]); \ + gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \ break; \ default: return 1; \ }} while (0) -static inline void -gen_neon_movl_scratch_T0(int scratch) +static TCGv neon_load_scratch(int scratch) { - uint32_t offset; - - offset = offsetof(CPUARMState, vfp.scratch[scratch]); - tcg_gen_st_i32(cpu_T[0], cpu_env, offset); + TCGv tmp = new_tmp(); + tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch])); + return tmp; } -static inline void -gen_neon_movl_scratch_T1(int scratch) +static void neon_store_scratch(int scratch, TCGv var) { - uint32_t offset; + tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch])); + dead_tmp(var); +} - offset = offsetof(CPUARMState, vfp.scratch[scratch]); - tcg_gen_st_i32(cpu_T[1], cpu_env, offset); +static inline TCGv neon_get_scalar(int size, int reg) +{ + TCGv tmp; + if (size == 1) { + tmp = neon_load_reg(reg >> 1, reg & 1); + } else { + tmp = neon_load_reg(reg >> 2, (reg >> 1) & 1); + if (reg & 1) { + gen_neon_dup_low16(tmp); + } else { + gen_neon_dup_high16(tmp); + } + } + return tmp; } -static inline void -gen_neon_movl_T0_scratch(int scratch) +static void gen_neon_unzip_u8(TCGv t0, TCGv t1) { - uint32_t offset; + TCGv rd, rm, tmp; + + rd = new_tmp(); + rm = new_tmp(); + tmp = new_tmp(); - offset = offsetof(CPUARMState, vfp.scratch[scratch]); - tcg_gen_ld_i32(cpu_T[0], cpu_env, offset); + tcg_gen_andi_i32(rd, t0, 0xff); + tcg_gen_shri_i32(tmp, t0, 8); + tcg_gen_andi_i32(tmp, tmp, 0xff00); + tcg_gen_or_i32(rd, rd, tmp); + tcg_gen_shli_i32(tmp, t1, 16); + tcg_gen_andi_i32(tmp, tmp, 0xff0000); + tcg_gen_or_i32(rd, rd, tmp); + tcg_gen_shli_i32(tmp, t1, 8); + tcg_gen_andi_i32(tmp, tmp, 0xff000000); + tcg_gen_or_i32(rd, rd, tmp); + + tcg_gen_shri_i32(rm, t0, 8); + tcg_gen_andi_i32(rm, rm, 0xff); + tcg_gen_shri_i32(tmp, t0, 16); + tcg_gen_andi_i32(tmp, tmp, 0xff00); + tcg_gen_or_i32(rm, rm, tmp); + tcg_gen_shli_i32(tmp, t1, 8); + tcg_gen_andi_i32(tmp, tmp, 0xff0000); + tcg_gen_or_i32(rm, rm, tmp); + tcg_gen_andi_i32(tmp, t1, 0xff000000); + tcg_gen_or_i32(t1, rm, tmp); + tcg_gen_mov_i32(t0, rd); + + dead_tmp(tmp); + dead_tmp(rm); + dead_tmp(rd); } -static inline void -gen_neon_movl_T1_scratch(int scratch) +static void gen_neon_zip_u8(TCGv t0, TCGv t1) { - uint32_t offset; + TCGv rd, rm, tmp; + + rd = new_tmp(); + rm = new_tmp(); + tmp = new_tmp(); - offset = offsetof(CPUARMState, vfp.scratch[scratch]); - tcg_gen_ld_i32(cpu_T[1], cpu_env, offset); + tcg_gen_andi_i32(rd, t0, 0xff); + tcg_gen_shli_i32(tmp, t1, 8); + tcg_gen_andi_i32(tmp, tmp, 0xff00); + tcg_gen_or_i32(rd, rd, tmp); + tcg_gen_shli_i32(tmp, t0, 16); + tcg_gen_andi_i32(tmp, tmp, 0xff0000); + tcg_gen_or_i32(rd, rd, tmp); + tcg_gen_shli_i32(tmp, t1, 24); + tcg_gen_andi_i32(tmp, tmp, 0xff000000); + tcg_gen_or_i32(rd, rd, tmp); + + tcg_gen_andi_i32(rm, t1, 0xff000000); + tcg_gen_shri_i32(tmp, t0, 8); + tcg_gen_andi_i32(tmp, tmp, 0xff0000); + tcg_gen_or_i32(rm, rm, tmp); + tcg_gen_shri_i32(tmp, t1, 8); + tcg_gen_andi_i32(tmp, tmp, 0xff00); + tcg_gen_or_i32(rm, rm, tmp); + tcg_gen_shri_i32(tmp, t0, 16); + tcg_gen_andi_i32(tmp, tmp, 0xff); + tcg_gen_or_i32(t1, rm, tmp); + tcg_gen_mov_i32(t0, rd); + + dead_tmp(tmp); + dead_tmp(rm); + dead_tmp(rd); } -static inline void gen_neon_get_scalar(int size, int reg) +static void gen_neon_zip_u16(TCGv t0, TCGv t1) { - if (size == 1) { - NEON_GET_REG(T0, reg >> 1, reg & 1); - } else { - NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1); - if (reg & 1) - gen_neon_dup_low16(cpu_T[0]); - else - gen_neon_dup_high16(cpu_T[0]); - } + TCGv tmp, tmp2; + + tmp = new_tmp(); + tmp2 = new_tmp(); + + tcg_gen_andi_i32(tmp, t0, 0xffff); + tcg_gen_shli_i32(tmp2, t1, 16); + tcg_gen_or_i32(tmp, tmp, tmp2); + tcg_gen_andi_i32(t1, t1, 0xffff0000); + tcg_gen_shri_i32(tmp2, t0, 16); + tcg_gen_or_i32(t1, t1, tmp2); + tcg_gen_mov_i32(t0, tmp); + + dead_tmp(tmp2); + dead_tmp(tmp); } static void gen_neon_unzip(int reg, int q, int tmp, int size) { int n; + TCGv t0, t1; for (n = 0; n < q + 1; n += 2) { - NEON_GET_REG(T0, reg, n); - NEON_GET_REG(T0, reg, n + n); + t0 = neon_load_reg(reg, n); + t1 = neon_load_reg(reg, n + 1); switch (size) { - case 0: gen_helper_neon_unzip_u8(); break; - case 1: gen_helper_neon_zip_u16(); break; /* zip and unzip are the same. */ + case 0: gen_neon_unzip_u8(t0, t1); break; + case 1: gen_neon_zip_u16(t0, t1); break; /* zip and unzip are the same. */ case 2: /* no-op */; break; default: abort(); } - gen_neon_movl_scratch_T0(tmp + n); - gen_neon_movl_scratch_T1(tmp + n + 1); + neon_store_scratch(tmp + n, t0); + neon_store_scratch(tmp + n + 1, t1); } } +static void gen_neon_trn_u8(TCGv t0, TCGv t1) +{ + TCGv rd, tmp; + + rd = new_tmp(); + tmp = new_tmp(); + + tcg_gen_shli_i32(rd, t0, 8); + tcg_gen_andi_i32(rd, rd, 0xff00ff00); + tcg_gen_andi_i32(tmp, t1, 0x00ff00ff); + tcg_gen_or_i32(rd, rd, tmp); + + tcg_gen_shri_i32(t1, t1, 8); + tcg_gen_andi_i32(t1, t1, 0x00ff00ff); + tcg_gen_andi_i32(tmp, t0, 0xff00ff00); + tcg_gen_or_i32(t1, t1, tmp); + tcg_gen_mov_i32(t0, rd); + + dead_tmp(tmp); + dead_tmp(rd); +} + +static void gen_neon_trn_u16(TCGv t0, TCGv t1) +{ + TCGv rd, tmp; + + rd = new_tmp(); + tmp = new_tmp(); + + tcg_gen_shli_i32(rd, t0, 16); + tcg_gen_andi_i32(tmp, t1, 0xffff); + tcg_gen_or_i32(rd, rd, tmp); + tcg_gen_shri_i32(t1, t1, 16); + tcg_gen_andi_i32(tmp, t0, 0xffff0000); + tcg_gen_or_i32(t1, t1, tmp); + tcg_gen_mov_i32(t0, rd); + + dead_tmp(tmp); + dead_tmp(rd); +} + + static struct { int nregs; int interleave; @@ -3685,6 +3670,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) int op; int nregs; int interleave; + int spacing; int stride; int size; int reg; @@ -3692,8 +3678,10 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) int load; int shift; int n; + TCGv addr; TCGv tmp; TCGv tmp2; + TCGv_i64 tmp64; if (!vfp_enabled(env)) return 1; @@ -3701,83 +3689,100 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) rn = (insn >> 16) & 0xf; rm = insn & 0xf; load = (insn & (1 << 21)) != 0; + addr = new_tmp(); if ((insn & (1 << 23)) == 0) { /* Load store all elements. */ op = (insn >> 8) & 0xf; size = (insn >> 6) & 3; - if (op > 10 || size == 3) + if (op > 10) return 1; nregs = neon_ls_element_type[op].nregs; interleave = neon_ls_element_type[op].interleave; - gen_movl_T1_reg(s, rn); + spacing = neon_ls_element_type[op].spacing; + if (size == 3 && (interleave | spacing) != 1) + return 1; + load_reg_var(s, addr, rn); stride = (1 << size) * interleave; for (reg = 0; reg < nregs; reg++) { if (interleave > 2 || (interleave == 2 && nregs == 2)) { - gen_movl_T1_reg(s, rn); - gen_op_addl_T1_im((1 << size) * reg); + load_reg_var(s, addr, rn); + tcg_gen_addi_i32(addr, addr, (1 << size) * reg); } else if (interleave == 2 && nregs == 4 && reg == 2) { - gen_movl_T1_reg(s, rn); - gen_op_addl_T1_im(1 << size); + load_reg_var(s, addr, rn); + tcg_gen_addi_i32(addr, addr, 1 << size); } - for (pass = 0; pass < 2; pass++) { - if (size == 2) { - if (load) { - tmp = gen_ld32(cpu_T[1], IS_USER(s)); - neon_store_reg(rd, pass, tmp); - } else { - tmp = neon_load_reg(rd, pass); - gen_st32(tmp, cpu_T[1], IS_USER(s)); - } - gen_op_addl_T1_im(stride); - } else if (size == 1) { - if (load) { - tmp = gen_ld16u(cpu_T[1], IS_USER(s)); - gen_op_addl_T1_im(stride); - tmp2 = gen_ld16u(cpu_T[1], IS_USER(s)); - gen_op_addl_T1_im(stride); - gen_bfi(tmp, tmp, tmp2, 16, 0xffff); - dead_tmp(tmp2); - neon_store_reg(rd, pass, tmp); - } else { - tmp = neon_load_reg(rd, pass); - tmp2 = new_tmp(); - tcg_gen_shri_i32(tmp2, tmp, 16); - gen_st16(tmp, cpu_T[1], IS_USER(s)); - gen_op_addl_T1_im(stride); - gen_st16(tmp2, cpu_T[1], IS_USER(s)); - gen_op_addl_T1_im(stride); - } - } else /* size == 0 */ { - if (load) { - TCGV_UNUSED(tmp2); - for (n = 0; n < 4; n++) { - tmp = gen_ld8u(cpu_T[1], IS_USER(s)); - gen_op_addl_T1_im(stride); - if (n == 0) { - tmp2 = tmp; - } else { - gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff); - dead_tmp(tmp); - } + if (size == 3) { + if (load) { + tmp64 = gen_ld64(addr, IS_USER(s)); + neon_store_reg64(tmp64, rd); + tcg_temp_free_i64(tmp64); + } else { + tmp64 = tcg_temp_new_i64(); + neon_load_reg64(tmp64, rd); + gen_st64(tmp64, addr, IS_USER(s)); + } + tcg_gen_addi_i32(addr, addr, stride); + } else { + for (pass = 0; pass < 2; pass++) { + if (size == 2) { + if (load) { + tmp = gen_ld32(addr, IS_USER(s)); + neon_store_reg(rd, pass, tmp); + } else { + tmp = neon_load_reg(rd, pass); + gen_st32(tmp, addr, IS_USER(s)); } - neon_store_reg(rd, pass, tmp2); - } else { - tmp2 = neon_load_reg(rd, pass); - for (n = 0; n < 4; n++) { - tmp = new_tmp(); - if (n == 0) { - tcg_gen_mov_i32(tmp, tmp2); - } else { - tcg_gen_shri_i32(tmp, tmp2, n * 8); + tcg_gen_addi_i32(addr, addr, stride); + } else if (size == 1) { + if (load) { + tmp = gen_ld16u(addr, IS_USER(s)); + tcg_gen_addi_i32(addr, addr, stride); + tmp2 = gen_ld16u(addr, IS_USER(s)); + tcg_gen_addi_i32(addr, addr, stride); + gen_bfi(tmp, tmp, tmp2, 16, 0xffff); + dead_tmp(tmp2); + neon_store_reg(rd, pass, tmp); + } else { + tmp = neon_load_reg(rd, pass); + tmp2 = new_tmp(); + tcg_gen_shri_i32(tmp2, tmp, 16); + gen_st16(tmp, addr, IS_USER(s)); + tcg_gen_addi_i32(addr, addr, stride); + gen_st16(tmp2, addr, IS_USER(s)); + tcg_gen_addi_i32(addr, addr, stride); + } + } else /* size == 0 */ { + if (load) { + TCGV_UNUSED(tmp2); + for (n = 0; n < 4; n++) { + tmp = gen_ld8u(addr, IS_USER(s)); + tcg_gen_addi_i32(addr, addr, stride); + if (n == 0) { + tmp2 = tmp; + } else { + gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff); + dead_tmp(tmp); + } } - gen_st8(tmp, cpu_T[1], IS_USER(s)); - gen_op_addl_T1_im(stride); + neon_store_reg(rd, pass, tmp2); + } else { + tmp2 = neon_load_reg(rd, pass); + for (n = 0; n < 4; n++) { + tmp = new_tmp(); + if (n == 0) { + tcg_gen_mov_i32(tmp, tmp2); + } else { + tcg_gen_shri_i32(tmp, tmp2, n * 8); + } + gen_st8(tmp, addr, IS_USER(s)); + tcg_gen_addi_i32(addr, addr, stride); + } + dead_tmp(tmp2); } - dead_tmp(tmp2); } } } - rd += neon_ls_element_type[op].spacing; + rd += spacing; } stride = nregs * 8; } else { @@ -3789,26 +3794,26 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) size = (insn >> 6) & 3; nregs = ((insn >> 8) & 3) + 1; stride = (insn & (1 << 5)) ? 2 : 1; - gen_movl_T1_reg(s, rn); + load_reg_var(s, addr, rn); for (reg = 0; reg < nregs; reg++) { switch (size) { case 0: - tmp = gen_ld8u(cpu_T[1], IS_USER(s)); + tmp = gen_ld8u(addr, IS_USER(s)); gen_neon_dup_u8(tmp, 0); break; case 1: - tmp = gen_ld16u(cpu_T[1], IS_USER(s)); + tmp = gen_ld16u(addr, IS_USER(s)); gen_neon_dup_low16(tmp); break; case 2: - tmp = gen_ld32(cpu_T[0], IS_USER(s)); + tmp = gen_ld32(addr, IS_USER(s)); break; case 3: return 1; default: /* Avoid compiler warnings. */ abort(); } - gen_op_addl_T1_im(1 << size); + tcg_gen_addi_i32(addr, addr, 1 << size); tmp2 = new_tmp(); tcg_gen_mov_i32(tmp2, tmp); neon_store_reg(rd, 0, tmp2); @@ -3836,18 +3841,18 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) abort(); } nregs = ((insn >> 8) & 3) + 1; - gen_movl_T1_reg(s, rn); + load_reg_var(s, addr, rn); for (reg = 0; reg < nregs; reg++) { if (load) { switch (size) { case 0: - tmp = gen_ld8u(cpu_T[1], IS_USER(s)); + tmp = gen_ld8u(addr, IS_USER(s)); break; case 1: - tmp = gen_ld16u(cpu_T[1], IS_USER(s)); + tmp = gen_ld16u(addr, IS_USER(s)); break; case 2: - tmp = gen_ld32(cpu_T[1], IS_USER(s)); + tmp = gen_ld32(addr, IS_USER(s)); break; default: /* Avoid compiler warnings. */ abort(); @@ -3864,22 +3869,23 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) tcg_gen_shri_i32(tmp, tmp, shift); switch (size) { case 0: - gen_st8(tmp, cpu_T[1], IS_USER(s)); + gen_st8(tmp, addr, IS_USER(s)); break; case 1: - gen_st16(tmp, cpu_T[1], IS_USER(s)); + gen_st16(tmp, addr, IS_USER(s)); break; case 2: - gen_st32(tmp, cpu_T[1], IS_USER(s)); + gen_st32(tmp, addr, IS_USER(s)); break; } } rd += stride; - gen_op_addl_T1_im(1 << size); + tcg_gen_addi_i32(addr, addr, 1 << size); } stride = nregs * (1 << size); } } + dead_tmp(addr); if (rm != 15) { TCGv base; @@ -3901,7 +3907,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c) { tcg_gen_and_i32(t, t, c); - tcg_gen_bic_i32(f, f, c); + tcg_gen_andc_i32(f, f, c); tcg_gen_or_i32(dest, t, f); } @@ -4047,10 +4053,6 @@ static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u) break; default: abort(); } - if (size < 2) { - dead_tmp(b); - dead_tmp(a); - } } /* Translate a NEON data processing instruction. Return nonzero if the @@ -4070,10 +4072,8 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) int pairwise; int u; int n; - uint32_t imm; - TCGv tmp; - TCGv tmp2; - TCGv tmp3; + uint32_t imm, mask; + TCGv tmp, tmp2, tmp3, tmp4, tmp5; TCGv_i64 tmp64; if (!vfp_enabled(env)) @@ -4183,6 +4183,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) pairwise = 0; break; } + for (pass = 0; pass < (q ? 4 : 2); pass++) { if (pairwise) { @@ -4192,16 +4193,16 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) else n = 0; if (pass < q + 1) { - NEON_GET_REG(T0, rn, n); - NEON_GET_REG(T1, rn, n + 1); + tmp = neon_load_reg(rn, n); + tmp2 = neon_load_reg(rn, n + 1); } else { - NEON_GET_REG(T0, rm, n); - NEON_GET_REG(T1, rm, n + 1); + tmp = neon_load_reg(rm, n); + tmp2 = neon_load_reg(rm, n + 1); } } else { /* Elementwise. */ - NEON_GET_REG(T0, rn, pass); - NEON_GET_REG(T1, rm, pass); + tmp = neon_load_reg(rn, pass); + tmp2 = neon_load_reg(rm, pass); } switch (op) { case 0: /* VHADD */ @@ -4216,35 +4217,34 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) case 3: /* Logic ops. */ switch ((u << 2) | size) { case 0: /* VAND */ - gen_op_andl_T0_T1(); + tcg_gen_and_i32(tmp, tmp, tmp2); break; case 1: /* BIC */ - gen_op_bicl_T0_T1(); + tcg_gen_andc_i32(tmp, tmp, tmp2); break; case 2: /* VORR */ - gen_op_orl_T0_T1(); + tcg_gen_or_i32(tmp, tmp, tmp2); break; case 3: /* VORN */ - gen_op_notl_T1(); - gen_op_orl_T0_T1(); + tcg_gen_orc_i32(tmp, tmp, tmp2); break; case 4: /* VEOR */ - gen_op_xorl_T0_T1(); + tcg_gen_xor_i32(tmp, tmp, tmp2); break; case 5: /* VBSL */ - tmp = neon_load_reg(rd, pass); - gen_neon_bsl(cpu_T[0], cpu_T[0], cpu_T[1], tmp); - dead_tmp(tmp); + tmp3 = neon_load_reg(rd, pass); + gen_neon_bsl(tmp, tmp, tmp2, tmp3); + dead_tmp(tmp3); break; case 6: /* VBIT */ - tmp = neon_load_reg(rd, pass); - gen_neon_bsl(cpu_T[0], cpu_T[0], tmp, cpu_T[1]); - dead_tmp(tmp); + tmp3 = neon_load_reg(rd, pass); + gen_neon_bsl(tmp, tmp, tmp3, tmp2); + dead_tmp(tmp3); break; case 7: /* VBIF */ - tmp = neon_load_reg(rd, pass); - gen_neon_bsl(cpu_T[0], tmp, cpu_T[0], cpu_T[1]); - dead_tmp(tmp); + tmp3 = neon_load_reg(rd, pass); + gen_neon_bsl(tmp, tmp3, tmp, tmp2); + dead_tmp(tmp3); break; } break; @@ -4283,18 +4283,19 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) break; case 15: /* VABA */ GEN_NEON_INTEGER_OP(abd); - NEON_GET_REG(T1, rd, pass); - gen_neon_add(size); + dead_tmp(tmp2); + tmp2 = neon_load_reg(rd, pass); + gen_neon_add(size, tmp, tmp2); break; case 16: if (!u) { /* VADD */ - if (gen_neon_add(size)) + if (gen_neon_add(size, tmp, tmp2)) return 1; } else { /* VSUB */ switch (size) { - case 0: gen_helper_neon_sub_u8(CPU_T001); break; - case 1: gen_helper_neon_sub_u16(CPU_T001); break; - case 2: gen_op_subl_T0_T1(); break; + case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break; + case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break; + case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break; default: return 1; } } @@ -4302,42 +4303,43 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) case 17: if (!u) { /* VTST */ switch (size) { - case 0: gen_helper_neon_tst_u8(CPU_T001); break; - case 1: gen_helper_neon_tst_u16(CPU_T001); break; - case 2: gen_helper_neon_tst_u32(CPU_T001); break; + case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break; + case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break; + case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break; default: return 1; } } else { /* VCEQ */ switch (size) { - case 0: gen_helper_neon_ceq_u8(CPU_T001); break; - case 1: gen_helper_neon_ceq_u16(CPU_T001); break; - case 2: gen_helper_neon_ceq_u32(CPU_T001); break; + case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break; + case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break; + case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break; default: return 1; } } break; case 18: /* Multiply. */ switch (size) { - case 0: gen_helper_neon_mul_u8(CPU_T001); break; - case 1: gen_helper_neon_mul_u16(CPU_T001); break; - case 2: gen_op_mul_T0_T1(); break; + case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break; + case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break; + case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break; default: return 1; } - NEON_GET_REG(T1, rd, pass); + dead_tmp(tmp2); + tmp2 = neon_load_reg(rd, pass); if (u) { /* VMLS */ - gen_neon_rsb(size); + gen_neon_rsb(size, tmp, tmp2); } else { /* VMLA */ - gen_neon_add(size); + gen_neon_add(size, tmp, tmp2); } break; case 19: /* VMUL */ if (u) { /* polynomial */ - gen_helper_neon_mul_p8(CPU_T001); + gen_helper_neon_mul_p8(tmp, tmp, tmp2); } else { /* Integer */ switch (size) { - case 0: gen_helper_neon_mul_u8(CPU_T001); break; - case 1: gen_helper_neon_mul_u16(CPU_T001); break; - case 2: gen_op_mul_T0_T1(); break; + case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break; + case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break; + case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break; default: return 1; } } @@ -4351,14 +4353,14 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) case 22: /* Hultiply high. */ if (!u) { /* VQDMULH */ switch (size) { - case 1: gen_helper_neon_qdmulh_s16(CPU_T0E01); break; - case 2: gen_helper_neon_qdmulh_s32(CPU_T0E01); break; + case 1: gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); break; + case 2: gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); break; default: return 1; } } else { /* VQRDHMUL */ switch (size) { - case 1: gen_helper_neon_qrdmulh_s16(CPU_T0E01); break; - case 2: gen_helper_neon_qrdmulh_s32(CPU_T0E01); break; + case 1: gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); break; + case 2: gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); break; default: return 1; } } @@ -4367,88 +4369,91 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) if (u) return 1; switch (size) { - case 0: gen_helper_neon_padd_u8(CPU_T001); break; - case 1: gen_helper_neon_padd_u16(CPU_T001); break; - case 2: gen_op_addl_T0_T1(); break; + case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break; + case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break; + case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break; default: return 1; } break; case 26: /* Floating point arithnetic. */ switch ((u << 2) | size) { case 0: /* VADD */ - gen_helper_neon_add_f32(CPU_T001); + gen_helper_neon_add_f32(tmp, tmp, tmp2); break; case 2: /* VSUB */ - gen_helper_neon_sub_f32(CPU_T001); + gen_helper_neon_sub_f32(tmp, tmp, tmp2); break; case 4: /* VPADD */ - gen_helper_neon_add_f32(CPU_T001); + gen_helper_neon_add_f32(tmp, tmp, tmp2); break; case 6: /* VABD */ - gen_helper_neon_abd_f32(CPU_T001); + gen_helper_neon_abd_f32(tmp, tmp, tmp2); break; default: return 1; } break; case 27: /* Float multiply. */ - gen_helper_neon_mul_f32(CPU_T001); + gen_helper_neon_mul_f32(tmp, tmp, tmp2); if (!u) { - NEON_GET_REG(T1, rd, pass); + dead_tmp(tmp2); + tmp2 = neon_load_reg(rd, pass); if (size == 0) { - gen_helper_neon_add_f32(CPU_T001); + gen_helper_neon_add_f32(tmp, tmp, tmp2); } else { - gen_helper_neon_sub_f32(cpu_T[0], cpu_T[1], cpu_T[0]); + gen_helper_neon_sub_f32(tmp, tmp2, tmp); } } break; case 28: /* Float compare. */ if (!u) { - gen_helper_neon_ceq_f32(CPU_T001); + gen_helper_neon_ceq_f32(tmp, tmp, tmp2); } else { if (size == 0) - gen_helper_neon_cge_f32(CPU_T001); + gen_helper_neon_cge_f32(tmp, tmp, tmp2); else - gen_helper_neon_cgt_f32(CPU_T001); + gen_helper_neon_cgt_f32(tmp, tmp, tmp2); } break; case 29: /* Float compare absolute. */ if (!u) return 1; if (size == 0) - gen_helper_neon_acge_f32(CPU_T001); + gen_helper_neon_acge_f32(tmp, tmp, tmp2); else - gen_helper_neon_acgt_f32(CPU_T001); + gen_helper_neon_acgt_f32(tmp, tmp, tmp2); break; case 30: /* Float min/max. */ if (size == 0) - gen_helper_neon_max_f32(CPU_T001); + gen_helper_neon_max_f32(tmp, tmp, tmp2); else - gen_helper_neon_min_f32(CPU_T001); + gen_helper_neon_min_f32(tmp, tmp, tmp2); break; case 31: if (size == 0) - gen_helper_recps_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env); + gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env); else - gen_helper_rsqrts_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env); + gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env); break; default: abort(); } + dead_tmp(tmp2); + /* Save the result. For elementwise operations we can put it straight into the destination register. For pairwise operations we have to be careful to avoid clobbering the source operands. */ if (pairwise && rd == rm) { - gen_neon_movl_scratch_T0(pass); + neon_store_scratch(pass, tmp); } else { - NEON_SET_REG(T0, rd, pass); + neon_store_reg(rd, pass, tmp); } } /* for pass */ if (pairwise && rd == rm) { for (pass = 0; pass < (q ? 4 : 2); pass++) { - gen_neon_movl_T0_scratch(pass); - NEON_SET_REG(T0, rd, pass); + tmp = neon_load_scratch(pass); + neon_store_reg(rd, pass, tmp); } } /* End of 3 register same size operations. */ @@ -4545,8 +4550,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) neon_store_reg64(cpu_V0, rd + pass); } else { /* size < 3 */ /* Operands in T0 and T1. */ - gen_op_movl_T1_im(imm); - NEON_GET_REG(T0, rm, pass); + tmp = neon_load_reg(rm, pass); + tmp2 = new_tmp(); + tcg_gen_movi_i32(tmp2, imm); switch (op) { case 0: /* VSHR */ case 1: /* VSRA */ @@ -4563,9 +4569,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) break; case 5: /* VSHL, VSLI */ switch (size) { - case 0: gen_helper_neon_shl_u8(CPU_T001); break; - case 1: gen_helper_neon_shl_u16(CPU_T001); break; - case 2: gen_helper_neon_shl_u32(CPU_T001); break; + case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break; + case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break; + case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break; default: return 1; } break; @@ -4574,51 +4580,58 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) break; case 7: /* VQSHLU */ switch (size) { - case 0: gen_helper_neon_qshl_u8(CPU_T0E01); break; - case 1: gen_helper_neon_qshl_u16(CPU_T0E01); break; - case 2: gen_helper_neon_qshl_u32(CPU_T0E01); break; + case 0: gen_helper_neon_qshl_u8(tmp, cpu_env, tmp, tmp2); break; + case 1: gen_helper_neon_qshl_u16(tmp, cpu_env, tmp, tmp2); break; + case 2: gen_helper_neon_qshl_u32(tmp, cpu_env, tmp, tmp2); break; default: return 1; } break; } + dead_tmp(tmp2); if (op == 1 || op == 3) { /* Accumulate. */ - NEON_GET_REG(T1, rd, pass); - gen_neon_add(size); + tmp2 = neon_load_reg(rd, pass); + gen_neon_add(size, tmp2, tmp); + dead_tmp(tmp2); } else if (op == 4 || (op == 5 && u)) { /* Insert */ switch (size) { case 0: if (op == 4) - imm = 0xff >> -shift; + mask = 0xff >> -shift; else - imm = (uint8_t)(0xff << shift); - imm |= imm << 8; - imm |= imm << 16; + mask = (uint8_t)(0xff << shift); + mask |= mask << 8; + mask |= mask << 16; break; case 1: if (op == 4) - imm = 0xffff >> -shift; + mask = 0xffff >> -shift; else - imm = (uint16_t)(0xffff << shift); - imm |= imm << 16; + mask = (uint16_t)(0xffff << shift); + mask |= mask << 16; break; case 2: - if (op == 4) - imm = 0xffffffffu >> -shift; - else - imm = 0xffffffffu << shift; + if (shift < -31 || shift > 31) { + mask = 0; + } else { + if (op == 4) + mask = 0xffffffffu >> -shift; + else + mask = 0xffffffffu << shift; + } break; default: abort(); } - tmp = neon_load_reg(rd, pass); - tcg_gen_andi_i32(cpu_T[0], cpu_T[0], imm); - tcg_gen_andi_i32(tmp, tmp, ~imm); - tcg_gen_or_i32(cpu_T[0], cpu_T[0], tmp); + tmp2 = neon_load_reg(rd, pass); + tcg_gen_andi_i32(tmp, tmp, mask); + tcg_gen_andi_i32(tmp2, tmp2, ~mask); + tcg_gen_or_i32(tmp, tmp, tmp2); + dead_tmp(tmp2); } - NEON_SET_REG(T0, rd, pass); + neon_store_reg(rd, pass, tmp); } } /* for pass */ } else if (op < 10) { @@ -4678,13 +4691,13 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) else gen_neon_narrow_satu(size - 1, tmp, cpu_V0); } - if (pass == 0) { - tmp2 = tmp; - } else { - neon_store_reg(rd, 0, tmp2); - neon_store_reg(rd, 1, tmp); - } + neon_store_reg(rd, pass, tmp); } /* for pass */ + if (size == 3) { + tcg_temp_free_i64(tmp64); + } else { + dead_tmp(tmp2); + } } else if (op == 10) { /* VSHLL */ if (q || size == 3) @@ -4780,9 +4793,6 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) if (invert) imm = ~imm; - if (op != 14 || !invert) - gen_op_movl_T1_im(imm); - for (pass = 0; pass < (q ? 4 : 2); pass++) { if (op & 1 && op < 12) { tmp = neon_load_reg(rd, pass); @@ -4849,11 +4859,11 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) always aligned so will never overlap with wide destinations in problematic ways. */ if (rd == rm && !src2_wide) { - NEON_GET_REG(T0, rm, 1); - gen_neon_movl_scratch_T0(2); + tmp = neon_load_reg(rm, 1); + neon_store_scratch(2, tmp); } else if (rd == rn && !src1_wide) { - NEON_GET_REG(T0, rn, 1); - gen_neon_movl_scratch_T0(2); + tmp = neon_load_reg(rn, 1); + neon_store_scratch(2, tmp); } TCGV_UNUSED(tmp3); for (pass = 0; pass < 2; pass++) { @@ -4862,9 +4872,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) TCGV_UNUSED(tmp); } else { if (pass == 1 && rd == rn) { - gen_neon_movl_T0_scratch(2); - tmp = new_tmp(); - tcg_gen_mov_i32(tmp, cpu_T[0]); + tmp = neon_load_scratch(2); } else { tmp = neon_load_reg(rn, pass); } @@ -4877,9 +4885,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) TCGV_UNUSED(tmp2); } else { if (pass == 1 && rd == rm) { - gen_neon_movl_T0_scratch(2); - tmp2 = new_tmp(); - tcg_gen_mov_i32(tmp2, cpu_T[0]); + tmp2 = neon_load_scratch(2); } else { tmp2 = neon_load_reg(rm, pass); } @@ -4922,6 +4928,8 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) case 8: case 9: case 10: case 11: case 12: case 13: /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */ gen_neon_mull(cpu_V0, tmp, tmp2, size, u); + dead_tmp(tmp2); + dead_tmp(tmp); break; case 14: /* Polynomial VMULL */ cpu_abort(env, "Polynomial VMULL not implemented"); @@ -5010,55 +5018,56 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) case 9: /* Floating point VMUL scalar */ case 12: /* VQDMULH scalar */ case 13: /* VQRDMULH scalar */ - gen_neon_get_scalar(size, rm); - gen_neon_movl_scratch_T0(0); + tmp = neon_get_scalar(size, rm); + neon_store_scratch(0, tmp); for (pass = 0; pass < (u ? 4 : 2); pass++) { - if (pass != 0) - gen_neon_movl_T0_scratch(0); - NEON_GET_REG(T1, rn, pass); + tmp = neon_load_scratch(0); + tmp2 = neon_load_reg(rn, pass); if (op == 12) { if (size == 1) { - gen_helper_neon_qdmulh_s16(CPU_T0E01); + gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); } else { - gen_helper_neon_qdmulh_s32(CPU_T0E01); + gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); } } else if (op == 13) { if (size == 1) { - gen_helper_neon_qrdmulh_s16(CPU_T0E01); + gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); } else { - gen_helper_neon_qrdmulh_s32(CPU_T0E01); + gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); } } else if (op & 1) { - gen_helper_neon_mul_f32(CPU_T001); + gen_helper_neon_mul_f32(tmp, tmp, tmp2); } else { switch (size) { - case 0: gen_helper_neon_mul_u8(CPU_T001); break; - case 1: gen_helper_neon_mul_u16(CPU_T001); break; - case 2: gen_op_mul_T0_T1(); break; + case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break; + case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break; + case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break; default: return 1; } } + dead_tmp(tmp2); if (op < 8) { /* Accumulate. */ - NEON_GET_REG(T1, rd, pass); + tmp2 = neon_load_reg(rd, pass); switch (op) { case 0: - gen_neon_add(size); + gen_neon_add(size, tmp, tmp2); break; case 1: - gen_helper_neon_add_f32(CPU_T001); + gen_helper_neon_add_f32(tmp, tmp, tmp2); break; case 4: - gen_neon_rsb(size); + gen_neon_rsb(size, tmp, tmp2); break; case 5: - gen_helper_neon_sub_f32(cpu_T[0], cpu_T[1], cpu_T[0]); + gen_helper_neon_sub_f32(tmp, tmp2, tmp); break; default: abort(); } + dead_tmp(tmp2); } - NEON_SET_REG(T0, rd, pass); + neon_store_reg(rd, pass, tmp); } break; case 2: /* VMLAL sclar */ @@ -5070,19 +5079,17 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) if (size == 0 && (op == 3 || op == 7 || op == 11)) return 1; - gen_neon_get_scalar(size, rm); - NEON_GET_REG(T1, rn, 1); + tmp2 = neon_get_scalar(size, rm); + tmp3 = neon_load_reg(rn, 1); for (pass = 0; pass < 2; pass++) { if (pass == 0) { tmp = neon_load_reg(rn, 0); } else { - tmp = new_tmp(); - tcg_gen_mov_i32(tmp, cpu_T[1]); + tmp = tmp3; } - tmp2 = new_tmp(); - tcg_gen_mov_i32(tmp2, cpu_T[0]); gen_neon_mull(cpu_V0, tmp, tmp2, size, u); + dead_tmp(tmp); if (op == 6 || op == 7) { gen_neon_negl(cpu_V0, size); } @@ -5108,6 +5115,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) } neon_store_reg64(cpu_V0, rd + pass); } + + dead_tmp(tmp2); + break; default: /* 14 and 15 are RESERVED */ return 1; @@ -5153,6 +5163,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8)); tcg_gen_shri_i64(tmp64, tmp64, imm * 8); tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64); + tcg_temp_free_i64(tmp64); } else { /* BUGFIX */ neon_load_reg64(cpu_V0, rn); @@ -5174,25 +5185,24 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) if (size == 3) return 1; for (pass = 0; pass < (q ? 2 : 1); pass++) { - NEON_GET_REG(T0, rm, pass * 2); - NEON_GET_REG(T1, rm, pass * 2 + 1); + tmp = neon_load_reg(rm, pass * 2); + tmp2 = neon_load_reg(rm, pass * 2 + 1); switch (size) { - case 0: tcg_gen_bswap32_i32(cpu_T[0], cpu_T[0]); break; - case 1: gen_swap_half(cpu_T[0]); break; + case 0: tcg_gen_bswap32_i32(tmp, tmp); break; + case 1: gen_swap_half(tmp); break; case 2: /* no-op */ break; default: abort(); } - NEON_SET_REG(T0, rd, pass * 2 + 1); + neon_store_reg(rd, pass * 2 + 1, tmp); if (size == 2) { - NEON_SET_REG(T1, rd, pass * 2); + neon_store_reg(rd, pass * 2, tmp2); } else { - gen_op_movl_T0_T1(); switch (size) { - case 0: tcg_gen_bswap32_i32(cpu_T[0], cpu_T[0]); break; - case 1: gen_swap_half(cpu_T[0]); break; + case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break; + case 1: gen_swap_half(tmp2); break; default: abort(); } - NEON_SET_REG(T0, rd, pass * 2); + neon_store_reg(rd, pass * 2, tmp2); } } break; @@ -5222,10 +5232,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) case 33: /* VTRN */ if (size == 2) { for (n = 0; n < (q ? 4 : 2); n += 2) { - NEON_GET_REG(T0, rm, n); - NEON_GET_REG(T1, rd, n + 1); - NEON_SET_REG(T1, rm, n); - NEON_SET_REG(T0, rd, n + 1); + tmp = neon_load_reg(rm, n); + tmp2 = neon_load_reg(rd, n + 1); + neon_store_reg(rm, n, tmp2); + neon_store_reg(rd, n + 1, tmp); } } else { goto elementwise; @@ -5245,16 +5255,16 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) {0, 2, 4, 6, 1, 3, 5, 7}; for (n = 0; n < 8; n++) { int reg = (n < 4) ? rd : rm; - gen_neon_movl_T0_scratch(unzip_order_q[n]); - NEON_SET_REG(T0, reg, n % 4); + tmp = neon_load_scratch(unzip_order_q[n]); + neon_store_reg(reg, n % 4, tmp); } } else { static int unzip_order[4] = {0, 4, 1, 5}; for (n = 0; n < 4; n++) { int reg = (n < 2) ? rd : rm; - gen_neon_movl_T0_scratch(unzip_order[n]); - NEON_SET_REG(T0, reg, n % 2); + tmp = neon_load_scratch(unzip_order[n]); + neon_store_reg(reg, n % 2, tmp); } } break; @@ -5267,21 +5277,21 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) return 1; count = (q ? 4 : 2); for (n = 0; n < count; n++) { - NEON_GET_REG(T0, rd, n); - NEON_GET_REG(T1, rd, n); + tmp = neon_load_reg(rd, n); + tmp2 = neon_load_reg(rd, n); switch (size) { - case 0: gen_helper_neon_zip_u8(); break; - case 1: gen_helper_neon_zip_u16(); break; + case 0: gen_neon_zip_u8(tmp, tmp2); break; + case 1: gen_neon_zip_u16(tmp, tmp2); break; case 2: /* no-op */; break; default: abort(); } - gen_neon_movl_scratch_T0(n * 2); - gen_neon_movl_scratch_T1(n * 2 + 1); + neon_store_scratch(n * 2, tmp); + neon_store_scratch(n * 2 + 1, tmp2); } for (n = 0; n < count * 2; n++) { int reg = (n < count) ? rd : rm; - gen_neon_movl_T0_scratch(n); - NEON_SET_REG(T0, reg, n % count); + tmp = neon_load_scratch(n); + neon_store_reg(reg, n % count, tmp); } break; case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */ @@ -5324,124 +5334,132 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) if (op == 30 || op == 31 || op >= 58) { tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass)); + TCGV_UNUSED(tmp); } else { - NEON_GET_REG(T0, rm, pass); + tmp = neon_load_reg(rm, pass); } switch (op) { case 1: /* VREV32 */ switch (size) { - case 0: tcg_gen_bswap32_i32(cpu_T[0], cpu_T[0]); break; - case 1: gen_swap_half(cpu_T[0]); break; + case 0: tcg_gen_bswap32_i32(tmp, tmp); break; + case 1: gen_swap_half(tmp); break; default: return 1; } break; case 2: /* VREV16 */ if (size != 0) return 1; - gen_rev16(cpu_T[0]); + gen_rev16(tmp); break; case 8: /* CLS */ switch (size) { - case 0: gen_helper_neon_cls_s8(cpu_T[0], cpu_T[0]); break; - case 1: gen_helper_neon_cls_s16(cpu_T[0], cpu_T[0]); break; - case 2: gen_helper_neon_cls_s32(cpu_T[0], cpu_T[0]); break; + case 0: gen_helper_neon_cls_s8(tmp, tmp); break; + case 1: gen_helper_neon_cls_s16(tmp, tmp); break; + case 2: gen_helper_neon_cls_s32(tmp, tmp); break; default: return 1; } break; case 9: /* CLZ */ switch (size) { - case 0: gen_helper_neon_clz_u8(cpu_T[0], cpu_T[0]); break; - case 1: gen_helper_neon_clz_u16(cpu_T[0], cpu_T[0]); break; - case 2: gen_helper_clz(cpu_T[0], cpu_T[0]); break; + case 0: gen_helper_neon_clz_u8(tmp, tmp); break; + case 1: gen_helper_neon_clz_u16(tmp, tmp); break; + case 2: gen_helper_clz(tmp, tmp); break; default: return 1; } break; case 10: /* CNT */ if (size != 0) return 1; - gen_helper_neon_cnt_u8(cpu_T[0], cpu_T[0]); + gen_helper_neon_cnt_u8(tmp, tmp); break; case 11: /* VNOT */ if (size != 0) return 1; - gen_op_notl_T0(); + tcg_gen_not_i32(tmp, tmp); break; case 14: /* VQABS */ switch (size) { - case 0: gen_helper_neon_qabs_s8(cpu_T[0], cpu_env, cpu_T[0]); break; - case 1: gen_helper_neon_qabs_s16(cpu_T[0], cpu_env, cpu_T[0]); break; - case 2: gen_helper_neon_qabs_s32(cpu_T[0], cpu_env, cpu_T[0]); break; + case 0: gen_helper_neon_qabs_s8(tmp, cpu_env, tmp); break; + case 1: gen_helper_neon_qabs_s16(tmp, cpu_env, tmp); break; + case 2: gen_helper_neon_qabs_s32(tmp, cpu_env, tmp); break; default: return 1; } break; case 15: /* VQNEG */ switch (size) { - case 0: gen_helper_neon_qneg_s8(cpu_T[0], cpu_env, cpu_T[0]); break; - case 1: gen_helper_neon_qneg_s16(cpu_T[0], cpu_env, cpu_T[0]); break; - case 2: gen_helper_neon_qneg_s32(cpu_T[0], cpu_env, cpu_T[0]); break; + case 0: gen_helper_neon_qneg_s8(tmp, cpu_env, tmp); break; + case 1: gen_helper_neon_qneg_s16(tmp, cpu_env, tmp); break; + case 2: gen_helper_neon_qneg_s32(tmp, cpu_env, tmp); break; default: return 1; } break; case 16: case 19: /* VCGT #0, VCLE #0 */ - gen_op_movl_T1_im(0); + tmp2 = tcg_const_i32(0); switch(size) { - case 0: gen_helper_neon_cgt_s8(CPU_T001); break; - case 1: gen_helper_neon_cgt_s16(CPU_T001); break; - case 2: gen_helper_neon_cgt_s32(CPU_T001); break; + case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break; + case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break; + case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break; default: return 1; } + tcg_temp_free(tmp2); if (op == 19) - gen_op_notl_T0(); + tcg_gen_not_i32(tmp, tmp); break; case 17: case 20: /* VCGE #0, VCLT #0 */ - gen_op_movl_T1_im(0); + tmp2 = tcg_const_i32(0); switch(size) { - case 0: gen_helper_neon_cge_s8(CPU_T001); break; - case 1: gen_helper_neon_cge_s16(CPU_T001); break; - case 2: gen_helper_neon_cge_s32(CPU_T001); break; + case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break; + case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break; + case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break; default: return 1; } + tcg_temp_free(tmp2); if (op == 20) - gen_op_notl_T0(); + tcg_gen_not_i32(tmp, tmp); break; case 18: /* VCEQ #0 */ - gen_op_movl_T1_im(0); + tmp2 = tcg_const_i32(0); switch(size) { - case 0: gen_helper_neon_ceq_u8(CPU_T001); break; - case 1: gen_helper_neon_ceq_u16(CPU_T001); break; - case 2: gen_helper_neon_ceq_u32(CPU_T001); break; + case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break; + case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break; + case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break; default: return 1; } + tcg_temp_free(tmp2); break; case 22: /* VABS */ switch(size) { - case 0: gen_helper_neon_abs_s8(cpu_T[0], cpu_T[0]); break; - case 1: gen_helper_neon_abs_s16(cpu_T[0], cpu_T[0]); break; - case 2: tcg_gen_abs_i32(cpu_T[0], cpu_T[0]); break; + case 0: gen_helper_neon_abs_s8(tmp, tmp); break; + case 1: gen_helper_neon_abs_s16(tmp, tmp); break; + case 2: tcg_gen_abs_i32(tmp, tmp); break; default: return 1; } break; case 23: /* VNEG */ - gen_op_movl_T1_im(0); if (size == 3) return 1; - gen_neon_rsb(size); + tmp2 = tcg_const_i32(0); + gen_neon_rsb(size, tmp, tmp2); + tcg_temp_free(tmp2); break; case 24: case 27: /* Float VCGT #0, Float VCLE #0 */ - gen_op_movl_T1_im(0); - gen_helper_neon_cgt_f32(CPU_T001); + tmp2 = tcg_const_i32(0); + gen_helper_neon_cgt_f32(tmp, tmp, tmp2); + tcg_temp_free(tmp2); if (op == 27) - gen_op_notl_T0(); + tcg_gen_not_i32(tmp, tmp); break; case 25: case 28: /* Float VCGE #0, Float VCLT #0 */ - gen_op_movl_T1_im(0); - gen_helper_neon_cge_f32(CPU_T001); + tmp2 = tcg_const_i32(0); + gen_helper_neon_cge_f32(tmp, tmp, tmp2); + tcg_temp_free(tmp2); if (op == 28) - gen_op_notl_T0(); + tcg_gen_not_i32(tmp, tmp); break; case 26: /* Float VCEQ #0 */ - gen_op_movl_T1_im(0); - gen_helper_neon_ceq_f32(CPU_T001); + tmp2 = tcg_const_i32(0); + gen_helper_neon_ceq_f32(tmp, tmp, tmp2); + tcg_temp_free(tmp2); break; case 30: /* Float VABS */ gen_vfp_abs(0); @@ -5450,24 +5468,24 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) gen_vfp_neg(0); break; case 32: /* VSWP */ - NEON_GET_REG(T1, rd, pass); - NEON_SET_REG(T1, rm, pass); + tmp2 = neon_load_reg(rd, pass); + neon_store_reg(rm, pass, tmp2); break; case 33: /* VTRN */ - NEON_GET_REG(T1, rd, pass); + tmp2 = neon_load_reg(rd, pass); switch (size) { - case 0: gen_helper_neon_trn_u8(); break; - case 1: gen_helper_neon_trn_u16(); break; + case 0: gen_neon_trn_u8(tmp, tmp2); break; + case 1: gen_neon_trn_u16(tmp, tmp2); break; case 2: abort(); default: return 1; } - NEON_SET_REG(T1, rm, pass); + neon_store_reg(rm, pass, tmp2); break; case 56: /* Integer VRECPE */ - gen_helper_recpe_u32(cpu_T[0], cpu_T[0], cpu_env); + gen_helper_recpe_u32(tmp, tmp, cpu_env); break; case 57: /* Integer VRSQRTE */ - gen_helper_rsqrte_u32(cpu_T[0], cpu_T[0], cpu_env); + gen_helper_rsqrte_u32(tmp, tmp, cpu_env); break; case 58: /* Float VRECPE */ gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env); @@ -5495,7 +5513,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass)); } else { - NEON_SET_REG(T0, rd, pass); + neon_store_reg(rd, pass, tmp); } } break; @@ -5510,8 +5528,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) tcg_gen_movi_i32(tmp, 0); } tmp2 = neon_load_reg(rm, 0); - gen_helper_neon_tbl(tmp2, tmp2, tmp, tcg_const_i32(rn), - tcg_const_i32(n)); + tmp4 = tcg_const_i32(rn); + tmp5 = tcg_const_i32(n); + gen_helper_neon_tbl(tmp2, tmp2, tmp, tmp4, tmp5); dead_tmp(tmp); if (insn & (1 << 6)) { tmp = neon_load_reg(rd, 1); @@ -5520,29 +5539,33 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) tcg_gen_movi_i32(tmp, 0); } tmp3 = neon_load_reg(rm, 1); - gen_helper_neon_tbl(tmp3, tmp3, tmp, tcg_const_i32(rn), - tcg_const_i32(n)); + gen_helper_neon_tbl(tmp3, tmp3, tmp, tmp4, tmp5); + tcg_temp_free_i32(tmp5); + tcg_temp_free_i32(tmp4); neon_store_reg(rd, 0, tmp2); neon_store_reg(rd, 1, tmp3); dead_tmp(tmp); } else if ((insn & 0x380) == 0) { /* VDUP */ if (insn & (1 << 19)) { - NEON_SET_REG(T0, rm, 1); + tmp = neon_load_reg(rm, 1); } else { - NEON_SET_REG(T0, rm, 0); + tmp = neon_load_reg(rm, 0); } if (insn & (1 << 16)) { - gen_neon_dup_u8(cpu_T[0], ((insn >> 17) & 3) * 8); + gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8); } else if (insn & (1 << 17)) { if ((insn >> 18) & 1) - gen_neon_dup_high16(cpu_T[0]); + gen_neon_dup_high16(tmp); else - gen_neon_dup_low16(cpu_T[0]); + gen_neon_dup_low16(tmp); } for (pass = 0; pass < (q ? 4 : 2); pass++) { - NEON_SET_REG(T0, rd, pass); + tmp2 = new_tmp(); + tcg_gen_mov_i32(tmp2, tmp); + neon_store_reg(rd, pass, tmp2); } + dead_tmp(tmp); } else { return 1; } @@ -5681,6 +5704,7 @@ static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow) tcg_gen_extu_i32_i64(tmp, tmp2); dead_tmp(tmp2); tcg_gen_add_i64(val, val, tmp); + tcg_temp_free_i64(tmp); } /* load and add a 64-bit value from a register pair. */ @@ -5698,6 +5722,7 @@ static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh) dead_tmp(tmpl); dead_tmp(tmph); tcg_gen_add_i64(val, val, tmp); + tcg_temp_free_i64(tmp); } /* Set N and Z flags from a 64-bit value. */ @@ -5772,7 +5797,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) } } else if ((insn & 0x0e5fffe0) == 0x084d0500) { /* srs */ - uint32_t offset; + int32_t offset; if (IS_USER(s)) goto illegal_op; ARCH(6); @@ -5781,13 +5806,15 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) addr = load_reg(s, 13); } else { addr = new_tmp(); - gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op1)); + tmp = tcg_const_i32(op1); + gen_helper_get_r13_banked(addr, cpu_env, tmp); + tcg_temp_free_i32(tmp); } i = (insn >> 23) & 3; switch (i) { case 0: offset = -4; break; /* DA */ - case 1: offset = -8; break; /* DB */ - case 2: offset = 0; break; /* IA */ + case 1: offset = 0; break; /* IA */ + case 2: offset = -8; break; /* DB */ case 3: offset = 4; break; /* IB */ default: abort(); } @@ -5795,32 +5822,34 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) tcg_gen_addi_i32(addr, addr, offset); tmp = load_reg(s, 14); gen_st32(tmp, addr, 0); - tmp = new_tmp(); - gen_helper_cpsr_read(tmp); + tmp = load_cpu_field(spsr); tcg_gen_addi_i32(addr, addr, 4); gen_st32(tmp, addr, 0); if (insn & (1 << 21)) { /* Base writeback. */ switch (i) { case 0: offset = -8; break; - case 1: offset = -4; break; - case 2: offset = 4; break; + case 1: offset = 4; break; + case 2: offset = -4; break; case 3: offset = 0; break; default: abort(); } if (offset) - tcg_gen_addi_i32(addr, tmp, offset); + tcg_gen_addi_i32(addr, addr, offset); if (op1 == (env->uncached_cpsr & CPSR_M)) { - gen_movl_reg_T1(s, 13); + store_reg(s, 13, addr); } else { - gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), cpu_T[1]); + tmp = tcg_const_i32(op1); + gen_helper_set_r13_banked(cpu_env, tmp, addr); + tcg_temp_free_i32(tmp); + dead_tmp(addr); } } else { dead_tmp(addr); } } else if ((insn & 0x0e5fffe0) == 0x081d0a00) { /* rfe */ - uint32_t offset; + int32_t offset; if (IS_USER(s)) goto illegal_op; ARCH(6); @@ -5829,8 +5858,8 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) i = (insn >> 23) & 3; switch (i) { case 0: offset = -4; break; /* DA */ - case 1: offset = -8; break; /* DB */ - case 2: offset = 0; break; /* IA */ + case 1: offset = 0; break; /* IA */ + case 2: offset = -8; break; /* DB */ case 3: offset = 4; break; /* IB */ default: abort(); } @@ -5844,8 +5873,8 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) /* Base writeback. */ switch (i) { case 0: offset = -8; break; - case 1: offset = -4; break; - case 2: offset = 4; break; + case 1: offset = 4; break; + case 2: offset = -4; break; case 3: offset = 0; break; default: abort(); } @@ -5856,6 +5885,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) dead_tmp(addr); } gen_rfe(s, tmp, tmp2); + return; } else if ((insn & 0x0e000000) == 0x0a000000) { /* branch link and change to thumb (blx <offset>) */ int32_t offset; @@ -5905,8 +5935,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) val |= (insn & 0x1f); } if (mask) { - gen_op_movl_T0_im(val); - gen_set_psr_T0(s, mask, 0); + gen_set_psr_im(s, mask, 0, val); } return; } @@ -5946,9 +5975,8 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) shift = ((insn >> 8) & 0xf) * 2; if (shift) val = (val >> shift) | (val << (32 - shift)); - gen_op_movl_T0_im(val); i = ((insn & (1 << 22)) != 0); - if (gen_set_psr_T0(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i)) + if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val)) goto illegal_op; } } @@ -5962,9 +5990,9 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) case 0x0: /* move program status register */ if (op1 & 1) { /* PSR = reg */ - gen_movl_T0_reg(s, rm); + tmp = load_reg(s, rm); i = ((op1 & 2) != 0); - if (gen_set_psr_T0(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i)) + if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp)) goto illegal_op; } else { /* reg = PSR */ @@ -6055,6 +6083,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) tcg_gen_shri_i64(tmp64, tmp64, 16); tmp = new_tmp(); tcg_gen_trunc_i64_i32(tmp, tmp64); + tcg_temp_free_i64(tmp64); if ((sh & 2) == 0) { tmp2 = load_reg(s, rn); gen_helper_add_setq(tmp, tmp, tmp2); @@ -6073,6 +6102,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) dead_tmp(tmp); gen_addq(s, tmp64, rn, rd); gen_storeq_reg(s, rn, rd, tmp64); + tcg_temp_free_i64(tmp64); } else { if (op1 == 0) { tmp2 = load_reg(s, rn); @@ -6249,7 +6279,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) } break; case 0x0e: - tcg_gen_bic_i32(tmp, tmp, tmp2); + tcg_gen_andc_i32(tmp, tmp, tmp2); if (logic_cc) { gen_logic_CC(tmp); } @@ -6323,6 +6353,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) if (insn & (1 << 20)) gen_logicq_cc(tmp64); gen_storeq_reg(s, rn, rd, tmp64); + tcg_temp_free_i64(tmp64); break; } } else { @@ -6335,10 +6366,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) ARCH(6K); else ARCH(6); - gen_movl_T1_reg(s, rn); - addr = cpu_T[1]; + addr = tcg_temp_local_new_i32(); + load_reg_var(s, addr, rn); if (insn & (1 << 20)) { - gen_helper_mark_exclusive(cpu_env, cpu_T[1]); + gen_helper_mark_exclusive(cpu_env, addr); switch (op1) { case 0: /* ldrex */ tmp = gen_ld32(addr, IS_USER(s)); @@ -6363,9 +6394,9 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) } else { int label = gen_new_label(); rm = insn & 0xf; - gen_helper_test_exclusive(cpu_T[0], cpu_env, addr); - tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0], - 0, label); + tmp2 = tcg_temp_local_new_i32(); + gen_helper_test_exclusive(tmp2, cpu_env, addr); + tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label); tmp = load_reg(s,rm); switch (op1) { case 0: /* strex */ @@ -6387,8 +6418,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) abort(); } gen_set_label(label); - gen_movl_reg_T0(s, rd); + tcg_gen_mov_i32(cpu_R[rd], tmp2); + tcg_temp_free(tmp2); } + tcg_temp_free(addr); } else { /* SWP instruction */ rm = (insn) & 0xf; @@ -6540,10 +6573,12 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) } sh = (insn >> 16) & 0x1f; if (sh != 0) { + tmp2 = tcg_const_i32(sh); if (insn & (1 << 22)) - gen_helper_usat(tmp, tmp, tcg_const_i32(sh)); + gen_helper_usat(tmp, tmp, tmp2); else - gen_helper_ssat(tmp, tmp, tcg_const_i32(sh)); + gen_helper_ssat(tmp, tmp, tmp2); + tcg_temp_free_i32(tmp2); } store_reg(s, rd, tmp); } else if ((insn & 0x00300fe0) == 0x00200f20) { @@ -6551,10 +6586,12 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) tmp = load_reg(s, rm); sh = (insn >> 16) & 0x1f; if (sh != 0) { + tmp2 = tcg_const_i32(sh); if (insn & (1 << 22)) - gen_helper_usat16(tmp, tmp, tcg_const_i32(sh)); + gen_helper_usat16(tmp, tmp, tmp2); else - gen_helper_ssat16(tmp, tmp, tcg_const_i32(sh)); + gen_helper_ssat16(tmp, tmp, tmp2); + tcg_temp_free_i32(tmp2); } store_reg(s, rd, tmp); } else if ((insn & 0x00700fe0) == 0x00000fa0) { @@ -6573,7 +6610,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) /* ??? In many cases it's not neccessary to do a rotate, a shift is sufficient. */ if (shift != 0) - tcg_gen_rori_i32(tmp, tmp, shift * 8); + tcg_gen_rotri_i32(tmp, tmp, shift * 8); op1 = (insn >> 20) & 7; switch (op1) { case 0: gen_sxtb16(tmp); break; @@ -6626,6 +6663,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) tcg_gen_shri_i64(tmp64, tmp64, 32); tmp = new_tmp(); tcg_gen_trunc_i64_i32(tmp, tmp64); + tcg_temp_free_i64(tmp64); if (rd != 15) { tmp2 = load_reg(s, rd); if (insn & (1 << 6)) { @@ -6654,6 +6692,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) dead_tmp(tmp); gen_addq(s, tmp64, rd, rn); gen_storeq_reg(s, rd, rn, tmp64); + tcg_temp_free_i64(tmp64); } else { /* smuad, smusd, smlad, smlsd */ if (rd != 15) @@ -6826,7 +6865,9 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) if (i == 15) { gen_bx(s, tmp); } else if (user) { - gen_helper_set_user_reg(tcg_const_i32(i), tmp); + tmp2 = tcg_const_i32(i); + gen_helper_set_user_reg(tmp2, tmp); + tcg_temp_free_i32(tmp2); dead_tmp(tmp); } else if (i == rn) { loaded_var = tmp; @@ -6843,7 +6884,9 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) tcg_gen_movi_i32(tmp, val); } else if (user) { tmp = new_tmp(); - gen_helper_get_user_reg(tmp, tcg_const_i32(i)); + tmp2 = tcg_const_i32(i); + gen_helper_get_user_reg(tmp, tmp2); + tcg_temp_free_i32(tmp2); } else { tmp = load_reg(s, i); } @@ -6944,70 +6987,70 @@ thumb2_logic_op(int op) Returns zero if the opcode is valid. */ static int -gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out) +gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1) { int logic_cc; logic_cc = 0; switch (op) { case 0: /* and */ - gen_op_andl_T0_T1(); + tcg_gen_and_i32(t0, t0, t1); logic_cc = conds; break; case 1: /* bic */ - gen_op_bicl_T0_T1(); + tcg_gen_andc_i32(t0, t0, t1); logic_cc = conds; break; case 2: /* orr */ - gen_op_orl_T0_T1(); + tcg_gen_or_i32(t0, t0, t1); logic_cc = conds; break; case 3: /* orn */ - gen_op_notl_T1(); - gen_op_orl_T0_T1(); + tcg_gen_not_i32(t1, t1); + tcg_gen_or_i32(t0, t0, t1); logic_cc = conds; break; case 4: /* eor */ - gen_op_xorl_T0_T1(); + tcg_gen_xor_i32(t0, t0, t1); logic_cc = conds; break; case 8: /* add */ if (conds) - gen_op_addl_T0_T1_cc(); + gen_helper_add_cc(t0, t0, t1); else - gen_op_addl_T0_T1(); + tcg_gen_add_i32(t0, t0, t1); break; case 10: /* adc */ if (conds) - gen_op_adcl_T0_T1_cc(); + gen_helper_adc_cc(t0, t0, t1); else - gen_adc_T0_T1(); + gen_adc(t0, t1); break; case 11: /* sbc */ if (conds) - gen_op_sbcl_T0_T1_cc(); + gen_helper_sbc_cc(t0, t0, t1); else - gen_sbc_T0_T1(); + gen_sub_carry(t0, t0, t1); break; case 13: /* sub */ if (conds) - gen_op_subl_T0_T1_cc(); + gen_helper_sub_cc(t0, t0, t1); else - gen_op_subl_T0_T1(); + tcg_gen_sub_i32(t0, t0, t1); break; case 14: /* rsb */ if (conds) - gen_op_rsbl_T0_T1_cc(); + gen_helper_sub_cc(t0, t1, t0); else - gen_op_rsbl_T0_T1(); + tcg_gen_sub_i32(t0, t1, t0); break; default: /* 5, 6, 7, 9, 12, 15. */ return 1; } if (logic_cc) { - gen_op_logic_T0_cc(); + gen_logic_CC(t0); if (shifter_out) - gen_set_CF_bit31(cpu_T[1]); + gen_set_CF_bit31(t1); } return 0; } @@ -7063,8 +7106,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) 16-bit instructions in case the second half causes an prefetch abort. */ offset = ((int32_t)insn << 21) >> 9; - gen_op_movl_T0_im(s->pc + 2 + offset); - gen_movl_reg_T0(s, 14); + tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset); return 0; } /* Fall through to 32-bit decode. */ @@ -7130,22 +7172,24 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) } } else if ((insn & (1 << 23)) == 0) { /* Load/store exclusive word. */ - gen_movl_T1_reg(s, rn); - addr = cpu_T[1]; + addr = tcg_temp_local_new(); + load_reg_var(s, addr, rn); if (insn & (1 << 20)) { - gen_helper_mark_exclusive(cpu_env, cpu_T[1]); + gen_helper_mark_exclusive(cpu_env, addr); tmp = gen_ld32(addr, IS_USER(s)); store_reg(s, rd, tmp); } else { int label = gen_new_label(); - gen_helper_test_exclusive(cpu_T[0], cpu_env, addr); - tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0], - 0, label); + tmp2 = tcg_temp_local_new(); + gen_helper_test_exclusive(tmp2, cpu_env, addr); + tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label); tmp = load_reg(s, rs); - gen_st32(tmp, cpu_T[1], IS_USER(s)); + gen_st32(tmp, addr, IS_USER(s)); gen_set_label(label); - gen_movl_reg_T0(s, rd); + tcg_gen_mov_i32(cpu_R[rd], tmp2); + tcg_temp_free(tmp2); } + tcg_temp_free(addr); } else if ((insn & (1 << 6)) == 0) { /* Table Branch. */ if (rn == 15) { @@ -7175,10 +7219,8 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) we never have multiple CPUs running in parallel, so it is good enough. */ op = (insn >> 4) & 0x3; - /* Must use a global reg for the address because we have - a conditional branch in the store instruction. */ - gen_movl_T1_reg(s, rn); - addr = cpu_T[1]; + addr = tcg_temp_local_new(); + load_reg_var(s, addr, rn); if (insn & (1 << 20)) { gen_helper_mark_exclusive(cpu_env, addr); switch (op) { @@ -7200,9 +7242,9 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) store_reg(s, rs, tmp); } else { int label = gen_new_label(); - /* Must use a global that is not killed by the branch. */ - gen_helper_test_exclusive(cpu_T[0], cpu_env, addr); - tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0], 0, label); + tmp2 = tcg_temp_local_new(); + gen_helper_test_exclusive(tmp2, cpu_env, addr); + tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label); tmp = load_reg(s, rs); switch (op) { case 0: @@ -7221,8 +7263,10 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) goto illegal_op; } gen_set_label(label); - gen_movl_reg_T0(s, rm); + tcg_gen_mov_i32(cpu_R[rm], tmp2); + tcg_temp_free(tmp2); } + tcg_temp_free(addr); } } else { /* Load/store multiple, RFE, SRS. */ @@ -7258,7 +7302,9 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) addr = load_reg(s, 13); } else { addr = new_tmp(); - gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op)); + tmp = tcg_const_i32(op); + gen_helper_get_r13_banked(addr, cpu_env, tmp); + tcg_temp_free_i32(tmp); } if ((insn & (1 << 24)) == 0) { tcg_gen_addi_i32(addr, addr, -8); @@ -7278,8 +7324,9 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) if (op == (env->uncached_cpsr & CPSR_M)) { store_reg(s, 13, addr); } else { - gen_helper_set_r13_banked(cpu_env, - tcg_const_i32(op), addr); + tmp = tcg_const_i32(op); + gen_helper_set_r13_banked(cpu_env, tmp, addr); + tcg_temp_free_i32(tmp); } } else { dead_tmp(addr); @@ -7332,21 +7379,27 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) } break; case 5: /* Data processing register constant shift. */ - if (rn == 15) - gen_op_movl_T0_im(0); - else - gen_movl_T0_reg(s, rn); - gen_movl_T1_reg(s, rm); + if (rn == 15) { + tmp = new_tmp(); + tcg_gen_movi_i32(tmp, 0); + } else { + tmp = load_reg(s, rn); + } + tmp2 = load_reg(s, rm); op = (insn >> 21) & 0xf; shiftop = (insn >> 4) & 3; shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c); conds = (insn & (1 << 20)) != 0; logic_cc = (conds && thumb2_logic_op(op)); - gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc); - if (gen_thumb2_data_op(s, op, conds, 0)) + gen_arm_shift_im(tmp2, shiftop, shift, logic_cc); + if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2)) goto illegal_op; - if (rd != 15) - gen_movl_reg_T0(s, rd); + dead_tmp(tmp2); + if (rd != 15) { + store_reg(s, rd, tmp); + } else { + dead_tmp(tmp); + } break; case 13: /* Misc data processing. */ op = ((insn >> 22) & 6) | ((insn >> 7) & 1); @@ -7371,7 +7424,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) /* ??? In many cases it's not neccessary to do a rotate, a shift is sufficient. */ if (shift != 0) - tcg_gen_rori_i32(tmp, tmp, shift * 8); + tcg_gen_rotri_i32(tmp, tmp, shift * 8); op = (insn >> 20) & 7; switch (op) { case 0: gen_sxth(tmp); break; @@ -7503,6 +7556,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) tcg_gen_shri_i64(tmp64, tmp64, 16); tmp = new_tmp(); tcg_gen_trunc_i64_i32(tmp, tmp64); + tcg_temp_free_i64(tmp64); if (rs != 15) { tmp2 = load_reg(s, rs); @@ -7572,6 +7626,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) dead_tmp(tmp); gen_addq(s, tmp64, rs, rd); gen_storeq_reg(s, rs, rd, tmp64); + tcg_temp_free_i64(tmp64); } else { if (op & 0x20) { /* Unsigned 64-bit multiply */ @@ -7598,6 +7653,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) gen_addq(s, tmp64, rs, rd); } gen_storeq_reg(s, rs, rd, tmp64); + tcg_temp_free_i64(tmp64); } break; } @@ -7633,8 +7689,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) if (insn & (1 << 14)) { /* Branch and link. */ - gen_op_movl_T1_im(s->pc | 1); - gen_movl_reg_T1(s, 14); + tcg_gen_movi_i32(cpu_R[14], s->pc | 1); } offset += s->pc; @@ -7662,6 +7717,8 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) tmp = load_reg(s, rn); addr = tcg_const_i32(insn & 0xff); gen_helper_v7m_msr(cpu_env, addr, tmp); + tcg_temp_free_i32(addr); + dead_tmp(tmp); gen_lookup_tb(s); break; } @@ -7669,10 +7726,10 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) case 1: /* msr spsr. */ if (IS_M(env)) goto illegal_op; - gen_movl_T0_reg(s, rn); - if (gen_set_psr_T0(s, + tmp = load_reg(s, rn); + if (gen_set_psr(s, msr_mask(env, s, (insn >> 8) & 0xf, op == 1), - op == 1)) + op == 1, tmp)) goto illegal_op; break; case 2: /* cps, nop-hint. */ @@ -7699,8 +7756,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) imm |= (insn & 0x1f); } if (offset) { - gen_op_movl_T0_im(imm); - gen_set_psr_T0(s, offset, 0); + gen_set_psr_im(s, offset, 0, imm); } break; case 3: /* Special control operations. */ @@ -7732,6 +7788,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) if (IS_M(env)) { addr = tcg_const_i32(insn & 0xff); gen_helper_v7m_mrs(tmp, cpu_env, addr); + tcg_temp_free_i32(addr); } else { gen_helper_cpsr_read(tmp); } @@ -7832,6 +7889,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) else gen_helper_ssat(tmp, tmp, tmp2); } + tcg_temp_free_i32(tmp2); break; } store_reg(s, rd, tmp); @@ -7898,19 +7956,25 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) shifter_out = 1; break; } - gen_op_movl_T1_im(imm); + tmp2 = new_tmp(); + tcg_gen_movi_i32(tmp2, imm); rn = (insn >> 16) & 0xf; - if (rn == 15) - gen_op_movl_T0_im(0); - else - gen_movl_T0_reg(s, rn); + if (rn == 15) { + tmp = new_tmp(); + tcg_gen_movi_i32(tmp, 0); + } else { + tmp = load_reg(s, rn); + } op = (insn >> 21) & 0xf; if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0, - shifter_out)) + shifter_out, tmp, tmp2)) goto illegal_op; + dead_tmp(tmp2); rd = (insn >> 8) & 0xf; if (rd != 15) { - gen_movl_reg_T0(s, rd); + store_reg(s, rd, tmp); + } else { + dead_tmp(tmp); } } } @@ -8054,32 +8118,35 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) switch (insn >> 12) { case 0: case 1: + rd = insn & 7; op = (insn >> 11) & 3; if (op == 3) { /* add/subtract */ rn = (insn >> 3) & 7; - gen_movl_T0_reg(s, rn); + tmp = load_reg(s, rn); if (insn & (1 << 10)) { /* immediate */ - gen_op_movl_T1_im((insn >> 6) & 7); + tmp2 = new_tmp(); + tcg_gen_movi_i32(tmp2, (insn >> 6) & 7); } else { /* reg */ rm = (insn >> 6) & 7; - gen_movl_T1_reg(s, rm); + tmp2 = load_reg(s, rm); } if (insn & (1 << 9)) { if (s->condexec_mask) - gen_op_subl_T0_T1(); + tcg_gen_sub_i32(tmp, tmp, tmp2); else - gen_op_subl_T0_T1_cc(); + gen_helper_sub_cc(tmp, tmp, tmp2); } else { if (s->condexec_mask) - gen_op_addl_T0_T1(); + tcg_gen_add_i32(tmp, tmp, tmp2); else - gen_op_addl_T0_T1_cc(); + gen_helper_add_cc(tmp, tmp, tmp2); } - gen_movl_reg_T0(s, rd); + dead_tmp(tmp2); + store_reg(s, rd, tmp); } else { /* shift immediate */ rm = (insn >> 3) & 7; @@ -8095,35 +8162,40 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) /* arithmetic large immediate */ op = (insn >> 11) & 3; rd = (insn >> 8) & 0x7; - if (op == 0) { - gen_op_movl_T0_im(insn & 0xff); - } else { - gen_movl_T0_reg(s, rd); - gen_op_movl_T1_im(insn & 0xff); - } - switch (op) { - case 0: /* mov */ + if (op == 0) { /* mov */ + tmp = new_tmp(); + tcg_gen_movi_i32(tmp, insn & 0xff); if (!s->condexec_mask) - gen_op_logic_T0_cc(); - break; - case 1: /* cmp */ - gen_op_subl_T0_T1_cc(); - break; - case 2: /* add */ - if (s->condexec_mask) - gen_op_addl_T0_T1(); - else - gen_op_addl_T0_T1_cc(); - break; - case 3: /* sub */ - if (s->condexec_mask) - gen_op_subl_T0_T1(); - else - gen_op_subl_T0_T1_cc(); - break; + gen_logic_CC(tmp); + store_reg(s, rd, tmp); + } else { + tmp = load_reg(s, rd); + tmp2 = new_tmp(); + tcg_gen_movi_i32(tmp2, insn & 0xff); + switch (op) { + case 1: /* cmp */ + gen_helper_sub_cc(tmp, tmp, tmp2); + dead_tmp(tmp); + dead_tmp(tmp2); + break; + case 2: /* add */ + if (s->condexec_mask) + tcg_gen_add_i32(tmp, tmp, tmp2); + else + gen_helper_add_cc(tmp, tmp, tmp2); + dead_tmp(tmp2); + store_reg(s, rd, tmp); + break; + case 3: /* sub */ + if (s->condexec_mask) + tcg_gen_sub_i32(tmp, tmp, tmp2); + else + gen_helper_sub_cc(tmp, tmp, tmp2); + dead_tmp(tmp2); + store_reg(s, rd, tmp); + break; + } } - if (op != 1) - gen_movl_reg_T0(s, rd); break; case 4: if (insn & (1 << 11)) { @@ -8145,19 +8217,22 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) op = (insn >> 8) & 3; switch (op) { case 0: /* add */ - gen_movl_T0_reg(s, rd); - gen_movl_T1_reg(s, rm); - gen_op_addl_T0_T1(); - gen_movl_reg_T0(s, rd); + tmp = load_reg(s, rd); + tmp2 = load_reg(s, rm); + tcg_gen_add_i32(tmp, tmp, tmp2); + dead_tmp(tmp2); + store_reg(s, rd, tmp); break; case 1: /* cmp */ - gen_movl_T0_reg(s, rd); - gen_movl_T1_reg(s, rm); - gen_op_subl_T0_T1_cc(); + tmp = load_reg(s, rd); + tmp2 = load_reg(s, rm); + gen_helper_sub_cc(tmp, tmp, tmp2); + dead_tmp(tmp2); + dead_tmp(tmp); break; case 2: /* mov/cpy */ - gen_movl_T0_reg(s, rm); - gen_movl_reg_T0(s, rd); + tmp = load_reg(s, rm); + store_reg(s, rd, tmp); break; case 3:/* branch [and link] exchange thumb register */ tmp = load_reg(s, rm); @@ -8187,114 +8262,126 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) val = 0; } - if (op == 9) /* neg */ - gen_op_movl_T0_im(0); - else if (op != 0xf) /* mvn doesn't read its first operand */ - gen_movl_T0_reg(s, rd); + if (op == 9) { /* neg */ + tmp = new_tmp(); + tcg_gen_movi_i32(tmp, 0); + } else if (op != 0xf) { /* mvn doesn't read its first operand */ + tmp = load_reg(s, rd); + } else { + TCGV_UNUSED(tmp); + } - gen_movl_T1_reg(s, rm); + tmp2 = load_reg(s, rm); switch (op) { case 0x0: /* and */ - gen_op_andl_T0_T1(); + tcg_gen_and_i32(tmp, tmp, tmp2); if (!s->condexec_mask) - gen_op_logic_T0_cc(); + gen_logic_CC(tmp); break; case 0x1: /* eor */ - gen_op_xorl_T0_T1(); + tcg_gen_xor_i32(tmp, tmp, tmp2); if (!s->condexec_mask) - gen_op_logic_T0_cc(); + gen_logic_CC(tmp); break; case 0x2: /* lsl */ if (s->condexec_mask) { - gen_helper_shl(cpu_T[1], cpu_T[1], cpu_T[0]); + gen_helper_shl(tmp2, tmp2, tmp); } else { - gen_helper_shl_cc(cpu_T[1], cpu_T[1], cpu_T[0]); - gen_op_logic_T1_cc(); + gen_helper_shl_cc(tmp2, tmp2, tmp); + gen_logic_CC(tmp2); } break; case 0x3: /* lsr */ if (s->condexec_mask) { - gen_helper_shr(cpu_T[1], cpu_T[1], cpu_T[0]); + gen_helper_shr(tmp2, tmp2, tmp); } else { - gen_helper_shr_cc(cpu_T[1], cpu_T[1], cpu_T[0]); - gen_op_logic_T1_cc(); + gen_helper_shr_cc(tmp2, tmp2, tmp); + gen_logic_CC(tmp2); } break; case 0x4: /* asr */ if (s->condexec_mask) { - gen_helper_sar(cpu_T[1], cpu_T[1], cpu_T[0]); + gen_helper_sar(tmp2, tmp2, tmp); } else { - gen_helper_sar_cc(cpu_T[1], cpu_T[1], cpu_T[0]); - gen_op_logic_T1_cc(); + gen_helper_sar_cc(tmp2, tmp2, tmp); + gen_logic_CC(tmp2); } break; case 0x5: /* adc */ if (s->condexec_mask) - gen_adc_T0_T1(); + gen_adc(tmp, tmp2); else - gen_op_adcl_T0_T1_cc(); + gen_helper_adc_cc(tmp, tmp, tmp2); break; case 0x6: /* sbc */ if (s->condexec_mask) - gen_sbc_T0_T1(); + gen_sub_carry(tmp, tmp, tmp2); else - gen_op_sbcl_T0_T1_cc(); + gen_helper_sbc_cc(tmp, tmp, tmp2); break; case 0x7: /* ror */ if (s->condexec_mask) { - gen_helper_ror(cpu_T[1], cpu_T[1], cpu_T[0]); + tcg_gen_andi_i32(tmp, tmp, 0x1f); + tcg_gen_rotr_i32(tmp2, tmp2, tmp); } else { - gen_helper_ror_cc(cpu_T[1], cpu_T[1], cpu_T[0]); - gen_op_logic_T1_cc(); + gen_helper_ror_cc(tmp2, tmp2, tmp); + gen_logic_CC(tmp2); } break; case 0x8: /* tst */ - gen_op_andl_T0_T1(); - gen_op_logic_T0_cc(); + tcg_gen_and_i32(tmp, tmp, tmp2); + gen_logic_CC(tmp); rd = 16; break; case 0x9: /* neg */ if (s->condexec_mask) - tcg_gen_neg_i32(cpu_T[0], cpu_T[1]); + tcg_gen_neg_i32(tmp, tmp2); else - gen_op_subl_T0_T1_cc(); + gen_helper_sub_cc(tmp, tmp, tmp2); break; case 0xa: /* cmp */ - gen_op_subl_T0_T1_cc(); + gen_helper_sub_cc(tmp, tmp, tmp2); rd = 16; break; case 0xb: /* cmn */ - gen_op_addl_T0_T1_cc(); + gen_helper_add_cc(tmp, tmp, tmp2); rd = 16; break; case 0xc: /* orr */ - gen_op_orl_T0_T1(); + tcg_gen_or_i32(tmp, tmp, tmp2); if (!s->condexec_mask) - gen_op_logic_T0_cc(); + gen_logic_CC(tmp); break; case 0xd: /* mul */ - gen_op_mull_T0_T1(); + tcg_gen_mul_i32(tmp, tmp, tmp2); if (!s->condexec_mask) - gen_op_logic_T0_cc(); + gen_logic_CC(tmp); break; case 0xe: /* bic */ - gen_op_bicl_T0_T1(); + tcg_gen_andc_i32(tmp, tmp, tmp2); if (!s->condexec_mask) - gen_op_logic_T0_cc(); + gen_logic_CC(tmp); break; case 0xf: /* mvn */ - gen_op_notl_T1(); + tcg_gen_not_i32(tmp2, tmp2); if (!s->condexec_mask) - gen_op_logic_T1_cc(); + gen_logic_CC(tmp2); val = 1; rm = rd; break; } if (rd != 16) { - if (val) - gen_movl_reg_T1(s, rm); - else - gen_movl_reg_T0(s, rd); + if (val) { + store_reg(s, rm, tmp2); + if (op != 0xf) + dead_tmp(tmp); + } else { + store_reg(s, rd, tmp); + dead_tmp(tmp2); + } + } else { + dead_tmp(tmp); + dead_tmp(tmp2); } break; @@ -8576,22 +8663,22 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) if (insn & 1) { addr = tcg_const_i32(16); gen_helper_v7m_msr(cpu_env, addr, tmp); + tcg_temp_free_i32(addr); } /* FAULTMASK */ if (insn & 2) { addr = tcg_const_i32(17); gen_helper_v7m_msr(cpu_env, addr, tmp); + tcg_temp_free_i32(addr); } + tcg_temp_free_i32(tmp); gen_lookup_tb(s); } else { if (insn & (1 << 4)) shift = CPSR_A | CPSR_I | CPSR_F; else shift = 0; - - val = ((insn & 7) << 6) & shift; - gen_op_movl_T0_im(val); - gen_set_psr_T0(s, shift, 0); + gen_set_psr_im(s, shift, 0, ((insn & 7) << 6) & shift); } break; @@ -8644,7 +8731,6 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) s->condlabel = gen_new_label(); gen_test_cc(cond ^ 1, s->condlabel); s->condjmp = 1; - gen_movl_T1_reg(s, 15); /* jump to the offset */ val = (uint32_t)s->pc + 2; @@ -8704,7 +8790,6 @@ static inline void gen_intermediate_code_internal(CPUState *env, /* generate intermediate code */ num_temps = 0; - memset(temps, 0, sizeof(temps)); pc_start = tb->pc; diff --git a/target-i386/helper.h b/target-i386/helper.h index ca953f47d..6b518ad89 100644 --- a/target-i386/helper.h +++ b/target-i386/helper.h @@ -193,6 +193,7 @@ DEF_HELPER_2(fxsave, void, tl, int) DEF_HELPER_2(fxrstor, void, tl, int) DEF_HELPER_1(bsf, tl, tl) DEF_HELPER_1(bsr, tl, tl) +DEF_HELPER_2(lzcnt, tl, tl, int) /* MMX/SSE */ diff --git a/target-i386/machine.c b/target-i386/machine.c index b364936eb..f6fdc9ddd 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -117,7 +117,7 @@ static void put_fpreg(QEMUFile *f, void *opaque, size_t size) qemu_put_be16s(f, &exp); } -const VMStateInfo vmstate_fpreg = { +static const VMStateInfo vmstate_fpreg = { .name = "fpreg", .get = get_fpreg, .put = put_fpreg, @@ -134,7 +134,7 @@ static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size) return 0; } -const VMStateInfo vmstate_fpreg_1_mmx = { +static const VMStateInfo vmstate_fpreg_1_mmx = { .name = "fpreg_1_mmx", .get = get_fpreg_1_mmx, .put = put_fpreg_error, @@ -150,7 +150,7 @@ static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size) return 0; } -const VMStateInfo vmstate_fpreg_1_no_mmx = { +static const VMStateInfo vmstate_fpreg_1_no_mmx = { .name = "fpreg_1_no_mmx", .get = get_fpreg_1_no_mmx, .put = put_fpreg_error, @@ -308,7 +308,7 @@ static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size) qemu_put_be32(f, *v); } -const VMStateInfo vmstate_hack_uint64_as_uint32 = { +static const VMStateInfo vmstate_hack_uint64_as_uint32 = { .name = "uint64_as_uint32", .get = get_uint64_as_uint32, .put = put_uint64_as_uint32, @@ -391,7 +391,7 @@ static int cpu_post_load(void *opaque, int version_id) return 0; } -const VMStateDescription vmstate_cpu = { +static const VMStateDescription vmstate_cpu = { .name = "cpu", .version_id = CPU_SAVE_VERSION, .minimum_version_id = 3, diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c index 26fe61204..5eea3221b 100644 --- a/target-i386/op_helper.c +++ b/target-i386/op_helper.c @@ -5479,11 +5479,14 @@ target_ulong helper_bsf(target_ulong t0) return count; } -target_ulong helper_bsr(target_ulong t0) +target_ulong helper_lzcnt(target_ulong t0, int wordsize) { int count; target_ulong res, mask; - + + if (wordsize > 0 && t0 == 0) { + return wordsize; + } res = t0; count = TARGET_LONG_BITS - 1; mask = (target_ulong)1 << (TARGET_LONG_BITS - 1); @@ -5491,9 +5494,16 @@ target_ulong helper_bsr(target_ulong t0) count--; res <<= 1; } + if (wordsize > 0) { + return wordsize - 1 - count; + } return count; } +target_ulong helper_bsr(target_ulong t0) +{ + return helper_lzcnt(t0, 0); +} static int compute_all_eflags(void) { diff --git a/target-i386/translate.c b/target-i386/translate.c index 251194394..64bc0a3f3 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -6573,23 +6573,36 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) ot = dflag + OT_WORD; modrm = ldub_code(s->pc++); reg = ((modrm >> 3) & 7) | rex_r; - gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); + gen_ldst_modrm(s,modrm, ot, OR_TMP0, 0); gen_extu(ot, cpu_T[0]); - label1 = gen_new_label(); - tcg_gen_movi_tl(cpu_cc_dst, 0); t0 = tcg_temp_local_new(); tcg_gen_mov_tl(t0, cpu_T[0]); - tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, label1); - if (b & 1) { - gen_helper_bsr(cpu_T[0], t0); + if ((b & 1) && (prefixes & PREFIX_REPZ) && + (s->cpuid_ext3_features & CPUID_EXT3_ABM)) { + switch(ot) { + case OT_WORD: gen_helper_lzcnt(cpu_T[0], t0, + tcg_const_i32(16)); break; + case OT_LONG: gen_helper_lzcnt(cpu_T[0], t0, + tcg_const_i32(32)); break; + case OT_QUAD: gen_helper_lzcnt(cpu_T[0], t0, + tcg_const_i32(64)); break; + } + gen_op_mov_reg_T0(ot, reg); } else { - gen_helper_bsf(cpu_T[0], t0); + label1 = gen_new_label(); + tcg_gen_movi_tl(cpu_cc_dst, 0); + tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, label1); + if (b & 1) { + gen_helper_bsr(cpu_T[0], t0); + } else { + gen_helper_bsf(cpu_T[0], t0); + } + gen_op_mov_reg_T0(ot, reg); + tcg_gen_movi_tl(cpu_cc_dst, 1); + gen_set_label(label1); + tcg_gen_discard_tl(cpu_cc_src); + s->cc_op = CC_OP_LOGICB + ot; } - gen_op_mov_reg_T0(ot, reg); - tcg_gen_movi_tl(cpu_cc_dst, 1); - gen_set_label(label1); - tcg_gen_discard_tl(cpu_cc_src); - s->cc_op = CC_OP_LOGICB + ot; tcg_temp_free(t0); } break; diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index ff6bb34c8..2c850a7cd 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -580,11 +580,14 @@ struct CPUPPCState { /* floating point status and control register */ uint32_t fpscr; - CPU_COMMON + /* Next instruction pointer */ + target_ulong nip; int access_type; /* when a memory exception occurs, the access type is stored here */ + CPU_COMMON + /* MMU context - only relevant for full system emulation */ #if !defined(CONFIG_USER_ONLY) #if defined(TARGET_PPC64) @@ -664,9 +667,6 @@ struct CPUPPCState { #endif /* Those resources are used only during code translation */ - /* Next instruction pointer */ - target_ulong nip; - /* opcode handlers */ opc_handler_t *opcodes[0x40]; diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 79d3b4ca9..db4dc172b 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -233,7 +233,7 @@ static void spr_write_ibatu (void *opaque, int sprn, int gprn) static void spr_write_ibatu_h (void *opaque, int sprn, int gprn) { - TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT4U) / 2); + TCGv_i32 t0 = tcg_const_i32(((sprn - SPR_IBAT4U) / 2) + 4); gen_helper_store_ibatu(t0, cpu_gpr[gprn]); tcg_temp_free_i32(t0); } @@ -247,7 +247,7 @@ static void spr_write_ibatl (void *opaque, int sprn, int gprn) static void spr_write_ibatl_h (void *opaque, int sprn, int gprn) { - TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT4L) / 2); + TCGv_i32 t0 = tcg_const_i32(((sprn - SPR_IBAT4L) / 2) + 4); gen_helper_store_ibatl(t0, cpu_gpr[gprn]); tcg_temp_free_i32(t0); } @@ -4166,8 +4166,14 @@ static void init_proc_e300 (CPUPPCState *env) SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, 0x00000000); + /* XXX : not implemented */ + spr_register(env, SPR_HID2, "HID2", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); /* Memory management */ gen_low_BATs(env); + gen_high_BATs(env); gen_6xx_7xx_soft_tlb(env, 64, 2); init_excp_603(env); env->dcache_line_size = 32; @@ -6719,36 +6725,12 @@ enum { CPU_POWERPC_e300c3 = 0x00850010, CPU_POWERPC_e300c4 = 0x00860010, /* MPC83xx microcontrollers */ -#define CPU_POWERPC_MPC8313 CPU_POWERPC_e300c3 -#define CPU_POWERPC_MPC8313E CPU_POWERPC_e300c3 -#define CPU_POWERPC_MPC8314 CPU_POWERPC_e300c3 -#define CPU_POWERPC_MPC8314E CPU_POWERPC_e300c3 -#define CPU_POWERPC_MPC8315 CPU_POWERPC_e300c3 -#define CPU_POWERPC_MPC8315E CPU_POWERPC_e300c3 -#define CPU_POWERPC_MPC8321 CPU_POWERPC_e300c2 -#define CPU_POWERPC_MPC8321E CPU_POWERPC_e300c2 -#define CPU_POWERPC_MPC8323 CPU_POWERPC_e300c2 -#define CPU_POWERPC_MPC8323E CPU_POWERPC_e300c2 -#define CPU_POWERPC_MPC8343A CPU_POWERPC_e300c1 -#define CPU_POWERPC_MPC8343EA CPU_POWERPC_e300c1 -#define CPU_POWERPC_MPC8347A CPU_POWERPC_e300c1 -#define CPU_POWERPC_MPC8347AT CPU_POWERPC_e300c1 -#define CPU_POWERPC_MPC8347AP CPU_POWERPC_e300c1 -#define CPU_POWERPC_MPC8347EA CPU_POWERPC_e300c1 -#define CPU_POWERPC_MPC8347EAT CPU_POWERPC_e300c1 -#define CPU_POWERPC_MPC8347EAP CPU_POWERPC_e300c1 -#define CPU_POWERPC_MPC8349 CPU_POWERPC_e300c1 -#define CPU_POWERPC_MPC8349A CPU_POWERPC_e300c1 -#define CPU_POWERPC_MPC8349E CPU_POWERPC_e300c1 -#define CPU_POWERPC_MPC8349EA CPU_POWERPC_e300c1 -#define CPU_POWERPC_MPC8358E CPU_POWERPC_e300c1 -#define CPU_POWERPC_MPC8360E CPU_POWERPC_e300c1 -#define CPU_POWERPC_MPC8377 CPU_POWERPC_e300c4 -#define CPU_POWERPC_MPC8377E CPU_POWERPC_e300c4 -#define CPU_POWERPC_MPC8378 CPU_POWERPC_e300c4 -#define CPU_POWERPC_MPC8378E CPU_POWERPC_e300c4 -#define CPU_POWERPC_MPC8379 CPU_POWERPC_e300c4 -#define CPU_POWERPC_MPC8379E CPU_POWERPC_e300c4 +#define CPU_POWERPC_MPC831x CPU_POWERPC_e300c3 +#define CPU_POWERPC_MPC832x CPU_POWERPC_e300c2 +#define CPU_POWERPC_MPC834x CPU_POWERPC_e300c1 +#define CPU_POWERPC_MPC835x CPU_POWERPC_e300c1 +#define CPU_POWERPC_MPC836x CPU_POWERPC_e300c1 +#define CPU_POWERPC_MPC837x CPU_POWERPC_e300c4 /* e500 family */ /* e500 cores */ #define CPU_POWERPC_e500 CPU_POWERPC_e500v2_v22 @@ -7109,11 +7091,19 @@ enum { #if 0 POWERPC_SVR_8323E = xxx, #endif + POWERPC_SVR_8343 = 0x80570010, POWERPC_SVR_8343A = 0x80570030, + POWERPC_SVR_8343E = 0x80560010, POWERPC_SVR_8343EA = 0x80560030, +#define POWERPC_SVR_8347 POWERPC_SVR_8347T + POWERPC_SVR_8347P = 0x80550010, /* PBGA package */ + POWERPC_SVR_8347T = 0x80530010, /* TBGA package */ #define POWERPC_SVR_8347A POWERPC_SVR_8347AT POWERPC_SVR_8347AP = 0x80550030, /* PBGA package */ POWERPC_SVR_8347AT = 0x80530030, /* TBGA package */ +#define POWERPC_SVR_8347E POWERPC_SVR_8347ET + POWERPC_SVR_8347EP = 0x80540010, /* PBGA package */ + POWERPC_SVR_8347ET = 0x80520010, /* TBGA package */ #define POWERPC_SVR_8347EA POWERPC_SVR_8347EAT POWERPC_SVR_8347EAP = 0x80540030, /* PBGA package */ POWERPC_SVR_8347EAT = 0x80520030, /* TBGA package */ @@ -7992,117 +7982,141 @@ static const ppc_def_t ppc_defs[] = { #if defined (TODO) /* MPC8313 */ POWERPC_DEF_SVR("MPC8313", - CPU_POWERPC_MPC8313, POWERPC_SVR_8313, e300), + CPU_POWERPC_MPC831x, POWERPC_SVR_8313, e300), #endif #if defined (TODO) /* MPC8313E */ POWERPC_DEF_SVR("MPC8313E", - CPU_POWERPC_MPC8313E, POWERPC_SVR_8313E, e300), + CPU_POWERPC_MPC831x, POWERPC_SVR_8313E, e300), #endif #if defined (TODO) /* MPC8314 */ POWERPC_DEF_SVR("MPC8314", - CPU_POWERPC_MPC8314, POWERPC_SVR_8314, e300), + CPU_POWERPC_MPC831x, POWERPC_SVR_8314, e300), #endif #if defined (TODO) /* MPC8314E */ POWERPC_DEF_SVR("MPC8314E", - CPU_POWERPC_MPC8314E, POWERPC_SVR_8314E, e300), + CPU_POWERPC_MPC831x, POWERPC_SVR_8314E, e300), #endif #if defined (TODO) /* MPC8315 */ POWERPC_DEF_SVR("MPC8315", - CPU_POWERPC_MPC8315, POWERPC_SVR_8315, e300), + CPU_POWERPC_MPC831x, POWERPC_SVR_8315, e300), #endif #if defined (TODO) /* MPC8315E */ POWERPC_DEF_SVR("MPC8315E", - CPU_POWERPC_MPC8315E, POWERPC_SVR_8315E, e300), + CPU_POWERPC_MPC831x, POWERPC_SVR_8315E, e300), #endif #if defined (TODO) /* MPC8321 */ POWERPC_DEF_SVR("MPC8321", - CPU_POWERPC_MPC8321, POWERPC_SVR_8321, e300), + CPU_POWERPC_MPC832x, POWERPC_SVR_8321, e300), #endif #if defined (TODO) /* MPC8321E */ POWERPC_DEF_SVR("MPC8321E", - CPU_POWERPC_MPC8321E, POWERPC_SVR_8321E, e300), + CPU_POWERPC_MPC832x, POWERPC_SVR_8321E, e300), #endif #if defined (TODO) /* MPC8323 */ POWERPC_DEF_SVR("MPC8323", - CPU_POWERPC_MPC8323, POWERPC_SVR_8323, e300), + CPU_POWERPC_MPC832x, POWERPC_SVR_8323, e300), #endif #if defined (TODO) /* MPC8323E */ POWERPC_DEF_SVR("MPC8323E", - CPU_POWERPC_MPC8323E, POWERPC_SVR_8323E, e300), + CPU_POWERPC_MPC832x, POWERPC_SVR_8323E, e300), #endif + /* MPC8343 */ + POWERPC_DEF_SVR("MPC8343", + CPU_POWERPC_MPC834x, POWERPC_SVR_8343, e300), /* MPC8343A */ POWERPC_DEF_SVR("MPC8343A", - CPU_POWERPC_MPC8343A, POWERPC_SVR_8343A, e300), + CPU_POWERPC_MPC834x, POWERPC_SVR_8343A, e300), + /* MPC8343E */ + POWERPC_DEF_SVR("MPC8343E", + CPU_POWERPC_MPC834x, POWERPC_SVR_8343E, e300), /* MPC8343EA */ POWERPC_DEF_SVR("MPC8343EA", - CPU_POWERPC_MPC8343EA, POWERPC_SVR_8343EA, e300), + CPU_POWERPC_MPC834x, POWERPC_SVR_8343EA, e300), + /* MPC8347 */ + POWERPC_DEF_SVR("MPC8347", + CPU_POWERPC_MPC834x, POWERPC_SVR_8347, e300), + /* MPC8347T */ + POWERPC_DEF_SVR("MPC8347T", + CPU_POWERPC_MPC834x, POWERPC_SVR_8347T, e300), + /* MPC8347P */ + POWERPC_DEF_SVR("MPC8347P", + CPU_POWERPC_MPC834x, POWERPC_SVR_8347P, e300), /* MPC8347A */ POWERPC_DEF_SVR("MPC8347A", - CPU_POWERPC_MPC8347A, POWERPC_SVR_8347A, e300), + CPU_POWERPC_MPC834x, POWERPC_SVR_8347A, e300), /* MPC8347AT */ POWERPC_DEF_SVR("MPC8347AT", - CPU_POWERPC_MPC8347AT, POWERPC_SVR_8347AT, e300), + CPU_POWERPC_MPC834x, POWERPC_SVR_8347AT, e300), /* MPC8347AP */ POWERPC_DEF_SVR("MPC8347AP", - CPU_POWERPC_MPC8347AP, POWERPC_SVR_8347AP, e300), + CPU_POWERPC_MPC834x, POWERPC_SVR_8347AP, e300), + /* MPC8347E */ + POWERPC_DEF_SVR("MPC8347E", + CPU_POWERPC_MPC834x, POWERPC_SVR_8347E, e300), + /* MPC8347ET */ + POWERPC_DEF_SVR("MPC8347ET", + CPU_POWERPC_MPC834x, POWERPC_SVR_8347ET, e300), + /* MPC8343EP */ + POWERPC_DEF_SVR("MPC8347EP", + CPU_POWERPC_MPC834x, POWERPC_SVR_8347EP, e300), /* MPC8347EA */ POWERPC_DEF_SVR("MPC8347EA", - CPU_POWERPC_MPC8347EA, POWERPC_SVR_8347EA, e300), + CPU_POWERPC_MPC834x, POWERPC_SVR_8347EA, e300), /* MPC8347EAT */ POWERPC_DEF_SVR("MPC8347EAT", - CPU_POWERPC_MPC8347EAT, POWERPC_SVR_8347EAT, e300), + CPU_POWERPC_MPC834x, POWERPC_SVR_8347EAT, e300), /* MPC8343EAP */ POWERPC_DEF_SVR("MPC8347EAP", - CPU_POWERPC_MPC8347EAP, POWERPC_SVR_8347EAP, e300), + CPU_POWERPC_MPC834x, POWERPC_SVR_8347EAP, e300), /* MPC8349 */ POWERPC_DEF_SVR("MPC8349", - CPU_POWERPC_MPC8349, POWERPC_SVR_8349, e300), + CPU_POWERPC_MPC834x, POWERPC_SVR_8349, e300), /* MPC8349A */ POWERPC_DEF_SVR("MPC8349A", - CPU_POWERPC_MPC8349A, POWERPC_SVR_8349A, e300), + CPU_POWERPC_MPC834x, POWERPC_SVR_8349A, e300), /* MPC8349E */ POWERPC_DEF_SVR("MPC8349E", - CPU_POWERPC_MPC8349E, POWERPC_SVR_8349E, e300), + CPU_POWERPC_MPC834x, POWERPC_SVR_8349E, e300), /* MPC8349EA */ POWERPC_DEF_SVR("MPC8349EA", - CPU_POWERPC_MPC8349EA, POWERPC_SVR_8349EA, e300), + CPU_POWERPC_MPC834x, POWERPC_SVR_8349EA, e300), #if defined (TODO) /* MPC8358E */ POWERPC_DEF_SVR("MPC8358E", - CPU_POWERPC_MPC8358E, POWERPC_SVR_8358E, e300), + CPU_POWERPC_MPC835x, POWERPC_SVR_8358E, e300), #endif #if defined (TODO) /* MPC8360E */ POWERPC_DEF_SVR("MPC8360E", - CPU_POWERPC_MPC8360E, POWERPC_SVR_8360E, e300), + CPU_POWERPC_MPC836x, POWERPC_SVR_8360E, e300), #endif /* MPC8377 */ POWERPC_DEF_SVR("MPC8377", - CPU_POWERPC_MPC8377, POWERPC_SVR_8377, e300), + CPU_POWERPC_MPC837x, POWERPC_SVR_8377, e300), /* MPC8377E */ POWERPC_DEF_SVR("MPC8377E", - CPU_POWERPC_MPC8377E, POWERPC_SVR_8377E, e300), + CPU_POWERPC_MPC837x, POWERPC_SVR_8377E, e300), /* MPC8378 */ POWERPC_DEF_SVR("MPC8378", - CPU_POWERPC_MPC8378, POWERPC_SVR_8378, e300), + CPU_POWERPC_MPC837x, POWERPC_SVR_8378, e300), /* MPC8378E */ POWERPC_DEF_SVR("MPC8378E", - CPU_POWERPC_MPC8378E, POWERPC_SVR_8378E, e300), + CPU_POWERPC_MPC837x, POWERPC_SVR_8378E, e300), /* MPC8379 */ POWERPC_DEF_SVR("MPC8379", - CPU_POWERPC_MPC8379, POWERPC_SVR_8379, e300), + CPU_POWERPC_MPC837x, POWERPC_SVR_8379, e300), /* MPC8379E */ POWERPC_DEF_SVR("MPC8379E", - CPU_POWERPC_MPC8379E, POWERPC_SVR_8379E, e300), + CPU_POWERPC_MPC837x, POWERPC_SVR_8379E, e300), /* e500 family */ /* PowerPC e500 core */ POWERPC_DEF("e500", CPU_POWERPC_e500v2_v22, e500v2), diff --git a/usb-linux.c b/usb-linux.c index 9e5d9c40e..d7121346f 100644 --- a/usb-linux.c +++ b/usb-linux.c @@ -275,7 +275,9 @@ static void async_complete(void *opaque) case -EPIPE: set_halt(s, p->devep); - /* fall through */ + p->len = USB_RET_STALL; + break; + default: p->len = USB_RET_NAK; break; |