	;
	;   C.A
	;
	;   (C)Copyright 1990-1992, Matthew Dillon, All Rights Reserved
	;
	;   Amiga startup code for resident and non-resident DCC programs.
	;
	;   DLINK supplied variables:
	;
	;   * __BSS_LEN   : # long words of BSS (occurs after DATA)
	;   * __DATA_LEN  : # long words of initialized data to copy
	;		    (if resident)
	;   * __DATA_BAS  : Base of data (read only if resident)
	;   * __RESIDENT  : Is this code residentable?	If this variable
	;		    is set then there are no absolute data/bss
	;		    references except __DATA_BAS and there is
	;		    NO BSS MEMORY ALLOCATED AFTER THE DATA
	;		    SECTION.
	;
	;		    If this variable is not set then absolute
	;		    references refer to the same storage as
	;		    A4 relative accesses and uninitialized
	;		    BSS space exists just after the data section.
	;
	;		    Note that in the large-data model + fragmented
	;		    sections, there are usually real BSS hunks
	;		    floating about that have been zerod by
	;		    LoadSeg() (in this case __BSS_LEN could be 0)
	;
	;   COMPILER:
	;
	;   * If -r option specified when compiling then the compiler
	;     will generate autoinit code to handle data initialization
	;     that would otherwise require a reloc32 hunk.
	;
	;   * If -r or -md specified compiler references all data items
	;     using A4-Relative addressing.
	;
	;   C LIB CODE:
	;
	;   * Resident: 	Allocate (__DATA_LEN+__BSS_LEN)*4
	;     Not Resident:	Zero out preallocated BSS.
	;
	;   * Generate A4 ref ptr to bss base + 32766 (uses Aztec's
	;     conventions).
	;
	;   * All library code uses the SMALL-DATA with alternate
	;     BSS and DATA section names (based in this source
	;     file) so the linker puts library related data/bss
	;     first.  BUT, BSS always comes after DATA unless
	;     you -frag the link (can't resident a frag'd link),
	;     so if there is more than 64KBytes of *initialized*
	;     data you must -frag the link.
	;
		section text,code

		xref	__RESIDENT	; (dlink), executable is residentable
		xref	__BSS_LEN	; (dlink), length of BSS
		xref	__DATA_BAS	; (dlink), base of initialized data
		xref	__DATA_LEN	; (dlink), length of data

		xref	__main		; we call _main()

		xref	_LVOSetSignal
		xref	_LVOAllocMem
		xref	_LVOFreeMem
		xref	_LVOForbid
		xref	_LVOReplyMsg

		xdef	__exit		; we are _exit()
		xdef	start
		xdef	_SysBase	; we export _SysBase
		xdef	__WBMsg

start:
;;;;;;;;;;;;;;;;movem.l D2-D7/A2-A6,-(sp)	;Not needed!

		move.l	4.W,A6		    ; Exec base

		move.l	sp,A2
		move.l	A0,-(sp)	    ; save arg for _main() call
		move.l	D0,-(sp)	    ; save arglen for _main() call

		;   If we are flagged resident then there is NO BSS ALLOCATED
		;   If we are not flagged resident then BSS IS ALLOCATED AFTER
		;	DATA, BUT NOT CLEARED.

		move.w	#__RESIDENT,D0
		beq	snotres

		;   Allocate BSS+DATA space and then copy static data.

		move.l	#__BSS_LEN,D0
		add.l	#__DATA_LEN,D0
		asl.l	#2,D0		    ; x4
		addq.l	#8,D0		    ; MemList header extra
		move.l	D0,D5		    ; D5 = #bytes
		moveq.l #0,D1		    ; Any memory ok
		jsr	_LVOAllocMem(A6)
		tst.l	D0
		bne	alok
		move.l	A2,sp
		moveq.l #-1,D0
		bra	exfail

alok		move.l	D0,A0
		clr.l	(A0)+		    ; MemList entry next ptr
		move.l	D5,(A0)+	    ; MemList entry #bytes
		lea	32766(A0),A4	    ; SET A4
		lea	-8(A0),A3	    ; A3 = MemList entry base
					    ; can't copy to MemList(A4) yet


		;   Copy data to allocated copy

					    ; A0 = dst
		lea	__DATA_BAS,A1	    ; A1 = src
		move.l	#__DATA_LEN,D0	    ; D0 = long words
		bra	bssent
bsslop		move.l	(A1)+,(A0)+
bssent		dbf	D0,bsslop
		sub.l	#$10000,D0
		bcc	bsslop
		bra	clrbss


		;   Not resident, BSS space has been allocated for us
		;   beyond the specified data, just load the base ptr

snotres 	lea	__DATA_BAS,A4
		lea	32766(A4),A4
		sub.l	A3,A3

clrbss
		;   CLEAR BSS	&-32766(A4) + __DATA_LEN*4

		lea	-32766(A4),A0
		move.l	#__DATA_LEN,D0
		asl.l	#2,D0
		add.l	D0,A0

		move.l	#__BSS_LEN,D0	    ; longwords of bss
		moveq.l #0,D1
		bra	clrent
clrlop		move.l	D1,(A0)+
clrent		dbf	D0,clrlop
		sub.l	#$10000,D0
		bcc	clrlop

		move.l	A3,___MemList(A4)   ; memlist entry (if resident)
		move.l	A2,__ExitSP(A4)     ; sp to restore

		moveq.l #0,D0		    ; new signals
		move.l	#$1000,D1	    ; signal mask
		jsr	_LVOSetSignal(A6)   ; clear ^C

		move.l	A6,_SysBase(A4)     ; resident segment.

		;   Return value of 0 indicates succcess.  Flags
		;   have been set.
		;
		;   Note that if the standard _main entry point is used,
		;   the very first autoinit0 code will check for and
		;   retrieve the workbench message.

		jsr	__AutoInit0	    ; A6 has SYSBase
		bne	xfail
		pea	1.W		    ; autoconfig loader
		jsr	__AutoConfig	    ; note, rt pulls stack
		addq.l	#4,sp
		jsr	__AutoInit1	    ; A6 has SYSBase
		bne	xfail
		jsr	__main(PC)

		;   fall through to low level exit... this avoids referencing
		;   exit() if the user overides _main().

xfail
		clr.l	-(sp)
		clr.l	-(sp)

		;   _EXIT()
		;
		;   since entry uses malloc we must free any incidental memory
		;   at __exit instead of _exit.
		;
		;   ReplyMsg(_WBMsg) just before returning

__exit:
		pea	-1.W
		jsr	__AutoConfig	    ; note, rt pulls stack
		addq.l	#4,sp
		move.l	_SysBase(A4),A6
		jsr	__AutoExit1	    ; A6 has SysBase
		jsr	__AutoExit0	    ; A6 has SysBase

		move.l	4(sp),D0
		move.l	__ExitSP(A4),A7     ; get sp... because we might free
					    ; the space taken by the variable!
		move.l	D0,-(sp)	    ; save exit code on original stack

		move.l	__WBMsg(A4),D6	    ; D6 = WBMsg if it exists

		move.l	___MemList(A4),D0   ; free memory
		beq	ex20

ex10		move.l	D0,A2
		move.l	(A2),A3 	    ; next...
		move.l	4(A2),D0	    ; bytes
		move.l	A2,A1		    ; ptr
		jsr	_LVOFreeMem(A6)
		move.l	A3,D0		    ; next...
		bne	ex10

ex20
		move.l	(sp)+,D0	    ; get exit code
		;move.l  4(sp),D0	     ; get exit code
		;move.l  A5,sp		     ; restore sp

		tst.l	D6		    ; reply to workbench msg if it
		beq	ex30		    ; exists
		jsr	_LVOForbid(A6)	    ; forbid through exit
		move.l	D6,A1
		jsr	_LVOReplyMsg(A6)

ex30
		;   FINIS, poof.

exfail
;;;;;;;;;;;;;;;;movem.l (sp)+,D2-D7/A2-A6
		rts


		;   Base of autoinit section

		section autoinit0,code
__AutoInit0:
		section autoinit1,code
__AutoInit1:
		section autoexit0,code
__AutoExit0:
		section autoexit1,code
__AutoExit1:
		section autoconfig,code
__AutoConfig:


		;   All library C code is compiled with the -S option
		;   which uses 'libdata' and 'libbss' section names,
		;   forcing library data to come before program data
		;   and library bss to come before program bss (because
		;   library data/bss sections are declared here first
		;   and sections of like name are coagulated).
		;
		;   All items are declared as data instead of bss, even
		;   through they could be bss, to support a >64K of
		;   initialized data with the small-data libraries.

		section libdata,data

		xdef	___MemList	; Used by malloc/free
		xdef	__ExitSP

_SysBase	ds.l	1		; Pointer to exec.library
__ExitSP	ds.l	1		; Stack pointer for use in exit
__WBMsg 	ds.l	1		; Workbench startup message
___MemList	ds.l	1		; List of allocated memory

		section libbss,bss
_Reserved	ds.l	0		; Force section to exist (dummy)

		END

