diff options
author | takasi-y@ops.dti.ne.jp <takasi-y@ops.dti.ne.jp> | 2010-02-18 00:46:45 +0900 |
---|---|---|
committer | Aurelien Jarno <aurelien@aurel32.net> | 2010-03-06 19:37:05 +0100 |
commit | d8714436929ab02bd396268f4a36ceea604e386a (patch) | |
tree | eb2b2cfc74cbdbab252e9dcab4ab02ce51694876 | |
parent | 597c0212a7b3f16af26dc29fbb5653999b8cd31f (diff) |
linux-user: Save/restore fpu registers to signal context on sh4
As "todo" comment in source code.
And modify restore_sigcontext() to have three args as kernel's does.
Signed-off-by: Takashi YOSHII <takasi-y@ops.dti.ne.jp>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
-rw-r--r-- | linux-user/signal.c | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/linux-user/signal.c b/linux-user/signal.c index a560a5ce0e..46491674fe 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -2812,6 +2812,7 @@ static int setup_sigcontext(struct target_sigcontext *sc, CPUState *regs, unsigned long mask) { int err = 0; + int i; #define COPY(x) err |= __put_user(regs->x, &sc->sc_##x) COPY(gregs[0]); COPY(gregs[1]); @@ -2827,7 +2828,11 @@ static int setup_sigcontext(struct target_sigcontext *sc, COPY(sr); COPY(pc); #undef COPY - /* todo: save FPU registers here */ + for (i=0; i<16; i++) { + err |= __put_user(regs->fregs[i], &sc->sc_fpregs[i]); + } + err |= __put_user(regs->fpscr, &sc->sc_fpscr); + err |= __put_user(regs->fpul, &sc->sc_fpul); /* non-iBCS2 extensions.. */ err |= __put_user(mask, &sc->oldmask); @@ -2835,10 +2840,11 @@ static int setup_sigcontext(struct target_sigcontext *sc, return err; } -static int restore_sigcontext(CPUState *regs, - struct target_sigcontext *sc) +static int restore_sigcontext(CPUState *regs, struct target_sigcontext *sc, + target_ulong *r0_p) { unsigned int err = 0; + int i; #define COPY(x) err |= __get_user(regs->x, &sc->sc_##x) COPY(gregs[1]); @@ -2854,9 +2860,14 @@ static int restore_sigcontext(CPUState *regs, COPY(sr); COPY(pc); #undef COPY - /* todo: restore FPU registers here */ + for (i=0; i<16; i++) { + err |= __get_user(regs->fregs[i], &sc->sc_fpregs[i]); + } + err |= __get_user(regs->fpscr, &sc->sc_fpscr); + err |= __get_user(regs->fpul, &sc->sc_fpul); regs->tra = -1; /* disable syscall checks */ + err |= __get_user(*r0_p, &sc->sc_gregs[0]); return err; } @@ -2980,6 +2991,7 @@ long do_sigreturn(CPUState *regs) abi_ulong frame_addr; sigset_t blocked; target_sigset_t target_set; + target_ulong r0; int i; int err = 0; @@ -3001,11 +3013,11 @@ long do_sigreturn(CPUState *regs) target_to_host_sigset_internal(&blocked, &target_set); sigprocmask(SIG_SETMASK, &blocked, NULL); - if (restore_sigcontext(regs, &frame->sc)) + if (restore_sigcontext(regs, &frame->sc, &r0)) goto badframe; unlock_user_struct(frame, frame_addr, 0); - return regs->gregs[0]; + return r0; badframe: unlock_user_struct(frame, frame_addr, 0); @@ -3018,6 +3030,7 @@ long do_rt_sigreturn(CPUState *regs) struct target_rt_sigframe *frame; abi_ulong frame_addr; sigset_t blocked; + target_ulong r0; #if defined(DEBUG_SIGNAL) fprintf(stderr, "do_rt_sigreturn\n"); @@ -3029,7 +3042,7 @@ long do_rt_sigreturn(CPUState *regs) target_to_host_sigset(&blocked, &frame->uc.uc_sigmask); sigprocmask(SIG_SETMASK, &blocked, NULL); - if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) goto badframe; if (do_sigaltstack(frame_addr + @@ -3038,7 +3051,7 @@ long do_rt_sigreturn(CPUState *regs) goto badframe; unlock_user_struct(frame, frame_addr, 0); - return regs->gregs[0]; + return r0; badframe: unlock_user_struct(frame, frame_addr, 0); |