*  Classface.asm - Intuition object/class method invocation
*  This is the Version for non-C language wich didn't use
*  the stupid C paramater stack :), it uses Register
*
*  Classface.asm is Copyright (C) Albert Weinert.
*  Freely distributable under the GNU Library General Public Licence.
*
*  Minor modifications by Frank Copeland [fjc].
*
* Code in here "freezes" these facts (and no others):
*       - pointer to an object's class immediately precedes the object pointer
*       - pointer to a class's superclass is (h_SIZEOF+4) into the class

        TTL ClassFace                  ; Added to assemble with PhxAss [fjc]

        INCLUDE 'exec/types.i'
        INCLUDE 'exec/nodes.i'

        INCLUDE 'utility/hooks.i'
        INCLUDE 'intuition/classusr.i'

* varargs interfaces for invoking method functions
        xdef    _a_DoMethodA
        xdef    _a_DoSuperMethodA
        xdef    _a_CoerceMethodA
        xdef    _a_SetSuperAttrs

        SECTION ClassFace,CODE         ; Added to assemble with PhxAss [fjc]

* DoMethod( o, method_id, param1, param2, ... )
* Invoke upon an object the method function defined by an object's class.
* This function is the only one that you should use unless you are
* implementing a class.
*
_a_DoMethodA: ;( a2 : Object; a1 : Msg );
        move.l  a2,-(a7)        ; rely on a6 being preserved
        move.l  a2,d0           ; be safe
        beq.s   cmnullreturn
        move.l  -4(a2),a0       ; object class ptr precedes object

        bra.s   cminvoke        ; will cleanup a2
        ; ----- don't return here

* DoSuperMethod( cl, o, method_id, param1, param2, ... )
* Invoke upon an object the method defined for the superclass
* of the class specified.  In a class implementation, you
* are passed a pointer to the class you are implementing, which
* you pass to this function to send a message to the object
* considered as a member of your superclass.
*
_a_DoSuperMethodA: ;( a0 : Class; a2 : Object; a1 : Msg );
        move.l  a2,-(a7)        ; rely on a6 being preserved
        move.l  a2,d0           ; be safe (object)
        beq.s   cmnullreturn
        move.l  a0,d0           ; be safe (class)
        beq.s   cmnullreturn
        move.l  h_SIZEOF+4(a0),a0       ; substitute superclass

        bra.s   cminvoke        ; will cleanup a2
        ; ----- don't return here

* CoerceMethod( cl, o, method_id, param1, param2, ... );
* Invoke upon the given object a method function for whatever
* specified class.  This is sort of the primitive basis behind
* DoMethod and DoSuperMethod.
*
_a_CoerceMethodA: ;( a0 : Class; a2 : Object; a1 : Msg );
        move.l  a2,-(a7)        ; rely on a6 being preserved
        move.l  a2,d0           ; be safe (object)
        beq.s   cmnullreturn
        move.l  a0,d0           ; be safe (class)
        beq.s   cmnullreturn
        ; --- registers ready, now call hook
        ;bra.s   cminvoke
        ; ----- don't return here


cminvoke:
        pea.l   cmreturn(pc)
        move.l  h_Entry(a0),-(sp)
        rts
cmnullreturn:
        moveq.l #0,d0
cmreturn:
        move.l  (sp)+,a2
        rts



* SetSuperAttrs( cl, o, tag1, data1, ..., TAG_END );
* A useful varargs conversion to the proper OM_SET method.
_a_SetSuperAttrs: ;( a0 : Class; a2 : Object; a1 : Msg );
        move.l  a2,-(a7)        ; save
        move.l  a2,d0           ; be safe (object)
        beq.s   cmnullreturn
        move.l  a0,d0           ; be safe (class)
        beq.s   cmnullreturn

        move.l  h_SIZEOF+4(a0),a0       ; substitute superclass
        move.l   #0,-(SP)
        move.l   a1,-(SP)
        move.l  #OM_SET,-(SP)        ; MethodID OM_SET
        move.l  SP,A1
        pea.l   ssaret(pc)
        move.l  h_Entry(a0),-(sp)
        rts
ssaret:
        lea     12(sp),sp
        move.l  (sp)+,a2
        rts

        end
