linux-user pull request 20220111

siginfo_t cleanup
 more prtctl() update
 target_struct.h cleanup
 -----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEEzS913cjjpNwuT1Fz8ww4vT8vvjwFAmHd3/QSHGxhdXJlbnRA
 dml2aWVyLmV1AAoJEPMMOL0/L748Dd8P/17YoylgR93nPL//v1hbd2lpENhhany/
 Oz3YDxETLmPPaMZtKCiMiZ5OtoojvD5PS4SrRDaaP+hfF+KdDIcLpIjMje1jonf+
 H9IDYUlDRym4ucYvK+ZwPzz/+rMq/iaYT8ih0XvPKjEmbewtWeuIFgmCo8a6fvxg
 Aci+r4NxfjUeN7nN8oltxUx4DbS1uEJEm+HDCxFxEh26fN0ab+0wiBl93swQ71MG
 OoHG8KNJTiLre4TBtqJCbVSDqTIq+aorwus9Fh4qwCsqZA0TesRlAcq+TjoSbc2m
 eAr5kcarxVhI/qLkRlq9epPn/GlULdzlU1YOuM5bOpdOwJlmeiQTlDKUG2CtQ4Ym
 kvzxkMNVyb5jfUzYHt0oJHPnHXGGCXNSVUQ5rL51igOQWCn/IJ89kmqhcyObPrTZ
 eFkjplkl+BvhwCJl1SgbMaTJxeI9iwR5jsZwwikTlNmyy2twh93lEPmWyJezYsln
 A8QxNOWBgSvitPriZqq5nYgTQ/uARtkMhrNjwKYF5NvWUF2Z3ps1S5IgRwk2W2r+
 LFldwPmDeUkxsTXtVE7IWGqFFZG1ttQ5wyfNq82Ft7Cdem8bhOmQ0fxQqa7YmUrU
 0EdNAQ/X9SIhjswy5+woArBTbybefDS3cY9ZUM3D/AOWe+gyFNktQ2UemDWXaPVf
 Xl5TF8k1Alko
 =/Z6c
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/lvivier-gitlab/tags/linux-user-for-7.0-pull-request' into staging

linux-user pull request 20220111
siginfo_t cleanup
more prtctl() update
target_struct.h cleanup

# gpg: Signature made Tue 11 Jan 2022 19:52:20 GMT
# gpg:                using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C
# gpg:                issuer "laurent@vivier.eu"
# gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full]
# gpg:                 aka "Laurent Vivier <laurent@vivier.eu>" [full]
# gpg:                 aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full]
# Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F  5173 F30C 38BD 3F2F BE3C

* remotes/lvivier-gitlab/tags/linux-user-for-7.0-pull-request: (30 commits)
  linux-user: Implement capability prctls
  linux-user: Implement PR_SET_PDEATHSIG
  linux-user: Map signal number in PR_GET_PDEATHSIG
  linux-user: Do not special-case NULL for PR_GET_PDEATHSIG
  linux-user: Move target_struct.h generic definitions to generic/
  linux-user/arm: Move target_oabi_flock64 out of target_structs.h
  linux-user/xtensa: Use force_sig_fault
  linux-user/sparc: Use force_sig_fault
  linux-user/sh4: Use force_sig_fault
  linux-user/s390x: Use force_sig_fault
  linux-user/riscv: Use force_sig_fault
  linux-user/ppc: Use force_sig_fault
  linux-user/openrisc: Use force_sig_fault
  target/mips: Extract trap code into env->error_code
  target/mips: Extract break code into env->error_code
  linux-user/mips: Use force_sig_fault
  linux-user/mips: Improve do_break
  linux-user/microblaze: Fix SIGFPE si_codes
  linux-user/microblaze: Use force_sig_fault
  linux-user/m68k: Use force_sig_fault
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2022-01-12 11:51:47 +00:00
commit 91f5f7a5df
34 changed files with 318 additions and 1161 deletions

View file

@ -1,58 +1 @@
/* #include "../generic/target_structs.h"
* ARM AArch64 specific structures for linux-user
*
* Copyright (c) 2013 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef AARCH64_TARGET_STRUCTS_H
#define AARCH64_TARGET_STRUCTS_H
struct target_ipc_perm {
abi_int __key; /* Key. */
abi_uint uid; /* Owner's user ID. */
abi_uint gid; /* Owner's group ID. */
abi_uint cuid; /* Creator's user ID. */
abi_uint cgid; /* Creator's group ID. */
abi_ushort mode; /* Read/write permission. */
abi_ushort __pad1;
abi_ushort __seq; /* Sequence number. */
abi_ushort __pad2;
abi_ulong __unused1;
abi_ulong __unused2;
};
struct target_shmid_ds {
struct target_ipc_perm shm_perm; /* operation permission struct */
abi_long shm_segsz; /* size of segment in bytes */
abi_ulong shm_atime; /* time of last shmat() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused1;
#endif
abi_ulong shm_dtime; /* time of last shmdt() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused2;
#endif
abi_ulong shm_ctime; /* time of last change by shmctl() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused3;
#endif
abi_int shm_cpid; /* pid of creator */
abi_int shm_lpid; /* pid of last shmop */
abi_ulong shm_nattch; /* number of current attaches */
abi_ulong __unused4;
abi_ulong __unused5;
};
#endif

View file

@ -27,8 +27,7 @@
void cpu_loop(CPUAlphaState *env) void cpu_loop(CPUAlphaState *env)
{ {
CPUState *cs = env_cpu(env); CPUState *cs = env_cpu(env);
int trapnr; int trapnr, si_code;
target_siginfo_t info;
abi_long sysret; abi_long sysret;
while (1) { while (1) {
@ -56,18 +55,10 @@ void cpu_loop(CPUAlphaState *env)
break; break;
case EXCP_OPCDEC: case EXCP_OPCDEC:
do_sigill: do_sigill:
info.si_signo = TARGET_SIGILL; force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc);
info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPC;
info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_ARITH: case EXCP_ARITH:
info.si_signo = TARGET_SIGFPE; force_sig_fault(TARGET_SIGFPE, TARGET_FPE_FLTINV, env->pc);
info.si_errno = 0;
info.si_code = TARGET_FPE_FLTINV;
info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_FEN: case EXCP_FEN:
/* No-op. Linux simply re-enables the FPU. */ /* No-op. Linux simply re-enables the FPU. */
@ -76,20 +67,10 @@ void cpu_loop(CPUAlphaState *env)
switch (env->error_code) { switch (env->error_code) {
case 0x80: case 0x80:
/* BPT */ /* BPT */
info.si_signo = TARGET_SIGTRAP; goto do_sigtrap_brkpt;
info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT;
info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
case 0x81: case 0x81:
/* BUGCHK */ /* BUGCHK */
info.si_signo = TARGET_SIGTRAP; goto do_sigtrap_unk;
info.si_errno = 0;
info.si_code = 0;
info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
case 0x83: case 0x83:
/* CALLSYS */ /* CALLSYS */
trapnr = env->ir[IR_V0]; trapnr = env->ir[IR_V0];
@ -130,47 +111,43 @@ void cpu_loop(CPUAlphaState *env)
abort(); abort();
case 0xAA: case 0xAA:
/* GENTRAP */ /* GENTRAP */
info.si_signo = TARGET_SIGFPE;
switch (env->ir[IR_A0]) { switch (env->ir[IR_A0]) {
case TARGET_GEN_INTOVF: case TARGET_GEN_INTOVF:
info.si_code = TARGET_FPE_INTOVF; si_code = TARGET_FPE_INTOVF;
break; break;
case TARGET_GEN_INTDIV: case TARGET_GEN_INTDIV:
info.si_code = TARGET_FPE_INTDIV; si_code = TARGET_FPE_INTDIV;
break; break;
case TARGET_GEN_FLTOVF: case TARGET_GEN_FLTOVF:
info.si_code = TARGET_FPE_FLTOVF; si_code = TARGET_FPE_FLTOVF;
break; break;
case TARGET_GEN_FLTUND: case TARGET_GEN_FLTUND:
info.si_code = TARGET_FPE_FLTUND; si_code = TARGET_FPE_FLTUND;
break; break;
case TARGET_GEN_FLTINV: case TARGET_GEN_FLTINV:
info.si_code = TARGET_FPE_FLTINV; si_code = TARGET_FPE_FLTINV;
break; break;
case TARGET_GEN_FLTINE: case TARGET_GEN_FLTINE:
info.si_code = TARGET_FPE_FLTRES; si_code = TARGET_FPE_FLTRES;
break; break;
case TARGET_GEN_ROPRAND: case TARGET_GEN_ROPRAND:
info.si_code = 0; si_code = TARGET_FPE_FLTUNK;
break; break;
default: default:
info.si_signo = TARGET_SIGTRAP; goto do_sigtrap_unk;
info.si_code = 0;
break;
} }
info.si_errno = 0; force_sig_fault(TARGET_SIGFPE, si_code, env->pc);
info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
default: default:
goto do_sigill; goto do_sigill;
} }
break; break;
case EXCP_DEBUG: case EXCP_DEBUG:
info.si_signo = TARGET_SIGTRAP; do_sigtrap_brkpt:
info.si_errno = 0; force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
info.si_code = TARGET_TRAP_BRKPT; break;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); do_sigtrap_unk:
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_UNK, env->pc);
break; break;
case EXCP_INTERRUPT: case EXCP_INTERRUPT:
/* Just indicate that signals should be handled asap. */ /* Just indicate that signals should be handled asap. */

View file

@ -1,59 +1 @@
/* #include "../generic/target_structs.h"
* ARM specific structures for linux-user
*
* Copyright (c) 2013 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ARM_TARGET_STRUCTS_H
#define ARM_TARGET_STRUCTS_H
struct target_ipc_perm {
abi_int __key; /* Key. */
abi_uint uid; /* Owner's user ID. */
abi_uint gid; /* Owner's group ID. */
abi_uint cuid; /* Creator's user ID. */
abi_uint cgid; /* Creator's group ID. */
abi_ushort mode; /* Read/write permission. */
abi_ushort __pad1;
abi_ushort __seq; /* Sequence number. */
abi_ushort __pad2;
abi_ulong __unused1;
abi_ulong __unused2;
};
struct target_shmid_ds {
struct target_ipc_perm shm_perm; /* operation permission struct */
abi_long shm_segsz; /* size of segment in bytes */
abi_ulong shm_atime; /* time of last shmat() */
abi_ulong __unused1;
abi_ulong shm_dtime; /* time of last shmdt() */
abi_ulong __unused2;
abi_ulong shm_ctime; /* time of last change by shmctl() */
abi_ulong __unused3;
abi_int shm_cpid; /* pid of creator */
abi_int shm_lpid; /* pid of last shmop */
abi_ulong shm_nattch; /* number of current attaches */
abi_ulong __unused4;
abi_ulong __unused5;
};
struct target_oabi_flock64 {
abi_short l_type;
abi_short l_whence;
abi_llong l_start;
abi_llong l_len;
abi_int l_pid;
} QEMU_PACKED;
#endif

View file

@ -28,8 +28,7 @@ void cpu_loop(CPUCRISState *env)
{ {
CPUState *cs = env_cpu(env); CPUState *cs = env_cpu(env);
int trapnr, ret; int trapnr, ret;
target_siginfo_t info;
while (1) { while (1) {
cpu_exec_start(cs); cpu_exec_start(cs);
trapnr = cpu_exec(cs); trapnr = cpu_exec(cs);
@ -38,8 +37,8 @@ void cpu_loop(CPUCRISState *env)
switch (trapnr) { switch (trapnr) {
case EXCP_INTERRUPT: case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */ /* just indicate that signals should be handled asap */
break; break;
case EXCP_BREAK: case EXCP_BREAK:
ret = do_syscall(env, ret = do_syscall(env,
env->regs[9], env->regs[9],
@ -57,10 +56,7 @@ void cpu_loop(CPUCRISState *env)
} }
break; break;
case EXCP_DEBUG: case EXCP_DEBUG:
info.si_signo = TARGET_SIGTRAP; force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_ATOMIC: case EXCP_ATOMIC:
cpu_exec_step_atomic(cs); cpu_exec_step_atomic(cs);

View file

@ -1,58 +1 @@
/* #include "../generic/target_structs.h"
* CRIS specific structures for linux-user
*
* Copyright (c) 2013 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CRIS_TARGET_STRUCTS_H
#define CRIS_TARGET_STRUCTS_H
struct target_ipc_perm {
abi_int __key; /* Key. */
abi_uint uid; /* Owner's user ID. */
abi_uint gid; /* Owner's group ID. */
abi_uint cuid; /* Creator's user ID. */
abi_uint cgid; /* Creator's group ID. */
abi_ushort mode; /* Read/write permission. */
abi_ushort __pad1;
abi_ushort __seq; /* Sequence number. */
abi_ushort __pad2;
abi_ulong __unused1;
abi_ulong __unused2;
};
struct target_shmid_ds {
struct target_ipc_perm shm_perm; /* operation permission struct */
abi_long shm_segsz; /* size of segment in bytes */
abi_ulong shm_atime; /* time of last shmat() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused1;
#endif
abi_ulong shm_dtime; /* time of last shmdt() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused2;
#endif
abi_ulong shm_ctime; /* time of last change by shmctl() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused3;
#endif
abi_int shm_cpid; /* pid of creator */
abi_int shm_lpid; /* pid of last shmop */
abi_ulong shm_nattch; /* number of current attaches */
abi_ulong __unused4;
abi_ulong __unused5;
};
#endif

View file

@ -0,0 +1,58 @@
/*
* Generic structures for linux-user
*
* Copyright (c) 2013 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GENERIC_TARGET_STRUCTS_H
#define GENERIC_TARGET_STRUCTS_H
struct target_ipc_perm {
abi_int __key; /* Key. */
abi_uint uid; /* Owner's user ID. */
abi_uint gid; /* Owner's group ID. */
abi_uint cuid; /* Creator's user ID. */
abi_uint cgid; /* Creator's group ID. */
abi_ushort mode; /* Read/write permission. */
abi_ushort __pad1;
abi_ushort __seq; /* Sequence number. */
abi_ushort __pad2;
abi_ulong __unused1;
abi_ulong __unused2;
};
struct target_shmid_ds {
struct target_ipc_perm shm_perm; /* operation permission struct */
abi_long shm_segsz; /* size of segment in bytes */
abi_ulong shm_atime; /* time of last shmat() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused1;
#endif
abi_ulong shm_dtime; /* time of last shmdt() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused2;
#endif
abi_ulong shm_ctime; /* time of last change by shmctl() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused3;
#endif
abi_int shm_cpid; /* pid of creator */
abi_int shm_lpid; /* pid of last shmop */
abi_ulong shm_nattch; /* number of current attaches */
abi_ulong __unused4;
abi_ulong __unused5;
};
#endif

View file

@ -1,54 +1 @@
/* #include "../generic/target_structs.h"
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/*
* Hexagon specific structures for linux-user
*/
#ifndef HEXAGON_TARGET_STRUCTS_H
#define HEXAGON_TARGET_STRUCTS_H
struct target_ipc_perm {
abi_int __key; /* Key. */
abi_uint uid; /* Owner's user ID. */
abi_uint gid; /* Owner's group ID. */
abi_uint cuid; /* Creator's user ID. */
abi_uint cgid; /* Creator's group ID. */
abi_ushort mode; /* Read/write permission. */
abi_ushort __pad1;
abi_ushort __seq; /* Sequence number. */
abi_ushort __pad2;
abi_ulong __unused1;
abi_ulong __unused2;
};
struct target_shmid_ds {
struct target_ipc_perm shm_perm; /* operation permission struct */
abi_long shm_segsz; /* size of segment in bytes */
abi_ulong shm_atime; /* time of last shmat() */
abi_ulong __unused1;
abi_ulong shm_dtime; /* time of last shmdt() */
abi_ulong __unused2;
abi_ulong shm_ctime; /* time of last change by shmctl() */
abi_ulong __unused3;
abi_int shm_cpid; /* pid of creator */
abi_int shm_lpid; /* pid of last shmop */
abi_ulong shm_nattch; /* number of current attaches */
abi_ulong __unused4;
abi_ulong __unused5;
};
#endif

View file

@ -110,7 +110,6 @@ static abi_ulong hppa_lws(CPUHPPAState *env)
void cpu_loop(CPUHPPAState *env) void cpu_loop(CPUHPPAState *env)
{ {
CPUState *cs = env_cpu(env); CPUState *cs = env_cpu(env);
target_siginfo_t info;
abi_ulong ret; abi_ulong ret;
int trapnr; int trapnr;
@ -145,28 +144,25 @@ void cpu_loop(CPUHPPAState *env)
env->iaoq_b = env->gr[31] + 4; env->iaoq_b = env->gr[31] + 4;
break; break;
case EXCP_ILL: case EXCP_ILL:
force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->iaoq_f);
break;
case EXCP_PRIV_OPR: case EXCP_PRIV_OPR:
force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->iaoq_f);
break;
case EXCP_PRIV_REG: case EXCP_PRIV_REG:
info.si_signo = TARGET_SIGILL; force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVREG, env->iaoq_f);
info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPN;
info._sifields._sigfault._addr = env->iaoq_f;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_OVERFLOW: case EXCP_OVERFLOW:
force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTOVF, env->iaoq_f);
break;
case EXCP_COND: case EXCP_COND:
force_sig_fault(TARGET_SIGFPE, TARGET_FPE_CONDTRAP, env->iaoq_f);
break;
case EXCP_ASSIST: case EXCP_ASSIST:
info.si_signo = TARGET_SIGFPE; force_sig_fault(TARGET_SIGFPE, 0, env->iaoq_f);
info.si_errno = 0;
info.si_code = 0;
info._sifields._sigfault._addr = env->iaoq_f;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_DEBUG: case EXCP_DEBUG:
info.si_signo = TARGET_SIGTRAP; force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->iaoq_f);
info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_INTERRUPT: case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */ /* just indicate that signals should be handled asap */

View file

@ -84,17 +84,6 @@ static void set_idt(int n, unsigned int dpl)
} }
#endif #endif
static void gen_signal(CPUX86State *env, int sig, int code, abi_ptr addr)
{
target_siginfo_t info = {
.si_signo = sig,
.si_code = code,
._sifields._sigfault._addr = addr
};
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
}
#ifdef TARGET_X86_64 #ifdef TARGET_X86_64
static bool write_ok_or_segv(CPUX86State *env, abi_ptr addr, size_t len) static bool write_ok_or_segv(CPUX86State *env, abi_ptr addr, size_t len)
{ {
@ -107,7 +96,7 @@ static bool write_ok_or_segv(CPUX86State *env, abi_ptr addr, size_t len)
} }
env->error_code = PG_ERROR_W_MASK | PG_ERROR_U_MASK; env->error_code = PG_ERROR_W_MASK | PG_ERROR_U_MASK;
gen_signal(env, TARGET_SIGSEGV, TARGET_SEGV_MAPERR, addr); force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, addr);
return false; return false;
} }
@ -193,11 +182,21 @@ static void emulate_vsyscall(CPUX86State *env)
return; return;
sigsegv: sigsegv:
/* Like force_sig(SIGSEGV). */ force_sig(TARGET_SIGSEGV);
gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0);
} }
#endif #endif
static bool maybe_handle_vm86_trap(CPUX86State *env, int trapnr)
{
#ifndef TARGET_X86_64
if (env->eflags & VM_MASK) {
handle_vm86_trap(env, trapnr);
return true;
}
#endif
return false;
}
void cpu_loop(CPUX86State *env) void cpu_loop(CPUX86State *env)
{ {
CPUState *cs = env_cpu(env); CPUState *cs = env_cpu(env);
@ -255,65 +254,54 @@ void cpu_loop(CPUX86State *env)
#endif #endif
case EXCP0B_NOSEG: case EXCP0B_NOSEG:
case EXCP0C_STACK: case EXCP0C_STACK:
gen_signal(env, TARGET_SIGBUS, TARGET_SI_KERNEL, 0); force_sig(TARGET_SIGBUS);
break; break;
case EXCP0D_GPF: case EXCP0D_GPF:
/* XXX: potential problem if ABI32 */ /* XXX: potential problem if ABI32 */
#ifndef TARGET_X86_64 if (maybe_handle_vm86_trap(env, trapnr)) {
if (env->eflags & VM_MASK) {
handle_vm86_fault(env);
break; break;
} }
#endif force_sig(TARGET_SIGSEGV);
gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0);
break; break;
case EXCP0E_PAGE: case EXCP0E_PAGE:
gen_signal(env, TARGET_SIGSEGV, force_sig_fault(TARGET_SIGSEGV,
(env->error_code & 1 ? (env->error_code & PG_ERROR_P_MASK ?
TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR), TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR),
env->cr[2]); env->cr[2]);
break; break;
case EXCP00_DIVZ: case EXCP00_DIVZ:
#ifndef TARGET_X86_64 if (maybe_handle_vm86_trap(env, trapnr)) {
if (env->eflags & VM_MASK) {
handle_vm86_trap(env, trapnr);
break; break;
} }
#endif force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, env->eip);
gen_signal(env, TARGET_SIGFPE, TARGET_FPE_INTDIV, env->eip);
break; break;
case EXCP01_DB: case EXCP01_DB:
case EXCP03_INT3: if (maybe_handle_vm86_trap(env, trapnr)) {
#ifndef TARGET_X86_64
if (env->eflags & VM_MASK) {
handle_vm86_trap(env, trapnr);
break; break;
} }
#endif force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->eip);
if (trapnr == EXCP01_DB) { break;
gen_signal(env, TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->eip); case EXCP03_INT3:
} else { if (maybe_handle_vm86_trap(env, trapnr)) {
gen_signal(env, TARGET_SIGTRAP, TARGET_SI_KERNEL, 0); break;
} }
force_sig(TARGET_SIGTRAP);
break; break;
case EXCP04_INTO: case EXCP04_INTO:
case EXCP05_BOUND: case EXCP05_BOUND:
#ifndef TARGET_X86_64 if (maybe_handle_vm86_trap(env, trapnr)) {
if (env->eflags & VM_MASK) {
handle_vm86_trap(env, trapnr);
break; break;
} }
#endif force_sig(TARGET_SIGSEGV);
gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0);
break; break;
case EXCP06_ILLOP: case EXCP06_ILLOP:
gen_signal(env, TARGET_SIGILL, TARGET_ILL_ILLOPN, env->eip); force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->eip);
break; break;
case EXCP_INTERRUPT: case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */ /* just indicate that signals should be handled asap */
break; break;
case EXCP_DEBUG: case EXCP_DEBUG:
gen_signal(env, TARGET_SIGTRAP, TARGET_TRAP_BRKPT, 0); force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->eip);
break; break;
case EXCP_ATOMIC: case EXCP_ATOMIC:
cpu_exec_step_atomic(cs); cpu_exec_step_atomic(cs);

View file

@ -1,58 +1 @@
/* #include "../generic/target_structs.h"
* i386 specific structures for linux-user
*
* Copyright (c) 2013 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef I386_TARGET_STRUCTS_H
#define I386_TARGET_STRUCTS_H
struct target_ipc_perm {
abi_int __key; /* Key. */
abi_uint uid; /* Owner's user ID. */
abi_uint gid; /* Owner's group ID. */
abi_uint cuid; /* Creator's user ID. */
abi_uint cgid; /* Creator's group ID. */
abi_ushort mode; /* Read/write permission. */
abi_ushort __pad1;
abi_ushort __seq; /* Sequence number. */
abi_ushort __pad2;
abi_ulong __unused1;
abi_ulong __unused2;
};
struct target_shmid_ds {
struct target_ipc_perm shm_perm; /* operation permission struct */
abi_long shm_segsz; /* size of segment in bytes */
abi_ulong shm_atime; /* time of last shmat() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused1;
#endif
abi_ulong shm_dtime; /* time of last shmdt() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused2;
#endif
abi_ulong shm_ctime; /* time of last change by shmctl() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused3;
#endif
abi_int shm_cpid; /* pid of creator */
abi_int shm_lpid; /* pid of last shmop */
abi_ulong shm_nattch; /* number of current attaches */
abi_ulong __unused4;
abi_ulong __unused5;
};
#endif

View file

@ -29,7 +29,6 @@ void cpu_loop(CPUM68KState *env)
CPUState *cs = env_cpu(env); CPUState *cs = env_cpu(env);
int trapnr; int trapnr;
unsigned int n; unsigned int n;
target_siginfo_t info;
for(;;) { for(;;) {
cpu_exec_start(cs); cpu_exec_start(cs);
@ -46,25 +45,13 @@ void cpu_loop(CPUM68KState *env)
case EXCP_ILLEGAL: case EXCP_ILLEGAL:
case EXCP_LINEA: case EXCP_LINEA:
case EXCP_LINEF: case EXCP_LINEF:
info.si_signo = TARGET_SIGILL; force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->pc);
info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPN;
info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_CHK: case EXCP_CHK:
info.si_signo = TARGET_SIGFPE; force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTOVF, env->pc);
info.si_errno = 0;
info.si_code = TARGET_FPE_INTOVF;
info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_DIV0: case EXCP_DIV0:
info.si_signo = TARGET_SIGFPE; force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, env->pc);
info.si_errno = 0;
info.si_code = TARGET_FPE_INTDIV;
info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_TRAP0: case EXCP_TRAP0:
{ {
@ -91,10 +78,7 @@ void cpu_loop(CPUM68KState *env)
/* just indicate that signals should be handled asap */ /* just indicate that signals should be handled asap */
break; break;
case EXCP_DEBUG: case EXCP_DEBUG:
info.si_signo = TARGET_SIGTRAP; force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_ATOMIC: case EXCP_ATOMIC:
cpu_exec_step_atomic(cs); cpu_exec_step_atomic(cs);

View file

@ -1,58 +1 @@
/* #include "../generic/target_structs.h"
* m68k specific structures for linux-user
*
* Copyright (c) 2013 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef M68K_TARGET_STRUCTS_H
#define M68K_TARGET_STRUCTS_H
struct target_ipc_perm {
abi_int __key; /* Key. */
abi_uint uid; /* Owner's user ID. */
abi_uint gid; /* Owner's group ID. */
abi_uint cuid; /* Creator's user ID. */
abi_uint cgid; /* Creator's group ID. */
abi_ushort mode; /* Read/write permission. */
abi_ushort __pad1;
abi_ushort __seq; /* Sequence number. */
abi_ushort __pad2;
abi_ulong __unused1;
abi_ulong __unused2;
};
struct target_shmid_ds {
struct target_ipc_perm shm_perm; /* operation permission struct */
abi_long shm_segsz; /* size of segment in bytes */
abi_ulong shm_atime; /* time of last shmat() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused1;
#endif
abi_ulong shm_dtime; /* time of last shmdt() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused2;
#endif
abi_ulong shm_ctime; /* time of last change by shmctl() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused3;
#endif
abi_int shm_cpid; /* pid of creator */
abi_int shm_lpid; /* pid of last shmop */
abi_ulong shm_nattch; /* number of current attaches */
abi_ulong __unused4;
abi_ulong __unused5;
};
#endif

View file

@ -27,9 +27,8 @@
void cpu_loop(CPUMBState *env) void cpu_loop(CPUMBState *env)
{ {
CPUState *cs = env_cpu(env); CPUState *cs = env_cpu(env);
int trapnr, ret; int trapnr, ret, si_code;
target_siginfo_t info;
while (1) { while (1) {
cpu_exec_start(cs); cpu_exec_start(cs);
trapnr = cpu_exec(cs); trapnr = cpu_exec(cs);
@ -38,8 +37,8 @@ void cpu_loop(CPUMBState *env)
switch (trapnr) { switch (trapnr) {
case EXCP_INTERRUPT: case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */ /* just indicate that signals should be handled asap */
break; break;
case EXCP_SYSCALL: case EXCP_SYSCALL:
/* Return address is 4 bytes after the call. */ /* Return address is 4 bytes after the call. */
env->regs[14] += 4; env->regs[14] += 4;
@ -67,6 +66,7 @@ void cpu_loop(CPUMBState *env)
*/ */
env->regs[14] = env->pc; env->regs[14] = env->pc;
break; break;
case EXCP_HW_EXCP: case EXCP_HW_EXCP:
env->regs[17] = env->pc + 4; env->regs[17] = env->pc + 4;
if (env->iflags & D_FLAG) { if (env->iflags & D_FLAG) {
@ -74,42 +74,41 @@ void cpu_loop(CPUMBState *env)
env->pc -= 4; env->pc -= 4;
/* FIXME: if branch was immed, replay the imm as well. */ /* FIXME: if branch was immed, replay the imm as well. */
} }
env->iflags &= ~(IMM_FLAG | D_FLAG); env->iflags &= ~(IMM_FLAG | D_FLAG);
switch (env->esr & 31) { switch (env->esr & 31) {
case ESR_EC_DIVZERO: case ESR_EC_DIVZERO:
info.si_signo = TARGET_SIGFPE; si_code = TARGET_FPE_INTDIV;
info.si_errno = 0; break;
info.si_code = TARGET_FPE_FLTDIV; case ESR_EC_FPU:
info._sifields._sigfault._addr = 0; /*
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); * Note that the kernel passes along fsr as si_code
break; * if there's no recognized bit set. Possibly this
case ESR_EC_FPU: * implies that si_code is 0, but follow the structure.
info.si_signo = TARGET_SIGFPE; */
info.si_errno = 0; si_code = env->fsr;
if (env->fsr & FSR_IO) { if (si_code & FSR_IO) {
info.si_code = TARGET_FPE_FLTINV; si_code = TARGET_FPE_FLTINV;
} } else if (si_code & FSR_OF) {
if (env->fsr & FSR_DZ) { si_code = TARGET_FPE_FLTOVF;
info.si_code = TARGET_FPE_FLTDIV; } else if (si_code & FSR_UF) {
} si_code = TARGET_FPE_FLTUND;
info._sifields._sigfault._addr = 0; } else if (si_code & FSR_DZ) {
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); si_code = TARGET_FPE_FLTDIV;
break; } else if (si_code & FSR_DO) {
default: si_code = TARGET_FPE_FLTRES;
fprintf(stderr, "Unhandled hw-exception: 0x%x\n", }
env->esr & ESR_EC_MASK); break;
cpu_dump_state(cs, stderr, 0); default:
exit(EXIT_FAILURE); fprintf(stderr, "Unhandled hw-exception: 0x%x\n",
break; env->esr & ESR_EC_MASK);
cpu_dump_state(cs, stderr, 0);
exit(EXIT_FAILURE);
} }
force_sig_fault(TARGET_SIGFPE, si_code, env->pc);
break; break;
case EXCP_DEBUG: case EXCP_DEBUG:
info.si_signo = TARGET_SIGTRAP; force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_ATOMIC: case EXCP_ATOMIC:
cpu_exec_step_atomic(cs); cpu_exec_step_atomic(cs);

View file

@ -1,58 +1 @@
/* #include "../generic/target_structs.h"
* MicroBlaze specific structures for linux-user
*
* Copyright (c) 2013 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MICROBLAZE_TARGET_STRUCTS_H
#define MICROBLAZE_TARGET_STRUCTS_H
struct target_ipc_perm {
abi_int __key; /* Key. */
abi_uint uid; /* Owner's user ID. */
abi_uint gid; /* Owner's group ID. */
abi_uint cuid; /* Creator's user ID. */
abi_uint cgid; /* Creator's group ID. */
abi_ushort mode; /* Read/write permission. */
abi_ushort __pad1;
abi_ushort __seq; /* Sequence number. */
abi_ushort __pad2;
abi_ulong __unused1;
abi_ulong __unused2;
};
struct target_shmid_ds {
struct target_ipc_perm shm_perm; /* operation permission struct */
abi_long shm_segsz; /* size of segment in bytes */
abi_ulong shm_atime; /* time of last shmat() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused1;
#endif
abi_ulong shm_dtime; /* time of last shmdt() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused2;
#endif
abi_ulong shm_ctime; /* time of last change by shmctl() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused3;
#endif
abi_int shm_cpid; /* pid of creator */
abi_int shm_lpid; /* pid of last shmop */
abi_ulong shm_nattch; /* number of current attaches */
abi_ulong __unused4;
abi_ulong __unused5;
};
#endif

View file

@ -40,36 +40,32 @@ enum {
BRK_DIVZERO = 7 BRK_DIVZERO = 7
}; };
static int do_break(CPUMIPSState *env, target_siginfo_t *info, static void do_tr_or_bp(CPUMIPSState *env, unsigned int code, bool trap)
unsigned int code)
{ {
int ret = -1; target_ulong pc = env->active_tc.PC;
switch (code) { switch (code) {
case BRK_OVERFLOW: case BRK_OVERFLOW:
force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTOVF, pc);
break;
case BRK_DIVZERO: case BRK_DIVZERO:
info->si_signo = TARGET_SIGFPE; force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, pc);
info->si_errno = 0;
info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV;
queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info);
ret = 0;
break; break;
default: default:
info->si_signo = TARGET_SIGTRAP; if (trap) {
info->si_errno = 0; force_sig(TARGET_SIGTRAP);
queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info); } else {
ret = 0; force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, pc);
}
break; break;
} }
return ret;
} }
void cpu_loop(CPUMIPSState *env) void cpu_loop(CPUMIPSState *env)
{ {
CPUState *cs = env_cpu(env); CPUState *cs = env_cpu(env);
target_siginfo_t info; int trapnr, si_code;
int trapnr; unsigned int code;
abi_long ret; abi_long ret;
# ifdef TARGET_ABI_MIPSO32 # ifdef TARGET_ABI_MIPSO32
unsigned int syscall_num; unsigned int syscall_num;
@ -160,149 +156,53 @@ done_syscall:
break; break;
case EXCP_CpU: case EXCP_CpU:
case EXCP_RI: case EXCP_RI:
info.si_signo = TARGET_SIGILL; case EXCP_DSPDIS:
info.si_errno = 0; force_sig(TARGET_SIGILL);
info.si_code = 0;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_INTERRUPT: case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */ /* just indicate that signals should be handled asap */
break; break;
case EXCP_DEBUG: case EXCP_DEBUG:
info.si_signo = TARGET_SIGTRAP; force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT,
info.si_errno = 0; env->active_tc.PC);
info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
case EXCP_DSPDIS:
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPC;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_FPE: case EXCP_FPE:
info.si_signo = TARGET_SIGFPE; si_code = TARGET_FPE_FLTUNK;
info.si_errno = 0;
info.si_code = TARGET_FPE_FLTUNK;
if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) { if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) {
info.si_code = TARGET_FPE_FLTINV; si_code = TARGET_FPE_FLTINV;
} else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_DIV0) { } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_DIV0) {
info.si_code = TARGET_FPE_FLTDIV; si_code = TARGET_FPE_FLTDIV;
} else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_OVERFLOW) { } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_OVERFLOW) {
info.si_code = TARGET_FPE_FLTOVF; si_code = TARGET_FPE_FLTOVF;
} else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_UNDERFLOW) { } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_UNDERFLOW) {
info.si_code = TARGET_FPE_FLTUND; si_code = TARGET_FPE_FLTUND;
} else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INEXACT) { } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INEXACT) {
info.si_code = TARGET_FPE_FLTRES; si_code = TARGET_FPE_FLTRES;
} }
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); force_sig_fault(TARGET_SIGFPE, si_code, env->active_tc.PC);
break; break;
/* The code below was inspired by the MIPS Linux kernel trap /* The code below was inspired by the MIPS Linux kernel trap
* handling code in arch/mips/kernel/traps.c. * handling code in arch/mips/kernel/traps.c.
*/ */
case EXCP_BREAK: case EXCP_BREAK:
{ /*
abi_ulong trap_instr; * As described in the original Linux kernel code, the below
unsigned int code; * checks on 'code' are to work around an old assembly bug.
*/
if (env->hflags & MIPS_HFLAG_M16) { code = env->error_code;
if (env->insn_flags & ASE_MICROMIPS) { if (code >= (1 << 10)) {
/* microMIPS mode */ code >>= 10;
ret = get_user_u16(trap_instr, env->active_tc.PC);
if (ret != 0) {
goto error;
}
if ((trap_instr >> 10) == 0x11) {
/* 16-bit instruction */
code = trap_instr & 0xf;
} else {
/* 32-bit instruction */
abi_ulong instr_lo;
ret = get_user_u16(instr_lo,
env->active_tc.PC + 2);
if (ret != 0) {
goto error;
}
trap_instr = (trap_instr << 16) | instr_lo;
code = ((trap_instr >> 6) & ((1 << 20) - 1));
/* Unfortunately, microMIPS also suffers from
the old assembler bug... */
if (code >= (1 << 10)) {
code >>= 10;
}
}
} else {
/* MIPS16e mode */
ret = get_user_u16(trap_instr, env->active_tc.PC);
if (ret != 0) {
goto error;
}
code = (trap_instr >> 6) & 0x3f;
}
} else {
ret = get_user_u32(trap_instr, env->active_tc.PC);
if (ret != 0) {
goto error;
}
/* As described in the original Linux kernel code, the
* below checks on 'code' are to work around an old
* assembly bug.
*/
code = ((trap_instr >> 6) & ((1 << 20) - 1));
if (code >= (1 << 10)) {
code >>= 10;
}
}
if (do_break(env, &info, code) != 0) {
goto error;
}
} }
do_tr_or_bp(env, code, false);
break; break;
case EXCP_TRAP: case EXCP_TRAP:
{ do_tr_or_bp(env, env->error_code, true);
abi_ulong trap_instr;
unsigned int code = 0;
if (env->hflags & MIPS_HFLAG_M16) {
/* microMIPS mode */
abi_ulong instr[2];
ret = get_user_u16(instr[0], env->active_tc.PC) ||
get_user_u16(instr[1], env->active_tc.PC + 2);
trap_instr = (instr[0] << 16) | instr[1];
} else {
ret = get_user_u32(trap_instr, env->active_tc.PC);
}
if (ret != 0) {
goto error;
}
/* The immediate versions don't provide a code. */
if (!(trap_instr & 0xFC000000)) {
if (env->hflags & MIPS_HFLAG_M16) {
/* microMIPS mode */
code = ((trap_instr >> 12) & ((1 << 4) - 1));
} else {
code = ((trap_instr >> 6) & ((1 << 10) - 1));
}
}
if (do_break(env, &info, code) != 0) {
goto error;
}
}
break; break;
case EXCP_ATOMIC: case EXCP_ATOMIC:
cpu_exec_step_atomic(cs); cpu_exec_step_atomic(cs);
break; break;
default: default:
error:
EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
abort(); abort();
} }

View file

@ -1,58 +1 @@
/* #include "../generic/target_structs.h"
* Nios2 specific structures for linux-user
*
* Copyright (c) 2016 Marek Vasut <marex@denx.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NIOS2_TARGET_STRUCTS_H
#define NIOS2_TARGET_STRUCTS_H
struct target_ipc_perm {
abi_int __key; /* Key. */
abi_uint uid; /* Owner's user ID. */
abi_uint gid; /* Owner's group ID. */
abi_uint cuid; /* Creator's user ID. */
abi_uint cgid; /* Creator's group ID. */
abi_ushort mode; /* Read/write permission. */
abi_ushort __pad1;
abi_ushort __seq; /* Sequence number. */
abi_ushort __pad2;
abi_ulong __unused1;
abi_ulong __unused2;
};
struct target_shmid_ds {
struct target_ipc_perm shm_perm; /* operation permission struct */
abi_long shm_segsz; /* size of segment in bytes */
abi_ulong shm_atime; /* time of last shmat() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused1;
#endif
abi_ulong shm_dtime; /* time of last shmdt() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused2;
#endif
abi_ulong shm_ctime; /* time of last change by shmctl() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused3;
#endif
abi_int shm_cpid; /* pid of creator */
abi_int shm_lpid; /* pid of last shmop */
abi_ulong shm_nattch; /* number of current attaches */
abi_ulong __unused4;
abi_ulong __unused5;
};
#endif

View file

@ -29,7 +29,6 @@ void cpu_loop(CPUOpenRISCState *env)
CPUState *cs = env_cpu(env); CPUState *cs = env_cpu(env);
int trapnr; int trapnr;
abi_long ret; abi_long ret;
target_siginfo_t info;
for (;;) { for (;;) {
cpu_exec_start(cs); cpu_exec_start(cs);
@ -55,27 +54,16 @@ void cpu_loop(CPUOpenRISCState *env)
} }
break; break;
case EXCP_ALIGN: case EXCP_ALIGN:
info.si_signo = TARGET_SIGBUS; force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN, env->eear);
info.si_errno = 0;
info.si_code = TARGET_BUS_ADRALN;
info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_ILLEGAL: case EXCP_ILLEGAL:
info.si_signo = TARGET_SIGILL; force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc);
info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPC;
info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_INTERRUPT: case EXCP_INTERRUPT:
/* We processed the pending cpu work above. */ /* We processed the pending cpu work above. */
break; break;
case EXCP_DEBUG: case EXCP_DEBUG:
info.si_signo = TARGET_SIGTRAP; force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_ATOMIC: case EXCP_ATOMIC:
cpu_exec_step_atomic(cs); cpu_exec_step_atomic(cs);

View file

@ -1,58 +1 @@
/* #include "../generic/target_structs.h"
* OpenRISC specific structures for linux-user
*
* Copyright (c) 2013 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPENRISC_TARGET_STRUCTS_H
#define OPENRISC_TARGET_STRUCTS_H
struct target_ipc_perm {
abi_int __key; /* Key. */
abi_uint uid; /* Owner's user ID. */
abi_uint gid; /* Owner's group ID. */
abi_uint cuid; /* Creator's user ID. */
abi_uint cgid; /* Creator's group ID. */
abi_ushort mode; /* Read/write permission. */
abi_ushort __pad1;
abi_ushort __seq; /* Sequence number. */
abi_ushort __pad2;
abi_ulong __unused1;
abi_ulong __unused2;
};
struct target_shmid_ds {
struct target_ipc_perm shm_perm; /* operation permission struct */
abi_long shm_segsz; /* size of segment in bytes */
abi_ulong shm_atime; /* time of last shmat() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused1;
#endif
abi_ulong shm_dtime; /* time of last shmdt() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused2;
#endif
abi_ulong shm_ctime; /* time of last change by shmctl() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused3;
#endif
abi_int shm_cpid; /* pid of creator */
abi_int shm_lpid; /* pid of last shmop */
abi_ulong shm_nattch; /* number of current attaches */
abi_ulong __unused4;
abi_ulong __unused5;
};
#endif

View file

@ -76,8 +76,7 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
void cpu_loop(CPUPPCState *env) void cpu_loop(CPUPPCState *env)
{ {
CPUState *cs = env_cpu(env); CPUState *cs = env_cpu(env);
target_siginfo_t info; int trapnr, si_signo, si_code;
int trapnr;
target_ulong ret; target_ulong ret;
for(;;) { for(;;) {
@ -102,61 +101,10 @@ void cpu_loop(CPUPPCState *env)
"Aborting\n"); "Aborting\n");
break; break;
case POWERPC_EXCP_DSI: /* Data storage exception */ case POWERPC_EXCP_DSI: /* Data storage exception */
/* XXX: check this. Seems bugged */
switch (env->error_code & 0xFF000000) {
case 0x40000000:
case 0x42000000:
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR;
break;
case 0x04000000:
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_ILLADR;
break;
case 0x08000000:
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_ACCERR;
break;
default:
/* Let's send a regular segfault... */
EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
env->error_code);
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR;
break;
}
info._sifields._sigfault._addr = env->spr[SPR_DAR];
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
case POWERPC_EXCP_ISI: /* Instruction storage exception */ case POWERPC_EXCP_ISI: /* Instruction storage exception */
/* XXX: check this */ /* FIXME: handle maperr in ppc_cpu_record_sigsegv. */
switch (env->error_code & 0xFF000000) { force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR,
case 0x40000000: env->spr[SPR_DAR]);
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR;
break;
case 0x10000000:
case 0x08000000:
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_ACCERR;
break;
default:
/* Let's send a regular segfault... */
EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
env->error_code);
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR;
break;
}
info._sifields._sigfault._addr = env->nip - 4;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case POWERPC_EXCP_EXTERNAL: /* External input */ case POWERPC_EXCP_EXTERNAL: /* External input */
cpu_abort(cs, "External interrupt while in user mode. " cpu_abort(cs, "External interrupt while in user mode. "
@ -167,24 +115,23 @@ void cpu_loop(CPUPPCState *env)
/* XXX: check this */ /* XXX: check this */
switch (env->error_code & ~0xF) { switch (env->error_code & ~0xF) {
case POWERPC_EXCP_FP: case POWERPC_EXCP_FP:
info.si_signo = TARGET_SIGFPE; si_signo = TARGET_SIGFPE;
info.si_errno = 0;
switch (env->error_code & 0xF) { switch (env->error_code & 0xF) {
case POWERPC_EXCP_FP_OX: case POWERPC_EXCP_FP_OX:
info.si_code = TARGET_FPE_FLTOVF; si_code = TARGET_FPE_FLTOVF;
break; break;
case POWERPC_EXCP_FP_UX: case POWERPC_EXCP_FP_UX:
info.si_code = TARGET_FPE_FLTUND; si_code = TARGET_FPE_FLTUND;
break; break;
case POWERPC_EXCP_FP_ZX: case POWERPC_EXCP_FP_ZX:
case POWERPC_EXCP_FP_VXZDZ: case POWERPC_EXCP_FP_VXZDZ:
info.si_code = TARGET_FPE_FLTDIV; si_code = TARGET_FPE_FLTDIV;
break; break;
case POWERPC_EXCP_FP_XX: case POWERPC_EXCP_FP_XX:
info.si_code = TARGET_FPE_FLTRES; si_code = TARGET_FPE_FLTRES;
break; break;
case POWERPC_EXCP_FP_VXSOFT: case POWERPC_EXCP_FP_VXSOFT:
info.si_code = TARGET_FPE_FLTINV; si_code = TARGET_FPE_FLTINV;
break; break;
case POWERPC_EXCP_FP_VXSNAN: case POWERPC_EXCP_FP_VXSNAN:
case POWERPC_EXCP_FP_VXISI: case POWERPC_EXCP_FP_VXISI:
@ -193,51 +140,50 @@ void cpu_loop(CPUPPCState *env)
case POWERPC_EXCP_FP_VXVC: case POWERPC_EXCP_FP_VXVC:
case POWERPC_EXCP_FP_VXSQRT: case POWERPC_EXCP_FP_VXSQRT:
case POWERPC_EXCP_FP_VXCVI: case POWERPC_EXCP_FP_VXCVI:
info.si_code = TARGET_FPE_FLTSUB; si_code = TARGET_FPE_FLTSUB;
break; break;
default: default:
EXCP_DUMP(env, "Unknown floating point exception (%02x)\n", EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
env->error_code); env->error_code);
si_code = 0;
break; break;
} }
break; break;
case POWERPC_EXCP_INVAL: case POWERPC_EXCP_INVAL:
info.si_signo = TARGET_SIGILL; si_signo = TARGET_SIGILL;
info.si_errno = 0;
switch (env->error_code & 0xF) { switch (env->error_code & 0xF) {
case POWERPC_EXCP_INVAL_INVAL: case POWERPC_EXCP_INVAL_INVAL:
info.si_code = TARGET_ILL_ILLOPC; si_code = TARGET_ILL_ILLOPC;
break; break;
case POWERPC_EXCP_INVAL_LSWX: case POWERPC_EXCP_INVAL_LSWX:
info.si_code = TARGET_ILL_ILLOPN; si_code = TARGET_ILL_ILLOPN;
break; break;
case POWERPC_EXCP_INVAL_SPR: case POWERPC_EXCP_INVAL_SPR:
info.si_code = TARGET_ILL_PRVREG; si_code = TARGET_ILL_PRVREG;
break; break;
case POWERPC_EXCP_INVAL_FP: case POWERPC_EXCP_INVAL_FP:
info.si_code = TARGET_ILL_COPROC; si_code = TARGET_ILL_COPROC;
break; break;
default: default:
EXCP_DUMP(env, "Unknown invalid operation (%02x)\n", EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
env->error_code & 0xF); env->error_code & 0xF);
info.si_code = TARGET_ILL_ILLADR; si_code = TARGET_ILL_ILLADR;
break; break;
} }
break; break;
case POWERPC_EXCP_PRIV: case POWERPC_EXCP_PRIV:
info.si_signo = TARGET_SIGILL; si_signo = TARGET_SIGILL;
info.si_errno = 0;
switch (env->error_code & 0xF) { switch (env->error_code & 0xF) {
case POWERPC_EXCP_PRIV_OPC: case POWERPC_EXCP_PRIV_OPC:
info.si_code = TARGET_ILL_PRVOPC; si_code = TARGET_ILL_PRVOPC;
break; break;
case POWERPC_EXCP_PRIV_REG: case POWERPC_EXCP_PRIV_REG:
info.si_code = TARGET_ILL_PRVREG; si_code = TARGET_ILL_PRVREG;
break; break;
default: default:
EXCP_DUMP(env, "Unknown privilege violation (%02x)\n", EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
env->error_code & 0xF); env->error_code & 0xF);
info.si_code = TARGET_ILL_PRVOPC; si_code = TARGET_ILL_PRVOPC;
break; break;
} }
break; break;
@ -250,28 +196,19 @@ void cpu_loop(CPUPPCState *env)
env->error_code); env->error_code);
break; break;
} }
info._sifields._sigfault._addr = env->nip; force_sig_fault(si_signo, si_code, env->nip);
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
info.si_signo = TARGET_SIGILL; case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
info.si_errno = 0; case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
info.si_code = TARGET_ILL_COPROC; case POWERPC_EXCP_VPU: /* Vector unavailable exception */
info._sifields._sigfault._addr = env->nip; force_sig_fault(TARGET_SIGILL, TARGET_ILL_COPROC, env->nip);
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case POWERPC_EXCP_SYSCALL: /* System call exception */ case POWERPC_EXCP_SYSCALL: /* System call exception */
case POWERPC_EXCP_SYSCALL_VECTORED: case POWERPC_EXCP_SYSCALL_VECTORED:
cpu_abort(cs, "Syscall exception while in user mode. " cpu_abort(cs, "Syscall exception while in user mode. "
"Aborting\n"); "Aborting\n");
break; break;
case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_COPROC;
info._sifields._sigfault._addr = env->nip;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
case POWERPC_EXCP_DECR: /* Decrementer exception */ case POWERPC_EXCP_DECR: /* Decrementer exception */
cpu_abort(cs, "Decrementer interrupt while in user mode. " cpu_abort(cs, "Decrementer interrupt while in user mode. "
"Aborting\n"); "Aborting\n");
@ -292,13 +229,6 @@ void cpu_loop(CPUPPCState *env)
cpu_abort(cs, "Instruction TLB exception while in user mode. " cpu_abort(cs, "Instruction TLB exception while in user mode. "
"Aborting\n"); "Aborting\n");
break; break;
case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_COPROC;
info._sifields._sigfault._addr = env->nip;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */ case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */
cpu_abort(cs, "Embedded floating-point data IRQ not handled\n"); cpu_abort(cs, "Embedded floating-point data IRQ not handled\n");
break; break;
@ -355,13 +285,6 @@ void cpu_loop(CPUPPCState *env)
cpu_abort(cs, "Hypervisor instruction segment exception " cpu_abort(cs, "Hypervisor instruction segment exception "
"while in user mode. Aborting\n"); "while in user mode. Aborting\n");
break; break;
case POWERPC_EXCP_VPU: /* Vector unavailable exception */
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_COPROC;
info._sifields._sigfault._addr = env->nip;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */ case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */
cpu_abort(cs, "Programmable interval timer interrupt " cpu_abort(cs, "Programmable interval timer interrupt "
"while in user mode. Aborting\n"); "while in user mode. Aborting\n");
@ -444,10 +367,7 @@ void cpu_loop(CPUPPCState *env)
env->gpr[3] = ret; env->gpr[3] = ret;
break; break;
case EXCP_DEBUG: case EXCP_DEBUG:
info.si_signo = TARGET_SIGTRAP; force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->nip);
info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_INTERRUPT: case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */ /* just indicate that signals should be handled asap */

View file

@ -30,8 +30,7 @@
void cpu_loop(CPURISCVState *env) void cpu_loop(CPURISCVState *env)
{ {
CPUState *cs = env_cpu(env); CPUState *cs = env_cpu(env);
int trapnr, signum, sigcode; int trapnr;
target_ulong sigaddr;
target_ulong ret; target_ulong ret;
for (;;) { for (;;) {
@ -40,10 +39,6 @@ void cpu_loop(CPURISCVState *env)
cpu_exec_end(cs); cpu_exec_end(cs);
process_queued_cpu_work(cs); process_queued_cpu_work(cs);
signum = 0;
sigcode = 0;
sigaddr = 0;
switch (trapnr) { switch (trapnr) {
case EXCP_INTERRUPT: case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */ /* just indicate that signals should be handled asap */
@ -79,39 +74,23 @@ void cpu_loop(CPURISCVState *env)
} }
break; break;
case RISCV_EXCP_ILLEGAL_INST: case RISCV_EXCP_ILLEGAL_INST:
signum = TARGET_SIGILL; force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc);
sigcode = TARGET_ILL_ILLOPC;
break; break;
case RISCV_EXCP_BREAKPOINT: case RISCV_EXCP_BREAKPOINT:
signum = TARGET_SIGTRAP; case EXCP_DEBUG:
sigcode = TARGET_TRAP_BRKPT; gdbstep:
sigaddr = env->pc; force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
break; break;
case RISCV_EXCP_SEMIHOST: case RISCV_EXCP_SEMIHOST:
env->gpr[xA0] = do_common_semihosting(cs); env->gpr[xA0] = do_common_semihosting(cs);
env->pc += 4; env->pc += 4;
break; break;
case EXCP_DEBUG:
gdbstep:
signum = TARGET_SIGTRAP;
sigcode = TARGET_TRAP_BRKPT;
break;
default: default:
EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n", EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n",
trapnr); trapnr);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (signum) {
target_siginfo_t info = {
.si_signo = signum,
.si_errno = 0,
.si_code = sigcode,
._sifields._sigfault._addr = sigaddr
};
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
}
process_pending_signals(env); process_pending_signals(env);
} }
} }

View file

@ -1,46 +1 @@
/* #include "../generic/target_structs.h"
* RISC-V specific structures for linux-user
*
* This is a copy of ../aarch64/target_structs.h atm.
*
*/
#ifndef RISCV_TARGET_STRUCTS_H
#define RISCV_TARGET_STRUCTS_H
struct target_ipc_perm {
abi_int __key; /* Key. */
abi_uint uid; /* Owner's user ID. */
abi_uint gid; /* Owner's group ID. */
abi_uint cuid; /* Creator's user ID. */
abi_uint cgid; /* Creator's group ID. */
abi_ushort mode; /* Read/write permission. */
abi_ushort __pad1;
abi_ushort __seq; /* Sequence number. */
abi_ushort __pad2;
abi_ulong __unused1;
abi_ulong __unused2;
};
struct target_shmid_ds {
struct target_ipc_perm shm_perm; /* operation permission struct */
abi_long shm_segsz; /* size of segment in bytes */
abi_ulong shm_atime; /* time of last shmat() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused1;
#endif
abi_ulong shm_dtime; /* time of last shmdt() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused2;
#endif
abi_ulong shm_ctime; /* time of last change by shmctl() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused3;
#endif
abi_int shm_cpid; /* pid of creator */
abi_int shm_lpid; /* pid of last shmop */
abi_ulong shm_nattch; /* number of current attaches */
abi_ulong __unused4;
abi_ulong __unused5;
};
#endif

View file

@ -58,7 +58,6 @@ void cpu_loop(CPUS390XState *env)
{ {
CPUState *cs = env_cpu(env); CPUState *cs = env_cpu(env);
int trapnr, n, sig; int trapnr, n, sig;
target_siginfo_t info;
target_ulong addr; target_ulong addr;
abi_long ret; abi_long ret;
@ -158,11 +157,7 @@ void cpu_loop(CPUS390XState *env)
*/ */
env->psw.addr += env->int_pgm_ilen; env->psw.addr += env->int_pgm_ilen;
do_signal: do_signal:
info.si_signo = sig; force_sig_fault(sig, n, addr);
info.si_errno = 0;
info.si_code = n;
info._sifields._sigfault._addr = addr;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_ATOMIC: case EXCP_ATOMIC:

View file

@ -28,7 +28,6 @@ void cpu_loop(CPUSH4State *env)
{ {
CPUState *cs = env_cpu(env); CPUState *cs = env_cpu(env);
int trapnr, ret; int trapnr, ret;
target_siginfo_t info;
while (1) { while (1) {
bool arch_interrupt = true; bool arch_interrupt = true;
@ -60,10 +59,7 @@ void cpu_loop(CPUSH4State *env)
/* just indicate that signals should be handled asap */ /* just indicate that signals should be handled asap */
break; break;
case EXCP_DEBUG: case EXCP_DEBUG:
info.si_signo = TARGET_SIGTRAP; force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_ATOMIC: case EXCP_ATOMIC:
cpu_exec_step_atomic(cs); cpu_exec_step_atomic(cs);

View file

@ -1,58 +1 @@
/* #include "../generic/target_structs.h"
* SH4 specific structures for linux-user
*
* Copyright (c) 2013 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SH4_TARGET_STRUCTS_H
#define SH4_TARGET_STRUCTS_H
struct target_ipc_perm {
abi_int __key; /* Key. */
abi_uint uid; /* Owner's user ID. */
abi_uint gid; /* Owner's group ID. */
abi_uint cuid; /* Creator's user ID. */
abi_uint cgid; /* Creator's group ID. */
abi_ushort mode; /* Read/write permission. */
abi_ushort __pad1;
abi_ushort __seq; /* Sequence number. */
abi_ushort __pad2;
abi_ulong __unused1;
abi_ulong __unused2;
};
struct target_shmid_ds {
struct target_ipc_perm shm_perm; /* operation permission struct */
abi_long shm_segsz; /* size of segment in bytes */
abi_ulong shm_atime; /* time of last shmat() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused1;
#endif
abi_ulong shm_dtime; /* time of last shmdt() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused2;
#endif
abi_ulong shm_ctime; /* time of last change by shmctl() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused3;
#endif
abi_int shm_cpid; /* pid of creator */
abi_int shm_lpid; /* pid of last shmop */
abi_ulong shm_nattch; /* number of current attaches */
abi_ulong __unused4;
abi_ulong __unused5;
};
#endif

View file

@ -155,7 +155,6 @@ void cpu_loop (CPUSPARCState *env)
CPUState *cs = env_cpu(env); CPUState *cs = env_cpu(env);
int trapnr; int trapnr;
abi_long ret; abi_long ret;
target_siginfo_t info;
while (1) { while (1) {
cpu_exec_start(cs); cpu_exec_start(cs);
@ -241,19 +240,10 @@ void cpu_loop (CPUSPARCState *env)
/* just indicate that signals should be handled asap */ /* just indicate that signals should be handled asap */
break; break;
case TT_ILL_INSN: case TT_ILL_INSN:
{ force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc);
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPC;
info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
}
break; break;
case EXCP_DEBUG: case EXCP_DEBUG:
info.si_signo = TARGET_SIGTRAP; force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXCP_ATOMIC: case EXCP_ATOMIC:
cpu_exec_step_atomic(cs); cpu_exec_step_atomic(cs);

View file

@ -6444,11 +6444,15 @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
int deathsig; int deathsig;
ret = get_errno(prctl(PR_GET_PDEATHSIG, &deathsig, ret = get_errno(prctl(PR_GET_PDEATHSIG, &deathsig,
arg3, arg4, arg5)); arg3, arg4, arg5));
if (!is_error(ret) && arg2 && put_user_s32(deathsig, arg2)) { if (!is_error(ret) &&
put_user_s32(host_to_target_signal(deathsig), arg2)) {
return -TARGET_EFAULT; return -TARGET_EFAULT;
} }
return ret; return ret;
} }
case PR_SET_PDEATHSIG:
return get_errno(prctl(PR_SET_PDEATHSIG, target_to_host_signal(arg2),
arg3, arg4, arg5));
case PR_GET_NAME: case PR_GET_NAME:
{ {
void *name = lock_user(VERIFY_WRITE, arg2, 16, 1); void *name = lock_user(VERIFY_WRITE, arg2, 16, 1);
@ -6500,10 +6504,15 @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
case PR_SET_UNALIGN: case PR_SET_UNALIGN:
return do_prctl_set_unalign(env, arg2); return do_prctl_set_unalign(env, arg2);
case PR_CAP_AMBIENT:
case PR_CAPBSET_READ:
case PR_CAPBSET_DROP:
case PR_GET_DUMPABLE: case PR_GET_DUMPABLE:
case PR_SET_DUMPABLE: case PR_SET_DUMPABLE:
case PR_GET_KEEPCAPS: case PR_GET_KEEPCAPS:
case PR_SET_KEEPCAPS: case PR_SET_KEEPCAPS:
case PR_GET_SECUREBITS:
case PR_SET_SECUREBITS:
case PR_GET_TIMING: case PR_GET_TIMING:
case PR_SET_TIMING: case PR_SET_TIMING:
case PR_GET_TIMERSLACK: case PR_GET_TIMERSLACK:
@ -6927,6 +6936,14 @@ typedef abi_long from_flock64_fn(struct flock64 *fl, abi_ulong target_addr);
typedef abi_long to_flock64_fn(abi_ulong target_addr, const struct flock64 *fl); typedef abi_long to_flock64_fn(abi_ulong target_addr, const struct flock64 *fl);
#if defined(TARGET_ARM) && TARGET_ABI_BITS == 32 #if defined(TARGET_ARM) && TARGET_ABI_BITS == 32
struct target_oabi_flock64 {
abi_short l_type;
abi_short l_whence;
abi_llong l_start;
abi_llong l_len;
abi_int l_pid;
} QEMU_PACKED;
static inline abi_long copy_from_user_oabi_flock64(struct flock64 *fl, static inline abi_long copy_from_user_oabi_flock64(struct flock64 *fl,
abi_ulong target_flock_addr) abi_ulong target_flock_addr)
{ {

View file

@ -688,7 +688,7 @@ typedef struct target_siginfo {
#define TARGET_FPE_FLTINV (7) /* floating point invalid operation */ #define TARGET_FPE_FLTINV (7) /* floating point invalid operation */
#define TARGET_FPE_FLTSUB (8) /* subscript out of range */ #define TARGET_FPE_FLTSUB (8) /* subscript out of range */
#define TARGET_FPE_FLTUNK (14) /* undiagnosed fp exception */ #define TARGET_FPE_FLTUNK (14) /* undiagnosed fp exception */
#define TARGET_NSIGFPE 15 #define TARGET_FPE_CONDTRAP (15) /* trap on condition */
/* /*
* SIGSEGV si_codes * SIGSEGV si_codes
@ -715,6 +715,7 @@ typedef struct target_siginfo {
#define TARGET_TRAP_TRACE (2) /* process trace trap */ #define TARGET_TRAP_TRACE (2) /* process trace trap */
#define TARGET_TRAP_BRANCH (3) /* process taken branch trap */ #define TARGET_TRAP_BRANCH (3) /* process taken branch trap */
#define TARGET_TRAP_HWBKPT (4) /* hardware breakpoint/watchpoint */ #define TARGET_TRAP_HWBKPT (4) /* hardware breakpoint/watchpoint */
#define TARGET_TRAP_UNK (5) /* undiagnosed trap */
struct target_rlimit { struct target_rlimit {
abi_ulong rlim_cur; abi_ulong rlim_cur;

View file

@ -19,41 +19,7 @@
#ifndef X86_64_TARGET_STRUCTS_H #ifndef X86_64_TARGET_STRUCTS_H
#define X86_64_TARGET_STRUCTS_H #define X86_64_TARGET_STRUCTS_H
struct target_ipc_perm { #include "../generic/target_structs.h"
abi_int __key; /* Key. */
abi_uint uid; /* Owner's user ID. */
abi_uint gid; /* Owner's group ID. */
abi_uint cuid; /* Creator's user ID. */
abi_uint cgid; /* Creator's group ID. */
abi_ushort mode; /* Read/write permission. */
abi_ushort __pad1;
abi_ushort __seq; /* Sequence number. */
abi_ushort __pad2;
abi_ulong __unused1;
abi_ulong __unused2;
};
struct target_shmid_ds {
struct target_ipc_perm shm_perm; /* operation permission struct */
abi_long shm_segsz; /* size of segment in bytes */
abi_ulong shm_atime; /* time of last shmat() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused1;
#endif
abi_ulong shm_dtime; /* time of last shmdt() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused2;
#endif
abi_ulong shm_ctime; /* time of last change by shmctl() */
#if TARGET_ABI_BITS == 32
abi_ulong __unused3;
#endif
abi_int shm_cpid; /* pid of creator */
abi_int shm_lpid; /* pid of last shmop */
abi_ulong shm_nattch; /* number of current attaches */
abi_ulong __unused4;
abi_ulong __unused5;
};
/* The x86 definition differs from the generic one in that the /* The x86 definition differs from the generic one in that the
* two padding fields exist whether the ABI is 32 bits or 64 bits. * two padding fields exist whether the ABI is 32 bits or 64 bits.

View file

@ -126,7 +126,6 @@ static void xtensa_underflow12(CPUXtensaState *env)
void cpu_loop(CPUXtensaState *env) void cpu_loop(CPUXtensaState *env)
{ {
CPUState *cs = env_cpu(env); CPUState *cs = env_cpu(env);
target_siginfo_t info;
abi_ulong ret; abi_ulong ret;
int trapnr; int trapnr;
@ -163,14 +162,12 @@ void cpu_loop(CPUXtensaState *env)
case EXC_USER: case EXC_USER:
switch (env->sregs[EXCCAUSE]) { switch (env->sregs[EXCCAUSE]) {
case ILLEGAL_INSTRUCTION_CAUSE: case ILLEGAL_INSTRUCTION_CAUSE:
force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC,
env->sregs[EPC1]);
break;
case PRIVILEGED_CAUSE: case PRIVILEGED_CAUSE:
info.si_signo = TARGET_SIGILL; force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC,
info.si_errno = 0; env->sregs[EPC1]);
info.si_code =
env->sregs[EXCCAUSE] == ILLEGAL_INSTRUCTION_CAUSE ?
TARGET_ILL_ILLOPC : TARGET_ILL_PRVOPC;
info._sifields._sigfault._addr = env->sregs[EPC1];
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case SYSCALL_CAUSE: case SYSCALL_CAUSE:
@ -219,11 +216,8 @@ void cpu_loop(CPUXtensaState *env)
break; break;
case INTEGER_DIVIDE_BY_ZERO_CAUSE: case INTEGER_DIVIDE_BY_ZERO_CAUSE:
info.si_signo = TARGET_SIGFPE; force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV,
info.si_errno = 0; env->sregs[EPC1]);
info.si_code = TARGET_FPE_INTDIV;
info._sifields._sigfault._addr = env->sregs[EPC1];
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
default: default:
@ -232,10 +226,8 @@ void cpu_loop(CPUXtensaState *env)
} }
break; break;
case EXCP_DEBUG: case EXCP_DEBUG:
info.si_signo = TARGET_SIGTRAP; force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT,
info.si_errno = 0; env->sregs[EPC1]);
info.si_code = TARGET_TRAP_BRKPT;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break; break;
case EXC_DEBUG: case EXC_DEBUG:
default: default:

View file

@ -822,7 +822,7 @@ static void gen_pool16c_insn(DisasContext *ctx)
gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode)); gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
break; break;
case BREAK16: case BREAK16:
generate_exception_end(ctx, EXCP_BREAK); generate_exception_break(ctx, extract32(ctx->opcode, 0, 4));
break; break;
case SDBBP16: case SDBBP16:
if (is_uhi(extract32(ctx->opcode, 0, 4))) { if (is_uhi(extract32(ctx->opcode, 0, 4))) {
@ -937,7 +937,7 @@ static void gen_pool16c_r6_insn(DisasContext *ctx)
break; break;
case R6_BREAK16: case R6_BREAK16:
/* BREAK16 */ /* BREAK16 */
generate_exception(ctx, EXCP_BREAK); generate_exception_break(ctx, extract32(ctx->opcode, 6, 4));
break; break;
case R6_SDBBP16: case R6_SDBBP16:
/* SDBBP16 */ /* SDBBP16 */
@ -1047,7 +1047,7 @@ static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
case TNE: case TNE:
mips32_op = OPC_TNE; mips32_op = OPC_TNE;
do_trap: do_trap:
gen_trap(ctx, mips32_op, rs, rt, -1); gen_trap(ctx, mips32_op, rs, rt, -1, extract32(ctx->opcode, 12, 4));
break; break;
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
case MFC0: case MFC0:
@ -1812,7 +1812,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
gen_pool32axf(env, ctx, rt, rs); gen_pool32axf(env, ctx, rt, rs);
break; break;
case BREAK32: case BREAK32:
generate_exception_end(ctx, EXCP_BREAK); generate_exception_break(ctx, extract32(ctx->opcode, 6, 20));
break; break;
case SIGRIE: case SIGRIE:
check_insn(ctx, ISA_MIPS_R6); check_insn(ctx, ISA_MIPS_R6);
@ -2439,7 +2439,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
check_insn_opc_removed(ctx, ISA_MIPS_R6); check_insn_opc_removed(ctx, ISA_MIPS_R6);
mips32_op = OPC_TEQI; mips32_op = OPC_TEQI;
do_trapi: do_trapi:
gen_trap(ctx, mips32_op, rs, -1, imm); gen_trap(ctx, mips32_op, rs, -1, imm, 0);
break; break;
case BNEZC: case BNEZC:

View file

@ -969,7 +969,7 @@ static int decode_ase_mips16e(CPUMIPSState *env, DisasContext *ctx)
gen_slt(ctx, OPC_SLTU, 24, rx, ry); gen_slt(ctx, OPC_SLTU, 24, rx, ry);
break; break;
case RR_BREAK: case RR_BREAK:
generate_exception_end(ctx, EXCP_BREAK); generate_exception_break(ctx, extract32(ctx->opcode, 5, 6));
break; break;
case RR_SLLV: case RR_SLLV:
gen_shift(ctx, OPC_SLLV, ry, rx, ry); gen_shift(ctx, OPC_SLLV, ry, rx, ry);

View file

@ -1268,11 +1268,11 @@ static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
switch (extract32(ctx->opcode, 10, 1)) { switch (extract32(ctx->opcode, 10, 1)) {
case NM_TEQ: case NM_TEQ:
check_nms(ctx); check_nms(ctx);
gen_trap(ctx, OPC_TEQ, rs, rt, -1); gen_trap(ctx, OPC_TEQ, rs, rt, -1, rd);
break; break;
case NM_TNE: case NM_TNE:
check_nms(ctx); check_nms(ctx);
gen_trap(ctx, OPC_TNE, rs, rt, -1); gen_trap(ctx, OPC_TNE, rs, rt, -1, rd);
break; break;
} }
break; break;

View file

@ -1367,6 +1367,16 @@ void generate_exception_end(DisasContext *ctx, int excp)
generate_exception_err(ctx, excp, 0); generate_exception_err(ctx, excp, 0);
} }
void generate_exception_break(DisasContext *ctx, int code)
{
#ifdef CONFIG_USER_ONLY
/* Pass the break code along to cpu_loop. */
tcg_gen_st_i32(tcg_constant_i32(code), cpu_env,
offsetof(CPUMIPSState, error_code));
#endif
generate_exception_end(ctx, EXCP_BREAK);
}
void gen_reserved_instruction(DisasContext *ctx) void gen_reserved_instruction(DisasContext *ctx)
{ {
generate_exception_end(ctx, EXCP_RI); generate_exception_end(ctx, EXCP_RI);
@ -4723,7 +4733,7 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
/* Traps */ /* Traps */
static void gen_trap(DisasContext *ctx, uint32_t opc, static void gen_trap(DisasContext *ctx, uint32_t opc,
int rs, int rt, int16_t imm) int rs, int rt, int16_t imm, int code)
{ {
int cond; int cond;
TCGv t0 = tcg_temp_new(); TCGv t0 = tcg_temp_new();
@ -4768,6 +4778,11 @@ static void gen_trap(DisasContext *ctx, uint32_t opc,
case OPC_TGEU: /* rs >= rs unsigned */ case OPC_TGEU: /* rs >= rs unsigned */
case OPC_TGEIU: /* r0 >= 0 unsigned */ case OPC_TGEIU: /* r0 >= 0 unsigned */
/* Always trap */ /* Always trap */
#ifdef CONFIG_USER_ONLY
/* Pass the break code along to cpu_loop. */
tcg_gen_st_i32(tcg_constant_i32(code), cpu_env,
offsetof(CPUMIPSState, error_code));
#endif
generate_exception_end(ctx, EXCP_TRAP); generate_exception_end(ctx, EXCP_TRAP);
break; break;
case OPC_TLT: /* rs < rs */ case OPC_TLT: /* rs < rs */
@ -4808,6 +4823,18 @@ static void gen_trap(DisasContext *ctx, uint32_t opc,
tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1); tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
break; break;
} }
#ifdef CONFIG_USER_ONLY
/* Pass the break code along to cpu_loop. */
tcg_gen_st_i32(tcg_constant_i32(code), cpu_env,
offsetof(CPUMIPSState, error_code));
#endif
/* Like save_cpu_state, only don't update saved values. */
if (ctx->base.pc_next != ctx->saved_pc) {
gen_save_pc(ctx->base.pc_next);
}
if (ctx->hflags != ctx->saved_hflags) {
tcg_gen_movi_i32(hflags, ctx->hflags);
}
generate_exception(ctx, EXCP_TRAP); generate_exception(ctx, EXCP_TRAP);
gen_set_label(l1); gen_set_label(l1);
} }
@ -14145,7 +14172,7 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
case OPC_TEQ: case OPC_TEQ:
case OPC_TNE: case OPC_TNE:
check_insn(ctx, ISA_MIPS2); check_insn(ctx, ISA_MIPS2);
gen_trap(ctx, op1, rs, rt, -1); gen_trap(ctx, op1, rs, rt, -1, extract32(ctx->opcode, 6, 10));
break; break;
case OPC_PMON: case OPC_PMON:
/* Pmon entry point, also R4010 selsl */ /* Pmon entry point, also R4010 selsl */
@ -14160,7 +14187,7 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
generate_exception_end(ctx, EXCP_SYSCALL); generate_exception_end(ctx, EXCP_SYSCALL);
break; break;
case OPC_BREAK: case OPC_BREAK:
generate_exception_end(ctx, EXCP_BREAK); generate_exception_break(ctx, extract32(ctx->opcode, 6, 20));
break; break;
case OPC_SYNC: case OPC_SYNC:
check_insn(ctx, ISA_MIPS2); check_insn(ctx, ISA_MIPS2);
@ -15279,11 +15306,10 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
case OPC_TLTI: case OPC_TLTI:
case OPC_TLTIU: case OPC_TLTIU:
case OPC_TEQI: case OPC_TEQI:
case OPC_TNEI: case OPC_TNEI:
check_insn(ctx, ISA_MIPS2); check_insn(ctx, ISA_MIPS2);
check_insn_opc_removed(ctx, ISA_MIPS_R6); check_insn_opc_removed(ctx, ISA_MIPS_R6);
gen_trap(ctx, op1, rs, -1, imm); gen_trap(ctx, op1, rs, -1, imm, 0);
break; break;
case OPC_SIGRIE: case OPC_SIGRIE:
check_insn(ctx, ISA_MIPS_R6); check_insn(ctx, ISA_MIPS_R6);

View file

@ -129,6 +129,7 @@ enum {
void generate_exception(DisasContext *ctx, int excp); void generate_exception(DisasContext *ctx, int excp);
void generate_exception_err(DisasContext *ctx, int excp, int err); void generate_exception_err(DisasContext *ctx, int excp, int err);
void generate_exception_end(DisasContext *ctx, int excp); void generate_exception_end(DisasContext *ctx, int excp);
void generate_exception_break(DisasContext *ctx, int code);
void gen_reserved_instruction(DisasContext *ctx); void gen_reserved_instruction(DisasContext *ctx);
void check_insn(DisasContext *ctx, uint64_t flags); void check_insn(DisasContext *ctx, uint64_t flags);