diff options
-rw-r--r-- | include/exec/user/thunk.h | 22 | ||||
-rw-r--r-- | linux-user/sparc/syscall_nr.h | 32 | ||||
-rw-r--r-- | linux-user/sparc/target_errno.h | 207 | ||||
-rw-r--r-- | linux-user/sparc/target_syscall.h | 4 | ||||
-rw-r--r-- | linux-user/sparc64/syscall_nr.h | 20 | ||||
-rw-r--r-- | linux-user/sparc64/target_syscall.h | 5 | ||||
-rw-r--r-- | linux-user/syscall.c | 66 | ||||
-rw-r--r-- | linux-user/syscall_defs.h | 25 | ||||
-rw-r--r-- | target/m68k/softfloat.c | 1 | ||||
-rw-r--r-- | target/openrisc/Makefile.objs | 9 | ||||
-rw-r--r-- | target/openrisc/fpu_helper.c | 252 | ||||
-rw-r--r-- | target/openrisc/helper.h | 25 | ||||
-rw-r--r-- | target/openrisc/insns.decode | 189 | ||||
-rw-r--r-- | target/openrisc/translate.c | 1726 | ||||
-rw-r--r-- | ui/console.c | 105 | ||||
-rw-r--r-- | ui/gtk.c | 60 | ||||
-rw-r--r-- | ui/sdl2.c | 2 | ||||
-rw-r--r-- | ui/vnc-jobs.c | 4 | ||||
-rw-r--r-- | ui/vnc.c | 10 | ||||
-rw-r--r-- | ui/vnc.h | 3 | ||||
-rw-r--r-- | vl.c | 76 |
21 files changed, 1562 insertions, 1281 deletions
diff --git a/include/exec/user/thunk.h b/include/exec/user/thunk.h index f19ef4b230..8f55b233b3 100644 --- a/include/exec/user/thunk.h +++ b/include/exec/user/thunk.h @@ -149,20 +149,32 @@ static inline int thunk_type_align(const argtype *type_ptr, int is_host) case TYPE_CHAR: return 1; case TYPE_SHORT: - return 2; + if (is_host) { + return __alignof__(short); + } else { + return ABI_SHORT_ALIGNMENT; + } case TYPE_INT: - return 4; + if (is_host) { + return __alignof__(int); + } else { + return ABI_INT_ALIGNMENT; + } case TYPE_LONGLONG: case TYPE_ULONGLONG: - return 8; + if (is_host) { + return __alignof__(long long); + } else { + return ABI_LLONG_ALIGNMENT; + } case TYPE_LONG: case TYPE_ULONG: case TYPE_PTRVOID: case TYPE_PTR: if (is_host) { - return sizeof(void *); + return __alignof__(long); } else { - return TARGET_ABI_BITS / 8; + return ABI_LONG_ALIGNMENT; } break; case TYPE_OLDDEVT: diff --git a/linux-user/sparc/syscall_nr.h b/linux-user/sparc/syscall_nr.h index e713c9d5f4..2d77e19bec 100644 --- a/linux-user/sparc/syscall_nr.h +++ b/linux-user/sparc/syscall_nr.h @@ -22,6 +22,7 @@ #define TARGET_NR_capset 22 /* Linux Specific */ #define TARGET_NR_setuid 23 /* Implemented via setreuid in SunOS */ #define TARGET_NR_getuid 24 /* Common */ +#define TARGET_NR_vmsplice 25 #define TARGET_NR_ptrace 26 /* Common */ #define TARGET_NR_alarm 27 /* Implemented via setitimer in SunOS */ #define TARGET_NR_sigaltstack 28 /* Common */ @@ -135,6 +136,7 @@ #define TARGET_NR_rmdir 137 /* Common */ #define TARGET_NR_utimes 138 /* SunOS Specific */ #define TARGET_NR_stat64 139 /* Linux sparc32 Specific */ +#define TARGET_NR_sendfile64 140 #define TARGET_NR_getpeername 141 /* Common */ #define TARGET_NR_futex 142 /* gethostid under SunOS */ #define TARGET_NR_gettid 143 /* ENOSYS under SunOS */ @@ -145,29 +147,51 @@ #define TARGET_NR_pciconfig_read 148 /* ENOSYS under SunOS */ #define TARGET_NR_pciconfig_write 149 /* ENOSYS under SunOS */ #define TARGET_NR_getsockname 150 /* Common */ +#define TARGET_NR_inotify_init 151 +#define TARGET_NR_inotify_add_watch 152 #define TARGET_NR_poll 153 /* Common */ #define TARGET_NR_getdents64 154 /* Linux specific */ #define TARGET_NR_fcntl64 155 /* Linux sparc32 Specific */ +#define TARGET_NR_inotify_rm_watch 156 #define TARGET_NR_statfs 157 /* Common */ #define TARGET_NR_fstatfs 158 /* Common */ #define TARGET_NR_umount 159 /* Common */ +#define TARGET_NR_sched_set_affinity 160 +#define TARGET_NR_sched_get_affinity 161 #define TARGET_NR_getdomainname 162 /* SunOS Specific */ #define TARGET_NR_setdomainname 163 /* Common */ #define TARGET_NR_quotactl 165 /* Common */ #define TARGET_NR_set_tid_address 166 /* Linux specific, exportfs under SunOS */ #define TARGET_NR_mount 167 /* Common */ #define TARGET_NR_ustat 168 /* Common */ +#define TARGET_NR_setxattr 169 +#define TARGET_NR_lsetxattr 170 +#define TARGET_NR_fsetxattr 171 +#define TARGET_NR_getxattr 172 +#define TARGET_NR_lgetxattr 173 #define TARGET_NR_getdents 174 /* Common */ #define TARGET_NR_setsid 175 /* Common */ #define TARGET_NR_fchdir 176 /* Common */ +#define TARGET_NR_fgetxattr 177 +#define TARGET_NR_listxattr 178 +#define TARGET_NR_llistxattr 179 +#define TARGET_NR_flistxattr 180 +#define TARGET_NR_removexattr 181 +#define TARGET_NR_lremovexattr 182 #define TARGET_NR_sigpending 183 /* Common */ #define TARGET_NR_query_module 184 /* Linux Specific */ #define TARGET_NR_setpgid 185 /* Common */ +#define TARGET_NR_fremovexattr 186 #define TARGET_NR_tkill 187 /* SunOS: fpathconf */ #define TARGET_NR_exit_group 188 /* Linux specific, sysconf undef SunOS */ #define TARGET_NR_uname 189 /* Linux Specific */ #define TARGET_NR_init_module 190 /* Linux Specific */ #define TARGET_NR_personality 191 /* Linux Specific */ +#define TARGET_NR_remap_file_pages 192 +#define TARGET_NR_epoll_create 193 +#define TARGET_NR_epoll_ctl 194 +#define TARGET_NR_epoll_wait 195 +#define TARGET_NR_ioprio_set 196 #define TARGET_NR_getppid 197 /* Linux Specific */ #define TARGET_NR_sigaction 198 /* Linux Specific */ #define TARGET_NR_sgetmask 199 /* Linux Specific */ @@ -189,6 +213,7 @@ #define TARGET_NR_ipc 215 /* Linux Specific */ #define TARGET_NR_sigreturn 216 /* Linux Specific */ #define TARGET_NR_clone 217 /* Linux Specific */ +#define TARGET_NR_ioprio_get 218 #define TARGET_NR_adjtimex 219 /* Linux Specific */ #define TARGET_NR_sigprocmask 220 /* Linux Specific */ #define TARGET_NR_create_module 221 /* Linux Specific */ @@ -202,6 +227,7 @@ #define TARGET_NR_setfsgid 229 /* Linux Specific */ #define TARGET_NR__newselect 230 /* Linux Specific */ #define TARGET_NR_time 231 /* Linux Specific */ +#define TARGET_NR_splice 232 #define TARGET_NR_stime 233 /* Linux Specific */ #define TARGET_NR_statfs64 234 /* Linux Specific */ #define TARGET_NR_fstatfs64 235 /* Linux Specific */ @@ -224,7 +250,7 @@ #define TARGET_NR_getsid 252 #define TARGET_NR_fdatasync 253 #define TARGET_NR_nfsservctl 254 -#define TARGET_NR_aplib 255 +#define TARGET_NR_sync_file_range 255 #define TARGET_NR_clock_settime 256 #define TARGET_NR_clock_gettime 257 #define TARGET_NR_clock_getres 258 @@ -326,3 +352,7 @@ #define TARGET_NR_listen 354 #define TARGET_NR_setsockopt 355 #define TARGET_NR_mlock2 356 +#define TARGET_NR_copy_file_range 357 +#define TARGET_NR_preadv2 358 +#define TARGET_NR_pwritev2 359 +#define TARGET_NR_statx 360 diff --git a/linux-user/sparc/target_errno.h b/linux-user/sparc/target_errno.h new file mode 100644 index 0000000000..9b846899cd --- /dev/null +++ b/linux-user/sparc/target_errno.h @@ -0,0 +1,207 @@ +#ifndef SPARC_TARGET_ERRNO_H +#define SPARC_TARGET_ERRNO_H + +/* Target errno definitions taken from asm-sparc/errno.h */ +#undef TARGET_EWOULDBLOCK +#define TARGET_EWOULDBLOCK TARGET_EAGAIN /* Operation would block */ +#undef TARGET_EINPROGRESS +#define TARGET_EINPROGRESS 36 /* Operation now in progress */ +#undef TARGET_EALREADY +#define TARGET_EALREADY 37 /* Operation already in progress */ +#undef TARGET_ENOTSOCK +#define TARGET_ENOTSOCK 38 /* Socket operation on non-socket */ +#undef TARGET_EDESTADDRREQ +#define TARGET_EDESTADDRREQ 39 /* Destination address required */ +#undef TARGET_EMSGSIZE +#define TARGET_EMSGSIZE 40 /* Message too long */ +#undef TARGET_EPROTOTYPE +#define TARGET_EPROTOTYPE 41 /* Protocol wrong type for socket */ +#undef TARGET_ENOPROTOOPT +#define TARGET_ENOPROTOOPT 42 /* Protocol not available */ +#undef TARGET_EPROTONOSUPPORT +#define TARGET_EPROTONOSUPPORT 43 /* Protocol not supported */ +#undef TARGET_ESOCKTNOSUPPORT +#define TARGET_ESOCKTNOSUPPORT 44 /* Socket type not supported */ +#undef TARGET_EOPNOTSUPP +#define TARGET_EOPNOTSUPP 45 /* Op not supported on transport endpoint */ +#undef TARGET_EPFNOSUPPORT +#define TARGET_EPFNOSUPPORT 46 /* Protocol family not supported */ +#undef TARGET_EAFNOSUPPORT +#define TARGET_EAFNOSUPPORT 47 /* Address family not supported by protocol */ +#undef TARGET_EADDRINUSE +#define TARGET_EADDRINUSE 48 /* Address already in use */ +#undef TARGET_EADDRNOTAVAIL +#define TARGET_EADDRNOTAVAIL 49 /* Cannot assign requested address */ +#undef TARGET_ENETDOWN +#define TARGET_ENETDOWN 50 /* Network is down */ +#undef TARGET_ENETUNREACH +#define TARGET_ENETUNREACH 51 /* Network is unreachable */ +#undef TARGET_ENETRESET +#define TARGET_ENETRESET 52 /* Net dropped connection because of reset */ +#undef TARGET_ECONNABORTED +#define TARGET_ECONNABORTED 53 /* Software caused connection abort */ +#undef TARGET_ECONNRESET +#define TARGET_ECONNRESET 54 /* Connection reset by peer */ +#undef TARGET_ENOBUFS +#define TARGET_ENOBUFS 55 /* No buffer space available */ +#undef TARGET_EISCONN +#define TARGET_EISCONN 56 /* Transport endpoint is already connected */ +#undef TARGET_ENOTCONN +#define TARGET_ENOTCONN 57 /* Transport endpoint is not connected */ +#undef TARGET_ESHUTDOWN +#define TARGET_ESHUTDOWN 58 /* No send after transport endpoint shutdown*/ +#undef TARGET_ETOOMANYREFS +#define TARGET_ETOOMANYREFS 59 /* Too many references: cannot splice */ +#undef TARGET_ETIMEDOUT +#define TARGET_ETIMEDOUT 60 /* Connection timed out */ +#undef TARGET_ECONNREFUSED +#define TARGET_ECONNREFUSED 61 /* Connection refused */ +#undef TARGET_ELOOP +#define TARGET_ELOOP 62 /* Too many symbolic links encountered */ +#undef TARGET_ENAMETOOLONG +#define TARGET_ENAMETOOLONG 63 /* File name too long */ +#undef TARGET_EHOSTDOWN +#define TARGET_EHOSTDOWN 64 /* Host is down */ +#undef TARGET_EHOSTUNREACH +#define TARGET_EHOSTUNREACH 65 /* No route to host */ +#undef TARGET_ENOTEMPTY +#define TARGET_ENOTEMPTY 66 /* Directory not empty */ +#undef TARGET_EPROCLIM +#define TARGET_EPROCLIM 67 /* SUNOS: Too many processes */ +#undef TARGET_EUSERS +#define TARGET_EUSERS 68 /* Too many users */ +#undef TARGET_EDQUOT +#define TARGET_EDQUOT 69 /* Quota exceeded */ +#undef TARGET_ESTALE +#define TARGET_ESTALE 70 /* Stale file handle */ +#undef TARGET_EREMOTE +#define TARGET_EREMOTE 71 /* Object is remote */ +#undef TARGET_ENOSTR +#define TARGET_ENOSTR 72 /* Device not a stream */ +#undef TARGET_ETIME +#define TARGET_ETIME 73 /* Timer expired */ +#undef TARGET_ENOSR +#define TARGET_ENOSR 74 /* Out of streams resources */ +#undef TARGET_ENOMSG +#define TARGET_ENOMSG 75 /* No message of desired type */ +#undef TARGET_EBADMSG +#define TARGET_EBADMSG 76 /* Not a data message */ +#undef TARGET_EIDRM +#define TARGET_EIDRM 77 /* Identifier removed */ +#undef TARGET_EDEADLK +#define TARGET_EDEADLK 78 /* Resource deadlock would occur */ +#undef TARGET_ENOLCK +#define TARGET_ENOLCK 79 /* No record locks available */ +#undef TARGET_ENONET +#define TARGET_ENONET 80 /* Machine is not on the network */ +#undef TARGET_ERREMOTE +#define TARGET_ERREMOTE 81 /* SunOS: Too many lvls of remote in path */ +#undef TARGET_ENOLINK +#define TARGET_ENOLINK 82 /* Link has been severed */ +#undef TARGET_EADV +#define TARGET_EADV 83 /* Advertise error */ +#undef TARGET_ESRMNT +#define TARGET_ESRMNT 84 /* Srmount error */ +#undef TARGET_ECOMM +#define TARGET_ECOMM 85 /* Communication error on send */ +#undef TARGET_EPROTO +#define TARGET_EPROTO 86 /* Protocol error */ +#undef TARGET_EMULTIHOP +#define TARGET_EMULTIHOP 87 /* Multihop attempted */ +#undef TARGET_EDOTDOT +#define TARGET_EDOTDOT 88 /* RFS specific error */ +#undef TARGET_EREMCHG +#define TARGET_EREMCHG 89 /* Remote address changed */ +#undef TARGET_ENOSYS +#define TARGET_ENOSYS 90 /* Function not implemented */ +#undef TARGET_ESTRPIPE +#define TARGET_ESTRPIPE 91 /* Streams pipe error */ +#undef TARGET_EOVERFLOW +#define TARGET_EOVERFLOW 92 /* Value too large for defined data type */ +#undef TARGET_EBADFD +#define TARGET_EBADFD 93 /* File descriptor in bad state */ +#undef TARGET_ECHRNG +#define TARGET_ECHRNG 94 /* Channel number out of range */ +#undef TARGET_EL2NSYNC +#define TARGET_EL2NSYNC 95 /* Level 2 not synchronized */ +#undef TARGET_EL3HLT +#define TARGET_EL3HLT 96 /* Level 3 halted */ +#undef TARGET_EL3RST +#define TARGET_EL3RST 97 /* Level 3 reset */ +#undef TARGET_ELNRNG +#define TARGET_ELNRNG 98 /* Link number out of range */ +#undef TARGET_EUNATCH +#define TARGET_EUNATCH 99 /* Protocol driver not attached */ +#undef TARGET_ENOCSI +#define TARGET_ENOCSI 100 /* No CSI structure available */ +#undef TARGET_EL2HLT +#define TARGET_EL2HLT 101 /* Level 2 halted */ +#undef TARGET_EBADE +#define TARGET_EBADE 102 /* Invalid exchange */ +#undef TARGET_EBADR +#define TARGET_EBADR 103 /* Invalid request descriptor */ +#undef TARGET_EXFULL +#define TARGET_EXFULL 104 /* Exchange full */ +#undef TARGET_ENOANO +#define TARGET_ENOANO 105 /* No anode */ +#undef TARGET_EBADRQC +#define TARGET_EBADRQC 106 /* Invalid request code */ +#undef TARGET_EBADSLT +#define TARGET_EBADSLT 107 /* Invalid slot */ +#undef TARGET_EDEADLOCK +#define TARGET_EDEADLOCK 108 /* File locking deadlock error */ +#undef TARGET_EBFONT +#define TARGET_EBFONT 109 /* Bad font file format */ +#undef TARGET_ELIBEXEC +#define TARGET_ELIBEXEC 110 /* Cannot exec a shared library directly */ +#undef TARGET_ENODATA +#define TARGET_ENODATA 111 /* No data available */ +#undef TARGET_ELIBBAD +#define TARGET_ELIBBAD 112 /* Accessing a corrupted shared library */ +#undef TARGET_ENOPKG +#define TARGET_ENOPKG 113 /* Package not installed */ +#undef TARGET_ELIBACC +#define TARGET_ELIBACC 114 /* Can not access a needed shared library */ +#undef TARGET_ENOTUNIQ +#define TARGET_ENOTUNIQ 115 /* Name not unique on network */ +#undef TARGET_ERESTART +#define TARGET_ERESTART 116 /* Interrupted syscall should be restarted */ +#undef TARGET_EUCLEAN +#define TARGET_EUCLEAN 117 /* Structure needs cleaning */ +#undef TARGET_ENOTNAM +#define TARGET_ENOTNAM 118 /* Not a XENIX named type file */ +#undef TARGET_ENAVAIL +#define TARGET_ENAVAIL 119 /* No XENIX semaphores available */ +#undef TARGET_EISNAM +#define TARGET_EISNAM 120 /* Is a named type file */ +#undef TARGET_EREMOTEIO +#define TARGET_EREMOTEIO 121 /* Remote I/O error */ +#undef TARGET_EILSEQ +#define TARGET_EILSEQ 122 /* Illegal byte sequence */ +#undef TARGET_ELIBMAX +#define TARGET_ELIBMAX 123 /* Atmpt to link in too many shared libs */ +#undef TARGET_ELIBSCN +#define TARGET_ELIBSCN 124 /* .lib section in a.out corrupted */ +#undef TARGET_ENOMEDIUM +#define TARGET_ENOMEDIUM 125 /* No medium found */ +#undef TARGET_EMEDIUMTYPE +#define TARGET_EMEDIUMTYPE 126 /* Wrong medium type */ +#undef TARGET_ECANCELED +#define TARGET_ECANCELED 127 /* Operation Cancelled */ +#undef TARGET_ENOKEY +#define TARGET_ENOKEY 128 /* Required key not available */ +#undef TARGET_EKEYEXPIRED +#define TARGET_EKEYEXPIRED 129 /* Key has expired */ +#undef TARGET_EKEYREVOKED +#define TARGET_EKEYREVOKED 130 /* Key has been revoked */ +#undef TARGET_EKEYREJECTED +#define TARGET_EKEYREJECTED 131 /* Key was rejected by service */ +#undef TARGET_EOWNERDEAD +#define TARGET_EOWNERDEAD 132 /* Owner died */ +#undef TARGET_ENOTRECOVERABLE +#define TARGET_ENOTRECOVERABLE 133 /* State not recoverable */ +#undef TARGET_ERFKILL +#define TARGET_ERFKILL 134 /* Operation not possible due to RF-kill */ +#undef TARGET_EHWPOISON +#define TARGET_EHWPOISON 135 /* Memory page has hardware error */ +#endif diff --git a/linux-user/sparc/target_syscall.h b/linux-user/sparc/target_syscall.h index 5f09abfe89..b9160a771b 100644 --- a/linux-user/sparc/target_syscall.h +++ b/linux-user/sparc/target_syscall.h @@ -1,6 +1,8 @@ #ifndef SPARC_TARGET_SYSCALL_H #define SPARC_TARGET_SYSCALL_H +#include "target_errno.h" + struct target_pt_regs { abi_ulong psr; abi_ulong pc; @@ -9,7 +11,7 @@ struct target_pt_regs { abi_ulong u_regs[16]; }; -#define UNAME_MACHINE "sun4" +#define UNAME_MACHINE "sparc" #define UNAME_MINIMUM_RELEASE "2.6.32" /* SPARC kernels don't define this in their Kconfig, but they have the diff --git a/linux-user/sparc64/syscall_nr.h b/linux-user/sparc64/syscall_nr.h index 2b49ead267..9391645598 100644 --- a/linux-user/sparc64/syscall_nr.h +++ b/linux-user/sparc64/syscall_nr.h @@ -23,7 +23,7 @@ #define TARGET_NR_capset 22 /* Linux Specific */ #define TARGET_NR_setuid 23 /* Implemented via setreuid in SunOS */ #define TARGET_NR_getuid 24 /* Common */ -/* #define TARGET_NR_time alias 25 ENOSYS under SunOS */ +#define TARGET_NR_vmsplice 25 #define TARGET_NR_ptrace 26 /* Common */ #define TARGET_NR_alarm 27 /* Implemented via setitimer in SunOS */ #define TARGET_NR_sigaltstack 28 /* Common */ @@ -149,8 +149,8 @@ #define TARGET_NR_pciconfig_read 148 /* ENOSYS under SunOS */ #define TARGET_NR_pciconfig_write 149 /* ENOSYS under SunOS */ #define TARGET_NR_getsockname 150 /* Common */ -/* #define TARGET_NR_getmsg 151 SunOS Specific */ -/* #define TARGET_NR_putmsg 152 SunOS Specific */ +#define TARGET_NR_inotify_init 151 +#define TARGET_NR_inotify_add_watch 152 #define TARGET_NR_poll 153 /* Common */ #define TARGET_NR_getdents64 154 /* Linux specific */ #define TARGET_NR_fcntl64 155 /* Linux sparc32 Specific */ @@ -194,7 +194,7 @@ #define TARGET_NR_epoll_create 193 /* Linux Specific */ #define TARGET_NR_epoll_ctl 194 /* Linux Specific */ #define TARGET_NR_epoll_wait 195 /* Linux Specific */ -/* #define TARGET_NR_ulimit 196 Linux Specific */ +#define TARGET_NR_ioprio_set 196 #define TARGET_NR_getppid 197 /* Linux Specific */ #define TARGET_NR_sigaction 198 /* Linux Specific */ #define TARGET_NR_sgetmask 199 /* Linux Specific */ @@ -216,7 +216,7 @@ #define TARGET_NR_ipc 215 /* Linux Specific */ #define TARGET_NR_sigreturn 216 /* Linux Specific */ #define TARGET_NR_clone 217 /* Linux Specific */ -/* #define TARGET_NR_modify_ldt 218 Linux Specific - i386 specific, unused */ +#define TARGET_NR_ioprio_get 218 #define TARGET_NR_adjtimex 219 /* Linux Specific */ #define TARGET_NR_sigprocmask 220 /* Linux Specific */ #define TARGET_NR_create_module 221 /* Linux Specific */ @@ -230,7 +230,7 @@ #define TARGET_NR_setfsgid 229 /* Linux Specific */ #define TARGET_NR__newselect 230 /* Linux Specific */ #define TARGET_NR_time 231 /* Linux sparc32 */ -/* #define TARGET_NR_oldstat 232 Linux Specific */ +#define TARGET_NR_splice 232 #define TARGET_NR_stime 233 /* Linux Specific */ #define TARGET_NR_statfs64 234 /* Linux Specific */ #define TARGET_NR_fstatfs64 235 /* Linux Specific */ @@ -253,7 +253,7 @@ #define TARGET_NR_getsid 252 #define TARGET_NR_fdatasync 253 #define TARGET_NR_nfsservctl 254 -#define TARGET_NR_aplib 255 +#define TARGET_NR_sync_file_range 255 #define TARGET_NR_clock_settime 256 #define TARGET_NR_clock_gettime 257 #define TARGET_NR_clock_getres 258 @@ -310,7 +310,7 @@ #define TARGET_NR_epoll_pwait 309 #define TARGET_NR_utimensat 310 #define TARGET_NR_signalfd 311 -#define TARGET_NR_timerfd 312 +#define TARGET_NR_timerfd_create 312 #define TARGET_NR_eventfd 313 #define TARGET_NR_fallocate 314 #define TARGET_NR_timerfd_settime 315 @@ -355,3 +355,7 @@ #define TARGET_NR_listen 354 #define TARGET_NR_setsockopt 355 #define TARGET_NR_mlock2 356 +#define TARGET_NR_copy_file_range 357 +#define TARGET_NR_preadv2 358 +#define TARGET_NR_pwritev2 359 +#define TARGET_NR_statx 360 diff --git a/linux-user/sparc64/target_syscall.h b/linux-user/sparc64/target_syscall.h index 2cbbaaed1b..3073a23e03 100644 --- a/linux-user/sparc64/target_syscall.h +++ b/linux-user/sparc64/target_syscall.h @@ -1,6 +1,8 @@ #ifndef SPARC64_TARGET_SYSCALL_H #define SPARC64_TARGET_SYSCALL_H +#include "../sparc/target_errno.h" + struct target_pt_regs { abi_ulong u_regs[16]; abi_ulong tstate; @@ -10,7 +12,7 @@ struct target_pt_regs { abi_ulong fprs; }; -#define UNAME_MACHINE "sun4u" +#define UNAME_MACHINE "sparc64" #define UNAME_MINIMUM_RELEASE "2.6.32" /* SPARC kernels don't define this in their Kconfig, but they have the @@ -29,5 +31,4 @@ static inline abi_ulong target_shmlba(CPUSPARCState *env) { return MAX(TARGET_PAGE_SIZE, 16 * 1024); } - #endif /* SPARC64_TARGET_SYSCALL_H */ diff --git a/linux-user/syscall.c b/linux-user/syscall.c index e4825747f9..af8603f1b7 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6546,28 +6546,50 @@ static int target_to_host_fcntl_cmd(int cmd) return -TARGET_EINVAL; } -#define TRANSTBL_CONVERT(a) { -1, TARGET_##a, -1, a } -static const bitmask_transtbl flock_tbl[] = { - TRANSTBL_CONVERT(F_RDLCK), - TRANSTBL_CONVERT(F_WRLCK), - TRANSTBL_CONVERT(F_UNLCK), - TRANSTBL_CONVERT(F_EXLCK), - TRANSTBL_CONVERT(F_SHLCK), - { 0, 0, 0, 0 } -}; +#define FLOCK_TRANSTBL \ + switch (type) { \ + TRANSTBL_CONVERT(F_RDLCK); \ + TRANSTBL_CONVERT(F_WRLCK); \ + TRANSTBL_CONVERT(F_UNLCK); \ + TRANSTBL_CONVERT(F_EXLCK); \ + TRANSTBL_CONVERT(F_SHLCK); \ + } + +static int target_to_host_flock(int type) +{ +#define TRANSTBL_CONVERT(a) case TARGET_##a: return a + FLOCK_TRANSTBL +#undef TRANSTBL_CONVERT + return -TARGET_EINVAL; +} + +static int host_to_target_flock(int type) +{ +#define TRANSTBL_CONVERT(a) case a: return TARGET_##a + FLOCK_TRANSTBL +#undef TRANSTBL_CONVERT + /* if we don't know how to convert the value coming + * from the host we copy to the target field as-is + */ + return type; +} static inline abi_long copy_from_user_flock(struct flock64 *fl, abi_ulong target_flock_addr) { struct target_flock *target_fl; - short l_type; + int l_type; if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) { return -TARGET_EFAULT; } __get_user(l_type, &target_fl->l_type); - fl->l_type = target_to_host_bitmask(l_type, flock_tbl); + l_type = target_to_host_flock(l_type); + if (l_type < 0) { + return l_type; + } + fl->l_type = l_type; __get_user(fl->l_whence, &target_fl->l_whence); __get_user(fl->l_start, &target_fl->l_start); __get_user(fl->l_len, &target_fl->l_len); @@ -6586,7 +6608,7 @@ static inline abi_long copy_to_user_flock(abi_ulong target_flock_addr, return -TARGET_EFAULT; } - l_type = host_to_target_bitmask(fl->l_type, flock_tbl); + l_type = host_to_target_flock(fl->l_type); __put_user(l_type, &target_fl->l_type); __put_user(fl->l_whence, &target_fl->l_whence); __put_user(fl->l_start, &target_fl->l_start); @@ -6604,14 +6626,18 @@ static inline abi_long copy_from_user_oabi_flock64(struct flock64 *fl, abi_ulong target_flock_addr) { struct target_oabi_flock64 *target_fl; - short l_type; + int l_type; if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) { return -TARGET_EFAULT; } __get_user(l_type, &target_fl->l_type); - fl->l_type = target_to_host_bitmask(l_type, flock_tbl); + l_type = target_to_host_flock(l_type); + if (l_type < 0) { + return l_type; + } + fl->l_type = l_type; __get_user(fl->l_whence, &target_fl->l_whence); __get_user(fl->l_start, &target_fl->l_start); __get_user(fl->l_len, &target_fl->l_len); @@ -6630,7 +6656,7 @@ static inline abi_long copy_to_user_oabi_flock64(abi_ulong target_flock_addr, return -TARGET_EFAULT; } - l_type = host_to_target_bitmask(fl->l_type, flock_tbl); + l_type = host_to_target_flock(fl->l_type); __put_user(l_type, &target_fl->l_type); __put_user(fl->l_whence, &target_fl->l_whence); __put_user(fl->l_start, &target_fl->l_start); @@ -6645,14 +6671,18 @@ static inline abi_long copy_from_user_flock64(struct flock64 *fl, abi_ulong target_flock_addr) { struct target_flock64 *target_fl; - short l_type; + int l_type; if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) { return -TARGET_EFAULT; } __get_user(l_type, &target_fl->l_type); - fl->l_type = target_to_host_bitmask(l_type, flock_tbl); + l_type = target_to_host_flock(l_type); + if (l_type < 0) { + return l_type; + } + fl->l_type = l_type; __get_user(fl->l_whence, &target_fl->l_whence); __get_user(fl->l_start, &target_fl->l_start); __get_user(fl->l_len, &target_fl->l_len); @@ -6671,7 +6701,7 @@ static inline abi_long copy_to_user_flock64(abi_ulong target_flock_addr, return -TARGET_EFAULT; } - l_type = host_to_target_bitmask(fl->l_type, flock_tbl); + l_type = host_to_target_flock(fl->l_type); __put_user(l_type, &target_fl->l_type); __put_user(fl->l_whence, &target_fl->l_whence); __put_user(fl->l_start, &target_fl->l_start); diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 361bb83a29..e4cd87cc00 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -2441,6 +2441,15 @@ struct target_statfs64 { #define TARGET_F_SETLKW 7 #define TARGET_F_GETOWN 11 /* for sockets. */ #define TARGET_F_SETOWN 12 /* for sockets. */ +#elif defined(TARGET_SPARC) +#define TARGET_F_RDLCK 1 +#define TARGET_F_WRLCK 2 +#define TARGET_F_UNLCK 3 +#define TARGET_F_GETOWN 5 /* for sockets. */ +#define TARGET_F_SETOWN 6 /* for sockets. */ +#define TARGET_F_GETLK 7 +#define TARGET_F_SETLK 8 +#define TARGET_F_SETLKW 9 #else #define TARGET_F_GETLK 5 #define TARGET_F_SETLK 6 @@ -2634,6 +2643,17 @@ struct target_statfs64 { #define TARGET_O_SYNC (TARGET___O_SYNC | TARGET_O_DSYNC) #endif +#if defined(TARGET_SPARC) +#define TARGET_ARCH_FLOCK_PAD abi_short __unused; +#define TARGET_ARCH_FLOCK64_PAD abi_short __unused; +#elif defined(TARGET_MIPS) +#define TARGET_ARCH_FLOCK_PAD abi_long pad[4]; +#define TARGET_ARCH_FLOCK64_PAD +#else +#define TARGET_ARCH_FLOCK_PAD +#define TARGET_ARCH_FLOCK64_PAD +#endif + struct target_flock { short l_type; short l_whence; @@ -2643,9 +2663,7 @@ struct target_flock { abi_long l_sysid; #endif int l_pid; -#if defined(TARGET_MIPS) - abi_long pad[4]; -#endif + TARGET_ARCH_FLOCK_PAD }; struct target_flock64 { @@ -2654,6 +2672,7 @@ struct target_flock64 { abi_llong l_start; abi_llong l_len; abi_int l_pid; + TARGET_ARCH_FLOCK64_PAD }; struct target_f_owner_ex { diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c index e41b07d042..d093997219 100644 --- a/target/m68k/softfloat.c +++ b/target/m68k/softfloat.c @@ -103,6 +103,7 @@ floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status) mul64To128(bSig, qTemp, &term0, &term1); sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1); shortShift128Left(aSig0, aSig1, 62, &aSig0, &aSig1); + expDiff -= 62; } expDiff += 64; if (0 < expDiff) { diff --git a/target/openrisc/Makefile.objs b/target/openrisc/Makefile.objs index 918b1c6e9c..1b98a911ea 100644 --- a/target/openrisc/Makefile.objs +++ b/target/openrisc/Makefile.objs @@ -3,3 +3,12 @@ obj-y += cpu.o exception.o interrupt.o mmu.o translate.o obj-y += exception_helper.o fpu_helper.o \ interrupt_helper.o mmu_helper.o sys_helper.o obj-y += gdbstub.o + +DECODETREE = $(SRC_PATH)/scripts/decodetree.py + +target/openrisc/decode.inc.c: \ + $(SRC_PATH)/target/openrisc/insns.decode $(DECODETREE) + $(call quiet-command,\ + $(PYTHON) $(DECODETREE) -o $@ $<, "GEN", $(TARGET_DIR)$@) + +target/openrisc/translate.o: target/openrisc/decode.inc.c diff --git a/target/openrisc/fpu_helper.c b/target/openrisc/fpu_helper.c index 977a1e8e55..265ce13337 100644 --- a/target/openrisc/fpu_helper.c +++ b/target/openrisc/fpu_helper.c @@ -24,121 +24,70 @@ #include "exception.h" #include "fpu/softfloat.h" -static inline uint32_t ieee_ex_to_openrisc(OpenRISCCPU *cpu, int fexcp) +static int ieee_ex_to_openrisc(int fexcp) { int ret = 0; - if (fexcp) { - if (fexcp & float_flag_invalid) { - cpu->env.fpcsr |= FPCSR_IVF; - ret = 1; - } - if (fexcp & float_flag_overflow) { - cpu->env.fpcsr |= FPCSR_OVF; - ret = 1; - } - if (fexcp & float_flag_underflow) { - cpu->env.fpcsr |= FPCSR_UNF; - ret = 1; - } - if (fexcp & float_flag_divbyzero) { - cpu->env.fpcsr |= FPCSR_DZF; - ret = 1; - } - if (fexcp & float_flag_inexact) { - cpu->env.fpcsr |= FPCSR_IXF; - ret = 1; - } + if (fexcp & float_flag_invalid) { + ret |= FPCSR_IVF; + } + if (fexcp & float_flag_overflow) { + ret |= FPCSR_OVF; + } + if (fexcp & float_flag_underflow) { + ret |= FPCSR_UNF; + } + if (fexcp & float_flag_divbyzero) { + ret |= FPCSR_DZF; + } + if (fexcp & float_flag_inexact) { + ret |= FPCSR_IXF; } - return ret; } -static inline void update_fpcsr(OpenRISCCPU *cpu) +void HELPER(update_fpcsr)(CPUOpenRISCState *env) { - int tmp = ieee_ex_to_openrisc(cpu, - get_float_exception_flags(&cpu->env.fp_status)); - - SET_FP_CAUSE(cpu->env.fpcsr, tmp); - if ((GET_FP_ENABLE(cpu->env.fpcsr) & tmp) && - (cpu->env.fpcsr & FPCSR_FPEE)) { - helper_exception(&cpu->env, EXCP_FPE); - } else { - UPDATE_FP_FLAGS(cpu->env.fpcsr, tmp); + int tmp = get_float_exception_flags(&env->fp_status); + + if (tmp) { + set_float_exception_flags(0, &env->fp_status); + tmp = ieee_ex_to_openrisc(tmp); + if (tmp) { + env->fpcsr |= tmp; + if (env->fpcsr & FPCSR_FPEE) { + helper_exception(env, EXCP_FPE); + } + } } } uint64_t HELPER(itofd)(CPUOpenRISCState *env, uint64_t val) { - uint64_t itofd; - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); - - set_float_exception_flags(0, &cpu->env.fp_status); - itofd = int32_to_float64(val, &cpu->env.fp_status); - update_fpcsr(cpu); - - return itofd; + return int32_to_float64(val, &env->fp_status); } uint32_t HELPER(itofs)(CPUOpenRISCState *env, uint32_t val) { - uint32_t itofs; - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); - - set_float_exception_flags(0, &cpu->env.fp_status); - itofs = int32_to_float32(val, &cpu->env.fp_status); - update_fpcsr(cpu); - - return itofs; + return int32_to_float32(val, &env->fp_status); } uint64_t HELPER(ftoid)(CPUOpenRISCState *env, uint64_t val) { - uint64_t ftoid; - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); - - set_float_exception_flags(0, &cpu->env.fp_status); - ftoid = float32_to_int64(val, &cpu->env.fp_status); - update_fpcsr(cpu); - - return ftoid; + return float32_to_int64(val, &env->fp_status); } uint32_t HELPER(ftois)(CPUOpenRISCState *env, uint32_t val) { - uint32_t ftois; - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); - - set_float_exception_flags(0, &cpu->env.fp_status); - ftois = float32_to_int32(val, &cpu->env.fp_status); - update_fpcsr(cpu); - - return ftois; + return float32_to_int32(val, &env->fp_status); } -#define FLOAT_OP(name, p) void helper_float_##_##p(void) - #define FLOAT_CALC(name) \ uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \ uint64_t fdt0, uint64_t fdt1) \ -{ \ - uint64_t result; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - result = float64_ ## name(fdt0, fdt1, &cpu->env.fp_status); \ - update_fpcsr(cpu); \ - return result; \ -} \ - \ +{ return float64_ ## name(fdt0, fdt1, &env->fp_status); } \ uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \ uint32_t fdt0, uint32_t fdt1) \ -{ \ - uint32_t result; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - result = float32_ ## name(fdt0, fdt1, &cpu->env.fp_status); \ - update_fpcsr(cpu); \ - return result; \ -} \ +{ return float32_ ## name(fdt0, fdt1, &env->fp_status); } FLOAT_CALC(add) FLOAT_CALC(sub) @@ -151,132 +100,29 @@ FLOAT_CALC(rem) uint64_t helper_float_madd_d(CPUOpenRISCState *env, uint64_t a, uint64_t b, uint64_t c) { - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); - uint64_t result; - set_float_exception_flags(0, &cpu->env.fp_status); - /* Note that or1ksim doesn't use merged operation. */ - result = float64_mul(b, c, &cpu->env.fp_status); - result = float64_add(result, a, &cpu->env.fp_status); - update_fpcsr(cpu); - return result; + /* Note that or1ksim doesn't use fused operation. */ + b = float64_mul(b, c, &env->fp_status); + return float64_add(a, b, &env->fp_status); } uint32_t helper_float_madd_s(CPUOpenRISCState *env, uint32_t a, uint32_t b, uint32_t c) { - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); - uint32_t result; - set_float_exception_flags(0, &cpu->env.fp_status); - /* Note that or1ksim doesn't use merged operation. */ - result = float32_mul(b, c, &cpu->env.fp_status); - result = float32_add(result, a, &cpu->env.fp_status); - update_fpcsr(cpu); - return result; + /* Note that or1ksim doesn't use fused operation. */ + b = float32_mul(b, c, &env->fp_status); + return float32_add(a, b, &env->fp_status); } -#define FLOAT_CMP(name) \ -uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \ - uint64_t fdt0, uint64_t fdt1) \ -{ \ - int res; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - res = float64_ ## name(fdt0, fdt1, &cpu->env.fp_status); \ - update_fpcsr(cpu); \ - return res; \ -} \ - \ -uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \ - uint32_t fdt0, uint32_t fdt1)\ -{ \ - int res; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - res = float32_ ## name(fdt0, fdt1, &cpu->env.fp_status); \ - update_fpcsr(cpu); \ - return res; \ -} +#define FLOAT_CMP(name, impl) \ +target_ulong helper_float_ ## name ## _d(CPUOpenRISCState *env, \ + uint64_t fdt0, uint64_t fdt1) \ +{ return float64_ ## impl(fdt0, fdt1, &env->fp_status); } \ +target_ulong helper_float_ ## name ## _s(CPUOpenRISCState *env, \ + uint32_t fdt0, uint32_t fdt1) \ +{ return float32_ ## impl(fdt0, fdt1, &env->fp_status); } -FLOAT_CMP(le) -FLOAT_CMP(eq) -FLOAT_CMP(lt) +FLOAT_CMP(le, le) +FLOAT_CMP(lt, lt) +FLOAT_CMP(eq, eq_quiet) #undef FLOAT_CMP - - -#define FLOAT_CMPNE(name) \ -uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \ - uint64_t fdt0, uint64_t fdt1) \ -{ \ - int res; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - res = !float64_eq_quiet(fdt0, fdt1, &cpu->env.fp_status); \ - update_fpcsr(cpu); \ - return res; \ -} \ - \ -uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \ - uint32_t fdt0, uint32_t fdt1) \ -{ \ - int res; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - res = !float32_eq_quiet(fdt0, fdt1, &cpu->env.fp_status); \ - update_fpcsr(cpu); \ - return res; \ -} - -FLOAT_CMPNE(ne) -#undef FLOAT_CMPNE - -#define FLOAT_CMPGT(name) \ -uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \ - uint64_t fdt0, uint64_t fdt1) \ -{ \ - int res; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - res = !float64_le(fdt0, fdt1, &cpu->env.fp_status); \ - update_fpcsr(cpu); \ - return res; \ -} \ - \ -uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \ - uint32_t fdt0, uint32_t fdt1) \ -{ \ - int res; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - res = !float32_le(fdt0, fdt1, &cpu->env.fp_status); \ - update_fpcsr(cpu); \ - return res; \ -} -FLOAT_CMPGT(gt) -#undef FLOAT_CMPGT - -#define FLOAT_CMPGE(name) \ -uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \ - uint64_t fdt0, uint64_t fdt1) \ -{ \ - int res; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - res = !float64_lt(fdt0, fdt1, &cpu->env.fp_status); \ - update_fpcsr(cpu); \ - return res; \ -} \ - \ -uint32_t helper_float_ ## name ## _s(CPUOpenRISCState *env, \ - uint32_t fdt0, uint32_t fdt1) \ -{ \ - int res; \ - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); \ - set_float_exception_flags(0, &cpu->env.fp_status); \ - res = !float32_lt(fdt0, fdt1, &cpu->env.fp_status); \ - update_fpcsr(cpu); \ - return res; \ -} - -FLOAT_CMPGE(ge) -#undef FLOAT_CMPGE diff --git a/target/openrisc/helper.h b/target/openrisc/helper.h index 4fd1a6bb8e..e37dabc77a 100644 --- a/target/openrisc/helper.h +++ b/target/openrisc/helper.h @@ -24,17 +24,19 @@ DEF_HELPER_FLAGS_1(ove_ov, TCG_CALL_NO_WG, void, env) DEF_HELPER_FLAGS_1(ove_cyov, TCG_CALL_NO_WG, void, env) /* float */ -DEF_HELPER_FLAGS_2(itofd, TCG_CALL_NO_WG, i64, env, i64) -DEF_HELPER_FLAGS_2(itofs, TCG_CALL_NO_WG, i32, env, i32) -DEF_HELPER_FLAGS_2(ftoid, TCG_CALL_NO_WG, i64, env, i64) -DEF_HELPER_FLAGS_2(ftois, TCG_CALL_NO_WG, i32, env, i32) +DEF_HELPER_FLAGS_1(update_fpcsr, TCG_CALL_NO_WG, void, env) -DEF_HELPER_FLAGS_4(float_madd_s, TCG_CALL_NO_WG, i32, env, i32, i32, i32) -DEF_HELPER_FLAGS_4(float_madd_d, TCG_CALL_NO_WG, i64, env, i64, i64, i64) +DEF_HELPER_FLAGS_2(itofd, TCG_CALL_NO_RWG, i64, env, i64) +DEF_HELPER_FLAGS_2(itofs, TCG_CALL_NO_RWG, i32, env, i32) +DEF_HELPER_FLAGS_2(ftoid, TCG_CALL_NO_RWG, i64, env, i64) +DEF_HELPER_FLAGS_2(ftois, TCG_CALL_NO_RWG, i32, env, i32) + +DEF_HELPER_FLAGS_4(float_madd_s, TCG_CALL_NO_RWG, i32, env, i32, i32, i32) +DEF_HELPER_FLAGS_4(float_madd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64) #define FOP_CALC(op) \ -DEF_HELPER_FLAGS_3(float_ ## op ## _s, TCG_CALL_NO_WG, i32, env, i32, i32) \ -DEF_HELPER_FLAGS_3(float_ ## op ## _d, TCG_CALL_NO_WG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(float_ ## op ## _s, TCG_CALL_NO_RWG, i32, env, i32, i32) \ +DEF_HELPER_FLAGS_3(float_ ## op ## _d, TCG_CALL_NO_RWG, i64, env, i64, i64) FOP_CALC(add) FOP_CALC(sub) FOP_CALC(mul) @@ -43,14 +45,11 @@ FOP_CALC(rem) #undef FOP_CALC #define FOP_CMP(op) \ -DEF_HELPER_FLAGS_3(float_ ## op ## _s, TCG_CALL_NO_WG, i32, env, i32, i32) \ -DEF_HELPER_FLAGS_3(float_ ## op ## _d, TCG_CALL_NO_WG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(float_ ## op ## _s, TCG_CALL_NO_RWG, tl, env, i32, i32) \ +DEF_HELPER_FLAGS_3(float_ ## op ## _d, TCG_CALL_NO_RWG, tl, env, i64, i64) FOP_CMP(eq) FOP_CMP(lt) FOP_CMP(le) -FOP_CMP(ne) -FOP_CMP(gt) -FOP_CMP(ge) #undef FOP_CMP /* interrupt */ diff --git a/target/openrisc/insns.decode b/target/openrisc/insns.decode new file mode 100644 index 0000000000..dad68c8422 --- /dev/null +++ b/target/openrisc/insns.decode @@ -0,0 +1,189 @@ +# +# OpenRISC instruction decode definitions. +# +# Copyright (c) 2018 Richard Henderson <rth@twiddle.net> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, see <http://www.gnu.org/licenses/>. +# + +&dab d a b +&da d a +&ab a b +&dal d a l +&ai a i + +#### +# System Instructions +#### + +l_sys 001000 0000000000 k:16 +l_trap 001000 0100000000 k:16 +l_msync 001000 1000000000 00000000 00000000 +l_psync 001000 1010000000 00000000 00000000 +l_csync 001000 1100000000 00000000 00000000 + +l_rfe 001001 ----- ----- -------- -------- + +#### +# Branch Instructions +#### + +l_j 000000 n:s26 +l_jal 000001 n:s26 +l_bnf 000011 n:s26 +l_bf 000100 n:s26 + +l_jr 010001 ---------- b:5 ----------- +l_jalr 010010 ---------- b:5 ----------- + +#### +# Memory Instructions +#### + +&load d a i +@load ...... d:5 a:5 i:s16 &load + +%store_i 21:s5 0:11 +&store a b i +@store ...... ..... a:5 b:5 ........... &store i=%store_i + +l_lwa 011011 ..... ..... ........ ........ @load +l_lwz 100001 ..... ..... ........ ........ @load +l_lws 100010 ..... ..... ........ ........ @load +l_lbz 100011 ..... ..... ........ ........ @load +l_lbs 100100 ..... ..... ........ ........ @load +l_lhz 100101 ..... ..... ........ ........ @load +l_lhs 100110 ..... ..... ........ ........ @load + +l_swa 110011 ..... ..... ..... ........... @store +l_sw 110101 ..... ..... ..... ........... @store +l_sb 110110 ..... ..... ..... ........... @store +l_sh 110111 ..... ..... ..... ........... @store + +#### +# Immediate Operand Instructions +#### + +%mtspr_k 21:5 0:11 + +&rri d a i +&rrk d a k +@rri ...... d:5 a:5 i:s16 &rri +@rrk ...... d:5 a:5 k:16 &rrk + +l_nop 000101 01--- ----- k:16 + +l_addi 100111 ..... ..... ........ ........ @rri +l_addic 101000 ..... ..... ........ ........ @rri +l_andi 101001 ..... ..... ........ ........ @rrk +l_ori 101010 ..... ..... ........ ........ @rrk +l_xori 101011 ..... ..... ........ ........ @rri +l_muli 101100 ..... ..... ........ ........ @rri + +l_mfspr 101101 ..... ..... ........ ........ @rrk +l_mtspr 110000 ..... a:5 b:5 ........... k=%mtspr_k + +l_maci 010011 ----- a:5 i:s16 + +l_movhi 000110 d:5 ----0 k:16 +l_macrc 000110 d:5 ----1 00000000 00000000 + +#### +# Arithmetic Instructions +#### + +l_exths 111000 d:5 a:5 ----- - 0000 -- 1100 +l_extbs 111000 d:5 a:5 ----- - 0001 -- 1100 +l_exthz 111000 d:5 a:5 ----- - 0010 -- 1100 +l_extbz 111000 d:5 a:5 ----- - 0011 -- 1100 + +l_add 111000 d:5 a:5 b:5 - 00 ---- 0000 +l_addc 111000 d:5 a:5 b:5 - 00 ---- 0001 +l_sub 111000 d:5 a:5 b:5 - 00 ---- 0010 +l_and 111000 d:5 a:5 b:5 - 00 ---- 0011 +l_or 111000 d:5 a:5 b:5 - 00 ---- 0100 +l_xor 111000 d:5 a:5 b:5 - 00 ---- 0101 +l_cmov 111000 d:5 a:5 b:5 - 00 ---- 1110 +l_ff1 111000 d:5 a:5 ----- - 00 ---- 1111 +l_fl1 111000 d:5 a:5 ----- - 01 ---- 1111 + +l_sll 111000 d:5 a:5 b:5 - 0000 -- 1000 +l_srl 111000 d:5 a:5 b:5 - 0001 -- 1000 +l_sra 111000 d:5 a:5 b:5 - 0010 -- 1000 +l_ror 111000 d:5 a:5 b:5 - 0011 -- 1000 + +l_mul 111000 d:5 a:5 b:5 - 11 ---- 0110 +l_mulu 111000 d:5 a:5 b:5 - 11 ---- 1011 +l_div 111000 d:5 a:5 b:5 - 11 ---- 1001 +l_divu 111000 d:5 a:5 b:5 - 11 ---- 1010 + +l_muld 111000 ----- a:5 b:5 - 11 ---- 0111 +l_muldu 111000 ----- a:5 b:5 - 11 ---- 1100 + +l_mac 110001 ----- a:5 b:5 ------- 0001 +l_macu 110001 ----- a:5 b:5 ------- 0011 +l_msb 110001 ----- a:5 b:5 ------- 0010 +l_msbu 110001 ----- a:5 b:5 ------- 0100 + +l_slli 101110 d:5 a:5 -------- 00 l:6 +l_srli 101110 d:5 a:5 -------- 01 l:6 +l_srai 101110 d:5 a:5 -------- 10 l:6 +l_rori 101110 d:5 a:5 -------- 11 l:6 + +#### +# Compare Instructions +#### + +l_sfeq 111001 00000 a:5 b:5 ----------- +l_sfne 111001 00001 a:5 b:5 ----------- +l_sfgtu 111001 00010 a:5 b:5 ----------- +l_sfgeu 111001 00011 a:5 b:5 ----------- +l_sfltu 111001 00100 a:5 b:5 ----------- +l_sfleu 111001 00101 a:5 b:5 ----------- +l_sfgts 111001 01010 a:5 b:5 ----------- +l_sfges 111001 01011 a:5 b:5 ----------- +l_sflts 111001 01100 a:5 b:5 ----------- +l_sfles 111001 01101 a:5 b:5 ----------- + +l_sfeqi 101111 00000 a:5 i:s16 +l_sfnei 101111 00001 a:5 i:s16 +l_sfgtui 101111 00010 a:5 i:s16 +l_sfgeui 101111 00011 a:5 i:s16 +l_sfltui 101111 00100 a:5 i:s16 +l_sfleui 101111 00101 a:5 i:s16 +l_sfgtsi 101111 01010 a:5 i:s16 +l_sfgesi 101111 01011 a:5 i:s16 +l_sfltsi 101111 01100 a:5 i:s16 +l_sflesi 101111 01101 a:5 i:s16 + +#### +# FP Instructions +#### + +lf_add_s 110010 d:5 a:5 b:5 --- 00000000 +lf_sub_s 110010 d:5 a:5 b:5 --- 00000001 +lf_mul_s 110010 d:5 a:5 b:5 --- 00000010 +lf_div_s 110010 d:5 a:5 b:5 --- 00000011 +lf_rem_s 110010 d:5 a:5 b:5 --- 00000110 +lf_madd_s 110010 d:5 a:5 b:5 --- 00000111 + +lf_itof_s 110010 d:5 a:5 00000 --- 00000100 +lf_ftoi_s 110010 d:5 a:5 00000 --- 00000101 + +lf_sfeq_s 110010 ----- a:5 b:5 --- 00001000 +lf_sfne_s 110010 ----- a:5 b:5 --- 00001001 +lf_sfgt_s 110010 ----- a:5 b:5 --- 00001010 +lf_sfge_s 110010 ----- a:5 b:5 --- 00001011 +lf_sflt_s 110010 ----- a:5 b:5 --- 00001100 +lf_sfle_s 110010 ----- a:5 b:5 --- 00001101 diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 7cf29cd5b0..e7c96ca990 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -31,6 +31,7 @@ #include "exec/helper-proto.h" #include "exec/helper-gen.h" +#include "exec/gen-icount.h" #include "trace-tcg.h" #include "exec/log.h" @@ -51,6 +52,9 @@ typedef struct DisasContext { uint32_t delayed_branch; } DisasContext; +/* Include the auto-generated decoder. */ +#include "decode.inc.c" + static TCGv cpu_sr; static TCGv cpu_R[32]; static TCGv cpu_R0; @@ -65,7 +69,6 @@ static TCGv cpu_lock_value; static TCGv_i32 fpcsr; static TCGv_i64 cpu_mac; /* MACHI:MACLO */ static TCGv_i32 cpu_dflag; -#include "exec/gen-icount.h" void openrisc_translate_init(void) { @@ -190,52 +193,6 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) } } -static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0) -{ - target_ulong tmp_pc = dc->base.pc_next + n26 * 4; - - switch (op0) { - case 0x00: /* l.j */ - tcg_gen_movi_tl(jmp_pc, tmp_pc); - break; - case 0x01: /* l.jal */ - tcg_gen_movi_tl(cpu_R[9], dc->base.pc_next + 8); - /* Optimize jal being used to load the PC for PIC. */ - if (tmp_pc == dc->base.pc_next + 8) { - return; - } - tcg_gen_movi_tl(jmp_pc, tmp_pc); - break; - case 0x03: /* l.bnf */ - case 0x04: /* l.bf */ - { - TCGv t_next = tcg_const_tl(dc->base.pc_next + 8); - TCGv t_true = tcg_const_tl(tmp_pc); - TCGv t_zero = tcg_const_tl(0); - - tcg_gen_movcond_tl(op0 == 0x03 ? TCG_COND_EQ : TCG_COND_NE, - jmp_pc, cpu_sr_f, t_zero, t_true, t_next); - - tcg_temp_free(t_next); - tcg_temp_free(t_true); - tcg_temp_free(t_zero); - } - break; - case 0x11: /* l.jr */ - tcg_gen_mov_tl(jmp_pc, cpu_R[reg]); - break; - case 0x12: /* l.jalr */ - tcg_gen_movi_tl(cpu_R[9], (dc->base.pc_next + 8)); - tcg_gen_mov_tl(jmp_pc, cpu_R[reg]); - break; - default: - gen_illegal_exception(dc); - break; - } - - dc->delayed_branch = 2; -} - static void gen_ove_cy(DisasContext *dc) { if (dc->tb_flags & SR_OVE) { @@ -498,24 +455,350 @@ static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb) gen_ove_cy(dc); } -static void gen_lwa(DisasContext *dc, TCGv rd, TCGv ra, int32_t ofs) +static bool trans_l_add(DisasContext *dc, arg_dab *a, uint32_t insn) { - TCGv ea = tcg_temp_new(); + LOG_DIS("l.add r%d, r%d, r%d\n", a->d, a->a, a->b); + check_r0_write(a->d); + gen_add(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); + return true; +} + +static bool trans_l_addc(DisasContext *dc, arg_dab *a, uint32_t insn) +{ + LOG_DIS("l.addc r%d, r%d, r%d\n", a->d, a->a, a->b); + check_r0_write(a->d); + gen_addc(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); + return true; +} - tcg_gen_addi_tl(ea, ra, ofs); - tcg_gen_qemu_ld_tl(rd, ea, dc->mem_idx, MO_TEUL); +static bool trans_l_sub(DisasContext *dc, arg_dab *a, uint32_t insn) +{ + LOG_DIS("l.sub r%d, r%d, r%d\n", a->d, a->a, a->b); + check_r0_write(a->d); + gen_sub(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); + return true; +} + +static bool trans_l_and(DisasContext *dc, arg_dab *a, uint32_t insn) +{ + LOG_DIS("l.and r%d, r%d, r%d\n", a->d, a->a, a->b); + check_r0_write(a->d); + tcg_gen_and_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); + return true; +} + +static bool trans_l_or(DisasContext *dc, arg_dab *a, uint32_t insn) +{ + LOG_DIS("l.or r%d, r%d, r%d\n", a->d, a->a, a->b); + check_r0_write(a->d); + tcg_gen_or_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); + return true; +} + +static bool trans_l_xor(DisasContext *dc, arg_dab *a, uint32_t insn) +{ + LOG_DIS("l.xor r%d, r%d, r%d\n", a->d, a->a, a->b); + check_r0_write(a->d); + tcg_gen_xor_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); + return true; +} + +static bool trans_l_sll(DisasContext *dc, arg_dab *a, uint32_t insn) +{ + LOG_DIS("l.sll r%d, r%d, r%d\n", a->d, a->a, a->b); + check_r0_write(a->d); + tcg_gen_shl_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); + return true; +} + +static bool trans_l_srl(DisasContext *dc, arg_dab *a, uint32_t insn) +{ + LOG_DIS("l.srl r%d, r%d, r%d\n", a->d, a->a, a->b); + check_r0_write(a->d); + tcg_gen_shr_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); + return true; +} + +static bool trans_l_sra(DisasContext *dc, arg_dab *a, uint32_t insn) +{ + LOG_DIS("l.sra r%d, r%d, r%d\n", a->d, a->a, a->b); + check_r0_write(a->d); + tcg_gen_sar_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); + return true; +} + +static bool trans_l_ror(DisasContext *dc, arg_dab *a, uint32_t insn) +{ + LOG_DIS("l.ror r%d, r%d, r%d\n", a->d, a->a, a->b); + check_r0_write(a->d); + tcg_gen_rotr_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); + return true; +} + +static bool trans_l_exths(DisasContext *dc, arg_da *a, uint32_t insn) +{ + LOG_DIS("l.exths r%d, r%d\n", a->d, a->a); + check_r0_write(a->d); + tcg_gen_ext16s_tl(cpu_R[a->d], cpu_R[a->a]); + return true; +} + +static bool trans_l_extbs(DisasContext *dc, arg_da *a, uint32_t insn) +{ + LOG_DIS("l.extbs r%d, r%d\n", a->d, a->a); + check_r0_write(a->d); + tcg_gen_ext8s_tl(cpu_R[a->d], cpu_R[a->a]); + return true; +} + +static bool trans_l_exthz(DisasContext *dc, arg_da *a, uint32_t insn) +{ + LOG_DIS("l.exthz r%d, r%d\n", a->d, a->a); + check_r0_write(a->d); + tcg_gen_ext16u_tl(cpu_R[a->d], cpu_R[a->a]); + return true; +} + +static bool trans_l_extbz(DisasContext *dc, arg_da *a, uint32_t insn) +{ + LOG_DIS("l.extbz r%d, r%d\n", a->d, a->a); + check_r0_write(a->d); + tcg_gen_ext8u_tl(cpu_R[a->d], cpu_R[a->a]); + return true; +} + +static bool trans_l_cmov(DisasContext *dc, arg_dab *a, uint32_t insn) +{ + TCGv zero; + LOG_DIS("l.cmov r%d, r%d, r%d\n", a->d, a->a, a->b); + + check_r0_write(a->d); + zero = tcg_const_tl(0); + tcg_gen_movcond_tl(TCG_COND_NE, cpu_R[a->d], cpu_sr_f, zero, + cpu_R[a->a], cpu_R[a->b]); + tcg_temp_free(zero); + return true; +} + +static bool trans_l_ff1(DisasContext *dc, arg_da *a, uint32_t insn) +{ + LOG_DIS("l.ff1 r%d, r%d\n", a->d, a->a); + + check_r0_write(a->d); + tcg_gen_ctzi_tl(cpu_R[a->d], cpu_R[a->a], -1); + tcg_gen_addi_tl(cpu_R[a->d], cpu_R[a->d], 1); + return true; +} + +static bool trans_l_fl1(DisasContext *dc, arg_da *a, uint32_t insn) +{ + LOG_DIS("l.fl1 r%d, r%d\n", a->d, a->a); + + check_r0_write(a->d); + tcg_gen_clzi_tl(cpu_R[a->d], cpu_R[a->a], TARGET_LONG_BITS); + tcg_gen_subfi_tl(cpu_R[a->d], TARGET_LONG_BITS, cpu_R[a->d]); + return true; +} + +static bool trans_l_mul(DisasContext *dc, arg_dab *a, uint32_t insn) +{ + LOG_DIS("l.mul r%d, r%d, r%d\n", a->d, a->a, a->b); + + check_r0_write(a->d); + gen_mul(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); + return true; +} + +static bool trans_l_mulu(DisasContext *dc, arg_dab *a, uint32_t insn) +{ + LOG_DIS("l.mulu r%d, r%d, r%d\n", a->d, a->a, a->b); + + check_r0_write(a->d); + gen_mulu(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); + return true; +} + +static bool trans_l_div(DisasContext *dc, arg_dab *a, uint32_t insn) +{ + LOG_DIS("l.div r%d, r%d, r%d\n", a->d, a->a, a->b); + + check_r0_write(a->d); + gen_div(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); + return true; +} + +static bool trans_l_divu(DisasContext *dc, arg_dab *a, uint32_t insn) +{ + LOG_DIS("l.divu r%d, r%d, r%d\n", a->d, a->a, a->b); + + check_r0_write(a->d); + gen_divu(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]); + return true; +} + +static bool trans_l_muld(DisasContext *dc, arg_ab *a, uint32_t insn) +{ + LOG_DIS("l.muld r%d, r%d\n", a->a, a->b); + gen_muld(dc, cpu_R[a->a], cpu_R[a->b]); + return true; +} + +static bool trans_l_muldu(DisasContext *dc, arg_ab *a, uint32_t insn) +{ + LOG_DIS("l.muldu r%d, r%d\n", a->a, a->b); + gen_muldu(dc, cpu_R[a->a], cpu_R[a->b]); + return true; +} + +static bool trans_l_j(DisasContext *dc, arg_l_j *a, uint32_t insn) +{ + target_ulong tmp_pc = dc->base.pc_next + a->n * 4; + + LOG_DIS("l.j %d\n", a->n); + tcg_gen_movi_tl(jmp_pc, tmp_pc); + dc->delayed_branch = 2; + return true; +} + +static bool trans_l_jal(DisasContext *dc, arg_l_jal *a, uint32_t insn) +{ + target_ulong tmp_pc = dc->base.pc_next + a->n * 4; + target_ulong ret_pc = dc->base.pc_next + 8; + + LOG_DIS("l.jal %d\n", a->n); + tcg_gen_movi_tl(cpu_R[9], ret_pc); + /* Optimize jal being used to load the PC for PIC. */ + if (tmp_pc != ret_pc) { + tcg_gen_movi_tl(jmp_pc, tmp_pc); + dc->delayed_branch = 2; + } + return true; +} + +static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond) +{ + target_ulong tmp_pc = dc->base.pc_next + a->n * 4; + TCGv t_next = tcg_const_tl(dc->base.pc_next + 8); + TCGv t_true = tcg_const_tl(tmp_pc); + TCGv t_zero = tcg_const_tl(0); + + tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, t_zero, t_true, t_next); + + tcg_temp_free(t_next); + tcg_temp_free(t_true); + tcg_temp_free(t_zero); + dc->delayed_branch = 2; +} + +static bool trans_l_bf(DisasContext *dc, arg_l_bf *a, uint32_t insn) +{ + LOG_DIS("l.bf %d\n", a->n); + do_bf(dc, a, TCG_COND_NE); + return true; +} + +static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a, uint32_t insn) +{ + LOG_DIS("l.bnf %d\n", a->n); + do_bf(dc, a, TCG_COND_EQ); + return true; +} + +static bool trans_l_jr(DisasContext *dc, arg_l_jr *a, uint32_t insn) +{ + LOG_DIS("l.jr r%d\n", a->b); + tcg_gen_mov_tl(jmp_pc, cpu_R[a->b]); + dc->delayed_branch = 2; + return true; +} + +static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a, uint32_t insn) +{ + LOG_DIS("l.jalr r%d\n", a->b); + tcg_gen_mov_tl(jmp_pc, cpu_R[a->b]); + tcg_gen_movi_tl(cpu_R[9], dc->base.pc_next + 8); + dc->delayed_branch = 2; + return true; +} + +static bool trans_l_lwa(DisasContext *dc, arg_load *a, uint32_t insn) +{ + TCGv ea; + + LOG_DIS("l.lwa r%d, r%d, %d\n", a->d, a->a, a->i); + + check_r0_write(a->d); + ea = tcg_temp_new(); + tcg_gen_addi_tl(ea, cpu_R[a->a], a->i); + tcg_gen_qemu_ld_tl(cpu_R[a->d], ea, dc->mem_idx, MO_TEUL); tcg_gen_mov_tl(cpu_lock_addr, ea); - tcg_gen_mov_tl(cpu_lock_value, rd); + tcg_gen_mov_tl(cpu_lock_value, cpu_R[a->d]); tcg_temp_free(ea); + return true; +} + +static void do_load(DisasContext *dc, arg_load *a, TCGMemOp mop) +{ + TCGv ea; + + check_r0_write(a->d); + ea = tcg_temp_new(); + tcg_gen_addi_tl(ea, cpu_R[a->a], a->i); + tcg_gen_qemu_ld_tl(cpu_R[a->d], ea, dc->mem_idx, mop); + tcg_temp_free(ea); +} + +static bool trans_l_lwz(DisasContext *dc, arg_load *a, uint32_t insn) +{ + LOG_DIS("l.lwz r%d, r%d, %d\n", a->d, a->a, a->i); + do_load(dc, a, MO_TEUL); + return true; +} + +static bool trans_l_lws(DisasContext *dc, arg_load *a, uint32_t insn) +{ + LOG_DIS("l.lws r%d, r%d, %d\n", a->d, a->a, a->i); + do_load(dc, a, MO_TESL); + return true; +} + +static bool trans_l_lbz(DisasContext *dc, arg_load *a, uint32_t insn) +{ + LOG_DIS("l.lbz r%d, r%d, %d\n", a->d, a->a, a->i); + do_load(dc, a, MO_UB); + return true; +} + +static bool trans_l_lbs(DisasContext *dc, arg_load *a, uint32_t insn) +{ + LOG_DIS("l.lbs r%d, r%d, %d\n", a->d, a->a, a->i); + do_load(dc, a, MO_SB); + return true; +} + +static bool trans_l_lhz(DisasContext *dc, arg_load *a, uint32_t insn) +{ + LOG_DIS("l.lhz r%d, r%d, %d\n", a->d, a->a, a->i); + do_load(dc, a, MO_TEUW); + return true; +} + +static bool trans_l_lhs(DisasContext *dc, arg_load *a, uint32_t insn) +{ + LOG_DIS("l.lhs r%d, r%d, %d\n", a->d, a->a, a->i); + do_load(dc, a, MO_TESW); + return true; } -static void gen_swa(DisasContext *dc, int b, TCGv ra, int32_t ofs) +static bool trans_l_swa(DisasContext *dc, arg_store *a, uint32_t insn) { TCGv ea, val; TCGLabel *lab_fail, *lab_done; + LOG_DIS("l.swa r%d, r%d, %d\n", a->a, a->b, a->i); + ea = tcg_temp_new(); - tcg_gen_addi_tl(ea, ra, ofs); + tcg_gen_addi_tl(ea, cpu_R[a->a], a->i); /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned to cpu_R[0]. Since l.swa is quite often immediately followed by a @@ -530,7 +813,7 @@ static void gen_swa(DisasContext *dc, int b, TCGv ra, int32_t ofs) val = tcg_temp_new(); tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value, - cpu_R[b], dc->mem_idx, MO_TEUL); + cpu_R[a->b], dc->mem_idx, MO_TEUL); tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value); tcg_temp_free(val); @@ -541,983 +824,553 @@ static void gen_swa(DisasContext *dc, int b, TCGv ra, int32_t ofs) gen_set_label(lab_done); tcg_gen_movi_tl(cpu_lock_addr, -1); + return true; } -static void dec_calc(DisasContext *dc, uint32_t insn) +static void do_store(DisasContext *dc, arg_store *a, TCGMemOp mop) { - uint32_t op0, op1, op2; - uint32_t ra, rb, rd; - op0 = extract32(insn, 0, 4); - op1 = extract32(insn, 8, 2); - op2 = extract32(insn, 6, 2); - ra = extract32(insn, 16, 5); - rb = extract32(insn, 11, 5); - rd = extract32(insn, 21, 5); - - switch (op1) { - case 0: - switch (op0) { - case 0x0: /* l.add */ - LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb); - gen_add(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); - return; - - case 0x1: /* l.addc */ - LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb); - gen_addc(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); - return; - - case 0x2: /* l.sub */ - LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb); - gen_sub(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); - return; - - case 0x3: /* l.and */ - LOG_DIS("l.and r%d, r%d, r%d\n", rd, ra, rb); - tcg_gen_and_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - return; - - case 0x4: /* l.or */ - LOG_DIS("l.or r%d, r%d, r%d\n", rd, ra, rb); - tcg_gen_or_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - return; - - case 0x5: /* l.xor */ - LOG_DIS("l.xor r%d, r%d, r%d\n", rd, ra, rb); - tcg_gen_xor_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - return; - - case 0x8: - switch (op2) { - case 0: /* l.sll */ - LOG_DIS("l.sll r%d, r%d, r%d\n", rd, ra, rb); - tcg_gen_shl_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - return; - case 1: /* l.srl */ - LOG_DIS("l.srl r%d, r%d, r%d\n", rd, ra, rb); - tcg_gen_shr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - return; - case 2: /* l.sra */ - LOG_DIS("l.sra r%d, r%d, r%d\n", rd, ra, rb); - tcg_gen_sar_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - return; - case 3: /* l.ror */ - LOG_DIS("l.ror r%d, r%d, r%d\n", rd, ra, rb); - tcg_gen_rotr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]); - return; - } - break; - - case 0xc: - switch (op2) { - case 0: /* l.exths */ - LOG_DIS("l.exths r%d, r%d\n", rd, ra); - tcg_gen_ext16s_tl(cpu_R[rd], cpu_R[ra]); - return; - case 1: /* l.extbs */ - LOG_DIS("l.extbs r%d, r%d\n", rd, ra); - tcg_gen_ext8s_tl(cpu_R[rd], cpu_R[ra]); - return; - case 2: /* l.exthz */ - LOG_DIS("l.exthz r%d, r%d\n", rd, ra); - tcg_gen_ext16u_tl(cpu_R[rd], cpu_R[ra]); - return; - case 3: /* l.extbz */ - LOG_DIS("l.extbz r%d, r%d\n", rd, ra); - tcg_gen_ext8u_tl(cpu_R[rd], cpu_R[ra]); - return; - } - break; - - case 0xd: - switch (op2) { - case 0: /* l.extws */ - LOG_DIS("l.extws r%d, r%d\n", rd, ra); - tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[ra]); - return; - case 1: /* l.extwz */ - LOG_DIS("l.extwz r%d, r%d\n", rd, ra); - tcg_gen_ext32u_tl(cpu_R[rd], cpu_R[ra]); - return; - } - break; - - case 0xe: /* l.cmov */ - LOG_DIS("l.cmov r%d, r%d, r%d\n", rd, ra, rb); - { - TCGv zero = tcg_const_tl(0); - tcg_gen_movcond_tl(TCG_COND_NE, cpu_R[rd], cpu_sr_f, zero, - cpu_R[ra], cpu_R[rb]); - tcg_temp_free(zero); - } - return; - - case 0xf: /* l.ff1 */ - LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb); - tcg_gen_ctzi_tl(cpu_R[rd], cpu_R[ra], -1); - tcg_gen_addi_tl(cpu_R[rd], cpu_R[rd], 1); - return; - } - break; - - case 1: - switch (op0) { - case 0xf: /* l.fl1 */ - LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb); - tcg_gen_clzi_tl(cpu_R[rd], cpu_R[ra], TARGET_LONG_BITS); - tcg_gen_subfi_tl(cpu_R[rd], TARGET_LONG_BITS, cpu_R[rd]); - return; - } - break; - - case 2: - break; - - case 3: - switch (op0) { - case 0x6: /* l.mul */ - LOG_DIS("l.mul r%d, r%d, r%d\n", rd, ra, rb); - gen_mul(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); - return; - - case 0x7: /* l.muld */ - LOG_DIS("l.muld r%d, r%d\n", ra, rb); - gen_muld(dc, cpu_R[ra], cpu_R[rb]); - break; + TCGv t0 = tcg_temp_new(); + tcg_gen_addi_tl(t0, cpu_R[a->a], a->i); + tcg_gen_qemu_st_tl(cpu_R[a->b], t0, dc->mem_idx, mop); + tcg_temp_free(t0); +} - case 0x9: /* l.div */ - LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb); - gen_div(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); - return; +static bool trans_l_sw(DisasContext *dc, arg_store *a, uint32_t insn) +{ + LOG_DIS("l.sw r%d, r%d, %d\n", a->a, a->b, a->i); + do_store(dc, a, MO_TEUL); + return true; +} - case 0xa: /* l.divu */ - LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb); - gen_divu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); - return; +static bool trans_l_sb(DisasContext *dc, arg_store *a, uint32_t insn) +{ + LOG_DIS("l.sb r%d, r%d, %d\n", a->a, a->b, a->i); + do_store(dc, a, MO_UB); + return true; +} - case 0xb: /* l.mulu */ - LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb); - gen_mulu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]); - return; +static bool trans_l_sh(DisasContext *dc, arg_store *a, uint32_t insn) +{ + LOG_DIS("l.sh r%d, r%d, %d\n", a->a, a->b, a->i); + do_store(dc, a, MO_TEUW); + return true; +} - case 0xc: /* l.muldu */ - LOG_DIS("l.muldu r%d, r%d\n", ra, rb); - gen_muldu(dc, cpu_R[ra], cpu_R[rb]); - return; - } - break; - } - gen_illegal_exception(dc); +static bool trans_l_nop(DisasContext *dc, arg_l_nop *a, uint32_t insn) +{ + LOG_DIS("l.nop %d\n", a->k); + return true; } -static void dec_misc(DisasContext *dc, uint32_t insn) +static bool trans_l_addi(DisasContext *dc, arg_rri *a, uint32_t insn) { - uint32_t op0, op1; - uint32_t ra, rb, rd; - uint32_t L6, K5, K16, K5_11; - int32_t I16, I5_11, N26; - TCGMemOp mop; TCGv t0; - op0 = extract32(insn, 26, 6); - op1 = extract32(insn, 24, 2); - ra = extract32(insn, 16, 5); - rb = extract32(insn, 11, 5); - rd = extract32(insn, 21, 5); - L6 = extract32(insn, 5, 6); - K5 = extract32(insn, 0, 5); - K16 = extract32(insn, 0, 16); - I16 = (int16_t)K16; - N26 = sextract32(insn, 0, 26); - K5_11 = (extract32(insn, 21, 5) << 11) | extract32(insn, 0, 11); - I5_11 = (int16_t)K5_11; - - switch (op0) { - case 0x00: /* l.j */ - LOG_DIS("l.j %d\n", N26); - gen_jump(dc, N26, 0, op0); - break; - - case 0x01: /* l.jal */ - LOG_DIS("l.jal %d\n", N26); - gen_jump(dc, N26, 0, op0); - break; - - case 0x03: /* l.bnf */ - LOG_DIS("l.bnf %d\n", N26); - gen_jump(dc, N26, 0, op0); - break; - - case 0x04: /* l.bf */ - LOG_DIS("l.bf %d\n", N26); - gen_jump(dc, N26, 0, op0); - break; - - case 0x05: - switch (op1) { - case 0x01: /* l.nop */ - LOG_DIS("l.nop %d\n", I16); - break; - - default: - gen_illegal_exception(dc); - break; - } - break; - - case 0x11: /* l.jr */ - LOG_DIS("l.jr r%d\n", rb); - gen_jump(dc, 0, rb, op0); - break; - - case 0x12: /* l.jalr */ - LOG_DIS("l.jalr r%d\n", rb); - gen_jump(dc, 0, rb, op0); - break; - - case 0x13: /* l.maci */ - LOG_DIS("l.maci r%d, %d\n", ra, I16); - t0 = tcg_const_tl(I16); - gen_mac(dc, cpu_R[ra], t0); - tcg_temp_free(t0); - break; - - case 0x09: /* l.rfe */ - LOG_DIS("l.rfe\n"); - { -#if defined(CONFIG_USER_ONLY) - return; -#else - if (dc->mem_idx == MMU_USER_IDX) { - gen_illegal_exception(dc); - return; - } - gen_helper_rfe(cpu_env); - dc->base.is_jmp = DISAS_UPDATE; -#endif - } - break; - - case 0x1b: /* l.lwa */ - LOG_DIS("l.lwa r%d, r%d, %d\n", rd, ra, I16); - check_r0_write(rd); - gen_lwa(dc, cpu_R[rd], cpu_R[ra], I16); - break; + LOG_DIS("l.addi r%d, r%d, %d\n", a->d, a->a, a->i); + check_r0_write(a->d); + t0 = tcg_const_tl(a->i); + gen_add(dc, cpu_R[a->d], cpu_R[a->a], t0); + tcg_temp_free(t0); + return true; +} - case 0x1c: /* l.cust1 */ - LOG_DIS("l.cust1\n"); - break; +static bool trans_l_addic(DisasContext *dc, arg_rri *a, uint32_t insn) +{ + TCGv t0; - case 0x1d: /* l.cust2 */ - LOG_DIS("l.cust2\n"); - break; + LOG_DIS("l.addic r%d, r%d, %d\n", a->d, a->a, a->i); + check_r0_write(a->d); + t0 = tcg_const_tl(a->i); + gen_addc(dc, cpu_R[a->d], cpu_R[a->a], t0); + tcg_temp_free(t0); + return true; +} - case 0x1e: /* l.cust3 */ - LOG_DIS("l.cust3\n"); - break; +static bool trans_l_muli(DisasContext *dc, arg_rri *a, uint32_t insn) +{ + TCGv t0; - case 0x1f: /* l.cust4 */ - LOG_DIS("l.cust4\n"); - break; + LOG_DIS("l.muli r%d, r%d, %d\n", a->d, a->a, a->i); + check_r0_write(a->d); + t0 = tcg_const_tl(a->i); + gen_mul(dc, cpu_R[a->d], cpu_R[a->a], t0); + tcg_temp_free(t0); + return true; +} - case 0x3c: /* l.cust5 */ - LOG_DIS("l.cust5 r%d, r%d, r%d, %d, %d\n", rd, ra, rb, L6, K5); - break; +static bool trans_l_maci(DisasContext *dc, arg_l_maci *a, uint32_t insn) +{ + TCGv t0; - case 0x3d: /* l.cust6 */ - LOG_DIS("l.cust6\n"); - break; + LOG_DIS("l.maci r%d, %d\n", a->a, a->i); + t0 = tcg_const_tl(a->i); + gen_mac(dc, cpu_R[a->a], t0); + tcg_temp_free(t0); + return true; +} - case 0x3e: /* l.cust7 */ - LOG_DIS("l.cust7\n"); - break; +static bool trans_l_andi(DisasContext *dc, arg_rrk *a, uint32_t insn) +{ + LOG_DIS("l.andi r%d, r%d, %d\n", a->d, a->a, a->k); + check_r0_write(a->d); + tcg_gen_andi_tl(cpu_R[a->d], cpu_R[a->a], a->k); + return true; +} - case 0x3f: /* l.cust8 */ - LOG_DIS("l.cust8\n"); - break; +static bool trans_l_ori(DisasContext *dc, arg_rrk *a, uint32_t insn) +{ + LOG_DIS("l.ori r%d, r%d, %d\n", a->d, a->a, a->k); + check_r0_write(a->d); + tcg_gen_ori_tl(cpu_R[a->d], cpu_R[a->a], a->k); + return true; +} -/* not used yet, open it when we need or64. */ -/*#ifdef TARGET_OPENRISC64 - case 0x20: l.ld - LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16); - check_ob64s(dc); - mop = MO_TEQ; - goto do_load; -#endif*/ +static bool trans_l_xori(DisasContext *dc, arg_rri *a, uint32_t insn) +{ + LOG_DIS("l.xori r%d, r%d, %d\n", a->d, a->a, a->i); + check_r0_write(a->d); + tcg_gen_xori_tl(cpu_R[a->d], cpu_R[a->a], a->i); + return true; +} - case 0x21: /* l.lwz */ - LOG_DIS("l.lwz r%d, r%d, %d\n", rd, ra, I16); - mop = MO_TEUL; - goto do_load; - - case 0x22: /* l.lws */ - LOG_DIS("l.lws r%d, r%d, %d\n", rd, ra, I16); - mop = MO_TESL; - goto do_load; - - case 0x23: /* l.lbz */ - LOG_DIS("l.lbz r%d, r%d, %d\n", rd, ra, I16); - mop = MO_UB; - goto do_load; - - case 0x24: /* l.lbs */ - LOG_DIS("l.lbs r%d, r%d, %d\n", rd, ra, I16); - mop = MO_SB; - goto do_load; - - case 0x25: /* l.lhz */ - LOG_DIS("l.lhz r%d, r%d, %d\n", rd, ra, I16); - mop = MO_TEUW; - goto do_load; - - case 0x26: /* l.lhs */ - LOG_DIS("l.lhs r%d, r%d, %d\n", rd, ra, I16); - mop = MO_TESW; - goto do_load; - - do_load: - check_r0_write(rd); - t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[ra], I16); - tcg_gen_qemu_ld_tl(cpu_R[rd], t0, dc->mem_idx, mop); - tcg_temp_free(t0); - break; - - case 0x27: /* l.addi */ - LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16); - check_r0_write(rd); - t0 = tcg_const_tl(I16); - gen_add(dc, cpu_R[rd], cpu_R[ra], t0); - tcg_temp_free(t0); - break; - - case 0x28: /* l.addic */ - LOG_DIS("l.addic r%d, r%d, %d\n", rd, ra, I16); - check_r0_write(rd); - t0 = tcg_const_tl(I16); - gen_addc(dc, cpu_R[rd], cpu_R[ra], t0); - tcg_temp_free(t0); - break; - - case 0x29: /* l.andi */ - LOG_DIS("l.andi r%d, r%d, %d\n", rd, ra, K16); - check_r0_write(rd); - tcg_gen_andi_tl(cpu_R[rd], cpu_R[ra], K16); - break; - - case 0x2a: /* l.ori */ - LOG_DIS("l.ori r%d, r%d, %d\n", rd, ra, K16); - check_r0_write(rd); - tcg_gen_ori_tl(cpu_R[rd], cpu_R[ra], K16); - break; - - case 0x2b: /* l.xori */ - LOG_DIS("l.xori r%d, r%d, %d\n", rd, ra, I16); - check_r0_write(rd); - tcg_gen_xori_tl(cpu_R[rd], cpu_R[ra], I16); - break; - - case 0x2c: /* l.muli */ - LOG_DIS("l.muli r%d, r%d, %d\n", rd, ra, I16); - check_r0_write(rd); - t0 = tcg_const_tl(I16); - gen_mul(dc, cpu_R[rd], cpu_R[ra], t0); - tcg_temp_free(t0); - break; - - case 0x2d: /* l.mfspr */ - LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, K16); - check_r0_write(rd); - { -#if defined(CONFIG_USER_ONLY) - return; -#else - TCGv_i32 ti = tcg_const_i32(K16); - if (dc->mem_idx == MMU_USER_IDX) { - gen_illegal_exception(dc); - return; - } - gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti); - tcg_temp_free_i32(ti); -#endif - } - break; +static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a, uint32_t insn) +{ + LOG_DIS("l.mfspr r%d, r%d, %d\n", a->d, a->a, a->k); + check_r0_write(a->d); - case 0x30: /* l.mtspr */ - LOG_DIS("l.mtspr r%d, r%d, %d\n", ra, rb, K5_11); - { -#if defined(CONFIG_USER_ONLY) - return; +#ifdef CONFIG_USER_ONLY + gen_illegal_exception(dc); #else - TCGv_i32 im = tcg_const_i32(K5_11); - if (dc->mem_idx == MMU_USER_IDX) { - gen_illegal_exception(dc); - return; - } - gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im); - tcg_temp_free_i32(im); + if (dc->mem_idx == MMU_USER_IDX) { + gen_illegal_exception(dc); + } else { + TCGv_i32 ti = tcg_const_i32(a->k); + gen_helper_mfspr(cpu_R[a->d], cpu_env, cpu_R[a->d], cpu_R[a->a], ti); + tcg_temp_free_i32(ti); + } #endif - } - break; - - case 0x33: /* l.swa */ - LOG_DIS("l.swa r%d, r%d, %d\n", ra, rb, I5_11); - gen_swa(dc, rb, cpu_R[ra], I5_11); - break; - -/* not used yet, open it when we need or64. */ -/*#ifdef TARGET_OPENRISC64 - case 0x34: l.sd - LOG_DIS("l.sd r%d, r%d, %d\n", ra, rb, I5_11); - check_ob64s(dc); - mop = MO_TEQ; - goto do_store; -#endif*/ + return true; +} - case 0x35: /* l.sw */ - LOG_DIS("l.sw r%d, r%d, %d\n", ra, rb, I5_11); - mop = MO_TEUL; - goto do_store; - - case 0x36: /* l.sb */ - LOG_DIS("l.sb r%d, r%d, %d\n", ra, rb, I5_11); - mop = MO_UB; - goto do_store; - - case 0x37: /* l.sh */ - LOG_DIS("l.sh r%d, r%d, %d\n", ra, rb, I5_11); - mop = MO_TEUW; - goto do_store; - - do_store: - { - TCGv t0 = tcg_temp_new(); - tcg_gen_addi_tl(t0, cpu_R[ra], I5_11); - tcg_gen_qemu_st_tl(cpu_R[rb], t0, dc->mem_idx, mop); - tcg_temp_free(t0); - } - break; +static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a, uint32_t insn) +{ + LOG_DIS("l.mtspr r%d, r%d, %d\n", a->a, a->b, a->k); - default: +#ifdef CONFIG_USER_ONLY + gen_illegal_exception(dc); +#else + if (dc->mem_idx == MMU_USER_IDX) { gen_illegal_exception(dc); - break; + } else { + TCGv_i32 ti = tcg_const_i32(a->k); + gen_helper_mtspr(cpu_env, cpu_R[a->a], cpu_R[a->b], ti); + tcg_temp_free_i32(ti); } +#endif + return true; } -static void dec_mac(DisasContext *dc, uint32_t insn) +static bool trans_l_mac(DisasContext *dc, arg_ab *a, uint32_t insn) { - uint32_t op0; - uint32_t ra, rb; - op0 = extract32(insn, 0, 4); - ra = extract32(insn, 16, 5); - rb = extract32(insn, 11, 5); + LOG_DIS("l.mac r%d, r%d\n", a->a, a->b); + gen_mac(dc, cpu_R[a->a], cpu_R[a->b]); + return true; +} - switch (op0) { - case 0x0001: /* l.mac */ - LOG_DIS("l.mac r%d, r%d\n", ra, rb); - gen_mac(dc, cpu_R[ra], cpu_R[rb]); - break; +static bool trans_l_msb(DisasContext *dc, arg_ab *a, uint32_t insn) +{ + LOG_DIS("l.msb r%d, r%d\n", a->a, a->b); + gen_msb(dc, cpu_R[a->a], cpu_R[a->b]); + return true; +} - case 0x0002: /* l.msb */ - LOG_DIS("l.msb r%d, r%d\n", ra, rb); - gen_msb(dc, cpu_R[ra], cpu_R[rb]); - break; +static bool trans_l_macu(DisasContext *dc, arg_ab *a, uint32_t insn) +{ + LOG_DIS("l.mac r%d, r%d\n", a->a, a->b); + gen_macu(dc, cpu_R[a->a], cpu_R[a->b]); + return true; +} - case 0x0003: /* l.macu */ - LOG_DIS("l.macu r%d, r%d\n", ra, rb); - gen_macu(dc, cpu_R[ra], cpu_R[rb]); - break; +static bool trans_l_msbu(DisasContext *dc, arg_ab *a, uint32_t insn) +{ + LOG_DIS("l.msb r%d, r%d\n", a->a, a->b); + gen_msbu(dc, cpu_R[a->a], cpu_R[a->b]); + return true; +} - case 0x0004: /* l.msbu */ - LOG_DIS("l.msbu r%d, r%d\n", ra, rb); - gen_msbu(dc, cpu_R[ra], cpu_R[rb]); - break; +static bool trans_l_slli(DisasContext *dc, arg_dal *a, uint32_t insn) +{ + LOG_DIS("l.slli r%d, r%d, %d\n", a->d, a->a, a->l); + check_r0_write(a->d); + tcg_gen_shli_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1)); + return true; +} - default: - gen_illegal_exception(dc); - break; - } -} - -static void dec_logic(DisasContext *dc, uint32_t insn) -{ - uint32_t op0; - uint32_t rd, ra, L6, S6; - op0 = extract32(insn, 6, 2); - rd = extract32(insn, 21, 5); - ra = extract32(insn, 16, 5); - L6 = extract32(insn, 0, 6); - S6 = L6 & (TARGET_LONG_BITS - 1); - - check_r0_write(rd); - switch (op0) { - case 0x00: /* l.slli */ - LOG_DIS("l.slli r%d, r%d, %d\n", rd, ra, L6); - tcg_gen_shli_tl(cpu_R[rd], cpu_R[ra], S6); - break; - - case 0x01: /* l.srli */ - LOG_DIS("l.srli r%d, r%d, %d\n", rd, ra, L6); - tcg_gen_shri_tl(cpu_R[rd], cpu_R[ra], S6); - break; - - case 0x02: /* l.srai */ - LOG_DIS("l.srai r%d, r%d, %d\n", rd, ra, L6); - tcg_gen_sari_tl(cpu_R[rd], cpu_R[ra], S6); - break; - - case 0x03: /* l.rori */ - LOG_DIS("l.rori r%d, r%d, %d\n", rd, ra, L6); - tcg_gen_rotri_tl(cpu_R[rd], cpu_R[ra], S6); - break; - - default: - gen_illegal_exception(dc); - break; - } +static bool trans_l_srli(DisasContext *dc, arg_dal *a, uint32_t insn) +{ + LOG_DIS("l.srli r%d, r%d, %d\n", a->d, a->a, a->l); + check_r0_write(a->d); + tcg_gen_shri_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1)); + return true; } -static void dec_M(DisasContext *dc, uint32_t insn) +static bool trans_l_srai(DisasContext *dc, arg_dal *a, uint32_t insn) { - uint32_t op0; - uint32_t rd; - uint32_t K16; - op0 = extract32(insn, 16, 1); - rd = extract32(insn, 21, 5); - K16 = extract32(insn, 0, 16); + LOG_DIS("l.srai r%d, r%d, %d\n", a->d, a->a, a->l); + check_r0_write(a->d); + tcg_gen_sari_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1)); + return true; +} - check_r0_write(rd); - switch (op0) { - case 0x0: /* l.movhi */ - LOG_DIS("l.movhi r%d, %d\n", rd, K16); - tcg_gen_movi_tl(cpu_R[rd], (K16 << 16)); - break; +static bool trans_l_rori(DisasContext *dc, arg_dal *a, uint32_t insn) +{ + LOG_DIS("l.rori r%d, r%d, %d\n", a->d, a->a, a->l); + check_r0_write(a->d); + tcg_gen_rotri_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1)); + return true; +} - case 0x1: /* l.macrc */ - LOG_DIS("l.macrc r%d\n", rd); - tcg_gen_trunc_i64_tl(cpu_R[rd], cpu_mac); - tcg_gen_movi_i64(cpu_mac, 0); - break; +static bool trans_l_movhi(DisasContext *dc, arg_l_movhi *a, uint32_t insn) +{ + LOG_DIS("l.movhi r%d, %d\n", a->d, a->k); + check_r0_write(a->d); + tcg_gen_movi_tl(cpu_R[a->d], a->k << 16); + return true; +} - default: - gen_illegal_exception(dc); - break; - } +static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a, uint32_t insn) +{ + LOG_DIS("l.macrc r%d\n", a->d); + check_r0_write(a->d); + tcg_gen_trunc_i64_tl(cpu_R[a->d], cpu_mac); + tcg_gen_movi_i64(cpu_mac, 0); + return true; } -static void dec_comp(DisasContext *dc, uint32_t insn) +static bool trans_l_sfeq(DisasContext *dc, arg_ab *a, TCGCond cond) { - uint32_t op0; - uint32_t ra, rb; + LOG_DIS("l.sfeq r%d, r%d\n", a->a, a->b); + tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); + return true; +} - op0 = extract32(insn, 21, 5); - ra = extract32(insn, 16, 5); - rb = extract32(insn, 11, 5); +static bool trans_l_sfne(DisasContext *dc, arg_ab *a, TCGCond cond) +{ + LOG_DIS("l.sfne r%d, r%d\n", a->a, a->b); + tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); + return true; +} - /* unsigned integers */ - tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]); - tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]); +static bool trans_l_sfgtu(DisasContext *dc, arg_ab *a, TCGCond cond) +{ + LOG_DIS("l.sfgtu r%d, r%d\n", a->a, a->b); + tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); + return true; +} - switch (op0) { - case 0x0: /* l.sfeq */ - LOG_DIS("l.sfeq r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[ra], cpu_R[rb]); - break; +static bool trans_l_sfgeu(DisasContext *dc, arg_ab *a, TCGCond cond) +{ + LOG_DIS("l.sfgeu r%d, r%d\n", a->a, a->b); + tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); + return true; +} - case 0x1: /* l.sfne */ - LOG_DIS("l.sfne r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, cpu_R[ra], cpu_R[rb]); - break; +static bool trans_l_sfltu(DisasContext *dc, arg_ab *a, TCGCond cond) +{ + LOG_DIS("l.sfltu r%d, r%d\n", a->a, a->b); + tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); + return true; +} - case 0x2: /* l.sfgtu */ - LOG_DIS("l.sfgtu r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[ra], cpu_R[rb]); - break; +static bool trans_l_sfleu(DisasContext *dc, arg_ab *a, TCGCond cond) +{ + LOG_DIS("l.sfleu r%d, r%d\n", a->a, a->b); + tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); + return true; +} - case 0x3: /* l.sfgeu */ - LOG_DIS("l.sfgeu r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[ra], cpu_R[rb]); - break; +static bool trans_l_sfgts(DisasContext *dc, arg_ab *a, TCGCond cond) +{ + LOG_DIS("l.sfgts r%d, r%d\n", a->a, a->b); + tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); + return true; +} - case 0x4: /* l.sfltu */ - LOG_DIS("l.sfltu r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[ra], cpu_R[rb]); - break; +static bool trans_l_sfges(DisasContext *dc, arg_ab *a, TCGCond cond) +{ + LOG_DIS("l.sfges r%d, r%d\n", a->a, a->b); + tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); + return true; +} - case 0x5: /* l.sfleu */ - LOG_DIS("l.sfleu r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[ra], cpu_R[rb]); - break; +static bool trans_l_sflts(DisasContext *dc, arg_ab *a, TCGCond cond) +{ + LOG_DIS("l.sflts r%d, r%d\n", a->a, a->b); + tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); + return true; +} - case 0xa: /* l.sfgts */ - LOG_DIS("l.sfgts r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, cpu_R[ra], cpu_R[rb]); - break; +static bool trans_l_sfles(DisasContext *dc, arg_ab *a, TCGCond cond) +{ + LOG_DIS("l.sfles r%d, r%d\n", a->a, a->b); + tcg_gen_setcond_tl(TCG_COND_LE, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]); + return true; +} - case 0xb: /* l.sfges */ - LOG_DIS("l.sfges r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, cpu_R[ra], cpu_R[rb]); - break; +static bool trans_l_sfeqi(DisasContext *dc, arg_ai *a, TCGCond cond) +{ + LOG_DIS("l.sfeqi r%d, %d\n", a->a, a->i); + tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[a->a], a->i); + return true; +} - case 0xc: /* l.sflts */ - LOG_DIS("l.sflts r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, cpu_R[ra], cpu_R[rb]); - break; +static bool trans_l_sfnei(DisasContext *dc, arg_ai *a, TCGCond cond) +{ + LOG_DIS("l.sfnei r%d, %d\n", a->a, a->i); + tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R[a->a], a->i); + return true; +} - case 0xd: /* l.sfles */ - LOG_DIS("l.sfles r%d, r%d\n", ra, rb); - tcg_gen_setcond_tl(TCG_COND_LE, cpu_sr_f, cpu_R[ra], cpu_R[rb]); - break; +static bool trans_l_sfgtui(DisasContext *dc, arg_ai *a, TCGCond cond) +{ + LOG_DIS("l.sfgtui r%d, %d\n", a->a, a->i); + tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[a->a], a->i); + return true; +} - default: - gen_illegal_exception(dc); - break; - } +static bool trans_l_sfgeui(DisasContext *dc, arg_ai *a, TCGCond cond) +{ + LOG_DIS("l.sfgeui r%d, %d\n", a->a, a->i); + tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[a->a], a->i); + return true; } -static void dec_compi(DisasContext *dc, uint32_t insn) +static bool trans_l_sfltui(DisasContext *dc, arg_ai *a, TCGCond cond) { - uint32_t op0, ra; - int32_t I16; + LOG_DIS("l.sfltui r%d, %d\n", a->a, a->i); + tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[a->a], a->i); + return true; +} - op0 = extract32(insn, 21, 5); - ra = extract32(insn, 16, 5); - I16 = sextract32(insn, 0, 16); +static bool trans_l_sfleui(DisasContext *dc, arg_ai *a, TCGCond cond) +{ + LOG_DIS("l.sfleui r%d, %d\n", a->a, a->i); + tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[a->a], a->i); + return true; +} - switch (op0) { - case 0x0: /* l.sfeqi */ - LOG_DIS("l.sfeqi r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[ra], I16); - break; +static bool trans_l_sfgtsi(DisasContext *dc, arg_ai *a, TCGCond cond) +{ + LOG_DIS("l.sfgtsi r%d, %d\n", a->a, a->i); + tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R[a->a], a->i); + return true; +} - case 0x1: /* l.sfnei */ - LOG_DIS("l.sfnei r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R[ra], I16); - break; +static bool trans_l_sfgesi(DisasContext *dc, arg_ai *a, TCGCond cond) +{ + LOG_DIS("l.sfgesi r%d, %d\n", a->a, a->i); + tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R[a->a], a->i); + return true; +} - case 0x2: /* l.sfgtui */ - LOG_DIS("l.sfgtui r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[ra], I16); - break; +static bool trans_l_sfltsi(DisasContext *dc, arg_ai *a, TCGCond cond) +{ + LOG_DIS("l.sfltsi r%d, %d\n", a->a, a->i); + tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R[a->a], a->i); + return true; +} - case 0x3: /* l.sfgeui */ - LOG_DIS("l.sfgeui r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[ra], I16); - break; +static bool trans_l_sflesi(DisasContext *dc, arg_ai *a, TCGCond cond) +{ + LOG_DIS("l.sflesi r%d, %d\n", a->a, a->i); + tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R[a->a], a->i); + return true; +} - case 0x4: /* l.sfltui */ - LOG_DIS("l.sfltui r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[ra], I16); - break; +static bool trans_l_sys(DisasContext *dc, arg_l_sys *a, uint32_t insn) +{ + LOG_DIS("l.sys %d\n", a->k); + tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); + gen_exception(dc, EXCP_SYSCALL); + dc->base.is_jmp = DISAS_NORETURN; + return true; +} - case 0x5: /* l.sfleui */ - LOG_DIS("l.sfleui r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[ra], I16); - break; +static bool trans_l_trap(DisasContext *dc, arg_l_trap *a, uint32_t insn) +{ + LOG_DIS("l.trap %d\n", a->k); + tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); + gen_exception(dc, EXCP_TRAP); + dc->base.is_jmp = DISAS_NORETURN; + return true; +} - case 0xa: /* l.sfgtsi */ - LOG_DIS("l.sfgtsi r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R[ra], I16); - break; +static bool trans_l_msync(DisasContext *dc, arg_l_msync *a, uint32_t insn) +{ + LOG_DIS("l.msync\n"); + tcg_gen_mb(TCG_MO_ALL); + return true; +} - case 0xb: /* l.sfgesi */ - LOG_DIS("l.sfgesi r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R[ra], I16); - break; +static bool trans_l_psync(DisasContext *dc, arg_l_psync *a, uint32_t insn) +{ + LOG_DIS("l.psync\n"); + return true; +} - case 0xc: /* l.sfltsi */ - LOG_DIS("l.sfltsi r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R[ra], I16); - break; +static bool trans_l_csync(DisasContext *dc, arg_l_csync *a, uint32_t insn) +{ + LOG_DIS("l.csync\n"); + return true; +} - case 0xd: /* l.sflesi */ - LOG_DIS("l.sflesi r%d, %d\n", ra, I16); - tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R[ra], I16); - break; +static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a, uint32_t insn) +{ + LOG_DIS("l.rfe\n"); - default: +#ifdef CONFIG_USER_ONLY + gen_illegal_exception(dc); +#else + if (dc->mem_idx == MMU_USER_IDX) { gen_illegal_exception(dc); - break; + } else { + gen_helper_rfe(cpu_env); + dc->base.is_jmp = DISAS_UPDATE; } +#endif + return true; } -static void dec_sys(DisasContext *dc, uint32_t insn) +static void do_fp2(DisasContext *dc, arg_da *a, + void (*fn)(TCGv, TCGv_env, TCGv)) { - uint32_t op0; - uint32_t K16; - - op0 = extract32(insn, 16, 10); - K16 = extract32(insn, 0, 16); - - switch (op0) { - case 0x000: /* l.sys */ - LOG_DIS("l.sys %d\n", K16); - tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); - gen_exception(dc, EXCP_SYSCALL); - dc->base.is_jmp = DISAS_NORETURN; - break; - - case 0x100: /* l.trap */ - LOG_DIS("l.trap %d\n", K16); - tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); - gen_exception(dc, EXCP_TRAP); - dc->base.is_jmp = DISAS_NORETURN; - break; - - case 0x300: /* l.csync */ - LOG_DIS("l.csync\n"); - break; - - case 0x200: /* l.msync */ - LOG_DIS("l.msync\n"); - tcg_gen_mb(TCG_MO_ALL); - break; + check_r0_write(a->d); + fn(cpu_R[a->d], cpu_env, cpu_R[a->a]); + gen_helper_update_fpcsr(cpu_env); +} - case 0x270: /* l.psync */ - LOG_DIS("l.psync\n"); - break; +static void do_fp3(DisasContext *dc, arg_dab *a, + void (*fn)(TCGv, TCGv_env, TCGv, TCGv)) +{ + check_r0_write(a->d); + fn(cpu_R[a->d], cpu_env, cpu_R[a->a], cpu_R[a->b]); + gen_helper_update_fpcsr(cpu_env); +} - default: - gen_illegal_exception(dc); - break; +static void do_fpcmp(DisasContext *dc, arg_ab *a, + void (*fn)(TCGv, TCGv_env, TCGv, TCGv), + bool inv, bool swap) +{ + if (swap) { + fn(cpu_sr_f, cpu_env, cpu_R[a->b], cpu_R[a->a]); + } else { + fn(cpu_sr_f, cpu_env, cpu_R[a->a], cpu_R[a->b]); + } + if (inv) { + tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1); } + gen_helper_update_fpcsr(cpu_env); +} + +static bool trans_lf_add_s(DisasContext *dc, arg_dab *a, uint32_t insn) +{ + LOG_DIS("lf.add.s r%d, r%d, r%d\n", a->d, a->a, a->b); + do_fp3(dc, a, gen_helper_float_add_s); + return true; } -static void dec_float(DisasContext *dc, uint32_t insn) -{ - uint32_t op0; - uint32_t ra, rb, rd; - op0 = extract32(insn, 0, 8); - ra = extract32(insn, 16, 5); - rb = extract32(insn, 11, 5); - rd = extract32(insn, 21, 5); - - switch (op0) { - case 0x00: /* lf.add.s */ - LOG_DIS("lf.add.s r%d, r%d, r%d\n", rd, ra, rb); - check_r0_write(rd); - gen_helper_float_add_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x01: /* lf.sub.s */ - LOG_DIS("lf.sub.s r%d, r%d, r%d\n", rd, ra, rb); - check_r0_write(rd); - gen_helper_float_sub_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x02: /* lf.mul.s */ - LOG_DIS("lf.mul.s r%d, r%d, r%d\n", rd, ra, rb); - check_r0_write(rd); - gen_helper_float_mul_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x03: /* lf.div.s */ - LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb); - check_r0_write(rd); - gen_helper_float_div_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x04: /* lf.itof.s */ - LOG_DIS("lf.itof r%d, r%d\n", rd, ra); - check_r0_write(rd); - gen_helper_itofs(cpu_R[rd], cpu_env, cpu_R[ra]); - break; - - case 0x05: /* lf.ftoi.s */ - LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra); - check_r0_write(rd); - gen_helper_ftois(cpu_R[rd], cpu_env, cpu_R[ra]); - break; - - case 0x06: /* lf.rem.s */ - LOG_DIS("lf.rem.s r%d, r%d, r%d\n", rd, ra, rb); - check_r0_write(rd); - gen_helper_float_rem_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x07: /* lf.madd.s */ - LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb); - check_r0_write(rd); - gen_helper_float_madd_s(cpu_R[rd], cpu_env, cpu_R[rd], - cpu_R[ra], cpu_R[rb]); - break; - - case 0x08: /* lf.sfeq.s */ - LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb); - gen_helper_float_eq_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x09: /* lf.sfne.s */ - LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb); - gen_helper_float_ne_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x0a: /* lf.sfgt.s */ - LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb); - gen_helper_float_gt_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x0b: /* lf.sfge.s */ - LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb); - gen_helper_float_ge_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x0c: /* lf.sflt.s */ - LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb); - gen_helper_float_lt_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x0d: /* lf.sfle.s */ - LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb); - gen_helper_float_le_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); - break; +static bool trans_lf_sub_s(DisasContext *dc, arg_dab *a, uint32_t insn) +{ + LOG_DIS("lf.sub.s r%d, r%d, r%d\n", a->d, a->a, a->b); + do_fp3(dc, a, gen_helper_float_sub_s); + return true; +} -/* not used yet, open it when we need or64. */ -/*#ifdef TARGET_OPENRISC64 - case 0x10: lf.add.d - LOG_DIS("lf.add.d r%d, r%d, r%d\n", rd, ra, rb); - check_of64s(dc); - check_r0_write(rd); - gen_helper_float_add_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x11: lf.sub.d - LOG_DIS("lf.sub.d r%d, r%d, r%d\n", rd, ra, rb); - check_of64s(dc); - check_r0_write(rd); - gen_helper_float_sub_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x12: lf.mul.d - LOG_DIS("lf.mul.d r%d, r%d, r%d\n", rd, ra, rb); - check_of64s(dc); - check_r0_write(rd); - gen_helper_float_mul_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x13: lf.div.d - LOG_DIS("lf.div.d r%d, r%d, r%d\n", rd, ra, rb); - check_of64s(dc); - check_r0_write(rd); - gen_helper_float_div_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x14: lf.itof.d - LOG_DIS("lf.itof r%d, r%d\n", rd, ra); - check_of64s(dc); - check_r0_write(rd); - gen_helper_itofd(cpu_R[rd], cpu_env, cpu_R[ra]); - break; - - case 0x15: lf.ftoi.d - LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra); - check_of64s(dc); - check_r0_write(rd); - gen_helper_ftoid(cpu_R[rd], cpu_env, cpu_R[ra]); - break; - - case 0x16: lf.rem.d - LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb); - check_of64s(dc); - check_r0_write(rd); - gen_helper_float_rem_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x17: lf.madd.d - LOG_DIS("lf.madd.d r%d, r%d, r%d\n", rd, ra, rb); - check_of64s(dc); - check_r0_write(rd); - gen_helper_float_madd_d(cpu_R[rd], cpu_env, cpu_R[rd], - cpu_R[ra], cpu_R[rb]); - break; - - case 0x18: lf.sfeq.d - LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb); - check_of64s(dc); - gen_helper_float_eq_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x1a: lf.sfgt.d - LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb); - check_of64s(dc); - gen_helper_float_gt_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x1b: lf.sfge.d - LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb); - check_of64s(dc); - gen_helper_float_ge_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x19: lf.sfne.d - LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb); - check_of64s(dc); - gen_helper_float_ne_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x1c: lf.sflt.d - LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb); - check_of64s(dc); - gen_helper_float_lt_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); - break; - - case 0x1d: lf.sfle.d - LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb); - check_of64s(dc); - gen_helper_float_le_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]); - break; -#endif*/ +static bool trans_lf_mul_s(DisasContext *dc, arg_dab *a, uint32_t insn) +{ + LOG_DIS("lf.mul.s r%d, r%d, r%d\n", a->d, a->a, a->b); + do_fp3(dc, a, gen_helper_float_mul_s); + return true; +} - default: - gen_illegal_exception(dc); - break; - } +static bool trans_lf_div_s(DisasContext *dc, arg_dab *a, uint32_t insn) +{ + LOG_DIS("lf.div.s r%d, r%d, r%d\n", a->d, a->a, a->b); + do_fp3(dc, a, gen_helper_float_div_s); + return true; } -static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu) +static bool trans_lf_rem_s(DisasContext *dc, arg_dab *a, uint32_t insn) { - uint32_t op0; - uint32_t insn; - insn = cpu_ldl_code(&cpu->env, dc->base.pc_next); - op0 = extract32(insn, 26, 6); + LOG_DIS("lf.rem.s r%d, r%d, r%d\n", a->d, a->a, a->b); + do_fp3(dc, a, gen_helper_float_rem_s); + return true; +} - switch (op0) { - case 0x06: - dec_M(dc, insn); - break; +static bool trans_lf_itof_s(DisasContext *dc, arg_da *a, uint32_t insn) +{ + LOG_DIS("lf.itof.s r%d, r%d\n", a->d, a->a); + do_fp2(dc, a, gen_helper_itofs); + return true; +} - case 0x08: - dec_sys(dc, insn); - break; +static bool trans_lf_ftoi_s(DisasContext *dc, arg_da *a, uint32_t insn) +{ + LOG_DIS("lf.ftoi.s r%d, r%d\n", a->d, a->a); + do_fp2(dc, a, gen_helper_ftois); + return true; +} - case 0x2e: - dec_logic(dc, insn); - break; +static bool trans_lf_madd_s(DisasContext *dc, arg_dab *a, uint32_t insn) +{ + LOG_DIS("lf.madd.s r%d, r%d, r%d\n", a->d, a->a, a->b); + check_r0_write(a->d); + gen_helper_float_madd_s(cpu_R[a->d], cpu_env, cpu_R[a->d], + cpu_R[a->a], cpu_R[a->b]); + gen_helper_update_fpcsr(cpu_env); + return true; +} - case 0x2f: - dec_compi(dc, insn); - break; +static bool trans_lf_sfeq_s(DisasContext *dc, arg_ab *a, uint32_t insn) +{ + LOG_DIS("lf.sfeq.s r%d, r%d\n", a->a, a->b); + do_fpcmp(dc, a, gen_helper_float_eq_s, false, false); + return true; +} - case 0x31: - dec_mac(dc, insn); - break; +static bool trans_lf_sfne_s(DisasContext *dc, arg_ab *a, uint32_t insn) +{ + LOG_DIS("lf.sfne.s r%d, r%d\n", a->a, a->b); + do_fpcmp(dc, a, gen_helper_float_eq_s, true, false); + return true; +} - case 0x32: - dec_float(dc, insn); - break; +static bool trans_lf_sfgt_s(DisasContext *dc, arg_ab *a, uint32_t insn) +{ + LOG_DIS("lf.sfgt.s r%d, r%d\n", a->a, a->b); + do_fpcmp(dc, a, gen_helper_float_lt_s, false, true); + return true; +} - case 0x38: - dec_calc(dc, insn); - break; +static bool trans_lf_sfge_s(DisasContext *dc, arg_ab *a, uint32_t insn) +{ + LOG_DIS("lf.sfge.s r%d, r%d\n", a->a, a->b); + do_fpcmp(dc, a, gen_helper_float_le_s, false, true); + return true; +} - case 0x39: - dec_comp(dc, insn); - break; +static bool trans_lf_sflt_s(DisasContext *dc, arg_ab *a, uint32_t insn) +{ + LOG_DIS("lf.sflt.s r%d, r%d\n", a->a, a->b); + do_fpcmp(dc, a, gen_helper_float_lt_s, false, false); + return true; +} - default: - dec_misc(dc, insn); - break; - } +static bool trans_lf_sfle_s(DisasContext *dc, arg_ab *a, uint32_t insn) +{ + LOG_DIS("lf.sfle.s r%d, r%d\n", a->a, a->b); + do_fpcmp(dc, a, gen_helper_float_le_s, false, false); + return true; } static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs) @@ -1574,8 +1427,11 @@ static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) { DisasContext *dc = container_of(dcbase, DisasContext, base); OpenRISCCPU *cpu = OPENRISC_CPU(cs); + uint32_t insn = cpu_ldl_code(&cpu->env, dc->base.pc_next); - disas_openrisc_insn(dc, cpu); + if (!decode(dc, insn)) { + gen_illegal_exception(dc); + } dc->base.pc_next += 4; /* delay slot */ diff --git a/ui/console.c b/ui/console.c index b02510cdca..945f05d728 100644 --- a/ui/console.c +++ b/ui/console.c @@ -165,6 +165,8 @@ struct QemuConsole { QEMUFIFO out_fifo; uint8_t out_fifo_buf[16]; QEMUTimer *kbd_timer; + + QTAILQ_ENTRY(QemuConsole) next; }; struct DisplayState { @@ -180,8 +182,8 @@ struct DisplayState { static DisplayState *display_state; static QemuConsole *active_console; -static QemuConsole **consoles; -static int nb_consoles = 0; +static QTAILQ_HEAD(consoles_head, QemuConsole) consoles = + QTAILQ_HEAD_INITIALIZER(consoles); static bool cursor_visible_phase; static QEMUTimer *cursor_timer; @@ -197,7 +199,7 @@ static void gui_update(void *opaque) uint64_t dcl_interval; DisplayState *ds = opaque; DisplayChangeListener *dcl; - int i; + QemuConsole *con; ds->refreshing = true; dpy_refresh(ds); @@ -212,9 +214,9 @@ static void gui_update(void *opaque) } if (ds->update_interval != interval) { ds->update_interval = interval; - for (i = 0; i < nb_consoles; i++) { - if (consoles[i]->hw_ops->update_interval) { - consoles[i]->hw_ops->update_interval(consoles[i]->hw, interval); + QTAILQ_FOREACH(con, &consoles, next) { + if (con->hw_ops->update_interval) { + con->hw_ops->update_interval(con->hw, interval); } } trace_console_refresh(interval); @@ -1292,10 +1294,13 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type, s->ds = ds; s->console_type = console_type; - consoles = g_realloc(consoles, sizeof(*consoles) * (nb_consoles+1)); - if (console_type != GRAPHIC_CONSOLE || qdev_hotplug) { - s->index = nb_consoles; - consoles[nb_consoles++] = s; + if (QTAILQ_EMPTY(&consoles)) { + s->index = 0; + QTAILQ_INSERT_TAIL(&consoles, s, next); + } else if (console_type != GRAPHIC_CONSOLE || qdev_hotplug) { + QemuConsole *last = QTAILQ_LAST(&consoles, consoles_head); + s->index = last->index + 1; + QTAILQ_INSERT_TAIL(&consoles, s, next); } else { /* * HACK: Put graphical consoles before text consoles. @@ -1303,15 +1308,24 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type, * Only do that for coldplugged devices. After initial device * initialization we will not renumber the consoles any more. */ - for (i = nb_consoles; i > 0; i--) { - if (consoles[i - 1]->console_type == GRAPHIC_CONSOLE) - break; - consoles[i] = consoles[i - 1]; - consoles[i]->index = i; + QemuConsole *c = QTAILQ_FIRST(&consoles); + + while (QTAILQ_NEXT(c, next) != NULL && + c->console_type == GRAPHIC_CONSOLE) { + c = QTAILQ_NEXT(c, next); + } + if (c->console_type == GRAPHIC_CONSOLE) { + /* have no text consoles */ + s->index = c->index + 1; + QTAILQ_INSERT_AFTER(&consoles, c, s, next); + } else { + s->index = c->index; + QTAILQ_INSERT_BEFORE(c, s, next); + /* renumber text consoles */ + for (i = s->index + 1; c != NULL; c = QTAILQ_NEXT(c, next), i++) { + c->index = i; + } } - s->index = i; - consoles[i] = s; - nb_consoles++; } return s; } @@ -1861,21 +1875,21 @@ static DisplayState *get_alloc_displaystate(void) DisplayState *init_displaystate(void) { gchar *name; - int i; + QemuConsole *con; get_alloc_displaystate(); - for (i = 0; i < nb_consoles; i++) { - if (consoles[i]->console_type != GRAPHIC_CONSOLE && - consoles[i]->ds == NULL) { - text_console_do_init(consoles[i]->chr, display_state); + QTAILQ_FOREACH(con, &consoles, next) { + if (con->console_type != GRAPHIC_CONSOLE && + con->ds == NULL) { + text_console_do_init(con->chr, display_state); } /* Hook up into the qom tree here (not in new_console()), once * all QemuConsoles are created and the order / numbering * doesn't change any more */ - name = g_strdup_printf("console[%d]", i); + name = g_strdup_printf("console[%d]", con->index); object_property_add_child(container_get(object_get_root(), "/backend"), - name, OBJECT(consoles[i]), &error_abort); + name, OBJECT(con), &error_abort); g_free(name); } @@ -1957,33 +1971,34 @@ void graphic_console_close(QemuConsole *con) QemuConsole *qemu_console_lookup_by_index(unsigned int index) { - if (index >= nb_consoles) { - return NULL; + QemuConsole *con; + + QTAILQ_FOREACH(con, &consoles, next) { + if (con->index == index) { + return con; + } } - return consoles[index]; + return NULL; } QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head) { + QemuConsole *con; Object *obj; uint32_t h; - int i; - for (i = 0; i < nb_consoles; i++) { - if (!consoles[i]) { - continue; - } - obj = object_property_get_link(OBJECT(consoles[i]), + QTAILQ_FOREACH(con, &consoles, next) { + obj = object_property_get_link(OBJECT(con), "device", &error_abort); if (DEVICE(obj) != dev) { continue; } - h = object_property_get_uint(OBJECT(consoles[i]), + h = object_property_get_uint(OBJECT(con), "head", &error_abort); if (h != head) { continue; } - return consoles[i]; + return con; } return NULL; } @@ -2013,22 +2028,19 @@ QemuConsole *qemu_console_lookup_by_device_name(const char *device_id, QemuConsole *qemu_console_lookup_unused(void) { + QemuConsole *con; Object *obj; - int i; - for (i = 0; i < nb_consoles; i++) { - if (!consoles[i]) { - continue; - } - if (consoles[i]->hw_ops != &unused_ops) { + QTAILQ_FOREACH(con, &consoles, next) { + if (con->hw_ops != &unused_ops) { continue; } - obj = object_property_get_link(OBJECT(consoles[i]), + obj = object_property_get_link(OBJECT(con), "device", &error_abort); if (obj != NULL) { continue; } - return consoles[i]; + return con; } return NULL; } @@ -2130,12 +2142,11 @@ static void text_console_update_cursor_timer(void) static void text_console_update_cursor(void *opaque) { QemuConsole *s; - int i, count = 0; + int count = 0; cursor_visible_phase = !cursor_visible_phase; - for (i = 0; i < nb_consoles; i++) { - s = consoles[i]; + QTAILQ_FOREACH(s, &consoles, next) { if (qemu_console_is_graphic(s) || !qemu_console_is_visible(s)) { continue; @@ -145,6 +145,7 @@ #define GDK_KEY_2 GDK_2 #define GDK_KEY_f GDK_f #define GDK_KEY_g GDK_g +#define GDK_KEY_m GDK_m #define GDK_KEY_q GDK_q #define GDK_KEY_plus GDK_plus #define GDK_KEY_equal GDK_equal @@ -208,6 +209,7 @@ struct GtkDisplayState { GtkWidget *show_tabs_item; GtkWidget *untabify_item; + GtkWidget *show_menubar_item; GtkWidget *vbox; GtkWidget *notebook; @@ -1387,6 +1389,30 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque) } } +static void gd_menu_show_menubar(GtkMenuItem *item, void *opaque) +{ + GtkDisplayState *s = opaque; + VirtualConsole *vc = gd_vc_find_current(s); + + if (s->full_screen) { + return; + } + + if (gtk_check_menu_item_get_active( + GTK_CHECK_MENU_ITEM(s->show_menubar_item))) { + gtk_widget_show(s->menu_bar); + } else { + gtk_widget_hide(s->menu_bar); + } + gd_update_windowsize(vc); +} + +static void gd_accel_show_menubar(void *opaque) +{ + GtkDisplayState *s = opaque; + gtk_menu_item_activate(GTK_MENU_ITEM(s->show_menubar_item)); +} + static void gd_menu_full_screen(GtkMenuItem *item, void *opaque) { GtkDisplayState *s = opaque; @@ -1403,7 +1429,10 @@ static void gd_menu_full_screen(GtkMenuItem *item, void *opaque) } else { gtk_window_unfullscreen(GTK_WINDOW(s->window)); gd_menu_show_tabs(GTK_MENU_ITEM(s->show_tabs_item), s); - gtk_widget_show(s->menu_bar); + if (gtk_check_menu_item_get_active( + GTK_CHECK_MENU_ITEM(s->show_menubar_item))) { + gtk_widget_show(s->menu_bar); + } s->full_screen = FALSE; if (vc->type == GD_VC_GFX) { vc->gfx.scale_x = 1.0; @@ -2036,6 +2065,8 @@ static void gd_connect_signals(GtkDisplayState *s) G_CALLBACK(gd_menu_show_tabs), s); g_signal_connect(s->untabify_item, "activate", G_CALLBACK(gd_menu_untabify), s); + g_signal_connect(s->show_menubar_item, "activate", + G_CALLBACK(gd_menu_show_menubar), s); g_signal_connect(s->window, "delete-event", G_CALLBACK(gd_window_close), s); @@ -2272,11 +2303,26 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s) s->untabify_item = gtk_menu_item_new_with_mnemonic(_("Detach Tab")); gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->untabify_item); + s->show_menubar_item = gtk_check_menu_item_new_with_mnemonic( + _("Show Menubar")); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->show_menubar_item), + TRUE); + gtk_accel_group_connect(s->accel_group, GDK_KEY_m, HOTKEY_MODIFIERS, 0, + g_cclosure_new_swap(G_CALLBACK(gd_accel_show_menubar), s, NULL)); +#if GTK_CHECK_VERSION(3, 8, 0) + gtk_accel_label_set_accel( + GTK_ACCEL_LABEL(gtk_bin_get_child(GTK_BIN(s->show_menubar_item))), + GDK_KEY_m, HOTKEY_MODIFIERS); +#endif + gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->show_menubar_item); + return view_menu; } static void gd_create_menus(GtkDisplayState *s) { + GtkSettings *settings; + s->accel_group = gtk_accel_group_new(); s->machine_menu = gd_create_menu_machine(s); s->view_menu = gd_create_menu_view(s); @@ -2292,6 +2338,10 @@ static void gd_create_menus(GtkDisplayState *s) g_object_set_data(G_OBJECT(s->window), "accel_group", s->accel_group); gtk_window_add_accel_group(GTK_WINDOW(s->window), s->accel_group); + + /* Disable the default "F10" menu shortcut. */ + settings = gtk_widget_get_settings(s->window); + g_object_set(G_OBJECT(settings), "gtk-menu-bar-accel", "", NULL); } @@ -2434,13 +2484,17 @@ static void early_gtk_display_init(DisplayOptions *opts) } assert(opts->type == DISPLAY_TYPE_GTK); - if (opts->has_gl && opts->gl) { + if (opts->has_gl && opts->gl != DISPLAYGL_MODE_OFF) { + if (opts->gl == DISPLAYGL_MODE_ES) { + error_report("gtk: opengl es not supported"); + return; + } #if defined(CONFIG_OPENGL) #if defined(CONFIG_GTK_GL) && defined(GDK_WINDOWING_WAYLAND) if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default())) { gtk_use_gl_area = true; gtk_gl_area_init(); - } + } else #endif { gtk_egl_init(); @@ -804,7 +804,6 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o) return; } sdl2_console = g_new0(struct sdl2_console, sdl2_num_outputs); - sdl2_console->opts = o; for (i = 0; i < sdl2_num_outputs; i++) { QemuConsole *con = qemu_console_lookup_by_index(i); assert(con != NULL); @@ -812,6 +811,7 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o) sdl2_console[i].hidden = true; } sdl2_console[i].idx = i; + sdl2_console[i].opts = o; #ifdef CONFIG_OPENGL sdl2_console[i].opengl = display_opengl; sdl2_console[i].dcl.ops = display_opengl ? &dcl_gl_ops : &dcl_2d_ops; diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c index 868dddef4b..b0b15d42a8 100644 --- a/ui/vnc-jobs.c +++ b/ui/vnc-jobs.c @@ -82,6 +82,7 @@ VncJob *vnc_job_new(VncState *vs) { VncJob *job = g_new0(VncJob, 1); + assert(vs->magic == VNC_MAGIC); job->vs = vs; vnc_lock_queue(queue); QLIST_INIT(&job->rectangles); @@ -214,6 +215,7 @@ static int vnc_worker_thread_loop(VncJobQueue *queue) /* Here job can only be NULL if queue->exit is true */ job = QTAILQ_FIRST(&queue->jobs); vnc_unlock_queue(queue); + assert(job->vs->magic == VNC_MAGIC); if (queue->exit) { return -1; @@ -236,6 +238,7 @@ static int vnc_worker_thread_loop(VncJobQueue *queue) /* Make a local copy of vs and switch output buffers */ vnc_async_encoding_start(job->vs, &vs); + vs.magic = VNC_MAGIC; /* Start sending rectangles */ n_rectangles = 0; @@ -289,6 +292,7 @@ disconnected: vnc_unlock_queue(queue); qemu_cond_broadcast(&queue->cond); g_free(job); + vs.magic = 0; return 0; } @@ -1138,6 +1138,7 @@ static void audio_capture_notify(void *opaque, audcnotification_e cmd) { VncState *vs = opaque; + assert(vs->magic == VNC_MAGIC); switch (cmd) { case AUD_CNOTIFY_DISABLE: vnc_lock_output(vs); @@ -1167,6 +1168,7 @@ static void audio_capture(void *opaque, void *buf, int size) { VncState *vs = opaque; + assert(vs->magic == VNC_MAGIC); vnc_lock_output(vs); if (vs->output.offset < vs->throttle_output_offset) { vnc_write_u8(vs, VNC_MSG_SERVER_QEMU); @@ -1275,6 +1277,7 @@ void vnc_disconnect_finish(VncState *vs) vs->ioc = NULL; object_unref(OBJECT(vs->sioc)); vs->sioc = NULL; + vs->magic = 0; g_free(vs); } @@ -1414,7 +1417,7 @@ static void vnc_client_write_locked(VncState *vs) static void vnc_client_write(VncState *vs) { - + assert(vs->magic == VNC_MAGIC); vnc_lock_output(vs); if (vs->output.offset) { vnc_client_write_locked(vs); @@ -1487,6 +1490,7 @@ static void vnc_jobs_bh(void *opaque) { VncState *vs = opaque; + assert(vs->magic == VNC_MAGIC); vnc_jobs_consume_buffer(vs); } @@ -1537,6 +1541,8 @@ gboolean vnc_client_io(QIOChannel *ioc G_GNUC_UNUSED, GIOCondition condition, void *opaque) { VncState *vs = opaque; + + assert(vs->magic == VNC_MAGIC); if (condition & G_IO_IN) { if (vnc_client_read(vs) < 0) { /* vs is free()ed here */ @@ -1568,6 +1574,7 @@ gboolean vnc_client_io(QIOChannel *ioc G_GNUC_UNUSED, void vnc_write(VncState *vs, const void *data, size_t len) { + assert(vs->magic == VNC_MAGIC); if (vs->disconnecting) { return; } @@ -3064,6 +3071,7 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc, int i; trace_vnc_client_connect(vs, sioc); + vs->magic = VNC_MAGIC; vs->sioc = sioc; object_ref(OBJECT(vs->sioc)); vs->ioc = QIO_CHANNEL(sioc); @@ -255,8 +255,11 @@ typedef enum { VNC_STATE_UPDATE_FORCE, } VncStateUpdate; +#define VNC_MAGIC ((uint64_t)0x05b3f069b3d204bb) + struct VncState { + uint64_t magic; QIOChannelSocket *sioc; /* The underlying socket */ QIOChannel *ioc; /* The channel currently used for I/O */ guint ioc_tag; @@ -120,12 +120,14 @@ int main(int argc, char **argv) #include "ui/qemu-spice.h" #include "qapi/string-input-visitor.h" #include "qapi/opts-visitor.h" +#include "qapi/clone-visitor.h" #include "qom/object_interfaces.h" #include "exec/semihost.h" #include "crypto/init.h" #include "sysemu/replay.h" #include "qapi/qapi-events-run-state.h" #include "qapi/qapi-visit-block-core.h" +#include "qapi/qapi-visit-ui.h" #include "qapi/qapi-commands-block-core.h" #include "qapi/qapi-commands-misc.h" #include "qapi/qapi-commands-run-state.h" @@ -2088,11 +2090,40 @@ static void select_vgahw(const char *p) } } +static void parse_display_qapi(const char *optarg) +{ + Error *err = NULL; + DisplayOptions *opts; + Visitor *v; + + v = qobject_input_visitor_new_str(optarg, "type", &err); + if (!v) { + error_report_err(err); + exit(1); + } + + visit_type_DisplayOptions(v, NULL, &opts, &error_fatal); + QAPI_CLONE_MEMBERS(DisplayOptions, &dpy, opts); + + qapi_free_DisplayOptions(opts); + visit_free(v); +} + static void parse_display(const char *p) { const char *opts; if (strstart(p, "sdl", &opts)) { + /* + * sdl DisplayType needs hand-crafted parser instead of + * parse_display_qapi() due to some options not in + * DisplayOptions, specifically: + * - frame + * Already deprecated. + * - ctrl_grab + alt_grab + * Not clear yet what happens to them long-term. Should + * replaced by something better or deprecated and dropped. + */ dpy.type = DISPLAY_TYPE_SDL; while (*opts) { const char *nextopt; @@ -2158,53 +2189,18 @@ static void parse_display(const char *p) opts = nextopt; } } else if (strstart(p, "vnc", &opts)) { + /* + * vnc isn't a (local) DisplayType but a protocol for remote + * display access. + */ if (*opts == '=') { vnc_parse(opts + 1, &error_fatal); } else { error_report("VNC requires a display argument vnc=<display>"); exit(1); } - } else if (strstart(p, "egl-headless", &opts)) { - dpy.type = DISPLAY_TYPE_EGL_HEADLESS; - } else if (strstart(p, "curses", &opts)) { - dpy.type = DISPLAY_TYPE_CURSES; - } else if (strstart(p, "gtk", &opts)) { - dpy.type = DISPLAY_TYPE_GTK; - while (*opts) { - const char *nextopt; - - if (strstart(opts, ",grab_on_hover=", &nextopt)) { - opts = nextopt; - dpy.u.gtk.has_grab_on_hover = true; - if (strstart(opts, "on", &nextopt)) { - dpy.u.gtk.grab_on_hover = true; - } else if (strstart(opts, "off", &nextopt)) { - dpy.u.gtk.grab_on_hover = false; - } else { - goto invalid_gtk_args; - } - } else if (strstart(opts, ",gl=", &nextopt)) { - opts = nextopt; - dpy.has_gl = true; - if (strstart(opts, "on", &nextopt)) { - dpy.gl = DISPLAYGL_MODE_ON; - } else if (strstart(opts, "off", &nextopt)) { - dpy.gl = DISPLAYGL_MODE_OFF; - } else { - goto invalid_gtk_args; - } - } else { - invalid_gtk_args: - error_report("invalid GTK option string"); - exit(1); - } - opts = nextopt; - } - } else if (strstart(p, "none", &opts)) { - dpy.type = DISPLAY_TYPE_NONE; } else { - error_report("unknown display type"); - exit(1); + parse_display_qapi(p); } } |