xref: /qemu/linux-user/mips/cpu_loop.c (revision 0c1bbedc)
1cd71c089SLaurent Vivier /*
2cd71c089SLaurent Vivier  *  qemu user cpu loop
3cd71c089SLaurent Vivier  *
4cd71c089SLaurent Vivier  *  Copyright (c) 2003-2008 Fabrice Bellard
5cd71c089SLaurent Vivier  *
6cd71c089SLaurent Vivier  *  This program is free software; you can redistribute it and/or modify
7cd71c089SLaurent Vivier  *  it under the terms of the GNU General Public License as published by
8cd71c089SLaurent Vivier  *  the Free Software Foundation; either version 2 of the License, or
9cd71c089SLaurent Vivier  *  (at your option) any later version.
10cd71c089SLaurent Vivier  *
11cd71c089SLaurent Vivier  *  This program is distributed in the hope that it will be useful,
12cd71c089SLaurent Vivier  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13cd71c089SLaurent Vivier  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14cd71c089SLaurent Vivier  *  GNU General Public License for more details.
15cd71c089SLaurent Vivier  *
16cd71c089SLaurent Vivier  *  You should have received a copy of the GNU General Public License
17cd71c089SLaurent Vivier  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18cd71c089SLaurent Vivier  */
19cd71c089SLaurent Vivier 
20cd71c089SLaurent Vivier #include "qemu/osdep.h"
21cd71c089SLaurent Vivier #include "qemu.h"
22cd71c089SLaurent Vivier #include "cpu_loop-common.h"
2358908ef6SLaurent Vivier #include "elf.h"
2458908ef6SLaurent Vivier 
2558908ef6SLaurent Vivier # ifdef TARGET_ABI_MIPSO32
2658908ef6SLaurent Vivier #  define MIPS_SYS(name, args) args,
2758908ef6SLaurent Vivier static const uint8_t mips_syscall_args[] = {
2858908ef6SLaurent Vivier         MIPS_SYS(sys_syscall    , 8)    /* 4000 */
2958908ef6SLaurent Vivier         MIPS_SYS(sys_exit       , 1)
3058908ef6SLaurent Vivier         MIPS_SYS(sys_fork       , 0)
3158908ef6SLaurent Vivier         MIPS_SYS(sys_read       , 3)
3258908ef6SLaurent Vivier         MIPS_SYS(sys_write      , 3)
3358908ef6SLaurent Vivier         MIPS_SYS(sys_open       , 3)    /* 4005 */
3458908ef6SLaurent Vivier         MIPS_SYS(sys_close      , 1)
3558908ef6SLaurent Vivier         MIPS_SYS(sys_waitpid    , 3)
3658908ef6SLaurent Vivier         MIPS_SYS(sys_creat      , 2)
3758908ef6SLaurent Vivier         MIPS_SYS(sys_link       , 2)
3858908ef6SLaurent Vivier         MIPS_SYS(sys_unlink     , 1)    /* 4010 */
3958908ef6SLaurent Vivier         MIPS_SYS(sys_execve     , 0)
4058908ef6SLaurent Vivier         MIPS_SYS(sys_chdir      , 1)
4158908ef6SLaurent Vivier         MIPS_SYS(sys_time       , 1)
4258908ef6SLaurent Vivier         MIPS_SYS(sys_mknod      , 3)
4358908ef6SLaurent Vivier         MIPS_SYS(sys_chmod      , 2)    /* 4015 */
4458908ef6SLaurent Vivier         MIPS_SYS(sys_lchown     , 3)
4558908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)
4658908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)    /* was sys_stat */
4758908ef6SLaurent Vivier         MIPS_SYS(sys_lseek      , 3)
4858908ef6SLaurent Vivier         MIPS_SYS(sys_getpid     , 0)    /* 4020 */
4958908ef6SLaurent Vivier         MIPS_SYS(sys_mount      , 5)
5058908ef6SLaurent Vivier         MIPS_SYS(sys_umount     , 1)
5158908ef6SLaurent Vivier         MIPS_SYS(sys_setuid     , 1)
5258908ef6SLaurent Vivier         MIPS_SYS(sys_getuid     , 0)
5358908ef6SLaurent Vivier         MIPS_SYS(sys_stime      , 1)    /* 4025 */
5458908ef6SLaurent Vivier         MIPS_SYS(sys_ptrace     , 4)
5558908ef6SLaurent Vivier         MIPS_SYS(sys_alarm      , 1)
5658908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)    /* was sys_fstat */
5758908ef6SLaurent Vivier         MIPS_SYS(sys_pause      , 0)
5858908ef6SLaurent Vivier         MIPS_SYS(sys_utime      , 2)    /* 4030 */
5958908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)
6058908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)
6158908ef6SLaurent Vivier         MIPS_SYS(sys_access     , 2)
6258908ef6SLaurent Vivier         MIPS_SYS(sys_nice       , 1)
6358908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)    /* 4035 */
6458908ef6SLaurent Vivier         MIPS_SYS(sys_sync       , 0)
6558908ef6SLaurent Vivier         MIPS_SYS(sys_kill       , 2)
6658908ef6SLaurent Vivier         MIPS_SYS(sys_rename     , 2)
6758908ef6SLaurent Vivier         MIPS_SYS(sys_mkdir      , 2)
6858908ef6SLaurent Vivier         MIPS_SYS(sys_rmdir      , 1)    /* 4040 */
6958908ef6SLaurent Vivier         MIPS_SYS(sys_dup                , 1)
7058908ef6SLaurent Vivier         MIPS_SYS(sys_pipe       , 0)
7158908ef6SLaurent Vivier         MIPS_SYS(sys_times      , 1)
7258908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)
7358908ef6SLaurent Vivier         MIPS_SYS(sys_brk                , 1)    /* 4045 */
7458908ef6SLaurent Vivier         MIPS_SYS(sys_setgid     , 1)
7558908ef6SLaurent Vivier         MIPS_SYS(sys_getgid     , 0)
7658908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)    /* was signal(2) */
7758908ef6SLaurent Vivier         MIPS_SYS(sys_geteuid    , 0)
7858908ef6SLaurent Vivier         MIPS_SYS(sys_getegid    , 0)    /* 4050 */
7958908ef6SLaurent Vivier         MIPS_SYS(sys_acct       , 0)
8058908ef6SLaurent Vivier         MIPS_SYS(sys_umount2    , 2)
8158908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)
8258908ef6SLaurent Vivier         MIPS_SYS(sys_ioctl      , 3)
8358908ef6SLaurent Vivier         MIPS_SYS(sys_fcntl      , 3)    /* 4055 */
8458908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 2)
8558908ef6SLaurent Vivier         MIPS_SYS(sys_setpgid    , 2)
8658908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)
8758908ef6SLaurent Vivier         MIPS_SYS(sys_olduname   , 1)
8858908ef6SLaurent Vivier         MIPS_SYS(sys_umask      , 1)    /* 4060 */
8958908ef6SLaurent Vivier         MIPS_SYS(sys_chroot     , 1)
9058908ef6SLaurent Vivier         MIPS_SYS(sys_ustat      , 2)
9158908ef6SLaurent Vivier         MIPS_SYS(sys_dup2       , 2)
9258908ef6SLaurent Vivier         MIPS_SYS(sys_getppid    , 0)
9358908ef6SLaurent Vivier         MIPS_SYS(sys_getpgrp    , 0)    /* 4065 */
9458908ef6SLaurent Vivier         MIPS_SYS(sys_setsid     , 0)
9558908ef6SLaurent Vivier         MIPS_SYS(sys_sigaction  , 3)
9658908ef6SLaurent Vivier         MIPS_SYS(sys_sgetmask   , 0)
9758908ef6SLaurent Vivier         MIPS_SYS(sys_ssetmask   , 1)
9858908ef6SLaurent Vivier         MIPS_SYS(sys_setreuid   , 2)    /* 4070 */
9958908ef6SLaurent Vivier         MIPS_SYS(sys_setregid   , 2)
10058908ef6SLaurent Vivier         MIPS_SYS(sys_sigsuspend , 0)
10158908ef6SLaurent Vivier         MIPS_SYS(sys_sigpending , 1)
10258908ef6SLaurent Vivier         MIPS_SYS(sys_sethostname        , 2)
10358908ef6SLaurent Vivier         MIPS_SYS(sys_setrlimit  , 2)    /* 4075 */
10458908ef6SLaurent Vivier         MIPS_SYS(sys_getrlimit  , 2)
10558908ef6SLaurent Vivier         MIPS_SYS(sys_getrusage  , 2)
10658908ef6SLaurent Vivier         MIPS_SYS(sys_gettimeofday, 2)
10758908ef6SLaurent Vivier         MIPS_SYS(sys_settimeofday, 2)
10858908ef6SLaurent Vivier         MIPS_SYS(sys_getgroups  , 2)    /* 4080 */
10958908ef6SLaurent Vivier         MIPS_SYS(sys_setgroups  , 2)
11058908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)    /* old_select */
11158908ef6SLaurent Vivier         MIPS_SYS(sys_symlink    , 2)
11258908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)    /* was sys_lstat */
11358908ef6SLaurent Vivier         MIPS_SYS(sys_readlink   , 3)    /* 4085 */
11458908ef6SLaurent Vivier         MIPS_SYS(sys_uselib     , 1)
11558908ef6SLaurent Vivier         MIPS_SYS(sys_swapon     , 2)
11658908ef6SLaurent Vivier         MIPS_SYS(sys_reboot     , 3)
11758908ef6SLaurent Vivier         MIPS_SYS(old_readdir    , 3)
11858908ef6SLaurent Vivier         MIPS_SYS(old_mmap       , 6)    /* 4090 */
11958908ef6SLaurent Vivier         MIPS_SYS(sys_munmap     , 2)
12058908ef6SLaurent Vivier         MIPS_SYS(sys_truncate   , 2)
12158908ef6SLaurent Vivier         MIPS_SYS(sys_ftruncate  , 2)
12258908ef6SLaurent Vivier         MIPS_SYS(sys_fchmod     , 2)
12358908ef6SLaurent Vivier         MIPS_SYS(sys_fchown     , 3)    /* 4095 */
12458908ef6SLaurent Vivier         MIPS_SYS(sys_getpriority        , 2)
12558908ef6SLaurent Vivier         MIPS_SYS(sys_setpriority        , 3)
12658908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)
12758908ef6SLaurent Vivier         MIPS_SYS(sys_statfs     , 2)
12858908ef6SLaurent Vivier         MIPS_SYS(sys_fstatfs    , 2)    /* 4100 */
12958908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)    /* was ioperm(2) */
13058908ef6SLaurent Vivier         MIPS_SYS(sys_socketcall , 2)
13158908ef6SLaurent Vivier         MIPS_SYS(sys_syslog     , 3)
13258908ef6SLaurent Vivier         MIPS_SYS(sys_setitimer  , 3)
13358908ef6SLaurent Vivier         MIPS_SYS(sys_getitimer  , 2)    /* 4105 */
13458908ef6SLaurent Vivier         MIPS_SYS(sys_newstat    , 2)
13558908ef6SLaurent Vivier         MIPS_SYS(sys_newlstat   , 2)
13658908ef6SLaurent Vivier         MIPS_SYS(sys_newfstat   , 2)
13758908ef6SLaurent Vivier         MIPS_SYS(sys_uname      , 1)
13858908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)    /* 4110 was iopl(2) */
13958908ef6SLaurent Vivier         MIPS_SYS(sys_vhangup    , 0)
14058908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)    /* was sys_idle() */
14158908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)    /* was sys_vm86 */
14258908ef6SLaurent Vivier         MIPS_SYS(sys_wait4      , 4)
14358908ef6SLaurent Vivier         MIPS_SYS(sys_swapoff    , 1)    /* 4115 */
14458908ef6SLaurent Vivier         MIPS_SYS(sys_sysinfo    , 1)
14558908ef6SLaurent Vivier         MIPS_SYS(sys_ipc                , 6)
14658908ef6SLaurent Vivier         MIPS_SYS(sys_fsync      , 1)
14758908ef6SLaurent Vivier         MIPS_SYS(sys_sigreturn  , 0)
14858908ef6SLaurent Vivier         MIPS_SYS(sys_clone      , 6)    /* 4120 */
14958908ef6SLaurent Vivier         MIPS_SYS(sys_setdomainname, 2)
15058908ef6SLaurent Vivier         MIPS_SYS(sys_newuname   , 1)
15158908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)    /* sys_modify_ldt */
15258908ef6SLaurent Vivier         MIPS_SYS(sys_adjtimex   , 1)
15358908ef6SLaurent Vivier         MIPS_SYS(sys_mprotect   , 3)    /* 4125 */
15458908ef6SLaurent Vivier         MIPS_SYS(sys_sigprocmask        , 3)
15558908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)    /* was create_module */
15658908ef6SLaurent Vivier         MIPS_SYS(sys_init_module        , 5)
15758908ef6SLaurent Vivier         MIPS_SYS(sys_delete_module, 1)
15858908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)    /* 4130 was get_kernel_syms */
15958908ef6SLaurent Vivier         MIPS_SYS(sys_quotactl   , 0)
16058908ef6SLaurent Vivier         MIPS_SYS(sys_getpgid    , 1)
16158908ef6SLaurent Vivier         MIPS_SYS(sys_fchdir     , 1)
16258908ef6SLaurent Vivier         MIPS_SYS(sys_bdflush    , 2)
16358908ef6SLaurent Vivier         MIPS_SYS(sys_sysfs      , 3)    /* 4135 */
16458908ef6SLaurent Vivier         MIPS_SYS(sys_personality        , 1)
16558908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)    /* for afs_syscall */
16658908ef6SLaurent Vivier         MIPS_SYS(sys_setfsuid   , 1)
16758908ef6SLaurent Vivier         MIPS_SYS(sys_setfsgid   , 1)
16858908ef6SLaurent Vivier         MIPS_SYS(sys_llseek     , 5)    /* 4140 */
16958908ef6SLaurent Vivier         MIPS_SYS(sys_getdents   , 3)
17058908ef6SLaurent Vivier         MIPS_SYS(sys_select     , 5)
17158908ef6SLaurent Vivier         MIPS_SYS(sys_flock      , 2)
17258908ef6SLaurent Vivier         MIPS_SYS(sys_msync      , 3)
17358908ef6SLaurent Vivier         MIPS_SYS(sys_readv      , 3)    /* 4145 */
17458908ef6SLaurent Vivier         MIPS_SYS(sys_writev     , 3)
17558908ef6SLaurent Vivier         MIPS_SYS(sys_cacheflush , 3)
17658908ef6SLaurent Vivier         MIPS_SYS(sys_cachectl   , 3)
17758908ef6SLaurent Vivier         MIPS_SYS(sys_sysmips    , 4)
17858908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)    /* 4150 */
17958908ef6SLaurent Vivier         MIPS_SYS(sys_getsid     , 1)
18058908ef6SLaurent Vivier         MIPS_SYS(sys_fdatasync  , 0)
18158908ef6SLaurent Vivier         MIPS_SYS(sys_sysctl     , 1)
18258908ef6SLaurent Vivier         MIPS_SYS(sys_mlock      , 2)
18358908ef6SLaurent Vivier         MIPS_SYS(sys_munlock    , 2)    /* 4155 */
18458908ef6SLaurent Vivier         MIPS_SYS(sys_mlockall   , 1)
18558908ef6SLaurent Vivier         MIPS_SYS(sys_munlockall , 0)
18658908ef6SLaurent Vivier         MIPS_SYS(sys_sched_setparam, 2)
18758908ef6SLaurent Vivier         MIPS_SYS(sys_sched_getparam, 2)
18858908ef6SLaurent Vivier         MIPS_SYS(sys_sched_setscheduler, 3)     /* 4160 */
18958908ef6SLaurent Vivier         MIPS_SYS(sys_sched_getscheduler, 1)
19058908ef6SLaurent Vivier         MIPS_SYS(sys_sched_yield        , 0)
19158908ef6SLaurent Vivier         MIPS_SYS(sys_sched_get_priority_max, 1)
19258908ef6SLaurent Vivier         MIPS_SYS(sys_sched_get_priority_min, 1)
19358908ef6SLaurent Vivier         MIPS_SYS(sys_sched_rr_get_interval, 2)  /* 4165 */
19458908ef6SLaurent Vivier         MIPS_SYS(sys_nanosleep, 2)
19558908ef6SLaurent Vivier         MIPS_SYS(sys_mremap     , 5)
19658908ef6SLaurent Vivier         MIPS_SYS(sys_accept     , 3)
19758908ef6SLaurent Vivier         MIPS_SYS(sys_bind       , 3)
19858908ef6SLaurent Vivier         MIPS_SYS(sys_connect    , 3)    /* 4170 */
19958908ef6SLaurent Vivier         MIPS_SYS(sys_getpeername        , 3)
20058908ef6SLaurent Vivier         MIPS_SYS(sys_getsockname        , 3)
20158908ef6SLaurent Vivier         MIPS_SYS(sys_getsockopt , 5)
20258908ef6SLaurent Vivier         MIPS_SYS(sys_listen     , 2)
20358908ef6SLaurent Vivier         MIPS_SYS(sys_recv       , 4)    /* 4175 */
20458908ef6SLaurent Vivier         MIPS_SYS(sys_recvfrom   , 6)
20558908ef6SLaurent Vivier         MIPS_SYS(sys_recvmsg    , 3)
20658908ef6SLaurent Vivier         MIPS_SYS(sys_send       , 4)
20758908ef6SLaurent Vivier         MIPS_SYS(sys_sendmsg    , 3)
20858908ef6SLaurent Vivier         MIPS_SYS(sys_sendto     , 6)    /* 4180 */
20958908ef6SLaurent Vivier         MIPS_SYS(sys_setsockopt , 5)
21058908ef6SLaurent Vivier         MIPS_SYS(sys_shutdown   , 2)
21158908ef6SLaurent Vivier         MIPS_SYS(sys_socket     , 3)
21258908ef6SLaurent Vivier         MIPS_SYS(sys_socketpair , 4)
21358908ef6SLaurent Vivier         MIPS_SYS(sys_setresuid  , 3)    /* 4185 */
21458908ef6SLaurent Vivier         MIPS_SYS(sys_getresuid  , 3)
21558908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)    /* was sys_query_module */
21658908ef6SLaurent Vivier         MIPS_SYS(sys_poll       , 3)
21758908ef6SLaurent Vivier         MIPS_SYS(sys_nfsservctl , 3)
21858908ef6SLaurent Vivier         MIPS_SYS(sys_setresgid  , 3)    /* 4190 */
21958908ef6SLaurent Vivier         MIPS_SYS(sys_getresgid  , 3)
22058908ef6SLaurent Vivier         MIPS_SYS(sys_prctl      , 5)
22158908ef6SLaurent Vivier         MIPS_SYS(sys_rt_sigreturn, 0)
22258908ef6SLaurent Vivier         MIPS_SYS(sys_rt_sigaction, 4)
22358908ef6SLaurent Vivier         MIPS_SYS(sys_rt_sigprocmask, 4) /* 4195 */
22458908ef6SLaurent Vivier         MIPS_SYS(sys_rt_sigpending, 2)
22558908ef6SLaurent Vivier         MIPS_SYS(sys_rt_sigtimedwait, 4)
22658908ef6SLaurent Vivier         MIPS_SYS(sys_rt_sigqueueinfo, 3)
22758908ef6SLaurent Vivier         MIPS_SYS(sys_rt_sigsuspend, 0)
22858908ef6SLaurent Vivier         MIPS_SYS(sys_pread64    , 6)    /* 4200 */
22958908ef6SLaurent Vivier         MIPS_SYS(sys_pwrite64   , 6)
23058908ef6SLaurent Vivier         MIPS_SYS(sys_chown      , 3)
23158908ef6SLaurent Vivier         MIPS_SYS(sys_getcwd     , 2)
23258908ef6SLaurent Vivier         MIPS_SYS(sys_capget     , 2)
23358908ef6SLaurent Vivier         MIPS_SYS(sys_capset     , 2)    /* 4205 */
23458908ef6SLaurent Vivier         MIPS_SYS(sys_sigaltstack        , 2)
23558908ef6SLaurent Vivier         MIPS_SYS(sys_sendfile   , 4)
23658908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)
23758908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)
23858908ef6SLaurent Vivier         MIPS_SYS(sys_mmap2      , 6)    /* 4210 */
23958908ef6SLaurent Vivier         MIPS_SYS(sys_truncate64 , 4)
24058908ef6SLaurent Vivier         MIPS_SYS(sys_ftruncate64        , 4)
24158908ef6SLaurent Vivier         MIPS_SYS(sys_stat64     , 2)
24258908ef6SLaurent Vivier         MIPS_SYS(sys_lstat64    , 2)
24358908ef6SLaurent Vivier         MIPS_SYS(sys_fstat64    , 2)    /* 4215 */
24458908ef6SLaurent Vivier         MIPS_SYS(sys_pivot_root , 2)
24558908ef6SLaurent Vivier         MIPS_SYS(sys_mincore    , 3)
24658908ef6SLaurent Vivier         MIPS_SYS(sys_madvise    , 3)
24758908ef6SLaurent Vivier         MIPS_SYS(sys_getdents64 , 3)
24858908ef6SLaurent Vivier         MIPS_SYS(sys_fcntl64    , 3)    /* 4220 */
24958908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)
25058908ef6SLaurent Vivier         MIPS_SYS(sys_gettid     , 0)
25158908ef6SLaurent Vivier         MIPS_SYS(sys_readahead  , 5)
25258908ef6SLaurent Vivier         MIPS_SYS(sys_setxattr   , 5)
25358908ef6SLaurent Vivier         MIPS_SYS(sys_lsetxattr  , 5)    /* 4225 */
25458908ef6SLaurent Vivier         MIPS_SYS(sys_fsetxattr  , 5)
25558908ef6SLaurent Vivier         MIPS_SYS(sys_getxattr   , 4)
25658908ef6SLaurent Vivier         MIPS_SYS(sys_lgetxattr  , 4)
25758908ef6SLaurent Vivier         MIPS_SYS(sys_fgetxattr  , 4)
25858908ef6SLaurent Vivier         MIPS_SYS(sys_listxattr  , 3)    /* 4230 */
25958908ef6SLaurent Vivier         MIPS_SYS(sys_llistxattr , 3)
26058908ef6SLaurent Vivier         MIPS_SYS(sys_flistxattr , 3)
26158908ef6SLaurent Vivier         MIPS_SYS(sys_removexattr        , 2)
26258908ef6SLaurent Vivier         MIPS_SYS(sys_lremovexattr, 2)
26358908ef6SLaurent Vivier         MIPS_SYS(sys_fremovexattr, 2)   /* 4235 */
26458908ef6SLaurent Vivier         MIPS_SYS(sys_tkill      , 2)
26558908ef6SLaurent Vivier         MIPS_SYS(sys_sendfile64 , 5)
26658908ef6SLaurent Vivier         MIPS_SYS(sys_futex      , 6)
26758908ef6SLaurent Vivier         MIPS_SYS(sys_sched_setaffinity, 3)
26858908ef6SLaurent Vivier         MIPS_SYS(sys_sched_getaffinity, 3)      /* 4240 */
26958908ef6SLaurent Vivier         MIPS_SYS(sys_io_setup   , 2)
27058908ef6SLaurent Vivier         MIPS_SYS(sys_io_destroy , 1)
27158908ef6SLaurent Vivier         MIPS_SYS(sys_io_getevents, 5)
27258908ef6SLaurent Vivier         MIPS_SYS(sys_io_submit  , 3)
27358908ef6SLaurent Vivier         MIPS_SYS(sys_io_cancel  , 3)    /* 4245 */
27458908ef6SLaurent Vivier         MIPS_SYS(sys_exit_group , 1)
27558908ef6SLaurent Vivier         MIPS_SYS(sys_lookup_dcookie, 3)
27658908ef6SLaurent Vivier         MIPS_SYS(sys_epoll_create, 1)
27758908ef6SLaurent Vivier         MIPS_SYS(sys_epoll_ctl  , 4)
27858908ef6SLaurent Vivier         MIPS_SYS(sys_epoll_wait , 3)    /* 4250 */
27958908ef6SLaurent Vivier         MIPS_SYS(sys_remap_file_pages, 5)
28058908ef6SLaurent Vivier         MIPS_SYS(sys_set_tid_address, 1)
28158908ef6SLaurent Vivier         MIPS_SYS(sys_restart_syscall, 0)
28258908ef6SLaurent Vivier         MIPS_SYS(sys_fadvise64_64, 7)
28358908ef6SLaurent Vivier         MIPS_SYS(sys_statfs64   , 3)    /* 4255 */
28458908ef6SLaurent Vivier         MIPS_SYS(sys_fstatfs64  , 2)
28558908ef6SLaurent Vivier         MIPS_SYS(sys_timer_create, 3)
28658908ef6SLaurent Vivier         MIPS_SYS(sys_timer_settime, 4)
28758908ef6SLaurent Vivier         MIPS_SYS(sys_timer_gettime, 2)
28858908ef6SLaurent Vivier         MIPS_SYS(sys_timer_getoverrun, 1)       /* 4260 */
28958908ef6SLaurent Vivier         MIPS_SYS(sys_timer_delete, 1)
29058908ef6SLaurent Vivier         MIPS_SYS(sys_clock_settime, 2)
29158908ef6SLaurent Vivier         MIPS_SYS(sys_clock_gettime, 2)
29258908ef6SLaurent Vivier         MIPS_SYS(sys_clock_getres, 2)
29358908ef6SLaurent Vivier         MIPS_SYS(sys_clock_nanosleep, 4)        /* 4265 */
29458908ef6SLaurent Vivier         MIPS_SYS(sys_tgkill     , 3)
29558908ef6SLaurent Vivier         MIPS_SYS(sys_utimes     , 2)
29658908ef6SLaurent Vivier         MIPS_SYS(sys_mbind      , 4)
29758908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)    /* sys_get_mempolicy */
29858908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)    /* 4270 sys_set_mempolicy */
29958908ef6SLaurent Vivier         MIPS_SYS(sys_mq_open    , 4)
30058908ef6SLaurent Vivier         MIPS_SYS(sys_mq_unlink  , 1)
30158908ef6SLaurent Vivier         MIPS_SYS(sys_mq_timedsend, 5)
30258908ef6SLaurent Vivier         MIPS_SYS(sys_mq_timedreceive, 5)
30358908ef6SLaurent Vivier         MIPS_SYS(sys_mq_notify  , 2)    /* 4275 */
30458908ef6SLaurent Vivier         MIPS_SYS(sys_mq_getsetattr, 3)
30558908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)    /* sys_vserver */
30658908ef6SLaurent Vivier         MIPS_SYS(sys_waitid     , 4)
30758908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall , 0)    /* available, was setaltroot */
30858908ef6SLaurent Vivier         MIPS_SYS(sys_add_key    , 5)
30958908ef6SLaurent Vivier         MIPS_SYS(sys_request_key, 4)
31058908ef6SLaurent Vivier         MIPS_SYS(sys_keyctl     , 5)
31158908ef6SLaurent Vivier         MIPS_SYS(sys_set_thread_area, 1)
31258908ef6SLaurent Vivier         MIPS_SYS(sys_inotify_init, 0)
31358908ef6SLaurent Vivier         MIPS_SYS(sys_inotify_add_watch, 3) /* 4285 */
31458908ef6SLaurent Vivier         MIPS_SYS(sys_inotify_rm_watch, 2)
31558908ef6SLaurent Vivier         MIPS_SYS(sys_migrate_pages, 4)
31658908ef6SLaurent Vivier         MIPS_SYS(sys_openat, 4)
31758908ef6SLaurent Vivier         MIPS_SYS(sys_mkdirat, 3)
31858908ef6SLaurent Vivier         MIPS_SYS(sys_mknodat, 4)        /* 4290 */
31958908ef6SLaurent Vivier         MIPS_SYS(sys_fchownat, 5)
32058908ef6SLaurent Vivier         MIPS_SYS(sys_futimesat, 3)
32158908ef6SLaurent Vivier         MIPS_SYS(sys_fstatat64, 4)
32258908ef6SLaurent Vivier         MIPS_SYS(sys_unlinkat, 3)
32358908ef6SLaurent Vivier         MIPS_SYS(sys_renameat, 4)       /* 4295 */
32458908ef6SLaurent Vivier         MIPS_SYS(sys_linkat, 5)
32558908ef6SLaurent Vivier         MIPS_SYS(sys_symlinkat, 3)
32658908ef6SLaurent Vivier         MIPS_SYS(sys_readlinkat, 4)
32758908ef6SLaurent Vivier         MIPS_SYS(sys_fchmodat, 3)
32858908ef6SLaurent Vivier         MIPS_SYS(sys_faccessat, 3)      /* 4300 */
32958908ef6SLaurent Vivier         MIPS_SYS(sys_pselect6, 6)
33058908ef6SLaurent Vivier         MIPS_SYS(sys_ppoll, 5)
33158908ef6SLaurent Vivier         MIPS_SYS(sys_unshare, 1)
33258908ef6SLaurent Vivier         MIPS_SYS(sys_splice, 6)
33358908ef6SLaurent Vivier         MIPS_SYS(sys_sync_file_range, 7) /* 4305 */
33458908ef6SLaurent Vivier         MIPS_SYS(sys_tee, 4)
33558908ef6SLaurent Vivier         MIPS_SYS(sys_vmsplice, 4)
33658908ef6SLaurent Vivier         MIPS_SYS(sys_move_pages, 6)
33758908ef6SLaurent Vivier         MIPS_SYS(sys_set_robust_list, 2)
33858908ef6SLaurent Vivier         MIPS_SYS(sys_get_robust_list, 3) /* 4310 */
33958908ef6SLaurent Vivier         MIPS_SYS(sys_kexec_load, 4)
34058908ef6SLaurent Vivier         MIPS_SYS(sys_getcpu, 3)
34158908ef6SLaurent Vivier         MIPS_SYS(sys_epoll_pwait, 6)
34258908ef6SLaurent Vivier         MIPS_SYS(sys_ioprio_set, 3)
34358908ef6SLaurent Vivier         MIPS_SYS(sys_ioprio_get, 2)
34458908ef6SLaurent Vivier         MIPS_SYS(sys_utimensat, 4)
34558908ef6SLaurent Vivier         MIPS_SYS(sys_signalfd, 3)
34658908ef6SLaurent Vivier         MIPS_SYS(sys_ni_syscall, 0)     /* was timerfd */
34758908ef6SLaurent Vivier         MIPS_SYS(sys_eventfd, 1)
34858908ef6SLaurent Vivier         MIPS_SYS(sys_fallocate, 6)      /* 4320 */
34958908ef6SLaurent Vivier         MIPS_SYS(sys_timerfd_create, 2)
35058908ef6SLaurent Vivier         MIPS_SYS(sys_timerfd_gettime, 2)
35158908ef6SLaurent Vivier         MIPS_SYS(sys_timerfd_settime, 4)
35258908ef6SLaurent Vivier         MIPS_SYS(sys_signalfd4, 4)
35358908ef6SLaurent Vivier         MIPS_SYS(sys_eventfd2, 2)       /* 4325 */
35458908ef6SLaurent Vivier         MIPS_SYS(sys_epoll_create1, 1)
35558908ef6SLaurent Vivier         MIPS_SYS(sys_dup3, 3)
35658908ef6SLaurent Vivier         MIPS_SYS(sys_pipe2, 2)
35758908ef6SLaurent Vivier         MIPS_SYS(sys_inotify_init1, 1)
35858908ef6SLaurent Vivier         MIPS_SYS(sys_preadv, 5)         /* 4330 */
35958908ef6SLaurent Vivier         MIPS_SYS(sys_pwritev, 5)
36058908ef6SLaurent Vivier         MIPS_SYS(sys_rt_tgsigqueueinfo, 4)
36158908ef6SLaurent Vivier         MIPS_SYS(sys_perf_event_open, 5)
36258908ef6SLaurent Vivier         MIPS_SYS(sys_accept4, 4)
36358908ef6SLaurent Vivier         MIPS_SYS(sys_recvmmsg, 5)       /* 4335 */
36458908ef6SLaurent Vivier         MIPS_SYS(sys_fanotify_init, 2)
36558908ef6SLaurent Vivier         MIPS_SYS(sys_fanotify_mark, 6)
36658908ef6SLaurent Vivier         MIPS_SYS(sys_prlimit64, 4)
36758908ef6SLaurent Vivier         MIPS_SYS(sys_name_to_handle_at, 5)
36858908ef6SLaurent Vivier         MIPS_SYS(sys_open_by_handle_at, 3) /* 4340 */
36958908ef6SLaurent Vivier         MIPS_SYS(sys_clock_adjtime, 2)
37058908ef6SLaurent Vivier         MIPS_SYS(sys_syncfs, 1)
37158908ef6SLaurent Vivier         MIPS_SYS(sys_sendmmsg, 4)
37258908ef6SLaurent Vivier         MIPS_SYS(sys_setns, 2)
37358908ef6SLaurent Vivier         MIPS_SYS(sys_process_vm_readv, 6) /* 345 */
37458908ef6SLaurent Vivier         MIPS_SYS(sys_process_vm_writev, 6)
37558908ef6SLaurent Vivier         MIPS_SYS(sys_kcmp, 5)
37658908ef6SLaurent Vivier         MIPS_SYS(sys_finit_module, 3)
37758908ef6SLaurent Vivier         MIPS_SYS(sys_sched_setattr, 2)
37858908ef6SLaurent Vivier         MIPS_SYS(sys_sched_getattr, 3)  /* 350 */
37958908ef6SLaurent Vivier         MIPS_SYS(sys_renameat2, 5)
38058908ef6SLaurent Vivier         MIPS_SYS(sys_seccomp, 3)
38158908ef6SLaurent Vivier         MIPS_SYS(sys_getrandom, 3)
38258908ef6SLaurent Vivier         MIPS_SYS(sys_memfd_create, 2)
38358908ef6SLaurent Vivier         MIPS_SYS(sys_bpf, 3)            /* 355 */
38458908ef6SLaurent Vivier         MIPS_SYS(sys_execveat, 5)
38558908ef6SLaurent Vivier         MIPS_SYS(sys_userfaultfd, 1)
38658908ef6SLaurent Vivier         MIPS_SYS(sys_membarrier, 2)
38758908ef6SLaurent Vivier         MIPS_SYS(sys_mlock2, 3)
38858908ef6SLaurent Vivier         MIPS_SYS(sys_copy_file_range, 6) /* 360 */
38958908ef6SLaurent Vivier         MIPS_SYS(sys_preadv2, 6)
39058908ef6SLaurent Vivier         MIPS_SYS(sys_pwritev2, 6)
39158908ef6SLaurent Vivier };
39258908ef6SLaurent Vivier #  undef MIPS_SYS
39358908ef6SLaurent Vivier # endif /* O32 */
39458908ef6SLaurent Vivier 
39558908ef6SLaurent Vivier static int do_store_exclusive(CPUMIPSState *env)
39658908ef6SLaurent Vivier {
39758908ef6SLaurent Vivier     target_ulong addr;
39858908ef6SLaurent Vivier     target_ulong page_addr;
39958908ef6SLaurent Vivier     target_ulong val;
4000b16dcd1SAleksandar Rikalo     uint32_t val_wp = 0;
4010b16dcd1SAleksandar Rikalo     uint32_t llnewval_wp = 0;
40258908ef6SLaurent Vivier     int flags;
40358908ef6SLaurent Vivier     int segv = 0;
40458908ef6SLaurent Vivier     int reg;
40558908ef6SLaurent Vivier     int d;
4060b16dcd1SAleksandar Rikalo     int wp;
40758908ef6SLaurent Vivier 
40858908ef6SLaurent Vivier     addr = env->lladdr;
40958908ef6SLaurent Vivier     page_addr = addr & TARGET_PAGE_MASK;
41058908ef6SLaurent Vivier     start_exclusive();
41158908ef6SLaurent Vivier     mmap_lock();
41258908ef6SLaurent Vivier     flags = page_get_flags(page_addr);
41358908ef6SLaurent Vivier     if ((flags & PAGE_READ) == 0) {
41458908ef6SLaurent Vivier         segv = 1;
41558908ef6SLaurent Vivier     } else {
41658908ef6SLaurent Vivier         reg = env->llreg & 0x1f;
41758908ef6SLaurent Vivier         d = (env->llreg & 0x20) != 0;
4180b16dcd1SAleksandar Rikalo         wp = (env->llreg & 0x40) != 0;
4190b16dcd1SAleksandar Rikalo         if (!wp) {
42058908ef6SLaurent Vivier             if (d) {
42158908ef6SLaurent Vivier                 segv = get_user_s64(val, addr);
42258908ef6SLaurent Vivier             } else {
42358908ef6SLaurent Vivier                 segv = get_user_s32(val, addr);
42458908ef6SLaurent Vivier             }
4250b16dcd1SAleksandar Rikalo         } else {
4260b16dcd1SAleksandar Rikalo             segv = get_user_s32(val, addr);
4270b16dcd1SAleksandar Rikalo             segv |= get_user_s32(val_wp, addr);
4280b16dcd1SAleksandar Rikalo             llnewval_wp = env->llnewval_wp;
4290b16dcd1SAleksandar Rikalo         }
43058908ef6SLaurent Vivier         if (!segv) {
4310b16dcd1SAleksandar Rikalo             if (val != env->llval && val_wp == llnewval_wp) {
43258908ef6SLaurent Vivier                 env->active_tc.gpr[reg] = 0;
43358908ef6SLaurent Vivier             } else {
4340b16dcd1SAleksandar Rikalo                 if (!wp) {
43558908ef6SLaurent Vivier                     if (d) {
43658908ef6SLaurent Vivier                         segv = put_user_u64(env->llnewval, addr);
43758908ef6SLaurent Vivier                     } else {
43858908ef6SLaurent Vivier                         segv = put_user_u32(env->llnewval, addr);
43958908ef6SLaurent Vivier                     }
4400b16dcd1SAleksandar Rikalo                 } else {
4410b16dcd1SAleksandar Rikalo                     segv = put_user_u32(env->llnewval, addr);
4420b16dcd1SAleksandar Rikalo                     segv |= put_user_u32(env->llnewval_wp, addr + 4);
4430b16dcd1SAleksandar Rikalo                 }
44458908ef6SLaurent Vivier                 if (!segv) {
44558908ef6SLaurent Vivier                     env->active_tc.gpr[reg] = 1;
44658908ef6SLaurent Vivier                 }
44758908ef6SLaurent Vivier             }
44858908ef6SLaurent Vivier         }
44958908ef6SLaurent Vivier     }
45058908ef6SLaurent Vivier     env->lladdr = -1;
45158908ef6SLaurent Vivier     if (!segv) {
45258908ef6SLaurent Vivier         env->active_tc.PC += 4;
45358908ef6SLaurent Vivier     }
45458908ef6SLaurent Vivier     mmap_unlock();
45558908ef6SLaurent Vivier     end_exclusive();
45658908ef6SLaurent Vivier     return segv;
45758908ef6SLaurent Vivier }
45858908ef6SLaurent Vivier 
45958908ef6SLaurent Vivier /* Break codes */
46058908ef6SLaurent Vivier enum {
46158908ef6SLaurent Vivier     BRK_OVERFLOW = 6,
46258908ef6SLaurent Vivier     BRK_DIVZERO = 7
46358908ef6SLaurent Vivier };
46458908ef6SLaurent Vivier 
46558908ef6SLaurent Vivier static int do_break(CPUMIPSState *env, target_siginfo_t *info,
46658908ef6SLaurent Vivier                     unsigned int code)
46758908ef6SLaurent Vivier {
46858908ef6SLaurent Vivier     int ret = -1;
46958908ef6SLaurent Vivier 
47058908ef6SLaurent Vivier     switch (code) {
47158908ef6SLaurent Vivier     case BRK_OVERFLOW:
47258908ef6SLaurent Vivier     case BRK_DIVZERO:
47358908ef6SLaurent Vivier         info->si_signo = TARGET_SIGFPE;
47458908ef6SLaurent Vivier         info->si_errno = 0;
47558908ef6SLaurent Vivier         info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV;
47658908ef6SLaurent Vivier         queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info);
47758908ef6SLaurent Vivier         ret = 0;
47858908ef6SLaurent Vivier         break;
47958908ef6SLaurent Vivier     default:
48058908ef6SLaurent Vivier         info->si_signo = TARGET_SIGTRAP;
48158908ef6SLaurent Vivier         info->si_errno = 0;
48258908ef6SLaurent Vivier         queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info);
48358908ef6SLaurent Vivier         ret = 0;
48458908ef6SLaurent Vivier         break;
48558908ef6SLaurent Vivier     }
48658908ef6SLaurent Vivier 
48758908ef6SLaurent Vivier     return ret;
48858908ef6SLaurent Vivier }
48958908ef6SLaurent Vivier 
49058908ef6SLaurent Vivier void cpu_loop(CPUMIPSState *env)
49158908ef6SLaurent Vivier {
49258908ef6SLaurent Vivier     CPUState *cs = CPU(mips_env_get_cpu(env));
49358908ef6SLaurent Vivier     target_siginfo_t info;
49458908ef6SLaurent Vivier     int trapnr;
49558908ef6SLaurent Vivier     abi_long ret;
49658908ef6SLaurent Vivier # ifdef TARGET_ABI_MIPSO32
49758908ef6SLaurent Vivier     unsigned int syscall_num;
49858908ef6SLaurent Vivier # endif
49958908ef6SLaurent Vivier 
50058908ef6SLaurent Vivier     for(;;) {
50158908ef6SLaurent Vivier         cpu_exec_start(cs);
50258908ef6SLaurent Vivier         trapnr = cpu_exec(cs);
50358908ef6SLaurent Vivier         cpu_exec_end(cs);
50458908ef6SLaurent Vivier         process_queued_cpu_work(cs);
50558908ef6SLaurent Vivier 
50658908ef6SLaurent Vivier         switch(trapnr) {
50758908ef6SLaurent Vivier         case EXCP_SYSCALL:
50858908ef6SLaurent Vivier             env->active_tc.PC += 4;
50958908ef6SLaurent Vivier # ifdef TARGET_ABI_MIPSO32
51058908ef6SLaurent Vivier             syscall_num = env->active_tc.gpr[2] - 4000;
51158908ef6SLaurent Vivier             if (syscall_num >= sizeof(mips_syscall_args)) {
51258908ef6SLaurent Vivier                 ret = -TARGET_ENOSYS;
51358908ef6SLaurent Vivier             } else {
51458908ef6SLaurent Vivier                 int nb_args;
51558908ef6SLaurent Vivier                 abi_ulong sp_reg;
51658908ef6SLaurent Vivier                 abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
51758908ef6SLaurent Vivier 
51858908ef6SLaurent Vivier                 nb_args = mips_syscall_args[syscall_num];
51958908ef6SLaurent Vivier                 sp_reg = env->active_tc.gpr[29];
52058908ef6SLaurent Vivier                 switch (nb_args) {
52158908ef6SLaurent Vivier                 /* these arguments are taken from the stack */
52258908ef6SLaurent Vivier                 case 8:
52358908ef6SLaurent Vivier                     if ((ret = get_user_ual(arg8, sp_reg + 28)) != 0) {
52458908ef6SLaurent Vivier                         goto done_syscall;
52558908ef6SLaurent Vivier                     }
52658908ef6SLaurent Vivier                 case 7:
52758908ef6SLaurent Vivier                     if ((ret = get_user_ual(arg7, sp_reg + 24)) != 0) {
52858908ef6SLaurent Vivier                         goto done_syscall;
52958908ef6SLaurent Vivier                     }
53058908ef6SLaurent Vivier                 case 6:
53158908ef6SLaurent Vivier                     if ((ret = get_user_ual(arg6, sp_reg + 20)) != 0) {
53258908ef6SLaurent Vivier                         goto done_syscall;
53358908ef6SLaurent Vivier                     }
53458908ef6SLaurent Vivier                 case 5:
53558908ef6SLaurent Vivier                     if ((ret = get_user_ual(arg5, sp_reg + 16)) != 0) {
53658908ef6SLaurent Vivier                         goto done_syscall;
53758908ef6SLaurent Vivier                     }
53858908ef6SLaurent Vivier                 default:
53958908ef6SLaurent Vivier                     break;
54058908ef6SLaurent Vivier                 }
54158908ef6SLaurent Vivier                 ret = do_syscall(env, env->active_tc.gpr[2],
54258908ef6SLaurent Vivier                                  env->active_tc.gpr[4],
54358908ef6SLaurent Vivier                                  env->active_tc.gpr[5],
54458908ef6SLaurent Vivier                                  env->active_tc.gpr[6],
54558908ef6SLaurent Vivier                                  env->active_tc.gpr[7],
54658908ef6SLaurent Vivier                                  arg5, arg6, arg7, arg8);
54758908ef6SLaurent Vivier             }
54858908ef6SLaurent Vivier done_syscall:
54958908ef6SLaurent Vivier # else
55058908ef6SLaurent Vivier             ret = do_syscall(env, env->active_tc.gpr[2],
55158908ef6SLaurent Vivier                              env->active_tc.gpr[4], env->active_tc.gpr[5],
55258908ef6SLaurent Vivier                              env->active_tc.gpr[6], env->active_tc.gpr[7],
55358908ef6SLaurent Vivier                              env->active_tc.gpr[8], env->active_tc.gpr[9],
55458908ef6SLaurent Vivier                              env->active_tc.gpr[10], env->active_tc.gpr[11]);
55558908ef6SLaurent Vivier # endif /* O32 */
55658908ef6SLaurent Vivier             if (ret == -TARGET_ERESTARTSYS) {
55758908ef6SLaurent Vivier                 env->active_tc.PC -= 4;
55858908ef6SLaurent Vivier                 break;
55958908ef6SLaurent Vivier             }
56058908ef6SLaurent Vivier             if (ret == -TARGET_QEMU_ESIGRETURN) {
56158908ef6SLaurent Vivier                 /* Returning from a successful sigreturn syscall.
56258908ef6SLaurent Vivier                    Avoid clobbering register state.  */
56358908ef6SLaurent Vivier                 break;
56458908ef6SLaurent Vivier             }
56558908ef6SLaurent Vivier             if ((abi_ulong)ret >= (abi_ulong)-1133) {
56658908ef6SLaurent Vivier                 env->active_tc.gpr[7] = 1; /* error flag */
56758908ef6SLaurent Vivier                 ret = -ret;
56858908ef6SLaurent Vivier             } else {
56958908ef6SLaurent Vivier                 env->active_tc.gpr[7] = 0; /* error flag */
57058908ef6SLaurent Vivier             }
57158908ef6SLaurent Vivier             env->active_tc.gpr[2] = ret;
57258908ef6SLaurent Vivier             break;
57358908ef6SLaurent Vivier         case EXCP_TLBL:
57458908ef6SLaurent Vivier         case EXCP_TLBS:
57558908ef6SLaurent Vivier         case EXCP_AdEL:
57658908ef6SLaurent Vivier         case EXCP_AdES:
57758908ef6SLaurent Vivier             info.si_signo = TARGET_SIGSEGV;
57858908ef6SLaurent Vivier             info.si_errno = 0;
57958908ef6SLaurent Vivier             /* XXX: check env->error_code */
58058908ef6SLaurent Vivier             info.si_code = TARGET_SEGV_MAPERR;
58158908ef6SLaurent Vivier             info._sifields._sigfault._addr = env->CP0_BadVAddr;
58258908ef6SLaurent Vivier             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
58358908ef6SLaurent Vivier             break;
58458908ef6SLaurent Vivier         case EXCP_CpU:
58558908ef6SLaurent Vivier         case EXCP_RI:
58658908ef6SLaurent Vivier             info.si_signo = TARGET_SIGILL;
58758908ef6SLaurent Vivier             info.si_errno = 0;
58858908ef6SLaurent Vivier             info.si_code = 0;
58958908ef6SLaurent Vivier             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
59058908ef6SLaurent Vivier             break;
59158908ef6SLaurent Vivier         case EXCP_INTERRUPT:
59258908ef6SLaurent Vivier             /* just indicate that signals should be handled asap */
59358908ef6SLaurent Vivier             break;
59458908ef6SLaurent Vivier         case EXCP_DEBUG:
59558908ef6SLaurent Vivier             {
59658908ef6SLaurent Vivier                 int sig;
59758908ef6SLaurent Vivier 
59858908ef6SLaurent Vivier                 sig = gdb_handlesig(cs, TARGET_SIGTRAP);
59958908ef6SLaurent Vivier                 if (sig)
60058908ef6SLaurent Vivier                   {
60158908ef6SLaurent Vivier                     info.si_signo = sig;
60258908ef6SLaurent Vivier                     info.si_errno = 0;
60358908ef6SLaurent Vivier                     info.si_code = TARGET_TRAP_BRKPT;
60458908ef6SLaurent Vivier                     queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
60558908ef6SLaurent Vivier                   }
60658908ef6SLaurent Vivier             }
60758908ef6SLaurent Vivier             break;
60858908ef6SLaurent Vivier         case EXCP_SC:
60958908ef6SLaurent Vivier             if (do_store_exclusive(env)) {
61058908ef6SLaurent Vivier                 info.si_signo = TARGET_SIGSEGV;
61158908ef6SLaurent Vivier                 info.si_errno = 0;
61258908ef6SLaurent Vivier                 info.si_code = TARGET_SEGV_MAPERR;
61358908ef6SLaurent Vivier                 info._sifields._sigfault._addr = env->active_tc.PC;
61458908ef6SLaurent Vivier                 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
61558908ef6SLaurent Vivier             }
61658908ef6SLaurent Vivier             break;
61758908ef6SLaurent Vivier         case EXCP_DSPDIS:
61858908ef6SLaurent Vivier             info.si_signo = TARGET_SIGILL;
61958908ef6SLaurent Vivier             info.si_errno = 0;
62058908ef6SLaurent Vivier             info.si_code = TARGET_ILL_ILLOPC;
62158908ef6SLaurent Vivier             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
62258908ef6SLaurent Vivier             break;
62358908ef6SLaurent Vivier         /* The code below was inspired by the MIPS Linux kernel trap
62458908ef6SLaurent Vivier          * handling code in arch/mips/kernel/traps.c.
62558908ef6SLaurent Vivier          */
62658908ef6SLaurent Vivier         case EXCP_BREAK:
62758908ef6SLaurent Vivier             {
62858908ef6SLaurent Vivier                 abi_ulong trap_instr;
62958908ef6SLaurent Vivier                 unsigned int code;
63058908ef6SLaurent Vivier 
63158908ef6SLaurent Vivier                 if (env->hflags & MIPS_HFLAG_M16) {
63258908ef6SLaurent Vivier                     if (env->insn_flags & ASE_MICROMIPS) {
63358908ef6SLaurent Vivier                         /* microMIPS mode */
63458908ef6SLaurent Vivier                         ret = get_user_u16(trap_instr, env->active_tc.PC);
63558908ef6SLaurent Vivier                         if (ret != 0) {
63658908ef6SLaurent Vivier                             goto error;
63758908ef6SLaurent Vivier                         }
63858908ef6SLaurent Vivier 
63958908ef6SLaurent Vivier                         if ((trap_instr >> 10) == 0x11) {
64058908ef6SLaurent Vivier                             /* 16-bit instruction */
64158908ef6SLaurent Vivier                             code = trap_instr & 0xf;
64258908ef6SLaurent Vivier                         } else {
64358908ef6SLaurent Vivier                             /* 32-bit instruction */
64458908ef6SLaurent Vivier                             abi_ulong instr_lo;
64558908ef6SLaurent Vivier 
64658908ef6SLaurent Vivier                             ret = get_user_u16(instr_lo,
64758908ef6SLaurent Vivier                                                env->active_tc.PC + 2);
64858908ef6SLaurent Vivier                             if (ret != 0) {
64958908ef6SLaurent Vivier                                 goto error;
65058908ef6SLaurent Vivier                             }
65158908ef6SLaurent Vivier                             trap_instr = (trap_instr << 16) | instr_lo;
65258908ef6SLaurent Vivier                             code = ((trap_instr >> 6) & ((1 << 20) - 1));
65358908ef6SLaurent Vivier                             /* Unfortunately, microMIPS also suffers from
65458908ef6SLaurent Vivier                                the old assembler bug...  */
65558908ef6SLaurent Vivier                             if (code >= (1 << 10)) {
65658908ef6SLaurent Vivier                                 code >>= 10;
65758908ef6SLaurent Vivier                             }
65858908ef6SLaurent Vivier                         }
65958908ef6SLaurent Vivier                     } else {
66058908ef6SLaurent Vivier                         /* MIPS16e mode */
66158908ef6SLaurent Vivier                         ret = get_user_u16(trap_instr, env->active_tc.PC);
66258908ef6SLaurent Vivier                         if (ret != 0) {
66358908ef6SLaurent Vivier                             goto error;
66458908ef6SLaurent Vivier                         }
66558908ef6SLaurent Vivier                         code = (trap_instr >> 6) & 0x3f;
66658908ef6SLaurent Vivier                     }
66758908ef6SLaurent Vivier                 } else {
66858908ef6SLaurent Vivier                     ret = get_user_u32(trap_instr, env->active_tc.PC);
66958908ef6SLaurent Vivier                     if (ret != 0) {
67058908ef6SLaurent Vivier                         goto error;
67158908ef6SLaurent Vivier                     }
67258908ef6SLaurent Vivier 
67358908ef6SLaurent Vivier                     /* As described in the original Linux kernel code, the
67458908ef6SLaurent Vivier                      * below checks on 'code' are to work around an old
67558908ef6SLaurent Vivier                      * assembly bug.
67658908ef6SLaurent Vivier                      */
67758908ef6SLaurent Vivier                     code = ((trap_instr >> 6) & ((1 << 20) - 1));
67858908ef6SLaurent Vivier                     if (code >= (1 << 10)) {
67958908ef6SLaurent Vivier                         code >>= 10;
68058908ef6SLaurent Vivier                     }
68158908ef6SLaurent Vivier                 }
68258908ef6SLaurent Vivier 
68358908ef6SLaurent Vivier                 if (do_break(env, &info, code) != 0) {
68458908ef6SLaurent Vivier                     goto error;
68558908ef6SLaurent Vivier                 }
68658908ef6SLaurent Vivier             }
68758908ef6SLaurent Vivier             break;
68858908ef6SLaurent Vivier         case EXCP_TRAP:
68958908ef6SLaurent Vivier             {
69058908ef6SLaurent Vivier                 abi_ulong trap_instr;
69158908ef6SLaurent Vivier                 unsigned int code = 0;
69258908ef6SLaurent Vivier 
69358908ef6SLaurent Vivier                 if (env->hflags & MIPS_HFLAG_M16) {
69458908ef6SLaurent Vivier                     /* microMIPS mode */
69558908ef6SLaurent Vivier                     abi_ulong instr[2];
69658908ef6SLaurent Vivier 
69758908ef6SLaurent Vivier                     ret = get_user_u16(instr[0], env->active_tc.PC) ||
69858908ef6SLaurent Vivier                           get_user_u16(instr[1], env->active_tc.PC + 2);
69958908ef6SLaurent Vivier 
70058908ef6SLaurent Vivier                     trap_instr = (instr[0] << 16) | instr[1];
70158908ef6SLaurent Vivier                 } else {
70258908ef6SLaurent Vivier                     ret = get_user_u32(trap_instr, env->active_tc.PC);
70358908ef6SLaurent Vivier                 }
70458908ef6SLaurent Vivier 
70558908ef6SLaurent Vivier                 if (ret != 0) {
70658908ef6SLaurent Vivier                     goto error;
70758908ef6SLaurent Vivier                 }
70858908ef6SLaurent Vivier 
70958908ef6SLaurent Vivier                 /* The immediate versions don't provide a code.  */
71058908ef6SLaurent Vivier                 if (!(trap_instr & 0xFC000000)) {
71158908ef6SLaurent Vivier                     if (env->hflags & MIPS_HFLAG_M16) {
71258908ef6SLaurent Vivier                         /* microMIPS mode */
71358908ef6SLaurent Vivier                         code = ((trap_instr >> 12) & ((1 << 4) - 1));
71458908ef6SLaurent Vivier                     } else {
71558908ef6SLaurent Vivier                         code = ((trap_instr >> 6) & ((1 << 10) - 1));
71658908ef6SLaurent Vivier                     }
71758908ef6SLaurent Vivier                 }
71858908ef6SLaurent Vivier 
71958908ef6SLaurent Vivier                 if (do_break(env, &info, code) != 0) {
72058908ef6SLaurent Vivier                     goto error;
72158908ef6SLaurent Vivier                 }
72258908ef6SLaurent Vivier             }
72358908ef6SLaurent Vivier             break;
72458908ef6SLaurent Vivier         case EXCP_ATOMIC:
72558908ef6SLaurent Vivier             cpu_exec_step_atomic(cs);
72658908ef6SLaurent Vivier             break;
72758908ef6SLaurent Vivier         default:
72858908ef6SLaurent Vivier error:
72958908ef6SLaurent Vivier             EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
73058908ef6SLaurent Vivier             abort();
73158908ef6SLaurent Vivier         }
73258908ef6SLaurent Vivier         process_pending_signals(env);
73358908ef6SLaurent Vivier     }
73458908ef6SLaurent Vivier }
735cd71c089SLaurent Vivier 
736cd71c089SLaurent Vivier void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
737cd71c089SLaurent Vivier {
73858908ef6SLaurent Vivier     CPUState *cpu = ENV_GET_CPU(env);
73958908ef6SLaurent Vivier     TaskState *ts = cpu->opaque;
74058908ef6SLaurent Vivier     struct image_info *info = ts->info;
74158908ef6SLaurent Vivier     int i;
74258908ef6SLaurent Vivier 
743*0c1bbedcSStefan Markovic     struct mode_req {
744*0c1bbedcSStefan Markovic         bool single;
745*0c1bbedcSStefan Markovic         bool soft;
746*0c1bbedcSStefan Markovic         bool fr1;
747*0c1bbedcSStefan Markovic         bool frdefault;
748*0c1bbedcSStefan Markovic         bool fre;
749*0c1bbedcSStefan Markovic     };
750*0c1bbedcSStefan Markovic 
751*0c1bbedcSStefan Markovic     static const struct mode_req fpu_reqs[] = {
752*0c1bbedcSStefan Markovic         [MIPS_ABI_FP_ANY]    = { true,  true,  true,  true,  true  },
753*0c1bbedcSStefan Markovic         [MIPS_ABI_FP_DOUBLE] = { false, false, false, true,  true  },
754*0c1bbedcSStefan Markovic         [MIPS_ABI_FP_SINGLE] = { true,  false, false, false, false },
755*0c1bbedcSStefan Markovic         [MIPS_ABI_FP_SOFT]   = { false, true,  false, false, false },
756*0c1bbedcSStefan Markovic         [MIPS_ABI_FP_OLD_64] = { false, false, false, false, false },
757*0c1bbedcSStefan Markovic         [MIPS_ABI_FP_XX]     = { false, false, true,  true,  true  },
758*0c1bbedcSStefan Markovic         [MIPS_ABI_FP_64]     = { false, false, true,  false, false },
759*0c1bbedcSStefan Markovic         [MIPS_ABI_FP_64A]    = { false, false, true,  false, true  }
760*0c1bbedcSStefan Markovic     };
761*0c1bbedcSStefan Markovic 
762*0c1bbedcSStefan Markovic     /*
763*0c1bbedcSStefan Markovic      * Mode requirements when .MIPS.abiflags is not present in the ELF.
764*0c1bbedcSStefan Markovic      * Not present means that everything is acceptable except FR1.
765*0c1bbedcSStefan Markovic      */
766*0c1bbedcSStefan Markovic     static struct mode_req none_req = { true, true, false, true, true };
767*0c1bbedcSStefan Markovic 
768*0c1bbedcSStefan Markovic     struct mode_req prog_req;
769*0c1bbedcSStefan Markovic     struct mode_req interp_req;
770*0c1bbedcSStefan Markovic 
77158908ef6SLaurent Vivier     for(i = 0; i < 32; i++) {
77258908ef6SLaurent Vivier         env->active_tc.gpr[i] = regs->regs[i];
77358908ef6SLaurent Vivier     }
77458908ef6SLaurent Vivier     env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1;
77558908ef6SLaurent Vivier     if (regs->cp0_epc & 1) {
77658908ef6SLaurent Vivier         env->hflags |= MIPS_HFLAG_M16;
77758908ef6SLaurent Vivier     }
778*0c1bbedcSStefan Markovic 
779*0c1bbedcSStefan Markovic #ifdef TARGET_ABI_MIPSO32
780*0c1bbedcSStefan Markovic # define MAX_FP_ABI MIPS_ABI_FP_64A
781*0c1bbedcSStefan Markovic #else
782*0c1bbedcSStefan Markovic # define MAX_FP_ABI MIPS_ABI_FP_SOFT
783*0c1bbedcSStefan Markovic #endif
784*0c1bbedcSStefan Markovic      if ((info->fp_abi > MAX_FP_ABI && info->fp_abi != MIPS_ABI_FP_UNKNOWN)
785*0c1bbedcSStefan Markovic         || (info->interp_fp_abi > MAX_FP_ABI &&
786*0c1bbedcSStefan Markovic             info->interp_fp_abi != MIPS_ABI_FP_UNKNOWN)) {
787*0c1bbedcSStefan Markovic         fprintf(stderr, "qemu: Unexpected FPU mode\n");
788*0c1bbedcSStefan Markovic         exit(1);
789*0c1bbedcSStefan Markovic     }
790*0c1bbedcSStefan Markovic 
791*0c1bbedcSStefan Markovic     prog_req = (info->fp_abi == MIPS_ABI_FP_UNKNOWN) ? none_req
792*0c1bbedcSStefan Markovic                                             : fpu_reqs[info->fp_abi];
793*0c1bbedcSStefan Markovic     interp_req = (info->interp_fp_abi == MIPS_ABI_FP_UNKNOWN) ? none_req
794*0c1bbedcSStefan Markovic                                             : fpu_reqs[info->interp_fp_abi];
795*0c1bbedcSStefan Markovic 
796*0c1bbedcSStefan Markovic     prog_req.single &= interp_req.single;
797*0c1bbedcSStefan Markovic     prog_req.soft &= interp_req.soft;
798*0c1bbedcSStefan Markovic     prog_req.fr1 &= interp_req.fr1;
799*0c1bbedcSStefan Markovic     prog_req.frdefault &= interp_req.frdefault;
800*0c1bbedcSStefan Markovic     prog_req.fre &= interp_req.fre;
801*0c1bbedcSStefan Markovic 
802*0c1bbedcSStefan Markovic     bool cpu_has_mips_r2_r6 = env->insn_flags & ISA_MIPS32R2 ||
803*0c1bbedcSStefan Markovic                               env->insn_flags & ISA_MIPS64R2 ||
804*0c1bbedcSStefan Markovic                               env->insn_flags & ISA_MIPS32R6 ||
805*0c1bbedcSStefan Markovic                               env->insn_flags & ISA_MIPS64R6;
806*0c1bbedcSStefan Markovic 
807*0c1bbedcSStefan Markovic     if (prog_req.fre && !prog_req.frdefault && !prog_req.fr1) {
808*0c1bbedcSStefan Markovic         env->CP0_Config5 |= (1 << CP0C5_FRE);
809*0c1bbedcSStefan Markovic         if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
810*0c1bbedcSStefan Markovic             env->hflags |= MIPS_HFLAG_FRE;
811*0c1bbedcSStefan Markovic         }
812*0c1bbedcSStefan Markovic     } else if ((prog_req.fr1 && prog_req.frdefault) ||
813*0c1bbedcSStefan Markovic          (prog_req.single && !prog_req.frdefault)) {
814*0c1bbedcSStefan Markovic         if ((env->active_fpu.fcr0 & (1 << FCR0_F64)
815*0c1bbedcSStefan Markovic             && cpu_has_mips_r2_r6) || prog_req.fr1) {
816*0c1bbedcSStefan Markovic             env->CP0_Status |= (1 << CP0St_FR);
817*0c1bbedcSStefan Markovic             env->hflags |= MIPS_HFLAG_F64;
818*0c1bbedcSStefan Markovic         }
819*0c1bbedcSStefan Markovic     } else  if (!prog_req.fre && !prog_req.frdefault &&
820*0c1bbedcSStefan Markovic           !prog_req.fr1 && !prog_req.single && !prog_req.soft) {
821*0c1bbedcSStefan Markovic         fprintf(stderr, "qemu: Can't find a matching FPU mode\n");
822*0c1bbedcSStefan Markovic         exit(1);
823*0c1bbedcSStefan Markovic     }
824*0c1bbedcSStefan Markovic 
825722ac96cSAleksandar Markovic     if (env->insn_flags & ISA_NANOMIPS32) {
826722ac96cSAleksandar Markovic         return;
827722ac96cSAleksandar Markovic     }
82858908ef6SLaurent Vivier     if (((info->elf_flags & EF_MIPS_NAN2008) != 0) !=
82958908ef6SLaurent Vivier         ((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) != 0)) {
83058908ef6SLaurent Vivier         if ((env->active_fpu.fcr31_rw_bitmask &
83158908ef6SLaurent Vivier               (1 << FCR31_NAN2008)) == 0) {
83258908ef6SLaurent Vivier             fprintf(stderr, "ELF binary's NaN mode not supported by CPU\n");
83358908ef6SLaurent Vivier             exit(1);
83458908ef6SLaurent Vivier         }
83558908ef6SLaurent Vivier         if ((info->elf_flags & EF_MIPS_NAN2008) != 0) {
83658908ef6SLaurent Vivier             env->active_fpu.fcr31 |= (1 << FCR31_NAN2008);
83758908ef6SLaurent Vivier         } else {
83858908ef6SLaurent Vivier             env->active_fpu.fcr31 &= ~(1 << FCR31_NAN2008);
83958908ef6SLaurent Vivier         }
84058908ef6SLaurent Vivier         restore_snan_bit_mode(env);
84158908ef6SLaurent Vivier     }
842cd71c089SLaurent Vivier }
843