/************************************************************************/
/*                                                                      */
/*  ENTRY:  Main entry point routine, it does the following             */
/*                                                                      */
/*          1. Initializes SP as (.startof.(stack) + .sizeof.(stack))   */
/*             which was defined at link time                           */
/*          2. Initializes __HEAP as starting address                   */
/*             of SECTION heap                                          */
/*          3. Initializes the frame pointer to zero for debugger       */
/*          4. Clears the 'zerovars' section.                           */
/*          5. Calls C initialization routine _START                    */
/*                                                                      */
/*      This module also contains the function _exit() which is called  */
/*      by exit() upon program termination.                             */
/*                                                                      */
/************************************************************************/
/*                                                                      */
/*      When using simple A5 relative addressing for purposes other     */
/*      then achieving perfectly reentrant libraries, set the command   */
/*      line switch "-D_A5_REL".                                        */
/*                                                                      */
/************************************************************************/
/*                                                                      */
/*      note:   The special character "%" which appears after           */
/*              some of the comment indicators indicates code which     */
/*              might be used in an environment requiring perfectly     */
/*              reentrant libraries.                                    */
/*                                                                      */
/*              The "%" must be removed if the comment indicator        */
/*              is removed.  It may be used to aid the user in          */
/*              modifying this routine for special applications.        */
/*                                                                      */
/*                   This code:                                         */
/*                      1.  Allocates memory for library static memory  */
/*                          (554 bytes) and stack for one task.         */
/*                      2.  Zeros appropriate memory in the allocated   */
/*                          A5 relative memory.                         */
/*                      3.  Zeros a section named "userzero" which      */
/*                          might contain uninitialized static data     */
/*                          for all user tasks.                         */
/*                                                                      */
/*                   Also, the user must:                               */
/*                      1.  Execute initialization of __HEAP only       */
/*                          once, preferably in the kernel.             */
/*                      2.  Disable interrupts while code which         */
/*                          allocates data and stack space is executing.*/
/*                      3.  Disable interrupts whenever the routine     */
/*                          sbrk() is running.                          */
/*                      4.  The linker command file must be modified    */
/*                          appropriately.                              */
/*                   How interrupts are disabled for 2. and 3. above is */
/*                   left to the user.                                  */
/*                                                                      */
/*                   Please see the section "Multi-Tasking Environments"*/
/*                   in the chapter "Embedded Environments" in the      */
/*                   "MCC68K Reference Manual" for more detail.  Note   */
/*                   that the sample code in this file corresponds most */
/*                   closely to the approach described in               */
/*                   "Multi-Tasking Environments" as opposed to         */
/*                   "Multi-Tasking Environments - a Second Approach".  */
/*                                                                      */
/*                   The user must also manually remove the statement   */
/*                                                                      */
/*                      MOVE.L   #?A5,A5   * A5 LIBRARY INITIALIZATION  */
/*                                                                      */
/*                   if either of the two above approaches are used.    */
/************************************************************************/
           
/*      @(#)entry.c     1.4 9/23/91     */

#include <string.h>             /* DECLARATIONS TO ELIMINATE COMPILER WARNING */

#if _PIC                        /* SET BY COMPILER */
    #if _68020 || _68030 || _68040 || _CPU32
        #define ADDR(x) (x).L(PC)
    #else
        #define ADDR(x) (x).W(PC)
    #endif
#else
    #define ADDR(x)     (x)
#endif

#pragma asm
              OPT       CASE
              COMMON    stack,,D            * DECLARE stack SECTION
              SECTION   code,,C             * CODE SECTION
              XDEF      ENTRY
              XDEF      __exit
*
              XREF      __START
              XREF      _exit
              XREF      _memset
#if _A5_REL                             /* SET BY USER ON COMMAND LINE */
              XREF      ?A5
#endif
*
ENTRY:        MOVE.W    #0,$fffa20              * turn OFF watchdog timer
              MOVE.L    #.STARTOF.(stack),SP    * INITIALIZE STACK POINTER
              ADD.L     #.SIZEOF.(stack),SP     * STACK GROWS DOWN
              LEA       __HEAP,A0               * INITIALIZE HEAP POINTER
              ADDQ.L    #4,A0                   * __HEAP POINTS TO ADDRESS -
              MOVE.L    A0,__HEAP               * JUST BEYOND ITSELF
              MOVE.L    #0,A6                   * FRAME POINTER INITIALIZATION
*%*
*%*           ALLOCATE SPACE FOR LIBRARY DATA AND STACK FOR 1 TASK AND
*%*           ADJUST POINTERS APPROPRIATELY 
*%*
*%            MOVE.L    __HEAP,A5       * ALLOCATE MEMORY FOR DATA AND -
*%            MOVE.L    A5,D0           * STACK SPACE OUT OF HEAP SPACE
*%            ADD.L     #.SIZEOF.(zerovars)+.SIZEOF.(stack)+3,D0
*%            LSR.L     #2,D0           * SHIFT TO LONG WORD ALIGN
*%            LSL.L     #2,D0           * AND SHIFT BACK
*%            MOVE.L    D0,SP           * PLACE IN STACK POINTER
*%            MOVE.L    SP,__HEAP       * ADJUST HEAP ADDRESS
*
*             THE FOLLOWING CODE CLEARS THE zerovars SECTION
*
              LEA       .STARTOF.(zerovars),A0          * START OF SECTION
*
*%            MOVE.L    A5,A0                           * START OF THE SECTION
*%            ADD.L     #?A5,A5                         * ADD OFFSET TO A5
*%            ADD.L     #-.STARTOF.(zerovars),A5        * SUBTRACT SECTION START
*
              MOVE.L    #.SIZEOF.(zerovars),-(SP)       * LENGTH OF THE SECTION
              CLR.L     -(SP)                           * ZERO TO STACK
              MOVE.L    A0,-(SP)                        * START OF SECTION
              JSR       ADDR(_memset)                   * CALL MEMSET TO ZERO
              ADD.L     #12,SP                          * SHRINK STACK
*%*
*%*           THE FOLLOWING CODE CLEARS THE userzero SECTION, IF IT EXISTS
*%*
*%            MOVE.L    #.SIZEOF.(userzero),-(SP)       * LENGTH OF THE SECTION
*%            CLR.L     -(SP)                           * ZERO TO STACK
*%            MOVE.L    #.STARTOF.(userzero),-(SP)      * SECTION START
*%            JSR       ADDR(_memset)                   * CALL MEMSET TO ZERO
*%            ADD.L     #12,SP                          * SHRINK STACK
*
*
#if _A5_REL                     /* SET BY USER ON COMMAND LINE */
*
*             THE FOLLOWING STATEMENT SHOULD NOT BE USED IF A5 RELATIVE
*             ADDRESSING IS TO BE USED TO ACHIEVE PERFECTLY RE-ENTRANT 
*             LIBRARIES.
*
              MOVE.L    #?A5,A5                 * A5 LIBRARY INITIALIZATION
#endif
*
*             THE ROUTINE __START INITIALIZES ALL NON-ZERO MEMORY,
*             OPENS stdin, stdout, stderr, stdaux, AND stdprn.  IT THEN
*             CALLS main.
*
              JSR       ADDR(__START)           * CALL C INITIALIZATION ROUTINE
*
*             __START SHOULD NEVER RETURN.  HOWEVER, IF IT DOES, CALL exit()
*             TO TERMINATE ROUTINE
*
              MOVE.L    D0,-(SP)                * PUSH RETURN VALUE ON STACK
              JSR       ADDR(_exit)             * CALL EXIT -- NO RETURN
*
*             __exit IS CALLED BY exit().  IT SIMPLY EXECUTES A STOP
*             INSTRUCTION.
*
__exit:
              STOP      #$2700
              BRA.S     __exit
              RTS
*
*       DEFINE THE SECTION heap AND PLACE __HEAP THERE
*
              SECTION   heap,,D                 * HEAP SECTION
              XDEF      __HEAP            
__HEAP        DS.L      1
              END       ENTRY
#pragma endasm
