/*
    (C) 1995, 96 AROS - The Amiga Replacement OS
    $Id$
    $Log$
    Desc:
    Lang: english
*/
#include "exec_intern.h"
#include <aros/lvo.h>

/*****************************************************************************

    NAME */
	#include <clib/exec_protos.h>

	__AROS_LH3(ULONG, MakeFunctions,

/*  SYNOPSIS */
	__AROS_LA(APTR, target,        A0),
	__AROS_LA(APTR, functionArray, A1),
	__AROS_LA(APTR, funcDispBase,  A2),

/*  LOCATION */
	struct ExecBase *, SysBase, 15, Exec)

/*  FUNCTION
	Creates the jumptable for a shared library and flushes the processor's
	instruction cache. Does not checksum the library.

    INPUTS
	target	      - The highest byte +1 of the jumptable. Typically
			this is the library's base address.
	functionArray - Pointer to either an array of function pointers or
			an array of WORD displacements to a given location
			in memory. A value of -1 terminates the array in both
			cases.
	funcDispBase  - The base location for WORD displacements or NULL
			for function pointers.

    RESULT
	Size of the jumptable.

    NOTES

    EXAMPLE

    BUGS

    SEE ALSO

    INTERNALS

    HISTORY

******************************************************************************/
{
    __AROS_FUNC_INIT

    /* Cast for easier access */
    LVEntry *jv=(LVEntry *)target;

    if(funcDispBase!=NULL)
    {
	/* If FuncDispBase is non-NULL it's an array of relative offsets */
	WORD *fp=(WORD *)functionArray;

	/* -1 terminates the array */
	while(*fp!=-1)
	{
	    /* Decrement vector pointer by one and install vector */
	    jv--;
	    jv->lve_Jmp = M68k_JMP;
	    jv->lve_FuncPtr = (APTR) ((UBYTE *)funcDispBase + *fp);

	    /* Use next array entry */
	    fp++;
	}
    }else
    {
	/* If FuncDispBase is NULL it's an array of function pointers */
	void **fp=(void **)functionArray;

	/* -1 terminates the array */
	while(*fp!=(void *)-1)
	{
	    /* Decrement vector pointer by one and install vector */
	    jv--;
	    jv->lve_Jmp = M68k_JMP;
	    jv->lve_FuncPtr = (APTR) *fp;

	    /* Use next array entry */
	    fp++;
	}
    }

    /* Clear instruction cache for the whole jumptable */
    CacheClearE(jv,(BYTE *)funcDispBase-(BYTE *)jv,CACRF_ClearI);

    /* Return size of jumptable */
    return (ULONG)((BYTE *)funcDispBase-(BYTE *)jv);
    __AROS_FUNC_EXIT
} /* MakeFunctions */

