/* UnboundTrapImpl.c */

/*
 * The following table describes the Mimosa calling convention.
 * 
 * unitsOut <= 4 & unitsIn <= 64 => The return value is passed back "normally"
 * (in a register) The arguments are passed "normally" (as C arguments) The
 * hidden argument (static link) is after the arguments unitsOut > 4 &
 * unitsIn <= 64 => The pointer to the return record is the first C argument
 * The "real" arguments are passed as C arguments following the first one The
 * hidden argument (static link) is after the arguments unitsOut <= 4 &
 * unitsIn > 64 => The return value is passed back "normally" (in a register)
 * The first C argument is a pointer to the argument record The hidden
 * argument (static link) is the second C argument unitsOut > 4 & unitsIn >
 * 64 => The pointer to the return record is the first C argument The second
 * C argument is a pointer to the argument record The hidden argument (static
 * link) is the third C argument In addition, the the underlying conventions
 * for argument passing differ on Sun-3 and Sun-4.  When passing a structure
 * (which is what C2C uses for anything larger than a word), the Sun-3 passes
 * the value on the stack, and the Sun-4 passes the address of the argument.
 * This is surprising, since the C language specifies that the value be
 * passed by value (the Sun-4 does not violate this semantics, but does make
 * copies of structure arguments). The conditional compilation in the
 * GetUnboundTrapHandler procedure compensates for this difference.
 *
 * The comment regarding the Sun-4 passing the address of the argument is not 
 * quite correct.  The Sun-4 C compiler builds a copy of the structure in the
 * stack and then passes the address of this structure.  It doesn't pass a
 * pointer to the structure itself as implied by the above comment.
 *   -- mna, July 18, 1991
 * 
 */

typedef struct {        
    void* (*code)();
    void* descriptor;        /* actually MesaProc* */
    } MesaProc;
 
typedef struct {        /* MACHINE DEPENDENT */
    MesaProc self;        /* place for InstallationScopesImpl */
                  /* to store the identity of the trap */
    MesaProc *binding;        /* place for InstallationScopesImpl to */
                    /* store a proc desc when eventually this */
                    /* procedure is bound */
    } TrapItem;
    
#define NULL 0
  

static void*
UnboundTrap00(trapItem)
    TrapItem       *trapItem;
{
    if (trapItem->binding != NULL) 
        return( trapItem->binding->code(trapItem->binding) );
    XR←RaiseUnbound(trapItem);
    /* if the preceding statement returns, the trapProc should have been */
    /* replaced by a binding for the previously unbound item */
    return( trapItem->self.code(trapItem) );
};

static void*
UnboundTrap04(arg0, trapItem)
    int        *arg0;
    TrapItem    *trapItem;
{
    if (trapItem->binding != NULL) 
        return( trapItem->binding->code(arg0, trapItem) );
    XR←RaiseUnbound(trapItem);
    return( trapItem->self.code(arg0, trapItem) );
};

static void*
UnboundTrap08(arg0, arg1, trapItem)
    int        *arg0, *arg1;
    TrapItem    *trapItem;
{
    if (trapItem->binding != NULL) 
        return( trapItem->binding->code(arg0, arg1, trapItem) );
    XR←RaiseUnbound(trapItem);
    return( trapItem->self.code(arg0, arg1, trapItem) );
};

static void*
UnboundTrap12(arg0, arg1, arg2, trapItem)
    int        *arg0, *arg1, *arg2;
    TrapItem    *trapItem;
{
    if (trapItem->binding != NULL) 
        return( trapItem->binding->code(arg0, arg1, arg2, trapItem) );
    XR←RaiseUnbound(trapItem);
    return( trapItem->self.code(arg0, arg1, arg2, trapItem) );
};

static void*
UnboundTrap16(arg0, arg1, arg2, arg3, trapItem)
    int        *arg0, *arg1, *arg2, *arg3;
    TrapItem    *trapItem;
{
    if (trapItem->binding != NULL) 
        return( trapItem->binding->code(arg0, arg1, arg2, arg3, trapItem) );
    XR←RaiseUnbound(trapItem);
    return( trapItem->self.code(arg0, arg1, arg2, arg3, trapItem) );
};

static void*
UnboundTrap20(arg0, arg1, arg2, arg3, arg4, trapItem)
    int        *arg0, *arg1, *arg2, *arg3, *arg4;
    TrapItem    *trapItem;
{
    if (trapItem->binding != NULL) 
        return( trapItem->binding->code(arg0, arg1, arg2, arg3, arg4, 
            trapItem) );
    XR←RaiseUnbound(trapItem);
    return( trapItem->self.code(arg0, arg1, arg2, arg3, arg4, 
        trapItem) );
};

static void*
UnboundTrap24(arg0, arg1, arg2, arg3, arg4, arg5, trapItem)
    int        *arg0, *arg1, *arg2, *arg3, *arg4, *arg5;
    TrapItem    *trapItem;
{
    if (trapItem->binding != NULL) 
        return( trapItem->binding->code(arg0, arg1, arg2, arg3, arg4, 
            arg5, trapItem) );
    XR←RaiseUnbound(trapItem);
    return( trapItem->self.code(arg0, arg1, arg2, arg3, arg4, arg5, 
        trapItem) );
};

static void*
UnboundTrap28(arg0, arg1, arg2, arg3, arg4, arg5, arg6, trapItem)
    int        *arg0, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
    TrapItem    *trapItem;
{
    if (trapItem->binding != NULL) 
        return( trapItem->binding->code(arg0, arg1, arg2, arg3, arg4, 
            arg5, arg6, trapItem) );
    XR←RaiseUnbound(trapItem);
    return( trapItem->self.code(arg0, arg1, arg2, arg3, arg4, arg5, 
        arg6, trapItem) );
};

static void*
UnboundTrap32(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, trapItem)
    int        *arg0, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
    int        *arg7;
    TrapItem    *trapItem;
{
    if (trapItem->binding != NULL) 
        return( trapItem->binding->code(arg0, arg1, arg2, arg3, arg4, 
            arg5, arg6, arg7, trapItem) );
    XR←RaiseUnbound(trapItem);
    return( trapItem->self.code(arg0, arg1, arg2, arg3, arg4, arg5, 
        arg6, arg7, trapItem) );
};

static void*
UnboundTrap36(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, 
    arg8, trapItem)
    int        *arg0, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
    int        *arg7, *arg8;
    TrapItem    *trapItem;
{
    if (trapItem->binding != NULL) 
        return( trapItem->binding->code(arg0, arg1, arg2, arg3, arg4, 
            arg5, arg6, arg7, arg8, trapItem) );
    XR←RaiseUnbound(trapItem);
    return( trapItem->self.code(arg0, arg1, arg2, arg3, arg4, arg5, 
        arg6, arg7, arg8, trapItem) );
};

static void*
UnboundTrap40(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, 
    arg8, arg9, trapItem)
    int        *arg0, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
    int        *arg7, *arg8, *arg9;
    TrapItem    *trapItem;
{
    if (trapItem->binding != NULL) 
        return( trapItem->binding->code(arg0, arg1, arg2, arg3, arg4, 
            arg5, arg6, arg7, arg8, arg9, trapItem) );
    XR←RaiseUnbound(trapItem);
    return( trapItem->self.code(arg0, arg1, arg2, arg3, arg4, arg5, 
        arg6, arg7, arg8, arg9, trapItem) );
};

static void*
UnboundTrap44(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, 
    arg8, arg9, arg10, trapItem)
    int        *arg0, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
    int        *arg7, *arg8, *arg9, *arg10;
    TrapItem    *trapItem;
{
    if (trapItem->binding != NULL) 
        return( trapItem->binding->code(arg0, arg1, arg2, arg3, arg4, 
            arg5, arg6, arg7, arg8, arg9, arg10, trapItem) );
    XR←RaiseUnbound(trapItem);
    return( trapItem->self.code(arg0, arg1, arg2, arg3, arg4, arg5, 
        arg6, arg7, arg8, arg9, arg10, trapItem) );
};

static void*
UnboundTrap48(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, 
    arg8, arg9, arg10, arg11, trapItem)
    int        *arg0, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
    int        *arg7, *arg8, *arg9, *arg10, *arg11;
    TrapItem    *trapItem;
{
    if (trapItem->binding != NULL) 
        return( trapItem->binding->code(arg0, arg1, arg2, arg3, arg4, 
            arg5, arg6, arg7, arg8, arg9, arg10, arg11, trapItem) );
    XR←RaiseUnbound(trapItem);
    return( trapItem->self.code(arg0, arg1, arg2, arg3, arg4, arg5, 
        arg6, arg7, arg8, arg9, arg10, arg11, trapItem) );
};

static void*
UnboundTrap52(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, 
    arg8, arg9, arg10, arg11, arg12, trapItem)
    int        *arg0, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
    int        *arg7, *arg8, *arg9, *arg10, *arg11, arg12;
    TrapItem    *trapItem;
{
    if (trapItem->binding != NULL) 
        return( trapItem->binding->code(arg0, arg1, arg2, arg3, arg4, 
            arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, trapItem) );
    XR←RaiseUnbound(trapItem);
    return( trapItem->self.code(arg0, arg1, arg2, arg3, arg4, arg5, 
        arg6, arg7, arg8, arg9, arg10, arg11, arg12, trapItem) );
};

static void*
UnboundTrap56(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, 
    arg8, arg9, arg10, arg11, arg12, arg13, trapItem)
    int        *arg0, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
    int        *arg7, *arg8, *arg9, *arg10, *arg11, *arg12, *arg13;
    TrapItem    *trapItem;
{
    if (trapItem->binding != NULL) 
        return( trapItem->binding->code(arg0, arg1, arg2, arg3, arg4, 
            arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, 
            trapItem) );
    XR←RaiseUnbound(trapItem);
    return( trapItem->self.code(arg0, arg1, arg2, arg3, arg4, arg5, 
        arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, 
        trapItem) );
};

static void*
UnboundTrap60(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, 
    arg8, arg9, arg10, arg11, arg12, arg13, arg14, trapItem)
    int        *arg0, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
    int        *arg7, *arg8, *arg9, *arg10, *arg11, *arg12, *arg13;
    int        *arg14;
    TrapItem    *trapItem;
{
    if (trapItem->binding != NULL) 
        return( trapItem->binding->code(arg0, arg1, arg2, arg3, arg4, 
            arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, 
            arg14, trapItem) );
    XR←RaiseUnbound(trapItem);
    return( trapItem->self.code(arg0, arg1, arg2, arg3, arg4, arg5, 
        arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, 
        trapItem) );
};

static void*
UnboundTrap64(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, 
    arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, trapItem)
    int        *arg0, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
    int        *arg7, *arg8, *arg9, *arg10, *arg11, *arg12, *arg13;
    int        *arg14, *arg15;
    TrapItem    *trapItem;
{
    if (trapItem->binding != NULL) 
        return( trapItem->binding->code(arg0, arg1, arg2, arg3, arg4, 
            arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, 
            arg14, arg15, trapItem) );
    XR←RaiseUnbound(trapItem);
    return( trapItem->self.code(arg0, arg1, arg2, arg3, arg4, arg5, 
        arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, 
        arg15, trapItem) );
};

static void*
UnboundTrap68(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, 
    arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, trapItem)
    int        *arg0, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
    int        *arg7, *arg8, *arg9, *arg10, *arg11, *arg12, *arg13;
    int        *arg14, *arg15, *arg16;
    TrapItem    *trapItem;
{
    if (trapItem->binding != NULL) 
        return( trapItem->binding->code(arg0, arg1, arg2, arg3, arg4, 
            arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, 
            arg14, arg15, arg16, trapItem) );
    XR←RaiseUnbound(trapItem);
    return( trapItem->self.code(arg0, arg1, arg2, arg3, arg4, arg5, 
        arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, 
        arg15, arg16, trapItem) );
};


static void*     (*(Handlers[])) () = {
    UnboundTrap00,
    UnboundTrap04,
    UnboundTrap08,
    UnboundTrap12,
    UnboundTrap16,
    UnboundTrap20,
    UnboundTrap24,
    UnboundTrap28,
    UnboundTrap32,
    UnboundTrap36,
    UnboundTrap40,
    UnboundTrap44,
    UnboundTrap48,
    UnboundTrap52,
    UnboundTrap56,
    UnboundTrap60,
    UnboundTrap64,
    UnboundTrap68
};

#if defined(mc68020) || defined(←IBMR2)
/* 
 * RS6000 C convention for passing structure arguments is
 * like the 68020 (and not the sparc).  A function with 
 * 3 incoming args (of 1 word each) uses the same regs as a 
 * function of a 2-word struct and a 1-word arg.  This is in
 * contrast to the sparc where the 2-word struct is passed in
 * a register as its address rather than as the words of the
 * structure themselves.  -- mna July 18, 1991
 */
void*            (*(
           XR←GetUnboundTrap(unitsOut, unitsIn, argsIn))) ()
    int             unitsOut, unitsIn, argsIn;
{
    int             index;
    if (unitsIn <= 64) {
        if (unitsOut <= 4)
            index = unitsIn / 4;
        else
            index = unitsIn / 4 + 1;
    } else {
        if (unitsOut <= 4)
            index = 1;
        else
            index = 2;
    };
    return (Handlers[index]);
};
#endif

#if defined(sparc)
void*            (*(
           XR←GetUnboundTrap(unitsOut, unitsIn, argsIn))) ()
    int             unitsOut, unitsIn, argsIn;
{
    int             index;
    if (unitsIn <= 64) {
        if (unitsOut <= 4)
            index = argsIn;
        else
            index = argsIn + 1;
    } else {
        if (unitsOut <= 4)
            index = 1;
        else
            index = 2;
    };
    return (Handlers[index]);
};
#endif
#if !defined(mc68020) && !defined(sparc) && !defined(←IBMR2)
-->fix it < --
#endif

void 
XR←RegisterUnboundSignaller(proc)
    int             (*(*proc)) ();
{
/* 
 * this should go away; it is still called, but its effects are no longer
 * required
 * caller: UnboundImpl in RuntimeSupport-Source.df; that should go away, too
 * supplanted by: XR←RaiseUnbound in InstallationScopesImpl.mesa
 */
};