aboutsummaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorLaurent Vivier <laurent@vivier.eu>2018-04-11 20:56:37 +0200
committerLaurent Vivier <laurent@vivier.eu>2018-04-30 09:48:03 +0200
commitd0a28415e674ec0fee9375a800fb2250e6e0612a (patch)
tree4f5fe709c7574d829f91ca8966adac2fe34a33aa /linux-user
parentd9673512267d081f01fe1e450ac0891ba7d005aa (diff)
linux-user: move sparc/sparc64 cpu loop to sparc directory
No code change, only move code from main.c to sparc/cpu_loop.c. Include sparc/cpu_loop.c in sparc64/cpu_loop.c to avoid to duplicate code. Signed-off-by: Laurent Vivier <laurent@vivier.eu> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Message-Id: <20180411185651.21351-6-laurent@vivier.eu>
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/main.c288
-rw-r--r--linux-user/sparc/cpu_loop.c280
-rw-r--r--linux-user/sparc64/cpu_loop.c8
3 files changed, 282 insertions, 294 deletions
diff --git a/linux-user/main.c b/linux-user/main.c
index 45d1588958..4816ec54bb 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -149,281 +149,6 @@ void fork_end(int child)
}
}
-#ifdef TARGET_SPARC
-#define SPARC64_STACK_BIAS 2047
-
-//#define DEBUG_WIN
-
-/* WARNING: dealing with register windows _is_ complicated. More info
- can be found at http://www.sics.se/~psm/sparcstack.html */
-static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
-{
- index = (index + cwp * 16) % (16 * env->nwindows);
- /* wrap handling : if cwp is on the last window, then we use the
- registers 'after' the end */
- if (index < 8 && env->cwp == env->nwindows - 1)
- index += 16 * env->nwindows;
- return index;
-}
-
-/* save the register window 'cwp1' */
-static inline void save_window_offset(CPUSPARCState *env, int cwp1)
-{
- unsigned int i;
- abi_ulong sp_ptr;
-
- sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
-#ifdef TARGET_SPARC64
- if (sp_ptr & 3)
- sp_ptr += SPARC64_STACK_BIAS;
-#endif
-#if defined(DEBUG_WIN)
- printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n",
- sp_ptr, cwp1);
-#endif
- for(i = 0; i < 16; i++) {
- /* FIXME - what to do if put_user() fails? */
- put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
- sp_ptr += sizeof(abi_ulong);
- }
-}
-
-static void save_window(CPUSPARCState *env)
-{
-#ifndef TARGET_SPARC64
- unsigned int new_wim;
- new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) &
- ((1LL << env->nwindows) - 1);
- save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
- env->wim = new_wim;
-#else
- save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
- env->cansave++;
- env->canrestore--;
-#endif
-}
-
-static void restore_window(CPUSPARCState *env)
-{
-#ifndef TARGET_SPARC64
- unsigned int new_wim;
-#endif
- unsigned int i, cwp1;
- abi_ulong sp_ptr;
-
-#ifndef TARGET_SPARC64
- new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) &
- ((1LL << env->nwindows) - 1);
-#endif
-
- /* restore the invalid window */
- cwp1 = cpu_cwp_inc(env, env->cwp + 1);
- sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
-#ifdef TARGET_SPARC64
- if (sp_ptr & 3)
- sp_ptr += SPARC64_STACK_BIAS;
-#endif
-#if defined(DEBUG_WIN)
- printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n",
- sp_ptr, cwp1);
-#endif
- for(i = 0; i < 16; i++) {
- /* FIXME - what to do if get_user() fails? */
- get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
- sp_ptr += sizeof(abi_ulong);
- }
-#ifdef TARGET_SPARC64
- env->canrestore++;
- if (env->cleanwin < env->nwindows - 1)
- env->cleanwin++;
- env->cansave--;
-#else
- env->wim = new_wim;
-#endif
-}
-
-static void flush_windows(CPUSPARCState *env)
-{
- int offset, cwp1;
-
- offset = 1;
- for(;;) {
- /* if restore would invoke restore_window(), then we can stop */
- cwp1 = cpu_cwp_inc(env, env->cwp + offset);
-#ifndef TARGET_SPARC64
- if (env->wim & (1 << cwp1))
- break;
-#else
- if (env->canrestore == 0)
- break;
- env->cansave++;
- env->canrestore--;
-#endif
- save_window_offset(env, cwp1);
- offset++;
- }
- cwp1 = cpu_cwp_inc(env, env->cwp + 1);
-#ifndef TARGET_SPARC64
- /* set wim so that restore will reload the registers */
- env->wim = 1 << cwp1;
-#endif
-#if defined(DEBUG_WIN)
- printf("flush_windows: nb=%d\n", offset - 1);
-#endif
-}
-
-void cpu_loop (CPUSPARCState *env)
-{
- CPUState *cs = CPU(sparc_env_get_cpu(env));
- int trapnr;
- abi_long ret;
- target_siginfo_t info;
-
- while (1) {
- cpu_exec_start(cs);
- trapnr = cpu_exec(cs);
- cpu_exec_end(cs);
- process_queued_cpu_work(cs);
-
- /* Compute PSR before exposing state. */
- if (env->cc_op != CC_OP_FLAGS) {
- cpu_get_psr(env);
- }
-
- switch (trapnr) {
-#ifndef TARGET_SPARC64
- case 0x88:
- case 0x90:
-#else
- case 0x110:
- case 0x16d:
-#endif
- ret = do_syscall (env, env->gregs[1],
- env->regwptr[0], env->regwptr[1],
- env->regwptr[2], env->regwptr[3],
- env->regwptr[4], env->regwptr[5],
- 0, 0);
- if (ret == -TARGET_ERESTARTSYS || ret == -TARGET_QEMU_ESIGRETURN) {
- break;
- }
- if ((abi_ulong)ret >= (abi_ulong)(-515)) {
-#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
- env->xcc |= PSR_CARRY;
-#else
- env->psr |= PSR_CARRY;
-#endif
- ret = -ret;
- } else {
-#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
- env->xcc &= ~PSR_CARRY;
-#else
- env->psr &= ~PSR_CARRY;
-#endif
- }
- env->regwptr[0] = ret;
- /* next instruction */
- env->pc = env->npc;
- env->npc = env->npc + 4;
- break;
- case 0x83: /* flush windows */
-#ifdef TARGET_ABI32
- case 0x103:
-#endif
- flush_windows(env);
- /* next instruction */
- env->pc = env->npc;
- env->npc = env->npc + 4;
- break;
-#ifndef TARGET_SPARC64
- case TT_WIN_OVF: /* window overflow */
- save_window(env);
- break;
- case TT_WIN_UNF: /* window underflow */
- restore_window(env);
- break;
- case TT_TFAULT:
- case TT_DFAULT:
- {
- info.si_signo = TARGET_SIGSEGV;
- info.si_errno = 0;
- /* XXX: check env->error_code */
- info.si_code = TARGET_SEGV_MAPERR;
- info._sifields._sigfault._addr = env->mmuregs[4];
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- }
- break;
-#else
- case TT_SPILL: /* window overflow */
- save_window(env);
- break;
- case TT_FILL: /* window underflow */
- restore_window(env);
- break;
- case TT_TFAULT:
- case TT_DFAULT:
- {
- info.si_signo = TARGET_SIGSEGV;
- info.si_errno = 0;
- /* XXX: check env->error_code */
- info.si_code = TARGET_SEGV_MAPERR;
- if (trapnr == TT_DFAULT)
- info._sifields._sigfault._addr = env->dmmu.mmuregs[4];
- else
- info._sifields._sigfault._addr = cpu_tsptr(env)->tpc;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- }
- break;
-#ifndef TARGET_ABI32
- case 0x16e:
- flush_windows(env);
- sparc64_get_context(env);
- break;
- case 0x16f:
- flush_windows(env);
- sparc64_set_context(env);
- break;
-#endif
-#endif
- case EXCP_INTERRUPT:
- /* just indicate that signals should be handled asap */
- break;
- case TT_ILL_INSN:
- {
- 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;
- case EXCP_DEBUG:
- {
- int sig;
-
- sig = gdb_handlesig(cs, TARGET_SIGTRAP);
- if (sig)
- {
- info.si_signo = sig;
- info.si_errno = 0;
- info.si_code = TARGET_TRAP_BRKPT;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- }
- }
- break;
- case EXCP_ATOMIC:
- cpu_exec_step_atomic(cs);
- break;
- default:
- printf ("Unhandled trap: 0x%x\n", trapnr);
- cpu_dump_state(cs, stderr, fprintf, 0);
- exit(EXIT_FAILURE);
- }
- process_pending_signals (env);
- }
-}
-
-#endif
-
#ifdef TARGET_PPC
static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env)
{
@@ -4002,18 +3727,7 @@ int main(int argc, char **argv, char **envp)
target_cpu_copy_regs(env, regs);
-#if defined(TARGET_SPARC)
- {
- int i;
- env->pc = regs->pc;
- env->npc = regs->npc;
- env->y = regs->y;
- for(i = 0; i < 8; i++)
- env->gregs[i] = regs->u_regs[i];
- for(i = 0; i < 8; i++)
- env->regwptr[i] = regs->u_regs[i + 8];
- }
-#elif defined(TARGET_PPC)
+#if defined(TARGET_PPC)
{
int i;
diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c
index b7700a5561..7c4796ca23 100644
--- a/linux-user/sparc/cpu_loop.c
+++ b/linux-user/sparc/cpu_loop.c
@@ -21,6 +21,286 @@
#include "qemu.h"
#include "cpu_loop-common.h"
+#define SPARC64_STACK_BIAS 2047
+
+//#define DEBUG_WIN
+
+/* WARNING: dealing with register windows _is_ complicated. More info
+ can be found at http://www.sics.se/~psm/sparcstack.html */
+static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
+{
+ index = (index + cwp * 16) % (16 * env->nwindows);
+ /* wrap handling : if cwp is on the last window, then we use the
+ registers 'after' the end */
+ if (index < 8 && env->cwp == env->nwindows - 1)
+ index += 16 * env->nwindows;
+ return index;
+}
+
+/* save the register window 'cwp1' */
+static inline void save_window_offset(CPUSPARCState *env, int cwp1)
+{
+ unsigned int i;
+ abi_ulong sp_ptr;
+
+ sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
+#ifdef TARGET_SPARC64
+ if (sp_ptr & 3)
+ sp_ptr += SPARC64_STACK_BIAS;
+#endif
+#if defined(DEBUG_WIN)
+ printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n",
+ sp_ptr, cwp1);
+#endif
+ for(i = 0; i < 16; i++) {
+ /* FIXME - what to do if put_user() fails? */
+ put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
+ sp_ptr += sizeof(abi_ulong);
+ }
+}
+
+static void save_window(CPUSPARCState *env)
+{
+#ifndef TARGET_SPARC64
+ unsigned int new_wim;
+ new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) &
+ ((1LL << env->nwindows) - 1);
+ save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
+ env->wim = new_wim;
+#else
+ save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
+ env->cansave++;
+ env->canrestore--;
+#endif
+}
+
+static void restore_window(CPUSPARCState *env)
+{
+#ifndef TARGET_SPARC64
+ unsigned int new_wim;
+#endif
+ unsigned int i, cwp1;
+ abi_ulong sp_ptr;
+
+#ifndef TARGET_SPARC64
+ new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) &
+ ((1LL << env->nwindows) - 1);
+#endif
+
+ /* restore the invalid window */
+ cwp1 = cpu_cwp_inc(env, env->cwp + 1);
+ sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
+#ifdef TARGET_SPARC64
+ if (sp_ptr & 3)
+ sp_ptr += SPARC64_STACK_BIAS;
+#endif
+#if defined(DEBUG_WIN)
+ printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n",
+ sp_ptr, cwp1);
+#endif
+ for(i = 0; i < 16; i++) {
+ /* FIXME - what to do if get_user() fails? */
+ get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
+ sp_ptr += sizeof(abi_ulong);
+ }
+#ifdef TARGET_SPARC64
+ env->canrestore++;
+ if (env->cleanwin < env->nwindows - 1)
+ env->cleanwin++;
+ env->cansave--;
+#else
+ env->wim = new_wim;
+#endif
+}
+
+static void flush_windows(CPUSPARCState *env)
+{
+ int offset, cwp1;
+
+ offset = 1;
+ for(;;) {
+ /* if restore would invoke restore_window(), then we can stop */
+ cwp1 = cpu_cwp_inc(env, env->cwp + offset);
+#ifndef TARGET_SPARC64
+ if (env->wim & (1 << cwp1))
+ break;
+#else
+ if (env->canrestore == 0)
+ break;
+ env->cansave++;
+ env->canrestore--;
+#endif
+ save_window_offset(env, cwp1);
+ offset++;
+ }
+ cwp1 = cpu_cwp_inc(env, env->cwp + 1);
+#ifndef TARGET_SPARC64
+ /* set wim so that restore will reload the registers */
+ env->wim = 1 << cwp1;
+#endif
+#if defined(DEBUG_WIN)
+ printf("flush_windows: nb=%d\n", offset - 1);
+#endif
+}
+
+void cpu_loop (CPUSPARCState *env)
+{
+ CPUState *cs = CPU(sparc_env_get_cpu(env));
+ int trapnr;
+ abi_long ret;
+ target_siginfo_t info;
+
+ while (1) {
+ cpu_exec_start(cs);
+ trapnr = cpu_exec(cs);
+ cpu_exec_end(cs);
+ process_queued_cpu_work(cs);
+
+ /* Compute PSR before exposing state. */
+ if (env->cc_op != CC_OP_FLAGS) {
+ cpu_get_psr(env);
+ }
+
+ switch (trapnr) {
+#ifndef TARGET_SPARC64
+ case 0x88:
+ case 0x90:
+#else
+ case 0x110:
+ case 0x16d:
+#endif
+ ret = do_syscall (env, env->gregs[1],
+ env->regwptr[0], env->regwptr[1],
+ env->regwptr[2], env->regwptr[3],
+ env->regwptr[4], env->regwptr[5],
+ 0, 0);
+ if (ret == -TARGET_ERESTARTSYS || ret == -TARGET_QEMU_ESIGRETURN) {
+ break;
+ }
+ if ((abi_ulong)ret >= (abi_ulong)(-515)) {
+#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
+ env->xcc |= PSR_CARRY;
+#else
+ env->psr |= PSR_CARRY;
+#endif
+ ret = -ret;
+ } else {
+#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
+ env->xcc &= ~PSR_CARRY;
+#else
+ env->psr &= ~PSR_CARRY;
+#endif
+ }
+ env->regwptr[0] = ret;
+ /* next instruction */
+ env->pc = env->npc;
+ env->npc = env->npc + 4;
+ break;
+ case 0x83: /* flush windows */
+#ifdef TARGET_ABI32
+ case 0x103:
+#endif
+ flush_windows(env);
+ /* next instruction */
+ env->pc = env->npc;
+ env->npc = env->npc + 4;
+ break;
+#ifndef TARGET_SPARC64
+ case TT_WIN_OVF: /* window overflow */
+ save_window(env);
+ break;
+ case TT_WIN_UNF: /* window underflow */
+ restore_window(env);
+ break;
+ case TT_TFAULT:
+ case TT_DFAULT:
+ {
+ info.si_signo = TARGET_SIGSEGV;
+ info.si_errno = 0;
+ /* XXX: check env->error_code */
+ info.si_code = TARGET_SEGV_MAPERR;
+ info._sifields._sigfault._addr = env->mmuregs[4];
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ }
+ break;
+#else
+ case TT_SPILL: /* window overflow */
+ save_window(env);
+ break;
+ case TT_FILL: /* window underflow */
+ restore_window(env);
+ break;
+ case TT_TFAULT:
+ case TT_DFAULT:
+ {
+ info.si_signo = TARGET_SIGSEGV;
+ info.si_errno = 0;
+ /* XXX: check env->error_code */
+ info.si_code = TARGET_SEGV_MAPERR;
+ if (trapnr == TT_DFAULT)
+ info._sifields._sigfault._addr = env->dmmu.mmuregs[4];
+ else
+ info._sifields._sigfault._addr = cpu_tsptr(env)->tpc;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ }
+ break;
+#ifndef TARGET_ABI32
+ case 0x16e:
+ flush_windows(env);
+ sparc64_get_context(env);
+ break;
+ case 0x16f:
+ flush_windows(env);
+ sparc64_set_context(env);
+ break;
+#endif
+#endif
+ case EXCP_INTERRUPT:
+ /* just indicate that signals should be handled asap */
+ break;
+ case TT_ILL_INSN:
+ {
+ 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;
+ case EXCP_DEBUG:
+ {
+ int sig;
+
+ sig = gdb_handlesig(cs, TARGET_SIGTRAP);
+ if (sig)
+ {
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = TARGET_TRAP_BRKPT;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ }
+ }
+ break;
+ case EXCP_ATOMIC:
+ cpu_exec_step_atomic(cs);
+ break;
+ default:
+ printf ("Unhandled trap: 0x%x\n", trapnr);
+ cpu_dump_state(cs, stderr, fprintf, 0);
+ exit(EXIT_FAILURE);
+ }
+ process_pending_signals (env);
+ }
+}
+
void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
{
+ int i;
+ env->pc = regs->pc;
+ env->npc = regs->npc;
+ env->y = regs->y;
+ for(i = 0; i < 8; i++)
+ env->gregs[i] = regs->u_regs[i];
+ for(i = 0; i < 8; i++)
+ env->regwptr[i] = regs->u_regs[i + 8];
}
diff --git a/linux-user/sparc64/cpu_loop.c b/linux-user/sparc64/cpu_loop.c
index b7700a5561..4fd44e1b1e 100644
--- a/linux-user/sparc64/cpu_loop.c
+++ b/linux-user/sparc64/cpu_loop.c
@@ -17,10 +17,4 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "qemu/osdep.h"
-#include "qemu.h"
-#include "cpu_loop-common.h"
-
-void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
-{
-}
+#include "../sparc/cpu_loop.c"