**
** ppc.library emulation
** (c)1998-2001 Frank Wille <frank@phoenix.owl.de>
**
** Library initialization
**
** V0.8h (20.04.2001) phx
**       The game continues... enabled StackSwap code, after Gunther
**       Nikl found out that d2 was trashed. Fixed.
**       Now using a stack size of 16K, which should be more than enough!
** V0.8g (17.03.2001) phx
**       StackSwap code disabled again. There are still strange problems
**       reported (crashing AmiDock or WarpGIF datatype). I don't
**       understand it... using a bigger stack should increase stability,
**       not decrease it. :(
** V0.8f (24.01.2001) phx
**       Using StackSwap to 64K to prevent problems with limited
**       ramlib stack space.
** V0.8e (16.12.2000) phx
**       No longer displays requesters for failed file accesses in DEBUGMODE.
**       Better use ppcdbmode to enable this feature.
**       Calls ReadENV() to read environment variables.
** V0.8c (21.10.2000) phx
**       Installs a patch for FreeMem() and FreeVec() to avoid problems
**       with freeing memory, which was previously allocated by the
**       WarpUp-kernel (which would result in an immediate "Defiant" crash).
**       Calls to the private M68k functions will also display a message
**       in the debug log.
** V0.7c (11.01.2000) phx
**       Ok, mea culpa. There *are* PPC boards with LC040 out, so I can't
**       use the FPU on the M68k side.
** V0.7b (07.01.2000) phx
**       Lib-Init requires an FPU to be present (040-FPU is sufficient,
**       no need for math emulation code).
** V0.6g (04.12.1999) phx
**       StackSwap to 16K in libinit implemented, but disabled due to
**       strange problems. Some PPC programs, which are loaded in
**       the same shell as ppc.library, will totally crash the system!
**       A larger stack size (e.g. 256k) will work, but I don't under-
**       stand the reasons.
** V0.6f (16.05.1999) phx
**       PPCAllocPooled == PPCAllocVecPooled and
**       PPCFreePooled == PPCFreeVecPooled.
** V0.6b (18.04.1999) phx
**       68k-Alloc/Free functions are implemented by context-switching
**       to the appropriate PPC-functions.
** V0.6  (10.04.1999) phx
**       MPSemaphore protects the LibBase from reserved0 on.
** V0.5d (09.04.1999) phx
**       PowerUp message system.
**       Debugging facility for unimplemented library functions.
**       MPSemaphore initializiation and cleanup. This special Semaphore
**       guarantees the access arbitration between M68k and PPC.
** V0.5c (20.03.1999) phx
**       Removed PPCAlert(), PPCPutMessage() and PSYSCALL_xxx(),
**       which are not accessible in the original kernel.
** V0.5  (24.01.1999) phx
**       Init/cleanup library-own memory pool.
**       Start ELF-LoadSeg patch.
**       New: CacheClearE.
** V0.4c (18.01.1999) phx
**       ELF-library support.
**       Renamed kernel_exit into kernel_cleanup.
**       Initialize TaskObjects list.
** V0.4b (05.01.1999) phx
**       Calls PowerPC functions kernel_init on library startup and
**       kernel_exit on library expunge (or startup error).
**       kernel_init() in kerntasks.c will determinte CPU type and
**       launch the required PPC support tasks (e.g. for TimerObjects).
** V0.4a (19.12.1998) phx
**	 New: PPCDebugMode.
** V0.4  (26.11.1998) phx
**       PowerPC type, cpu clock and bus clock will be determined when
**       initializing the library base.
**	 New: PPCGetAttrs,ReadByte,WriteByte,ReadWord,WriteWord,
**        ReadLong,WriteLong,WriteLongFlush.
**       Included all kernel symbols of ppc.library V46.19,
**       except _KERNEL_xxxxx.
** V0.1  (15.11.1998) phx
**       First partially working ppc.library emulation. Synchronous PPC
**       tasks, started by runelf, which only use the basic PowerUp kernel
**       functions for I/O, memory and context-switch seem to work fine.
** V0.0  (31.10.1998) phx
**       created
**

	include	"exec/types.i"
	include	"exec/initializers.i"
	include	"exec/resident.i"
	include	"exec/execbase.i"
	include "exec/tasks.i"
	include "exec/memory.i"
	include	"ppclibemu.i"
	include	"powerpc/powerpc.i"
	include	"powerpc_lib.i"


; Stack size for LibInit (which approximately requires 1500 bytes)
STKSIZE		equ	$4000


XAFUNC	macro
	xref	\1
	dc.l	\1
	endm

XCFUNC	macro
	xref	_\1
	dc.l	_\1
	endm

; PowerPC code/data references
	xref	ppcLinkerDB
	xref	_kernel_init
	xref	_kernel_cleanup

; supp.c - memory pools, read environment variables
	xref	_newpool32
	xref	_freepool32
	xref	_ReadENV

; mpsema68k.c
	xref	_initMPSemaphore68k
	xref	_freeMPSemaphore68k

; ELF LoadSeg Patch
	xref	_ELFLoadSegPatch
	xref	_RemLoadSegPatch

; FreeMem/Vec Patch
	xref	_SetFreeMemPatch
	xref	_RemFreeMemPatch



	section	CODE,code

	moveq	#-1,d0
	rts


; struct Resident
	cnop	2,4
ppcModule:
	dc.w	RTC_MATCHWORD
	dc.l	ppcModule
	dc.l	initTab
	dc.b	RTF_AUTOINIT
	dc.b	VERSION
	dc.b	NT_LIBRARY
	dc.b	0
	dc.l 	ppcLibName
	dc.l	ppcLibId
	dc.l	initTab

initTab:
	dc.l	ppclib_SIZE
	dc.l	funcs
	dc.l	dataTable
	dc.l	libinit


; Library functions
funcs:
	dc.l	libopen
	dc.l	libclose
	dc.l	libexpunge
	dc.l	libnull

; M68k library functions
	XCFUNC	PPCLoadObject
	XCFUNC	PPCUnLoadObject
	XCFUNC	PPCRunObject
	XCFUNC	PPCAllocMem
	XCFUNC	PPCFreeMem
	XCFUNC	PPCAllocVec
	XCFUNC	PPCFreeVec
	XAFUNC	PPCDebugMode
	dc.l	PPCReset
	XCFUNC	PPCCreateTask
	XCFUNC	PPCDeleteTask
	XCFUNC	PPCSignalTask
	XCFUNC	PPCFindTask
	dc.l	private1
	dc.l	PPCRunKernelObject
	dc.l	private2
	dc.l	private3
	XCFUNC	PPCGetTaskAttrs
	XCFUNC	PPCGetAttrs
	XCFUNC	PPCFindTaskObject
	dc.l	PPCRunKernelObjectFPU
	XCFUNC	PPCReadLong
	XCFUNC	PPCWriteLong
	dc.l	private4
	dc.l	private5
	dc.l	PPCStartTask
	dc.l	PPCStopTask
	XCFUNC	PPCSetTaskAttrs
	XCFUNC	PPCGetObjectAttrs
	XCFUNC	PPCWriteLongFlush
	XCFUNC	PPCReadWord
	XCFUNC	PPCWriteWord
	XCFUNC	PPCReadByte
	XCFUNC	PPCWriteByte
	XCFUNC	PPCCreatePool
	XCFUNC	PPCDeletePool
	XCFUNC	PPCAllocPooled
	XCFUNC	PPCFreePooled
	XCFUNC	PPCAllocVecPooled
	XCFUNC	PPCFreeVecPooled
	XCFUNC	PPCCreatePort
	XCFUNC	PPCDeletePort
	XCFUNC	PPCObtainPort
	XCFUNC	PPCReleasePort
	XCFUNC	PPCCreateMessage
	XCFUNC	PPCDeleteMessage
	XCFUNC	PPCGetMessageAttr
	XCFUNC	PPCGetMessage
	dc.l	PPCPutMessage
	XCFUNC	PPCReplyMessage
	XCFUNC	PPCSendMessage
	XCFUNC	PPCWaitPort
	XCFUNC	PPCCacheClearE
	XCFUNC	PPCCacheInvalidE
	dc.l	private6
	dc.l	private7
	XCFUNC	PPCCreatePortList
	XCFUNC	PPCDeletePortList
	XCFUNC	PPCAddPortList
	XCFUNC	PPCRemPortList
	XCFUNC	PPCWaitPortList
	XCFUNC	PPCGetPortListAttr
	XCFUNC	PPCSetPortListAttr
	XCFUNC	PPCLoadObjectTagList
	dc.l	PPCSetAttrs
	dc.l	private8
	dc.l	private9
	XCFUNC	PPCCacheTrashE
	dc.l	private10
	dc.l	private11

; Offset -450: PowerUp kernel emulation functions
	XCFUNC	kernPPCAdd64
	XCFUNC	kernPPCAdd64p
	XCFUNC	kernPPCAddHead
	XCFUNC	kernPPCAddHeadSync
	XCFUNC	kernPPCAddPortList
	XCFUNC	kernPPCAddTail
	XCFUNC	kernPPCAddTailSync
	XCFUNC	kernPPCAllocVec		; = kernPPCAllocMem
	XCFUNC	kernPPCAllocVecPooled	; = kernPPCAllocPooled
	XCFUNC	kernPPCAllocSignal
	XCFUNC	kernPPCAllocVec
	XCFUNC	kernPPCAllocVecPooled
	XCFUNC	kernPPCAnd64
	XCFUNC	kernPPCAnd64p
	XCFUNC	kernPPCAsl64
	XCFUNC	kernPPCAsl64p
	XCFUNC	kernPPCAsr64
	XCFUNC	kernPPCAsr64p
	XCFUNC	kernPPCAttemptSemaphore
	XCFUNC	kernPPCAttemptSemaphoreByName
	XCFUNC	kernPPCAttemptSemaphoreShared
	XCFUNC	kernPPCCacheFlush
	XCFUNC	kernPPCCacheFlushAll
	XCFUNC	kernPPCCacheInvalid
	XCFUNC	kernPPCCallM68k
	XCFUNC	kernPPCCallOS
	XCFUNC	kernPPCClose
	XCFUNC	kernPPCCloseLibrary
	XCFUNC	kernPPCCmp64
	XCFUNC	kernPPCCmp64p
	XCFUNC	kernPPCCoerceMethodA
	XCFUNC	kernPPCCreateMessage
	XCFUNC	kernPPCCreatePool
	XCFUNC	kernPPCCreatePort
	XCFUNC	kernPPCCreatePortList
	XCFUNC	kernPPCCreateSemaphore
	XCFUNC	kernPPCCreateTask
	XCFUNC	kernPPCCreateTimerObject
	XCFUNC	kernPPCDeleteMessage
	XCFUNC	kernPPCDeletePool
	XCFUNC	kernPPCDeletePort
	XCFUNC	kernPPCDeletePortList
	XCFUNC	kernPPCDeleteSemaphore
	XCFUNC	kernPPCDeleteTimerObject
	XCFUNC	kernPPCDivRem64
	XCFUNC	kernPPCDivRem64p
	XCFUNC	kernPPCDivs64
	XCFUNC	kernPPCDivs64p
	XCFUNC	kernPPCDivu64
	XCFUNC	kernPPCDivu64p
	XCFUNC	kernPPCDoMethodA
	XCFUNC	kernPPCDoSuperMethodA
	XCFUNC	kernPPCEnqueue
	XCFUNC	kernPPCEnqueueSync
	XCFUNC	kernPPCFindName
	XCFUNC	kernPPCFindNameSync
	XCFUNC	kernPPCFindTagItem
	XCFUNC	kernPPCFindTask
	XCFUNC	kernPPCFinishTask
	XCFUNC	kernPPCfprintf
	XCFUNC	kernPPCFreeVec		; = kernPPCFreeMem
	XCFUNC	kernPPCFreeVecPooled	; = kernPPCFreePooled
	XCFUNC	kernPPCFreeSignal
	XCFUNC	kernPPCFreeVec
	XCFUNC	kernPPCFreeVecPooled
	XCFUNC	kernPPCGetAttr
	XCFUNC	kernPPCGetLibSymbol
	XCFUNC	kernPPCGetMessage
	XCFUNC	kernPPCGetMessageAttr
	XCFUNC	kernPPCGetObjectAttrs
	XCFUNC	kernPPCGetPortListAttr
	XCFUNC	kernPPCGetTagData
	XCFUNC	kernPPCGetTaskAttr
	XCFUNC	kernPPCGetTimerObject
	XCFUNC	kernPPCHandleTimerJobs
	XCFUNC	kernPPCInput
	XCFUNC	kernPPCInsert
	XCFUNC	kernPPCInsertSync
	XCFUNC	kernPPCkprintf
	XCFUNC	kernPPCLoadObject
	XCFUNC	kernPPCLoadObjectTagList
	XCFUNC	kernPPCLockBus
	XCFUNC	kernPPCLsl64
	XCFUNC	kernPPCLsl64p
	XCFUNC	kernPPCLsr64
	XCFUNC	kernPPCLsr64p
	XCFUNC	kernPPCMods64
	XCFUNC	kernPPCMods64p
	XCFUNC	kernPPCModu64
	XCFUNC	kernPPCModu64p
	XCFUNC	kernPPCMuls64
	XCFUNC	kernPPCMuls64p
	XCFUNC	kernPPCMulu64
	XCFUNC	kernPPCMulu64p
	XCFUNC	kernPPCNeg64
	XCFUNC	kernPPCNeg64p
	XCFUNC	kernPPCNewList
	XCFUNC	kernPPCNextTagItem
	XCFUNC	kernPPCObtainPort
	XCFUNC	kernPPCObtainSemaphore
	XCFUNC	kernPPCObtainSemaphoreByName
	XCFUNC	kernPPCObtainSemaphoreShared
	XCFUNC	kernPPCOpen
	XCFUNC	kernPPCOpenLibrary
	XCFUNC	kernPPCOr64
	XCFUNC	kernPPCOr64p
	XCFUNC	kernPPCOutput
	XCFUNC	kernPPCprintf
	XCFUNC	kernPPCRawDoFmt
	XCFUNC	kernPPCRead
	XCFUNC	kernPPCReadByte
	XCFUNC	kernPPCReadLong
	XCFUNC	kernPPCReadWord
	XCFUNC	kernPPCReleasePort
	XCFUNC	kernPPCReleaseSemaphore
	XCFUNC	kernPPCRemHead
	XCFUNC	kernPPCRemHeadSync
	XCFUNC	kernPPCRemove
	XCFUNC	kernPPCRemoveSync
	XCFUNC	kernPPCRemPortList
	XCFUNC	kernPPCRemTail
	XCFUNC	kernPPCRemTailSync
	XCFUNC	kernPPCReplyMessage
	XCFUNC	kernPPCRevision
	XCFUNC	kernPPCSeek
	XCFUNC	kernPPCSendMessage
	XCFUNC	kernPPCSetPortListAttr
	XCFUNC	kernPPCSetSignal
	XCFUNC	kernPPCSetTaskAttr
	XCFUNC	kernPPCSetTimerObject
	XCFUNC	kernPPCSignal
	XCFUNC	kernPPCsprintf
	XCFUNC	kernPPCSub64
	XCFUNC	kernPPCSub64p
	XCFUNC	kernPPCUnLoadObject
	XCFUNC	kernPPCUnLockBus
	XCFUNC	kernPPCVersion
	XCFUNC	kernPPCvfprintf
	XCFUNC	kernPPCvkprintf
	XCFUNC	kernPPCvprintf
	XCFUNC	kernPPCvsprintf
	XCFUNC	kernPPCWait
	XCFUNC	kernPPCWaitPort
	XCFUNC	kernPPCWaitPortList
	XCFUNC	kernPPCWrite
	XCFUNC	kernPPCWriteByte
	XCFUNC	kernPPCWriteLong
	XCFUNC	kernPPCWriteWord
	XCFUNC	kernPPCXor64
	XCFUNC	kernPPCXor64p
	XCFUNC	kernmemcpy
	XCFUNC	kernstrcmp
	XCFUNC	kernstrcpy
	XCFUNC	kernstrlen
	XCFUNC	kern__adddi3
	XCFUNC	kern__anddi3
	XCFUNC	kern__ashldi3
	XCFUNC	kern__ashrdi3
	XCFUNC	kern__cmpdi2
	XCFUNC	kern__divdi3
	XCFUNC	kern__fixdfdi
	XCFUNC	kern__fixsfdi
	XCFUNC	kern__fixunsdfdi
	XCFUNC	kern__fixunssfdi
	XCFUNC	kern__floatdidf
	XCFUNC	kern__floatdisf
	XCFUNC	kern__floatunsdidf
	XCFUNC	kern__iordi3
	XCFUNC	kern__lmulq
	XCFUNC	kern__lshldi3
	XCFUNC	kern__lshrdi3
	XCFUNC	kern__moddi3
	XCFUNC	kern__muldi3
	XCFUNC	kern__negdi2
	XCFUNC	kern__qdivrem
	XCFUNC	kern__subdi3
	XCFUNC	kern__ucmpdi2
	XCFUNC	kern__udivdi3
	XCFUNC	kern__umoddi3
	XCFUNC	kern__xordi3
; the end
	dc.l	-1


dataTable:
	INITBYTE LN_TYPE,NT_LIBRARY
	INITLONG LN_NAME,ppcLibName
	INITBYTE LIB_FLAGS,LIBF_SUMUSED|LIBF_CHANGED
	INITWORD LIB_VERSION,VERSION
	INITWORD LIB_REVISION,REVISION
	INITLONG LIB_IDSTRING,ppcLibId
	dc.l	0

ppcLibName:
	dc.b	"ppc.library",0
ppcLibId:
	REVTXT
powerpcName:
	dc.b	"powerpc.library",0
DOSName:
	dc.b	"dos.library",0
UtilName:
	dc.b	"utility.library",0
IntName:
	dc.b	"intuition.library",0


	cnop	0,4
libinit:
; a6 = ExecBase
; a0 = SegList
; d0 = PPCLibBase
	movem.l	d2/a4-a5,-(sp)
	move.l	d0,a5
	IFD	DEBUGMODE
	or.w	#PPCLibF_Debug,ppclib_Flags(a5)
	ENDC
	move.l	a0,ppclib_SegList(a5)
	move.l	a6,ppclib_SysBase(a5)
	move.l	ppcLinkerDB,ppclib_WOSLinkerDB(a5)
	moveq	#0,d0
	cmp.w	#39,LIB_VERSION(a6)	; OS3.0 required
	blo	initx
	move.w	AttnFlags(a6),d1
	btst	#AFB_68040,d1		; 040/060 is also required
	beq	initx

	move.l	#STKSIZE,d2		; allocate a stack for init.
	move.l	d2,d0
	move.l	#MEMF_PUBLIC,d1
	CALLSYS	AllocMem
	tst.l	d0
	beq	initx
	move.l	d0,-(sp)
	sub.w	#StackSwapStruct_SIZEOF,sp
	move.l	sp,a4			; a4 StackSwapStruct
	move.l	d0,stk_Lower(a4)
	add.l	d2,d0
	move.l	d0,stk_Upper(a4)
	subq.l	#8,d0
	move.l	d0,stk_Pointer(a4)
	move.l	a4,a0
	CALLSYS	StackSwap

	lea	ppclib_PowerPCBase(a5),a0
	move.w	#((ppclib_SIZE-ppclib_PowerPCBase)>>2)-1,d0
1$:	clr.l	(a0)+			; init library base
	dbf	d0,1$
;	lea	ppclib_LibSS(a5),a0
;	move.b	#NT_SEMAPHORE,LN_TYPE(a0)
;	lea	ppcLibName(pc),a1
;	move.l	a1,LN_NAME(a0)
;	CALLSYS	InitSemaphore
	lea	ppclib_ElfObjects(a5),a0
	NEWLIST	a0
	lea	ppclib_TaskObjects(a5),a0
	NEWLIST	a0

	lea	powerpcName(pc),a1
	moveq	#WARPOS_VER,d0
	CALLSYS	OpenLibrary		; powerpc.library for emulation
	move.l	d0,ppclib_PowerPCBase(a5)
	beq	init2
	DPRINT	a5,"ppc.library init! PPCLibBase=0x%08lx, PowerPCBase=0x%08lx\n",a5,d0

	lea	DOSName(pc),a1
	moveq	#36,d0
	CALLSYS	OpenLibrary		; open dos.library V36
	move.l	d0,ppclib_DOSBase(a5)
	beq	init3
	lea	UtilName(pc),a1
	moveq	#36,d0
	CALLSYS	OpenLibrary		; open utility.library V36
	move.l	d0,ppclib_UtilityBase(a5)
	beq	init4
	lea	IntName(pc),a1
	moveq	#36,d0
	CALLSYS	OpenLibrary		; open intuition.library V36
	move.l	d0,ppclib_IntuitionBase(a5)
	beq	init5

	bsr	MPSemaphore_Init
	beq	init6
	bsr	M68k_Init		; get memory, LoadSeg-patch
	beq	init6
	bsr	PowerPC_Init		; init kernel emulation
	bne	init1

init6:	move.l	ppclib_IntuitionBase(a5),a1
	CALLSYS	CloseLibrary
init5:	move.l	ppclib_UtilityBase(a5),a1
	CALLSYS	CloseLibrary
init4:	move.l	ppclib_DOSBase(a5),a1
	CALLSYS	CloseLibrary
init3:	move.l	ppclib_PowerPCBase(a5),a1
	CALLSYS	CloseLibrary
init2:	sub.l	a5,a5

init1:	move.l	a4,a0			; swap to original stack
	CALLSYS	StackSwap
	add.w	#StackSwapStruct_SIZEOF,sp
	move.l	(sp)+,a1
	move.l	d2,d0
	CALLSYS	FreeMem
	move.l	a5,d0
initx:	movem.l	(sp)+,d2/a4-a5
	rts


libnull:
	moveq	#0,d0
	rts


	cnop	0,4
libopen:
	addq.w	#1,LIB_OPENCNT(a6)
	IFD	DEBUGMODE
	moveq	#0,d0
	move.w	LIB_OPENCNT(a6),d0
	DPRINT	a6,"ppc.library opened (OpenCnt=%ld)\n",d0
	ENDC
	bclr	#LIBB_DELEXP,LIB_FLAGS(a6)
	move.l	a6,d0
	rts


	cnop	0,4
libclose:
	subq.w	#1,LIB_OPENCNT(a6)
	IFD	DEBUGMODE
	moveq	#0,d0
	move.w	LIB_OPENCNT(a6),d0
	DPRINT	a6,"ppc.library closed (OpenCnt=%ld)\n",d0
	tst.w	d0
	ENDC
	bne	libnull
	btst	#LIBB_DELEXP,LIB_FLAGS(a6)
	beq	libnull
; fall through

libexpunge:
	DPRINT	a6,"ppc.library expunged!\n"
	movem.l	d2/a5-a6,-(sp)
	move.l	a6,a5
	move.l	ppclib_SysBase(a5),a6
	CALLSYS	Forbid
	tst.w	LIB_OPENCNT(a5)
	beq	2$			; somebody else is using the lib?

1$:	bset	#LIBB_DELEXP,LIB_FLAGS(a5)
	CALLSYS	Permit
	moveq	#0,d0
	bra	9$

2$:	bsr	M68k_Exit		; free memory pool, remove patch
	beq	1$
	move.l	a5,a1
	CALLSYS	Remove			; remove library from system
	CALLSYS	Permit
	bsr	PowerPC_Exit		; kernel emulation cleanup
	bsr	MPSemaphore_Exit
	move.l	ppclib_IntuitionBase(a5),a1
	CALLSYS	CloseLibrary
	move.l	ppclib_UtilityBase(a5),a1
	CALLSYS	CloseLibrary
	move.l	ppclib_DOSBase(a5),a1
	CALLSYS	CloseLibrary
	move.l	ppclib_PowerPCBase(a5),a1
	CALLSYS	CloseLibrary
	move.l	ppclib_SegList(a5),d2
	moveq	#0,d0
	move.l	a5,a1
	move.w	LIB_NEGSIZE(a5),d0
	sub.l	d0,a1
	add.w	LIB_POSSIZE(a5),d0
	CALLSYS	FreeMem			; free PPCLibBase
	move.l	d2,d0			; return SegList ptr

9$:	movem.l	(sp)+,d2/a5-a6
	rts


MPSemaphore_Init:
; a5 = PPCBase
; Make sure, that the protected block of the PPCBase structure is
; 32-bytes aligned in length and position!
	move.l	#ppclib_reserved0+31,d0
	add.l	a5,d0
	and.b	#$e0,d0
	move.l	#ppclib_SIZE,d1
	add.l	a5,d1
	and.b	#$e0,d1
	DPRINT	a5,"MPSemaphore protects 0x%08lx-0x%08lx\n",d0,d1
	sub.l	d0,d1
	move.l	d1,-(sp)
	move.l	d0,-(sp)
	pea	ppclib_LibMPS(a5)
	move.l	a5,-(sp)
	jsr	_initMPSemaphore68k	; (ppcbase,ppcbase->LibMPS,
	add.w	#16,sp			;  ppcbase,sizeof(ppcbase)&~31)
	tst.b	d0
	rts

MPSemaphore_Exit:
; a5 = PPCBase
	pea	ppclib_LibMPS(a5)
	move.l	a5,-(sp)
	jsr	_freeMPSemaphore68k	; (ppcbase,ppcbase->LibMPS)
	addq.l	#8,sp
	rts


M68k_Init:
; a5 = PPCBase
	move.l	a5,-(sp)
	jsr	_ReadENV		; check environment variables
	pea	1024.w
	jsr	_newpool32		; init memory pool for library
	addq.l	#8,sp
	move.l	d0,ppclib_LibPool(a5)
	beq	1$
	move.l	a5,a0
	jsr	_SetFreeMemPatch	; set FreeMem()/FreeVec() patch
	tst.b	d0
	beq	2$
	move.l	a5,a0
	jsr	_ELFLoadSegPatch	; set LoadSeg() patch
	tst.b	d0
	bne	1$
	move.l	a5,a0
	jsr	_RemFreeMemPatch
2$:	move.l	a5,-(sp)
	move.l	ppclib_LibPool(a5),-(sp)
	jsr	_freepool32		; patch failed - free pool
	addq.l	#8,sp
	moveq	#0,d0
1$:	rts

M68k_Exit:
; a5 = PPCBase
	move.l	a5,a0
	jsr	_RemFreeMemPatch
	tst.b	d0
	beq	1$
	move.l	a5,a0
	jsr	_RemLoadSegPatch
	tst.b	d0			; patch removed successfully?
	beq	1$
	move.l	a5,-(sp)
	move.l	ppclib_LibPool(a5),-(sp)
	jsr	_freepool32
	addq.l	#8,sp
	moveq	#1,d0
1$:	rts


PowerPC_Init:
; determine CPU type, clock-, bus-speed, launch PPC support tasks
; a5 = PPCBase
	move.l	a6,-(sp)
	move.l	ppclib_PowerPCBase(a5),a6
	lea	_kernel_init,a0
	bsr	runPPC
	tst.b	d0
	beq	PowerPC_InitError
	move.l	(sp)+,a6
	rts

PowerPC_Exit:
; kernel emulation cleanup
; a5 = PPCBase
	move.l	a6,-(sp)
	move.l	ppclib_PowerPCBase(a5),a6
PowerPC_InitError:
	lea	_kernel_cleanup,a0
	bsr	runPPC
	moveq	#0,d0
	move.l	(sp)+,a6
	rts


	cnop	0,4
runPPC:
; a0 = PowerPC function to call
; a5 = PPCBase
; a6 = PowerPCBase
; -> d0 = PowerPC return code (r3)
	sub.w	#PP_SIZE,sp
	move.l	a5,PP_REGS+0*4(sp)	; r3 = PPCBase
	clr.l	PP_OFFSET(sp)
	clr.l	PP_FLAGS(sp)
	clr.l	PP_STACKPTR(sp)
	clr.l	PP_STACKSIZE(sp)
	move.l	a0,PP_CODE(sp)
	move.l	sp,a0
	jsr	_LVORunPPC(a6)
	move.l	PP_REGS+0*4(sp),d0
	add.w	#PP_SIZE,sp
	rts


; Debugging of unimplemented function calls
PPCReset:
	DPRINT	a6,"Called unimplemented 68k function PPCReset\n"
	moveq	#0,d0
	rts
private1:
	DPRINT	a6,"Called unimplemented 68k function private1\n"
	moveq	#0,d0
	rts
private2:
	DPRINT	a6,"Called unimplemented 68k function private2\n"
	moveq	#0,d0
	rts
private3:
	DPRINT	a6,"Called unimplemented 68k function private3\n"
	moveq	#0,d0
	rts
private4:
	DPRINT	a6,"Called unimplemented 68k function private4\n"
	moveq	#0,d0
	rts
private5:
	DPRINT	a6,"Called unimplemented 68k function private5\n"
	moveq	#0,d0
	rts
private6:
	DPRINT	a6,"Called unimplemented 68k function private6\n"
	moveq	#0,d0
	rts
private7:
	DPRINT	a6,"Called unimplemented 68k function private7\n"
	moveq	#0,d0
	rts
private8:
	DPRINT	a6,"Called unimplemented 68k function private8\n"
	moveq	#0,d0
	rts
private9:
	DPRINT	a6,"Called unimplemented 68k function private9\n"
	moveq	#0,d0
	rts
private10:
	DPRINT	a6,"Called unimplemented 68k function private10\n"
	moveq	#0,d0
	rts
private11:
	DPRINT	a6,"Called unimplemented 68k function private11\n"
	moveq	#0,d0
	rts
PPCPutMessage:
	DPRINT	a6,"Called unimplemented 68k function PPCPutMessage\n"
	moveq	#0,d0
	rts
PPCRunKernelObject:
	DPRINT	a6,"Called unimplemented 68k function PPCRunKernelObject\n"
	moveq	#0,d0
	rts
PPCRunKernelObjectFPU:
	DPRINT	a6,"Called unimplemented 68k function PPCRunKernelObjectFPU\n"
	moveq	#0,d0
	rts
PPCStartTask:
	DPRINT	a6,"Called unimplemented 68k function PPCStartTask\n"
	moveq	#0,d0
	rts
PPCStopTask:
	DPRINT	a6,"Called unimplemented 68k function PPCStopTask\n"
	moveq	#0,d0
	rts
PPCSetAttrs:
	DPRINT	a6,"Called unimplemented 68k function PPCSetAttrs\n"
	moveq	#0,d0
	rts
