Implement sparc64_[gs]et_context

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3334 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
blueswir1 2007-10-05 17:01:51 +00:00
parent 65f9ee8d67
commit 5bfb56b264
3 changed files with 247 additions and 0 deletions

View File

@ -634,6 +634,14 @@ void cpu_loop (CPUSPARCState *env)
queue_signal(info.si_signo, &info);
}
break;
case 0x16e:
flush_windows(env);
sparc64_get_context(env);
break;
case 0x16f:
flush_windows(env);
sparc64_set_context(env);
break;
#endif
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */

View File

@ -160,6 +160,9 @@ void save_v86_state(CPUX86State *env);
void handle_vm86_trap(CPUX86State *env, int trapno);
void handle_vm86_fault(CPUX86State *env);
int do_vm86(CPUX86State *env, long subfunction, target_ulong v86_addr);
#elif defined(TARGET_SPARC64)
void sparc64_set_context(CPUSPARCState *env);
void sparc64_get_context(CPUSPARCState *env);
#endif
/* mmap.c */

View File

@ -1443,6 +1443,9 @@ struct target_rt_signal_frame {
#define UREG_I0 0
#define UREG_I1 1
#define UREG_I2 2
#define UREG_I3 3
#define UREG_I4 4
#define UREG_I5 5
#define UREG_I6 6
#define UREG_I7 7
#define UREG_L0 8
@ -1704,6 +1707,239 @@ long do_rt_sigreturn(CPUState *env)
return -ENOSYS;
}
#ifdef TARGET_SPARC64
#define MC_TSTATE 0
#define MC_PC 1
#define MC_NPC 2
#define MC_Y 3
#define MC_G1 4
#define MC_G2 5
#define MC_G3 6
#define MC_G4 7
#define MC_G5 8
#define MC_G6 9
#define MC_G7 10
#define MC_O0 11
#define MC_O1 12
#define MC_O2 13
#define MC_O3 14
#define MC_O4 15
#define MC_O5 16
#define MC_O6 17
#define MC_O7 18
#define MC_NGREG 19
typedef target_ulong target_mc_greg_t;
typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG];
struct target_mc_fq {
target_ulong *mcfq_addr;
uint32_t mcfq_insn;
};
struct target_mc_fpu {
union {
uint32_t sregs[32];
uint64_t dregs[32];
//uint128_t qregs[16];
} mcfpu_fregs;
target_ulong mcfpu_fsr;
target_ulong mcfpu_fprs;
target_ulong mcfpu_gsr;
struct target_mc_fq *mcfpu_fq;
unsigned char mcfpu_qcnt;
unsigned char mcfpu_qentsz;
unsigned char mcfpu_enab;
};
typedef struct target_mc_fpu target_mc_fpu_t;
typedef struct {
target_mc_gregset_t mc_gregs;
target_mc_greg_t mc_fp;
target_mc_greg_t mc_i7;
target_mc_fpu_t mc_fpregs;
} target_mcontext_t;
struct target_ucontext {
struct target_ucontext *uc_link;
target_ulong uc_flags;
target_sigset_t uc_sigmask;
target_mcontext_t uc_mcontext;
};
/* A V9 register window */
struct target_reg_window {
target_ulong locals[8];
target_ulong ins[8];
};
#define TARGET_STACK_BIAS 2047
/* {set, get}context() needed for 64-bit SparcLinux userland. */
void sparc64_set_context(CPUSPARCState *env)
{
struct target_ucontext *ucp = (struct target_ucontext *)
env->regwptr[UREG_I0];
target_mc_gregset_t *grp;
target_ulong pc, npc, tstate;
target_ulong fp, i7;
unsigned char fenab;
int err;
unsigned int i;
target_ulong *src, *dst;
grp = &ucp->uc_mcontext.mc_gregs;
err = get_user(pc, &((*grp)[MC_PC]));
err |= get_user(npc, &((*grp)[MC_NPC]));
if (err || ((pc | npc) & 3))
goto do_sigsegv;
if (env->regwptr[UREG_I1]) {
target_sigset_t target_set;
sigset_t set;
if (TARGET_NSIG_WORDS == 1) {
if (get_user(target_set.sig[0], &ucp->uc_sigmask.sig[0]))
goto do_sigsegv;
} else {
src = &ucp->uc_sigmask;
dst = &target_set;
for (i = 0; i < sizeof(target_sigset_t) / sizeof(target_ulong);
i++, dst++, src++)
err |= get_user(dst, src);
if (err)
goto do_sigsegv;
}
target_to_host_sigset_internal(&set, &target_set);
sigprocmask(SIG_SETMASK, &set, NULL);
}
env->pc = pc;
env->npc = npc;
err |= get_user(env->y, &((*grp)[MC_Y]));
err |= get_user(tstate, &((*grp)[MC_TSTATE]));
env->asi = (tstate >> 24) & 0xff;
PUT_CCR(env, tstate >> 32);
PUT_CWP64(env, tstate & 0x1f);
err |= get_user(env->gregs[1], (&(*grp)[MC_G1]));
err |= get_user(env->gregs[2], (&(*grp)[MC_G2]));
err |= get_user(env->gregs[3], (&(*grp)[MC_G3]));
err |= get_user(env->gregs[4], (&(*grp)[MC_G4]));
err |= get_user(env->gregs[5], (&(*grp)[MC_G5]));
err |= get_user(env->gregs[6], (&(*grp)[MC_G6]));
err |= get_user(env->gregs[7], (&(*grp)[MC_G7]));
err |= get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0]));
err |= get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1]));
err |= get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2]));
err |= get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3]));
err |= get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4]));
err |= get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5]));
err |= get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6]));
err |= get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7]));
err |= get_user(fp, &(ucp->uc_mcontext.mc_fp));
err |= get_user(i7, &(ucp->uc_mcontext.mc_i7));
err |= put_user(fp,
(&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6])));
err |= put_user(i7,
(&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7])));
err |= get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab));
err |= get_user(env->fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs));
src = &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs);
dst = &env->fpr;
for (i = 0; i < 64; i++, dst++, src++)
err |= get_user(dst, src);
err |= get_user(env->fsr,
&(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr));
err |= get_user(env->gsr,
&(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr));
if (err)
goto do_sigsegv;
return;
do_sigsegv:
force_sig(SIGSEGV);
}
void sparc64_get_context(CPUSPARCState *env)
{
struct target_ucontext *ucp = (struct target_ucontext *)
env->regwptr[UREG_I0];
target_mc_gregset_t *grp;
target_mcontext_t *mcp;
target_ulong fp, i7;
int err;
unsigned int i;
target_ulong *src, *dst;
target_sigset_t target_set;
sigset_t set;
mcp = &ucp->uc_mcontext;
grp = &mcp->mc_gregs;
/* Skip over the trap instruction, first. */
env->pc = env->npc;
env->npc += 4;
err = 0;
sigprocmask(0, NULL, &set);
host_to_target_sigset_internal(&target_set, &set);
if (TARGET_NSIG_WORDS == 1)
err |= put_user(target_set.sig[0],
(target_ulong *)&ucp->uc_sigmask);
else {
src = &target_set;
dst = &ucp->uc_sigmask;
for (i = 0; i < sizeof(target_sigset_t) / sizeof(target_ulong);
i++, dst++, src++)
err |= put_user(src, dst);
if (err)
goto do_sigsegv;
}
err |= put_user(env->tstate, &((*grp)[MC_TSTATE]));
err |= put_user(env->pc, &((*grp)[MC_PC]));
err |= put_user(env->npc, &((*grp)[MC_NPC]));
err |= put_user(env->y, &((*grp)[MC_Y]));
err |= put_user(env->gregs[1], &((*grp)[MC_G1]));
err |= put_user(env->gregs[2], &((*grp)[MC_G2]));
err |= put_user(env->gregs[3], &((*grp)[MC_G3]));
err |= put_user(env->gregs[4], &((*grp)[MC_G4]));
err |= put_user(env->gregs[5], &((*grp)[MC_G5]));
err |= put_user(env->gregs[6], &((*grp)[MC_G6]));
err |= put_user(env->gregs[7], &((*grp)[MC_G7]));
err |= put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0]));
err |= put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1]));
err |= put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2]));
err |= put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3]));
err |= put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4]));
err |= put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5]));
err |= put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6]));
err |= put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7]));
err |= get_user(fp,
(&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6])));
err |= get_user(i7,
(&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7])));
err |= put_user(fp, &(mcp->mc_fp));
err |= put_user(i7, &(mcp->mc_i7));
src = &env->fpr;
dst = &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs);
for (i = 0; i < 64; i++, dst++, src++)
err |= put_user(src, dst);
err |= put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
err |= put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
err |= put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
if (err)
goto do_sigsegv;
return;
do_sigsegv:
force_sig(SIGSEGV);
}
#endif
#elif defined(TARGET_MIPS64)
# warning signal handling not implemented