static void setup_rt_frame(int sig, struct target_sigaction *ka,

                           target_siginfo_t *info,

                           target_sigset_t *set, CPUSH4State *regs)

{

    struct target_rt_sigframe *frame;

    abi_ulong frame_addr;

    int i;

    int err = 0;

    int signal;



    frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));

    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))

	goto give_sigsegv;



    signal = current_exec_domain_sig(sig);



    err |= copy_siginfo_to_user(&frame->info, info);



    

    __put_user(0, &frame->uc.tuc_flags);

    __put_user(0, (unsigned long *)&frame->uc.tuc_link);

    __put_user((unsigned long)target_sigaltstack_used.ss_sp,

               &frame->uc.tuc_stack.ss_sp);

    __put_user(sas_ss_flags(regs->gregs[15]),

               &frame->uc.tuc_stack.ss_flags);

    __put_user(target_sigaltstack_used.ss_size,

               &frame->uc.tuc_stack.ss_size);

    setup_sigcontext(&frame->uc.tuc_mcontext,

			    regs, set->sig[0]);

    for(i = 0; i < TARGET_NSIG_WORDS; i++) {

        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);

    }



    



    if (ka->sa_flags & TARGET_SA_RESTORER) {

        regs->pr = (unsigned long) ka->sa_restorer;

    } else {

        

        __put_user(MOVW(2), &frame->retcode[0]);

        __put_user(TRAP_NOARG, &frame->retcode[1]);

        __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);

        regs->pr = (unsigned long) frame->retcode;

    }



    if (err)

        goto give_sigsegv;



    

    regs->gregs[15] = frame_addr;

    regs->gregs[4] = signal; 

    regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);

    regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);

    regs->pc = (unsigned long) ka->_sa_handler;



    unlock_user_struct(frame, frame_addr, 1);

    return;



give_sigsegv:

    unlock_user_struct(frame, frame_addr, 1);

    force_sig(TARGET_SIGSEGV);

}
