home *** CD-ROM | disk | FTP | other *** search
- *--------------------------------------------------------------------*
- * Startup code to create reentrant program files using the
- * Manx Aztec 'C' compiler (any version).
- *
- * Created by: Olaf Barthel, MXM
- * Brabeckstrasse 35
- * D-3000 Hannover 71
- *
- * Federal Republic of Germany
- *
- *
- * Z-Net: O.BARTHEL@A-Link-H
- * Fido: Olaf Barthel@2:247/200
- * Sub: olsen@veeble.uucp
- * UUCP: olsen%veeble@horga.as.sub.org
- *
- * Copyright (C) 1990 by MXM, all rights reserved.
- *
- *--------------------------------------------------------------------*
- *
- * This startup code permits to create 100% reentrant programs.
- * Neither is arp.library required, nor is the program to be
- * terminated via exit() (such as with Lattice/SAS 'C').
- *
- * The following conditions must be met for the program to
- * work properly:
- *
- * 1) The program MUST not use the large code/large data model.
- *
- * 2) The program MUST not use scatter loading or overlays.
- *
- * Since the entire data segment, containing initialized
- * and uninitialized data (bss), is cloned both data types
- * will reside in the same type of memory (chip/public).
- * This may not be a problem since it already is the default
- * with the small memory/small data model.
- *
- * Important! Your program MUST not perform a segment split
- * using the detach.o?? module or its segment list
- * will be deallocated. Should this happen the next
- * call to your resident program will crash your
- * Amiga!
- *
- * Should you discover any 'undocumented features' or errors
- * in this program, please DO inform me ASAP!
- *
- *--------------------------------------------------------------------*
- *
- * To create a resident program, use the following sequence:
- *
- * AS Resident.asm
- * CC <Programm.c>
- *
- * LN <Programm.o> Resident.o -Lc
- *
- *--------------------------------------------------------------------*
-
- include "exec/types.i"
- include "exec/tasks.i"
- include "exec/alerts.i"
- include "exec/memory.i"
- include "exec/execbase.i"
- include "libraries/dosextens.i"
-
- *--------------------------------------------------------------------*
- *
- * Global macro definitions (doesn't use asmsupp.i).
- *
- *--------------------------------------------------------------------*
-
- CALL macro
- xref _LVO\1
- jsr _LVO\1(a6)
- endm
-
- AbsExecBase equ (4).w
-
- *--------------------------------------------------------------------*
- *
- * Global static and shared data.
- *
- *--------------------------------------------------------------------*
-
- dseg
-
- DosName:
- dc.b 'dos.library',0 ; Name of dos.library.
-
- MemName:
- dc.b 'MXM',0 ; Identification of the
- ; cloned data segment.
-
- public __H1_org,__H1_end,__H2_org,__H2_end
- public __savsp,_SysBase,_DOSBase
-
- *--------------------------------------------------------------------*
-
- cseg
-
- entry .begin
-
- public .begin,_geta4,__main
-
- mc68881
-
- *--------------------------------------------------------------------*
- *
- * Global entry point of the program to follow.
- *
- *--------------------------------------------------------------------*
-
- .begin
- move.l sp,a3 ; Remember stackpointer.
-
- far data
- lea __H1_org+32766,a4 ; Get the data base register.
- near data
-
- lea __H1_end,a1
- lea __H2_org,a2
-
- cmp.l a1,a2 ; Small code/small data?
- bne Error1 ; Obviously not!
-
- movem.l d0/a0,-(sp) ; Remember command line.
-
- lea __H1_org,a1 ; Where's the data segment?
- move.l AbsExecBase,a6 ; SysBase.
-
- CALL TypeOfMem ; Check memory type
-
- bset #MEMB_CLEAR,d0 ; We want clear memory.
- bclr #MEMB_FAST,d0 ; Not necessarily fast mem!
-
- *--------------------------------------------------------------------*
- *
- * We will create a MemEntry structure right on the stack and
- * will copy the contents of the data segment to the allocated
- * block of memory.
- *
- *--------------------------------------------------------------------*
-
- pea (__H2_end-__H1_org).w ; Length of data segment.
- move.l d0,-(sp) ; Type of memory.
- pea (1).w ; Number of entries (1).
- clr.l -(sp) ; Node...
- clr.l -(sp) ; Still node...
- clr.l -(sp) ; Ever still node...
-
- lea (sp),a0 ; Start of MemEntry.
-
- CALL AllocEntry ; Allocate!
-
- add.w #24,sp ; Fix the stack.
-
- move.l d0,a1 ; Did we get an entry?
- beq Error2 ; Fix the stack and quit!
-
- pea (a1) ; Put it on the stack.
-
- *--------------------------------------------------------------------*
- *
- * To help geta4() to identify the MemEntry we will give it
- * a unique name.
- *
- *--------------------------------------------------------------------*
-
- lea MemName,a0 ; Get the node name.
-
- move.l a0,LN_NAME(a1) ; Put it in the MemEntry.
-
- move.l ThisTask(a6),a0 ; Get current task.
-
- lea TC_MEMENTRY(a0),a0 ; Look for MemList.
-
- CALL AddTail ; Add the MemEntry.
-
- move.l (sp)+,a1 ; Get the MemEntry.
- move.l ML_SIZE+ME_ADDR(a1),a1 ; Remember memory block.
-
- lea __H1_org,a0 ; Get start of data segment.
-
- move.l #((__H1_end-__H1_org)/4)-1,d0 ; Remember its length.
-
- *--------------------------------------------------------------------*
- *
- * This loop will copy the contents of the data segment to
- * our 'fake' segment.
- *
- *--------------------------------------------------------------------*
-
- 1$ move.l (a0)+,(a1)+ ; Copy data.
- dbra d0,1$
-
- *--------------------------------------------------------------------*
- *
- * Do the last setups for the main program.
- *
- *--------------------------------------------------------------------*
-
- start bsr _geta4 ; Load the base register.
- move.l a3,__savsp ; Set the original stack
- ; pointer.
- lea DosName,a1 ; Name of dos.library.
- moveq #0,d0 ; No special version.
- CALL OpenLibrary ; Open the tin...
- move.l d0,_DOSBase ; Successful?
- bne 2$ ; Start the main program.
-
- move.l #AG_OpenLib!AO_DOSLib,d7 ; Blast!
- lea ThisTask(a6),a5 ; Current task.
- CALL Alert ; Call Mr.Guru.
- bra Error2 ; Finish it.
-
- 2$ move.l a6,_SysBase ; Set SysBase.
-
- andi.w #AFF_68881,AttnFlags(a6) ; FPU present?
- beq 3$
-
- lea Restore,a5
- CALL Supervisor ; Reset FPU.
-
- 3$ jsr __main ; Call main routine.
- addq.l #8,sp ; Fix the stack.
-
- *--------------------------------------------------------------------*
- *
- * If __main simply 'drops through' dos.library won't have been
- * closed. To keep the counts even, we will test if DOS is still
- * open and close it if necessary.
- *
- *--------------------------------------------------------------------*
-
- move.l _DOSBase,a1
- move.l a1,d0 ; dos.library still open?
- beq 4$ ; Don't think so.
-
- move.l AbsExecBase,a6 ; SysBase.
- CALL CloseLibrary ; Close the library.
-
- 4$ rts ; Back to shell.
-
- *--------------------------------------------------------------------*
-
- Error2: addq.l #8,sp ; Fix the stack.
-
- move.l AbsExecBase,a6 ; SysBase.
-
- *--------------------------------------------------------------------*
- *
- * This part handles early startup failure. If this program was
- * started from Workbench the startup message will probably
- * be roaming around. We will intercept it and send it back
- * to the caller.
- *
- *--------------------------------------------------------------------*
-
- move.l ThisTask(a6),a0 ; Get current task.
- tst.l pr_CLI(a0) ; Started from Workbench?
- bne Error1
-
- lea pr_MsgPort(a0),a0 ; Remember our MsgPort.
- move.l a0,a3
-
- CALL WaitPort ; Wait for WBenchStartup.
-
- move.l a3,a0 ; Return MsgPort.
-
- CALL GetMsg ; Pick up WBenchMsg.
-
- move.l d0,a3 ; Remember Message.
-
- CALL Forbid ; Turn off multitasking.
-
- move.l a3,a1 ; Return the message.
-
- CALL ReplyMsg ; And reply it.
-
- Error1: moveq #-1,d0 ; Failed!
- rts
-
- *--------------------------------------------------------------------*
- *
- * This subroutine will reset the FPU (if any)!
- *
- *--------------------------------------------------------------------*
-
- Restore:
- clr.l -(sp)
- frestore (sp)+ ; Reset the FPU.
- rte
-
- *--------------------------------------------------------------------*
- *
- * One of the most important routines of this file. Sets
- * the global data segment pointer to a defined value.
- *
- *--------------------------------------------------------------------*
-
- _geta4:
- movem.l d0-d1/a0-a1/a6,-(sp) ; Save some registers.
- move.l AbsExecBase,a6 ; SysBase.
- move.l ThisTask(a6),a0 ; Get current task.
- lea TC_MEMENTRY(a0),a0 ; Remember MemList.
- lea MemName,a1 ; Get name of MemEntry.
-
- CALL FindName ; Scan the list...
-
- move.l d0,a1
- move.l ML_SIZE+ME_ADDR(a1),a4 ; Start of data segment.
- lea 32766(a4),a4 ; Add the offset.
-
- movem.l (sp)+,d0-d1/a0-a1/a6 ; Restore all registers.
- rts
-
- *--------------------------------------------------------------------*
-
- end
-