/*      $NetBSD: linux_machdep.h,v 1.7 2008/04/28 20:23:42 martin Exp $ */

/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by ITOH Yasufumi.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef _M68K_LINUX_MACHDEP_H
#define _M68K_LINUX_MACHDEP_H

#include <m68k/frame.h>
#include <compat/linux/common/linux_types.h>
#include <compat/linux/common/linux_signal.h>
#include <compat/linux/common/linux_siginfo.h>

/*
* Signal stack definitions for old signal interface.
*/

struct linux_sigcontext {
       linux_old_sigset_t      sc_mask;        /* signal mask to restore */
       u_int                   sc_sp;          /* usp to restore */
       u_int                   sc_d0;
       u_int                   sc_d1;
       u_int                   sc_a0;
       u_int                   sc_a1;
       u_short                 sc_ps;          /* processor status (sr reg) */
       u_int                   sc_pc;

       /*
        * The Linux sigstate (state of hardware).
        */
       struct linux_sigstate {
               u_short         ss_format:4,    /* frame # */
                               ss_vector:12;   /* vector offset */
               struct linux_fpframe {
                       u_int           fpf_regs[2][3]; /* only fp0 and fp1 */
                       u_int           fpf_fpcr;
                       u_int           fpf_fpsr;
                       u_int           fpf_fpiar;
                       union FPF_u1    FPF_u1;
                       union FPF_u2    FPF_u2;
               } ss_fpstate;                   /* 68881/68882 state info */
               union F_u       ss_frame;       /* original exception frame */
       } sc_ss;
};

/*
* The Linux compatible signal frame
* On Linux, the sigtramp code is on the frame structure.
*/
struct linux_sigframe {
       void            *sf_psigtramp;
       int             sf_signum;      /* signo for handler */
       int             sf_code;        /* Linux stores vector offset here */
       struct linux_sigcontext *sf_scp; /* context ptr for handler */
       int             sf_sigtramp[2];
       struct linux_sigc2 {
#if LINUX__NSIG_WORDS > 1
               /* This breaks backward compatibility, but Linux 2.1 has.... */
               u_long  c_extrasigmask[LINUX__NSIG_WORDS - 1];
#endif
               struct  linux_sigcontext c_sc;  /* actual context */
       } sf_c;
};

#define LINUX_SF_SIGTRAMP0 0xDEFC0014   /* addaw #20,sp */
#define LINUX_SF_SIGTRAMP1 (0x70004E40 | (LINUX_SYS_sigreturn << 16))
                               /* moveq #LINUX_SYS_sigreturn,d0; trap #0 */

/*
* Signal stack definitions for new RT signal interface.
*/

typedef struct linux_gregset {
       u_int   gr_regs[16];            /* d0-d7/a0-a6/usp */
       u_int   gr_pc;
       u_int   gr_sr;
} linux_gregset_t;

typedef struct linux_fpregset {
       u_int   fpr_fpcr;
       u_int   fpr_fpsr;
       u_int   fpr_fpiar;
       u_int   fpr_regs[8][3];         /* fp0-fp7 */
} linux_fpregset_t;

struct linux_mcontext {
       int                     mc_version;
       linux_gregset_t         mc_gregs;
       linux_fpregset_t        mc_fpregs;
};

#define LINUX_MCONTEXT_VERSION  2

struct linux_ucontext {
       u_long                  uc_flags;       /* 0 */
       struct linux_ucontext   *uc_link;       /* 0 */
       linux_stack_t           uc_stack;
       struct linux_mcontext   uc_mc;
       struct linux_rt_sigstate {
               struct linux_rt_fpframe {
                       union FPF_u1    FPF_u1;
                       union FPF_u2    FPF_u2;
               } ss_fpstate;
               unsigned int    ss_unused1:16,
                               ss_format:4,
                               ss_vector:12;
               union F_u       ss_frame;       /* original exception frame */
               int             ss_unused2[4];
       } uc_ss;
       linux_sigset_t          uc_sigmask;
};

/*
* The Linux compatible RT signal frame
* On Linux, the sigtramp code is on the frame structure.
*/
struct linux_rt_sigframe {
       void                    *sf_psigtramp;
       int                     sf_signum;
       struct linux_siginfo    *sf_pinfo;
       void                    *sf_puc;
       struct linux_siginfo    sf_info;
       struct linux_ucontext   sf_uc;
       int                     sf_sigtramp[2];
};

#define LINUX_RT_SF_SIGTRAMP0 (0x203C0000 | (LINUX_SYS_rt_sigreturn >> 16))
#define LINUX_RT_SF_SIGTRAMP1 (0x00004E40 | (LINUX_SYS_rt_sigreturn << 16))
                       /* movel #LINUX_SYS_rt_sigreturn,#d0; trap #0 */

#ifdef _KERNEL
__BEGIN_DECLS
void linux_syscall_intern(struct proc *);
__END_DECLS
#endif /* !_KERNEL */

#endif /* _M68K_LINUX_MACHDEP_H */