xref: /qemu/linux-user/mips/cpu_loop.c (revision 29a0af61)
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 /* Break codes */
39658908ef6SLaurent Vivier enum {
39758908ef6SLaurent Vivier     BRK_OVERFLOW = 6,
39858908ef6SLaurent Vivier     BRK_DIVZERO = 7
39958908ef6SLaurent Vivier };
40058908ef6SLaurent Vivier 
40158908ef6SLaurent Vivier static int do_break(CPUMIPSState *env, target_siginfo_t *info,
40258908ef6SLaurent Vivier                     unsigned int code)
40358908ef6SLaurent Vivier {
40458908ef6SLaurent Vivier     int ret = -1;
40558908ef6SLaurent Vivier 
40658908ef6SLaurent Vivier     switch (code) {
40758908ef6SLaurent Vivier     case BRK_OVERFLOW:
40858908ef6SLaurent Vivier     case BRK_DIVZERO:
40958908ef6SLaurent Vivier         info->si_signo = TARGET_SIGFPE;
41058908ef6SLaurent Vivier         info->si_errno = 0;
41158908ef6SLaurent Vivier         info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV;
41258908ef6SLaurent Vivier         queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info);
41358908ef6SLaurent Vivier         ret = 0;
41458908ef6SLaurent Vivier         break;
41558908ef6SLaurent Vivier     default:
41658908ef6SLaurent Vivier         info->si_signo = TARGET_SIGTRAP;
41758908ef6SLaurent Vivier         info->si_errno = 0;
41858908ef6SLaurent Vivier         queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info);
41958908ef6SLaurent Vivier         ret = 0;
42058908ef6SLaurent Vivier         break;
42158908ef6SLaurent Vivier     }
42258908ef6SLaurent Vivier 
42358908ef6SLaurent Vivier     return ret;
42458908ef6SLaurent Vivier }
42558908ef6SLaurent Vivier 
42658908ef6SLaurent Vivier void cpu_loop(CPUMIPSState *env)
42758908ef6SLaurent Vivier {
42858908ef6SLaurent Vivier     CPUState *cs = CPU(mips_env_get_cpu(env));
42958908ef6SLaurent Vivier     target_siginfo_t info;
43058908ef6SLaurent Vivier     int trapnr;
43158908ef6SLaurent Vivier     abi_long ret;
43258908ef6SLaurent Vivier # ifdef TARGET_ABI_MIPSO32
43358908ef6SLaurent Vivier     unsigned int syscall_num;
43458908ef6SLaurent Vivier # endif
43558908ef6SLaurent Vivier 
43658908ef6SLaurent Vivier     for(;;) {
43758908ef6SLaurent Vivier         cpu_exec_start(cs);
43858908ef6SLaurent Vivier         trapnr = cpu_exec(cs);
43958908ef6SLaurent Vivier         cpu_exec_end(cs);
44058908ef6SLaurent Vivier         process_queued_cpu_work(cs);
44158908ef6SLaurent Vivier 
44258908ef6SLaurent Vivier         switch(trapnr) {
44358908ef6SLaurent Vivier         case EXCP_SYSCALL:
44458908ef6SLaurent Vivier             env->active_tc.PC += 4;
44558908ef6SLaurent Vivier # ifdef TARGET_ABI_MIPSO32
44658908ef6SLaurent Vivier             syscall_num = env->active_tc.gpr[2] - 4000;
44758908ef6SLaurent Vivier             if (syscall_num >= sizeof(mips_syscall_args)) {
44858908ef6SLaurent Vivier                 ret = -TARGET_ENOSYS;
44958908ef6SLaurent Vivier             } else {
45058908ef6SLaurent Vivier                 int nb_args;
45158908ef6SLaurent Vivier                 abi_ulong sp_reg;
45258908ef6SLaurent Vivier                 abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
45358908ef6SLaurent Vivier 
45458908ef6SLaurent Vivier                 nb_args = mips_syscall_args[syscall_num];
45558908ef6SLaurent Vivier                 sp_reg = env->active_tc.gpr[29];
45658908ef6SLaurent Vivier                 switch (nb_args) {
45758908ef6SLaurent Vivier                 /* these arguments are taken from the stack */
45858908ef6SLaurent Vivier                 case 8:
45958908ef6SLaurent Vivier                     if ((ret = get_user_ual(arg8, sp_reg + 28)) != 0) {
46058908ef6SLaurent Vivier                         goto done_syscall;
46158908ef6SLaurent Vivier                     }
46258908ef6SLaurent Vivier                 case 7:
46358908ef6SLaurent Vivier                     if ((ret = get_user_ual(arg7, sp_reg + 24)) != 0) {
46458908ef6SLaurent Vivier                         goto done_syscall;
46558908ef6SLaurent Vivier                     }
46658908ef6SLaurent Vivier                 case 6:
46758908ef6SLaurent Vivier                     if ((ret = get_user_ual(arg6, sp_reg + 20)) != 0) {
46858908ef6SLaurent Vivier                         goto done_syscall;
46958908ef6SLaurent Vivier                     }
47058908ef6SLaurent Vivier                 case 5:
47158908ef6SLaurent Vivier                     if ((ret = get_user_ual(arg5, sp_reg + 16)) != 0) {
47258908ef6SLaurent Vivier                         goto done_syscall;
47358908ef6SLaurent Vivier                     }
47458908ef6SLaurent Vivier                 default:
47558908ef6SLaurent Vivier                     break;
47658908ef6SLaurent Vivier                 }
47758908ef6SLaurent Vivier                 ret = do_syscall(env, env->active_tc.gpr[2],
47858908ef6SLaurent Vivier                                  env->active_tc.gpr[4],
47958908ef6SLaurent Vivier                                  env->active_tc.gpr[5],
48058908ef6SLaurent Vivier                                  env->active_tc.gpr[6],
48158908ef6SLaurent Vivier                                  env->active_tc.gpr[7],
48258908ef6SLaurent Vivier                                  arg5, arg6, arg7, arg8);
48358908ef6SLaurent Vivier             }
48458908ef6SLaurent Vivier done_syscall:
48558908ef6SLaurent Vivier # else
48658908ef6SLaurent Vivier             ret = do_syscall(env, env->active_tc.gpr[2],
48758908ef6SLaurent Vivier                              env->active_tc.gpr[4], env->active_tc.gpr[5],
48858908ef6SLaurent Vivier                              env->active_tc.gpr[6], env->active_tc.gpr[7],
48958908ef6SLaurent Vivier                              env->active_tc.gpr[8], env->active_tc.gpr[9],
49058908ef6SLaurent Vivier                              env->active_tc.gpr[10], env->active_tc.gpr[11]);
49158908ef6SLaurent Vivier # endif /* O32 */
49258908ef6SLaurent Vivier             if (ret == -TARGET_ERESTARTSYS) {
49358908ef6SLaurent Vivier                 env->active_tc.PC -= 4;
49458908ef6SLaurent Vivier                 break;
49558908ef6SLaurent Vivier             }
49658908ef6SLaurent Vivier             if (ret == -TARGET_QEMU_ESIGRETURN) {
49758908ef6SLaurent Vivier                 /* Returning from a successful sigreturn syscall.
49858908ef6SLaurent Vivier                    Avoid clobbering register state.  */
49958908ef6SLaurent Vivier                 break;
50058908ef6SLaurent Vivier             }
50158908ef6SLaurent Vivier             if ((abi_ulong)ret >= (abi_ulong)-1133) {
50258908ef6SLaurent Vivier                 env->active_tc.gpr[7] = 1; /* error flag */
50358908ef6SLaurent Vivier                 ret = -ret;
50458908ef6SLaurent Vivier             } else {
50558908ef6SLaurent Vivier                 env->active_tc.gpr[7] = 0; /* error flag */
50658908ef6SLaurent Vivier             }
50758908ef6SLaurent Vivier             env->active_tc.gpr[2] = ret;
50858908ef6SLaurent Vivier             break;
50958908ef6SLaurent Vivier         case EXCP_TLBL:
51058908ef6SLaurent Vivier         case EXCP_TLBS:
51158908ef6SLaurent Vivier         case EXCP_AdEL:
51258908ef6SLaurent Vivier         case EXCP_AdES:
51358908ef6SLaurent Vivier             info.si_signo = TARGET_SIGSEGV;
51458908ef6SLaurent Vivier             info.si_errno = 0;
51558908ef6SLaurent Vivier             /* XXX: check env->error_code */
51658908ef6SLaurent Vivier             info.si_code = TARGET_SEGV_MAPERR;
51758908ef6SLaurent Vivier             info._sifields._sigfault._addr = env->CP0_BadVAddr;
51858908ef6SLaurent Vivier             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
51958908ef6SLaurent Vivier             break;
52058908ef6SLaurent Vivier         case EXCP_CpU:
52158908ef6SLaurent Vivier         case EXCP_RI:
52258908ef6SLaurent Vivier             info.si_signo = TARGET_SIGILL;
52358908ef6SLaurent Vivier             info.si_errno = 0;
52458908ef6SLaurent Vivier             info.si_code = 0;
52558908ef6SLaurent Vivier             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
52658908ef6SLaurent Vivier             break;
52758908ef6SLaurent Vivier         case EXCP_INTERRUPT:
52858908ef6SLaurent Vivier             /* just indicate that signals should be handled asap */
52958908ef6SLaurent Vivier             break;
53058908ef6SLaurent Vivier         case EXCP_DEBUG:
531b10089a1SPeter Maydell             info.si_signo = TARGET_SIGTRAP;
53258908ef6SLaurent Vivier             info.si_errno = 0;
53358908ef6SLaurent Vivier             info.si_code = TARGET_TRAP_BRKPT;
53458908ef6SLaurent Vivier             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
53558908ef6SLaurent Vivier             break;
53658908ef6SLaurent Vivier         case EXCP_DSPDIS:
53758908ef6SLaurent Vivier             info.si_signo = TARGET_SIGILL;
53858908ef6SLaurent Vivier             info.si_errno = 0;
53958908ef6SLaurent Vivier             info.si_code = TARGET_ILL_ILLOPC;
54058908ef6SLaurent Vivier             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
54158908ef6SLaurent Vivier             break;
54258908ef6SLaurent Vivier         /* The code below was inspired by the MIPS Linux kernel trap
54358908ef6SLaurent Vivier          * handling code in arch/mips/kernel/traps.c.
54458908ef6SLaurent Vivier          */
54558908ef6SLaurent Vivier         case EXCP_BREAK:
54658908ef6SLaurent Vivier             {
54758908ef6SLaurent Vivier                 abi_ulong trap_instr;
54858908ef6SLaurent Vivier                 unsigned int code;
54958908ef6SLaurent Vivier 
55058908ef6SLaurent Vivier                 if (env->hflags & MIPS_HFLAG_M16) {
55158908ef6SLaurent Vivier                     if (env->insn_flags & ASE_MICROMIPS) {
55258908ef6SLaurent Vivier                         /* microMIPS mode */
55358908ef6SLaurent Vivier                         ret = get_user_u16(trap_instr, env->active_tc.PC);
55458908ef6SLaurent Vivier                         if (ret != 0) {
55558908ef6SLaurent Vivier                             goto error;
55658908ef6SLaurent Vivier                         }
55758908ef6SLaurent Vivier 
55858908ef6SLaurent Vivier                         if ((trap_instr >> 10) == 0x11) {
55958908ef6SLaurent Vivier                             /* 16-bit instruction */
56058908ef6SLaurent Vivier                             code = trap_instr & 0xf;
56158908ef6SLaurent Vivier                         } else {
56258908ef6SLaurent Vivier                             /* 32-bit instruction */
56358908ef6SLaurent Vivier                             abi_ulong instr_lo;
56458908ef6SLaurent Vivier 
56558908ef6SLaurent Vivier                             ret = get_user_u16(instr_lo,
56658908ef6SLaurent Vivier                                                env->active_tc.PC + 2);
56758908ef6SLaurent Vivier                             if (ret != 0) {
56858908ef6SLaurent Vivier                                 goto error;
56958908ef6SLaurent Vivier                             }
57058908ef6SLaurent Vivier                             trap_instr = (trap_instr << 16) | instr_lo;
57158908ef6SLaurent Vivier                             code = ((trap_instr >> 6) & ((1 << 20) - 1));
57258908ef6SLaurent Vivier                             /* Unfortunately, microMIPS also suffers from
57358908ef6SLaurent Vivier                                the old assembler bug...  */
57458908ef6SLaurent Vivier                             if (code >= (1 << 10)) {
57558908ef6SLaurent Vivier                                 code >>= 10;
57658908ef6SLaurent Vivier                             }
57758908ef6SLaurent Vivier                         }
57858908ef6SLaurent Vivier                     } else {
57958908ef6SLaurent Vivier                         /* MIPS16e mode */
58058908ef6SLaurent Vivier                         ret = get_user_u16(trap_instr, env->active_tc.PC);
58158908ef6SLaurent Vivier                         if (ret != 0) {
58258908ef6SLaurent Vivier                             goto error;
58358908ef6SLaurent Vivier                         }
58458908ef6SLaurent Vivier                         code = (trap_instr >> 6) & 0x3f;
58558908ef6SLaurent Vivier                     }
58658908ef6SLaurent Vivier                 } else {
58758908ef6SLaurent Vivier                     ret = get_user_u32(trap_instr, env->active_tc.PC);
58858908ef6SLaurent Vivier                     if (ret != 0) {
58958908ef6SLaurent Vivier                         goto error;
59058908ef6SLaurent Vivier                     }
59158908ef6SLaurent Vivier 
59258908ef6SLaurent Vivier                     /* As described in the original Linux kernel code, the
59358908ef6SLaurent Vivier                      * below checks on 'code' are to work around an old
59458908ef6SLaurent Vivier                      * assembly bug.
59558908ef6SLaurent Vivier                      */
59658908ef6SLaurent Vivier                     code = ((trap_instr >> 6) & ((1 << 20) - 1));
59758908ef6SLaurent Vivier                     if (code >= (1 << 10)) {
59858908ef6SLaurent Vivier                         code >>= 10;
59958908ef6SLaurent Vivier                     }
60058908ef6SLaurent Vivier                 }
60158908ef6SLaurent Vivier 
60258908ef6SLaurent Vivier                 if (do_break(env, &info, code) != 0) {
60358908ef6SLaurent Vivier                     goto error;
60458908ef6SLaurent Vivier                 }
60558908ef6SLaurent Vivier             }
60658908ef6SLaurent Vivier             break;
60758908ef6SLaurent Vivier         case EXCP_TRAP:
60858908ef6SLaurent Vivier             {
60958908ef6SLaurent Vivier                 abi_ulong trap_instr;
61058908ef6SLaurent Vivier                 unsigned int code = 0;
61158908ef6SLaurent Vivier 
61258908ef6SLaurent Vivier                 if (env->hflags & MIPS_HFLAG_M16) {
61358908ef6SLaurent Vivier                     /* microMIPS mode */
61458908ef6SLaurent Vivier                     abi_ulong instr[2];
61558908ef6SLaurent Vivier 
61658908ef6SLaurent Vivier                     ret = get_user_u16(instr[0], env->active_tc.PC) ||
61758908ef6SLaurent Vivier                           get_user_u16(instr[1], env->active_tc.PC + 2);
61858908ef6SLaurent Vivier 
61958908ef6SLaurent Vivier                     trap_instr = (instr[0] << 16) | instr[1];
62058908ef6SLaurent Vivier                 } else {
62158908ef6SLaurent Vivier                     ret = get_user_u32(trap_instr, env->active_tc.PC);
62258908ef6SLaurent Vivier                 }
62358908ef6SLaurent Vivier 
62458908ef6SLaurent Vivier                 if (ret != 0) {
62558908ef6SLaurent Vivier                     goto error;
62658908ef6SLaurent Vivier                 }
62758908ef6SLaurent Vivier 
62858908ef6SLaurent Vivier                 /* The immediate versions don't provide a code.  */
62958908ef6SLaurent Vivier                 if (!(trap_instr & 0xFC000000)) {
63058908ef6SLaurent Vivier                     if (env->hflags & MIPS_HFLAG_M16) {
63158908ef6SLaurent Vivier                         /* microMIPS mode */
63258908ef6SLaurent Vivier                         code = ((trap_instr >> 12) & ((1 << 4) - 1));
63358908ef6SLaurent Vivier                     } else {
63458908ef6SLaurent Vivier                         code = ((trap_instr >> 6) & ((1 << 10) - 1));
63558908ef6SLaurent Vivier                     }
63658908ef6SLaurent Vivier                 }
63758908ef6SLaurent Vivier 
63858908ef6SLaurent Vivier                 if (do_break(env, &info, code) != 0) {
63958908ef6SLaurent Vivier                     goto error;
64058908ef6SLaurent Vivier                 }
64158908ef6SLaurent Vivier             }
64258908ef6SLaurent Vivier             break;
64358908ef6SLaurent Vivier         case EXCP_ATOMIC:
64458908ef6SLaurent Vivier             cpu_exec_step_atomic(cs);
64558908ef6SLaurent Vivier             break;
64658908ef6SLaurent Vivier         default:
64758908ef6SLaurent Vivier error:
64858908ef6SLaurent Vivier             EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
64958908ef6SLaurent Vivier             abort();
65058908ef6SLaurent Vivier         }
65158908ef6SLaurent Vivier         process_pending_signals(env);
65258908ef6SLaurent Vivier     }
65358908ef6SLaurent Vivier }
654cd71c089SLaurent Vivier 
655cd71c089SLaurent Vivier void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
656cd71c089SLaurent Vivier {
657*29a0af61SRichard Henderson     CPUState *cpu = env_cpu(env);
65858908ef6SLaurent Vivier     TaskState *ts = cpu->opaque;
65958908ef6SLaurent Vivier     struct image_info *info = ts->info;
66058908ef6SLaurent Vivier     int i;
66158908ef6SLaurent Vivier 
6620c1bbedcSStefan Markovic     struct mode_req {
6630c1bbedcSStefan Markovic         bool single;
6640c1bbedcSStefan Markovic         bool soft;
6650c1bbedcSStefan Markovic         bool fr1;
6660c1bbedcSStefan Markovic         bool frdefault;
6670c1bbedcSStefan Markovic         bool fre;
6680c1bbedcSStefan Markovic     };
6690c1bbedcSStefan Markovic 
6700c1bbedcSStefan Markovic     static const struct mode_req fpu_reqs[] = {
6710c1bbedcSStefan Markovic         [MIPS_ABI_FP_ANY]    = { true,  true,  true,  true,  true  },
6720c1bbedcSStefan Markovic         [MIPS_ABI_FP_DOUBLE] = { false, false, false, true,  true  },
6730c1bbedcSStefan Markovic         [MIPS_ABI_FP_SINGLE] = { true,  false, false, false, false },
6740c1bbedcSStefan Markovic         [MIPS_ABI_FP_SOFT]   = { false, true,  false, false, false },
6750c1bbedcSStefan Markovic         [MIPS_ABI_FP_OLD_64] = { false, false, false, false, false },
6760c1bbedcSStefan Markovic         [MIPS_ABI_FP_XX]     = { false, false, true,  true,  true  },
6770c1bbedcSStefan Markovic         [MIPS_ABI_FP_64]     = { false, false, true,  false, false },
6780c1bbedcSStefan Markovic         [MIPS_ABI_FP_64A]    = { false, false, true,  false, true  }
6790c1bbedcSStefan Markovic     };
6800c1bbedcSStefan Markovic 
6810c1bbedcSStefan Markovic     /*
6820c1bbedcSStefan Markovic      * Mode requirements when .MIPS.abiflags is not present in the ELF.
6830c1bbedcSStefan Markovic      * Not present means that everything is acceptable except FR1.
6840c1bbedcSStefan Markovic      */
6850c1bbedcSStefan Markovic     static struct mode_req none_req = { true, true, false, true, true };
6860c1bbedcSStefan Markovic 
6870c1bbedcSStefan Markovic     struct mode_req prog_req;
6880c1bbedcSStefan Markovic     struct mode_req interp_req;
6890c1bbedcSStefan Markovic 
69058908ef6SLaurent Vivier     for(i = 0; i < 32; i++) {
69158908ef6SLaurent Vivier         env->active_tc.gpr[i] = regs->regs[i];
69258908ef6SLaurent Vivier     }
69358908ef6SLaurent Vivier     env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1;
69458908ef6SLaurent Vivier     if (regs->cp0_epc & 1) {
69558908ef6SLaurent Vivier         env->hflags |= MIPS_HFLAG_M16;
69658908ef6SLaurent Vivier     }
6970c1bbedcSStefan Markovic 
6980c1bbedcSStefan Markovic #ifdef TARGET_ABI_MIPSO32
6990c1bbedcSStefan Markovic # define MAX_FP_ABI MIPS_ABI_FP_64A
7000c1bbedcSStefan Markovic #else
7010c1bbedcSStefan Markovic # define MAX_FP_ABI MIPS_ABI_FP_SOFT
7020c1bbedcSStefan Markovic #endif
7030c1bbedcSStefan Markovic      if ((info->fp_abi > MAX_FP_ABI && info->fp_abi != MIPS_ABI_FP_UNKNOWN)
7040c1bbedcSStefan Markovic         || (info->interp_fp_abi > MAX_FP_ABI &&
7050c1bbedcSStefan Markovic             info->interp_fp_abi != MIPS_ABI_FP_UNKNOWN)) {
7060c1bbedcSStefan Markovic         fprintf(stderr, "qemu: Unexpected FPU mode\n");
7070c1bbedcSStefan Markovic         exit(1);
7080c1bbedcSStefan Markovic     }
7090c1bbedcSStefan Markovic 
7100c1bbedcSStefan Markovic     prog_req = (info->fp_abi == MIPS_ABI_FP_UNKNOWN) ? none_req
7110c1bbedcSStefan Markovic                                             : fpu_reqs[info->fp_abi];
7120c1bbedcSStefan Markovic     interp_req = (info->interp_fp_abi == MIPS_ABI_FP_UNKNOWN) ? none_req
7130c1bbedcSStefan Markovic                                             : fpu_reqs[info->interp_fp_abi];
7140c1bbedcSStefan Markovic 
7150c1bbedcSStefan Markovic     prog_req.single &= interp_req.single;
7160c1bbedcSStefan Markovic     prog_req.soft &= interp_req.soft;
7170c1bbedcSStefan Markovic     prog_req.fr1 &= interp_req.fr1;
7180c1bbedcSStefan Markovic     prog_req.frdefault &= interp_req.frdefault;
7190c1bbedcSStefan Markovic     prog_req.fre &= interp_req.fre;
7200c1bbedcSStefan Markovic 
7210c1bbedcSStefan Markovic     bool cpu_has_mips_r2_r6 = env->insn_flags & ISA_MIPS32R2 ||
7220c1bbedcSStefan Markovic                               env->insn_flags & ISA_MIPS64R2 ||
7230c1bbedcSStefan Markovic                               env->insn_flags & ISA_MIPS32R6 ||
7240c1bbedcSStefan Markovic                               env->insn_flags & ISA_MIPS64R6;
7250c1bbedcSStefan Markovic 
7260c1bbedcSStefan Markovic     if (prog_req.fre && !prog_req.frdefault && !prog_req.fr1) {
7270c1bbedcSStefan Markovic         env->CP0_Config5 |= (1 << CP0C5_FRE);
7280c1bbedcSStefan Markovic         if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
7290c1bbedcSStefan Markovic             env->hflags |= MIPS_HFLAG_FRE;
7300c1bbedcSStefan Markovic         }
7310c1bbedcSStefan Markovic     } else if ((prog_req.fr1 && prog_req.frdefault) ||
7320c1bbedcSStefan Markovic          (prog_req.single && !prog_req.frdefault)) {
7330c1bbedcSStefan Markovic         if ((env->active_fpu.fcr0 & (1 << FCR0_F64)
7340c1bbedcSStefan Markovic             && cpu_has_mips_r2_r6) || prog_req.fr1) {
7350c1bbedcSStefan Markovic             env->CP0_Status |= (1 << CP0St_FR);
7360c1bbedcSStefan Markovic             env->hflags |= MIPS_HFLAG_F64;
7370c1bbedcSStefan Markovic         }
7380c1bbedcSStefan Markovic     } else  if (!prog_req.fre && !prog_req.frdefault &&
7390c1bbedcSStefan Markovic           !prog_req.fr1 && !prog_req.single && !prog_req.soft) {
7400c1bbedcSStefan Markovic         fprintf(stderr, "qemu: Can't find a matching FPU mode\n");
7410c1bbedcSStefan Markovic         exit(1);
7420c1bbedcSStefan Markovic     }
7430c1bbedcSStefan Markovic 
744722ac96cSAleksandar Markovic     if (env->insn_flags & ISA_NANOMIPS32) {
745722ac96cSAleksandar Markovic         return;
746722ac96cSAleksandar Markovic     }
74758908ef6SLaurent Vivier     if (((info->elf_flags & EF_MIPS_NAN2008) != 0) !=
74858908ef6SLaurent Vivier         ((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) != 0)) {
74958908ef6SLaurent Vivier         if ((env->active_fpu.fcr31_rw_bitmask &
75058908ef6SLaurent Vivier               (1 << FCR31_NAN2008)) == 0) {
75158908ef6SLaurent Vivier             fprintf(stderr, "ELF binary's NaN mode not supported by CPU\n");
75258908ef6SLaurent Vivier             exit(1);
75358908ef6SLaurent Vivier         }
75458908ef6SLaurent Vivier         if ((info->elf_flags & EF_MIPS_NAN2008) != 0) {
75558908ef6SLaurent Vivier             env->active_fpu.fcr31 |= (1 << FCR31_NAN2008);
75658908ef6SLaurent Vivier         } else {
75758908ef6SLaurent Vivier             env->active_fpu.fcr31 &= ~(1 << FCR31_NAN2008);
75858908ef6SLaurent Vivier         }
75958908ef6SLaurent Vivier         restore_snan_bit_mode(env);
76058908ef6SLaurent Vivier     }
761cd71c089SLaurent Vivier }
762