Implement sparc64_[gs]et_context
authorblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>
Fri, 5 Oct 2007 17:01:51 +0000 (17:01 +0000)
committerblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>
Fri, 5 Oct 2007 17:01:51 +0000 (17:01 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3334 c046a42c-6fe2-441c-8c8c-71466251a162

linux-user/main.c
linux-user/qemu.h
linux-user/signal.c

index 9c3d67d497ef3a59ad8efd77123f528b5d49118e..127ae109a81e6d5009570aa6691e636e6a948301 100644 (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 */
index e07ac7b4dcd26e1dea37b33ae888b60a882a305c..defa6b71e7f1dab9fa852bebc78dd47041e348eb 100644 (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 */
index d17c506d2d75029e6cc555fccc4ea5828efc238c..52041dafdf6d9f8737609f80ef190ba7c710cba0 100644 (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