+
+#define FOR64_TRANSITION 1
+
+
+#ifdef FOR64_TRANSITION
+
+struct osigreturn_args {
+ struct ucontext *uctx;
+};
+
+/* ARGSUSED */
+int
+osigreturn(p, uap, retval)
+ struct proc *p;
+ struct osigreturn_args *uap;
+ int *retval;
+{
+ struct ucontext uctx;
+ struct ucontext *p_uctx;
+ struct mcontext64 mctx64;
+ struct mcontext64 *p_64mctx;
+ struct mcontext *p_mctx;
+ int error;
+ thread_act_t th_act;
+ struct sigacts *ps = p->p_sigacts;
+ sigset_t mask;
+ register sig_t action;
+ unsigned long state_count;
+ unsigned int state_flavor;
+ struct uthread * ut;
+ int vec_used = 0;
+ void *tsptr, *fptr, *vptr, *mactx;
+ void ppc_checkthreadstate(void *, int);
+
+ th_act = current_act();
+ /* lets use the larger one */
+ mactx = (void *)&mctx64;
+
+ ut = (struct uthread *)get_bsdthread_info(th_act);
+ if (error = copyin(uap->uctx, &uctx, sizeof(struct ucontext))) {
+ return(error);
+ }
+ if (error = copyin(uctx.uc_mcontext, mactx, uctx.uc_mcsize)) {
+ return(error);
+ }
+
+ if (uctx.uc_onstack & 01)
+ p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
+ else
+ p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
+
+ ut->uu_sigmask = uctx.uc_sigmask & ~sigcantmask;
+ if (ut->uu_siglist & ~ut->uu_sigmask)
+ signal_setast(current_act());
+
+ vec_used = 0;
+ switch (uctx.uc_mcsize) {
+ case UC_FLAVOR64_VEC_SIZE :
+ vec_used = 1;
+ case UC_FLAVOR64_SIZE : {
+ p_64mctx = (struct mcontext64 *)mactx;
+ tsptr = (void *)&p_64mctx->ss;
+ fptr = (void *)&p_64mctx->fs;
+ vptr = (void *)&p_64mctx->vs;
+ state_flavor = PPC_THREAD_STATE64;
+ state_count = PPC_THREAD_STATE64_COUNT;
+ }
+ break;
+ case UC_FLAVOR_VEC_SIZE :
+ vec_used = 1;
+ case UC_FLAVOR_SIZE:
+ default: {
+ p_mctx = (struct mcontext *)mactx;
+ tsptr = (void *)&p_mctx->ss;
+ fptr = (void *)&p_mctx->fs;
+ vptr = (void *)&p_mctx->vs;
+ state_flavor = PPC_THREAD_STATE;
+ state_count = PPC_THREAD_STATE_COUNT;
+ }
+ break;
+ } /* switch () */
+
+ /* validate the thread state, set/reset appropriate mode bits in srr1 */
+ (void)ppc_checkthreadstate(tsptr, state_flavor);
+
+ if (thread_setstatus(th_act, state_flavor, tsptr, &state_count) != KERN_SUCCESS) {
+ return(EINVAL);
+ }
+
+ state_count = PPC_FLOAT_STATE_COUNT;
+ if (thread_setstatus(th_act, PPC_FLOAT_STATE, fptr, &state_count) != KERN_SUCCESS) {
+ return(EINVAL);
+ }
+
+ mask = sigmask(SIGFPE);
+ if (((ut->uu_sigmask & mask) == 0) && (p->p_sigcatch & mask) && ((p->p_sigignore & mask) == 0)) {
+ action = ps->ps_sigact[SIGFPE];
+ if((action != SIG_DFL) && (action != SIG_IGN)) {
+ thread_enable_fpe(th_act, 1);
+ }
+ }
+
+ if (vec_used) {
+ state_count = PPC_VECTOR_STATE_COUNT;
+ if (thread_setstatus(th_act, PPC_VECTOR_STATE, vptr, &state_count) != KERN_SUCCESS) {
+ return(EINVAL);
+ }
+ }
+ return (EJUSTRETURN);
+}
+
+#endif /* FOR64_TRANSITION */
+