home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
351.lha
/
ontrap
/
c.a
< prev
next >
Wrap
Text File
|
1990-02-28
|
11KB
|
435 lines
*
* C initial startup procedure under AmigaDOS
*
* Use the following command line to make c.o
* asm -u -iINCLUDE: c.a
*
* Use the following command line to make cres.o
* asm -u -dRESIDENT -iINCLUDE: -ocres.o c.a
*
INCLUDE "exec/types.i"
INCLUDE "exec/alerts.i"
INCLUDE "exec/nodes.i"
INCLUDE "exec/lists.i"
INCLUDE "exec/ports.i"
INCLUDE "exec/libraries.i"
INCLUDE "exec/tasks.i"
INCLUDE "exec/memory.i"
INCLUDE "exec/execbase.i"
INCLUDE "libraries/dos.i"
INCLUDE "libraries/dosextens.i"
INCLUDE "workbench/startup.i"
INCLUDE "exec/funcdef.i"
INCLUDE "exec/exec_lib.i"
INCLUDE "libraries/dos_lib.i"
MEMFLAGS EQU MEMF_CLEAR+MEMF_PUBLIC
AbsExecBase EQU 4
; some usefull macros:
callsys macro
CALLLIB _LVO\1
endm
xdef XCEXIT * exit(code) is standard way to leave C.
xdef @XCEXIT
xref LinkerDB * linker defined base value
xref _BSSBAS * linker defined base of BSS
xref _BSSLEN * linker defined length of BSS
IFD RESIDENT
xref RESLEN
xref RESBASE
xref NEWDATAL
xref _stack
ENDC
* library references
section text,code
xref _main * Name of C program to start with.
xref MemCleanup * Free all allocated memory
xref __fpinit * initialize floating point
xref __fpterm * terminate floating point
start:
movem.l d1-d6/a0-a6,-(a7)
move.l a0,a2 * save command pointer
move.l d0,d2 * and command length
lea LinkerDB,a4 * load base register
move.l AbsExecBase.W,a6
IFND RESIDENT
lea _BSSBAS,a3 * get base of BSS
moveq #0,d1
move.l #_BSSLEN,d0 * get length of BSS in longwords
bra.s clr_lp * and clear for length given
clr_bss move.l d1,(a3)+
clr_lp dbf d0,clr_bss
move.l a7,_StackPtr(A4) * Save stack ptr
move.l a6,SysBase(A4)
ENDC
IFD RESIDENT
movem.l d2,-(a7)
movem.l a0-a2,-(a7)
*------ get the size of the stack, if CLI use cli_DefaultStack
*------ if WB use a7 - TC_SPLOWER
move.l ThisTask(a6),A3
move.l pr_CLI(A3),d1
beq.s fromwb
lsl.l #2,d1
move.l d1,a0
move.l cli_DefaultStack(a0),d1
lsl.l #2,d1 * # longwords -> # bytes
bra.s dostack
fromwb:
move.l a7,d1
sub.l TC_SPLOWER(a3),d1
dostack:
moveq #0,d2 * use d2 as flag for newstack or not
move.l #RESLEN,d0
cmp.l _stack(a4),d1 * This a4 is in the original
* set of data
bcc.s nochange
move.l _stack(a4),d1
add.l d1,d0 * increase size of mem for new stack
moveq #1,d2 * set flag
nochange:
move.l d1,a3 * save stacksize to set up stack checking
move.l #MEMFLAGS,d1
callsys AllocMem
tst.l d0
bne.s ok1
movem.l (a7)+,d2/a0-a2
rts
ok1: move.l d0,a0
move.l d0,a2
;a2 now has difference
move.l d0,a1
move.l #NEWDATAL,d0
sub.l #RESBASE,a4
;copy data over
cpy: move.l (a4)+,(a0)+
subq.l #1,d0
bne.s cpy
;a4 now points at number of relocs
move.l (a4)+,d0
reloc: beq.s nreloc
move.l a1,a0
add.l (a4)+,a0 * a0 now has add of reloc
add.l (a0),a2
move.l a2,(a0)
move.l a1,a2 * restore offset
subq.l #1,d0
bra.s reloc
nreloc: move.l a1,a4 * set up new base register
add.l #RESBASE,a4
move.l #RESLEN,realdatasize(a4)
movem.l (a7)+,a0-a2
move.l a6,SysBase(A4)
tst.b d2
movem.l (a7)+,d2 * restore d2
movem.l a7,_StackPtr(A4) * Save stack ptr (movem doesn't
* change flags
beq.s nochg2
*------ set up new stack
move.l a4,d0
sub.l #RESBASE,d0
add.l #RESLEN,d0
add.l _stack(a4),d0 * here a4 will be pointing at the
* new data, but _stack will be the
* same if all goes well
sub.l #128,d0 * 128 down for good measure
move.l d0,a7
move.l _stack(a4),d0
move.l d0,4(a7) * fill in size of new stack
add.l d0,realdatasize(a4) * need to know how much to free later
nochg2:
*------ Set _base for stack checking
move.l a7,d1
sub.l a3,d1 * get top of stack
add.l #128,D1 * allow for parms overflow
move.l D1,_base(A4) * save for stack checking
ENDC
clrwb:
clr.l WBenchMsg(A4)
*JVP--- get the address of our task
move.l ThisTask(a6),A3
*JVP--- set up for my very own trap handler
move.l TC_TRAPCODE(a3),oldTrapCode(a4) * save the old trap code
lea trapcode,a0 * do something a little less
move.l a0,TC_TRAPCODE(a3) * drastic.
*----- clear any pending signals
moveq #0,d0
move.l #$00003000,d1
callsys SetSignal
*------ attempt to open DOS library:
lea DOSName(PC),A1
moveq.l #0,D0
callsys OpenLibrary
move.l D0,DOSBase(A4)
bne.s ok2
moveq.l #100,d0
bra.w exit2
ok2:
*------ are we running as a son of Workbench?
move.l ThisTask(a6),A3
move.l pr_CurrentDir(A3),curdir(A4)
tst.l pr_CLI(A3)
beq.s fromWorkbench
*=======================================================================
*====== CLI Startup Code ===============================================
*=======================================================================
*
* Entry: D2 = command length
* A2 = Command pointer
fromCLI:
ifnd RESIDENT * we need to set _base if not resident
move.l a7,D0 * get top of stack
sub.l 4(a7),D0 * compute bottom
add.l #128,D0 * allow for parms overflow
move.l D0,_base(A4) * save for stack checking
endc
*------ find command name:
move.l pr_CLI(a3),a0
add.l a0,a0 * bcpl pointer conversion
add.l a0,a0
move.l cli_CommandName(a0),a1
add.l a1,a1 * bcpl pointer conversion
add.l a1,a1
*------ collect parameters:
move.l d2,d0 * get command line length
moveq.l #0,d1
move.b (a1)+,d1
move.l a1,_ProgramName(A4)
add.l d1,d0 * add length of command name
addq.l #1,d0 * allow for space after command
clr.w -(A7) * set null terminator for command line
addq.l #1,D0 * force to even number of bytes
andi.w #$fffe,D0 *(round up)
sub.l D0,A7 * make room on stack for command line
subq.l #2,D0
clr.w 0(A7,D0)
*------ copy command line onto stack
move.l d2,d0 * get command line length
subq.l #1,d0
add.l d1,d2
copy_line:
move.b 0(A2,D0.W),0(A7,D2.W) * copy command line to stack
subq.l #1,d2
dbf d0,copy_line
move.b #' ',0(a7,d2.w) * add space between command and parms
subq.l #1,d2
copy_cmd:
move.b 0(a1,d2.w),0(a7,d2.w) * copy command name to stack
dbf d2,copy_cmd
move.l A7,A1
move.l A1,-(A7) * push command line address
bra.s main * call C entrypoint
*=======================================================================
*====== Workbench Startup Code =========================================
*=======================================================================
fromWorkbench:
ifnd RESIDENT * we need to set _base if not resident
move.l TC_SPLOWER(a3),_base(A4) * set base of stack
moveq #127,d0
addq.l #1,d0 * Efficient way of getting in 128
add.l d0,_base(A4) * allow for parms overflow
endc
*------ we are now set up. wait for a message from our starter
lea pr_MsgPort(A3),a0 * our process base
callsys WaitPort
lea pr_MsgPort(A3),a0 * our process base
callsys GetMsg
move.l d0,WBenchMsg(a4)
move.l d0,-(SP)
*
move.l d0,a2 * get first argument
move.l sm_ArgList(a2),d0
beq.s do_cons
move.l DOSBase(a4),a6
move.l d0,a0
move.l wa_Lock(a0),d1
move.l d1,curdir(A4)
callsys CurrentDir
do_cons:
move.l sm_ToolWindow(a2),d1 * get the window argument
beq.s do_main
move.l #MODE_OLDFILE,d2
callsys Open
move.l d0,stdin(a4)
beq.s do_main
lsl.l #2,d0
move.l d0,a0
move.l fh_Type(a0),pr_ConsoleTask(A3)
do_main:
move.l WBenchMsg(A4),a0 * get address of workbench message
move.l a0,-(a7) * push argv
pea NULL(a4) * push argc
move.l sm_ArgList(a0),a0 * get address of arguments
move.l wa_Name(a0),_ProgramName(A4) * get name of program
*=============================================
*------ common code --------
*=============================================
main jsr __fpinit(PC) * Initialize floating point
jsr _main(PC) * call C entrypoint
moveq.l #0,d0 * set successful status
bra.s exit2
*
XCEXIT:
move.l 4(SP),d0 * extract return code
@XCEXIT:
exit2:
move.l d0,-(a7)
move.l _ONEXIT(A4),d0 * exit trap function?
beq.s exit3
move.l d0,a0
jsr (a0)
exit3 jsr MemCleanup(PC) * cleanup leftover memory alloc.
move.l AbsExecBase.W,a6
move.l DOSBase(A4),a1
callsys CloseLibrary * close Dos library
jsr __fpterm(PC) * clean up any floating point
done_1c:
*------ if we ran from CLI, skip workbench cleanup:
tst.l WBenchMsg(A4)
beq.s exitToDOS
move.l stdin(a4),d1
beq.s done_4
callsys Close
done_4:
*------ return the startup message to our parent
* we forbid so workbench can't UnLoadSeg() us
* before we are done:
move.l AbsExecBase.W,A6
callsys Forbid
move.l WBenchMsg(a4),a1
callsys ReplyMsg
*------ this rts sends us back to DOS:
exitToDOS:
*JVP--- restore original TC_TRAPCODE leaving the shell as it was.
move.l ThisTask(a6),a1
move.l oldTrapCode(a4),TC_TRAPCODE(a1) * politely restore this guy.
IFD RESIDENT
move.l realdatasize(a4),d0
move.l a4,a1
sub.l #RESBASE,a1
move.l AbsExecBase.W,a6
move.l (A7)+,d6
movea.l _StackPtr(a4),a5
callsys FreeMem
move.l d6,d0
movea.l a5,sp
ELSE
move.l (A7)+,D0
movea.l _StackPtr(a4),SP * restore stack ptr
ENDC
movem.l (a7)+,d1-d6/a0-a6
rts
*JVP---------------------------------------------------------------------
* Trap handler. Helps avoid the GURU.
trapcode:
move.l (sp)+,d0 ; get the trap code off the supervisor stack
andi #$DFFF,SR ; switch back to Usermode
lea LinkerDB,A4 ; load linker defined base register
move.l d0,_TRAPCODE(A4) ; Make the trap code available to C functions
move.l _ONTRAP(A4),d0 ; get the new trap vector
beq 1$ ; skip C routine call if not supplied
move.l d0,a0 ; make it a funtion address
jsr (a0) ; Let C code clean up.
1$: move.l _TRAPCODE(A4),d0 ; use the trap code as the return code
add.l #1000,d0 ; give it an offset to force exit message
jmp exit2 ; exit this error prone program.
DOSName dc.b 'dos.library',0
section __MERGED,BSS
*
xref DOSBase
xdef NULL,SysBase,WBenchMsg
xdef curdir,_mbase,_mnext,_msize,_tsize
xdef _oserr,_OSERR,_FPERR,_SIGFPE,_ONERR,_ONEXIT,_ONBREAK
xdef _SIGINT
xdef _ProgramName,_StackPtr,_base
*JVP--- ontrap externals
xdef _ONTRAP,_TRAPCODE
*
ifd RESIDENT
realdatasize ds.b 4 * size of memory allocated for data +
* possible stack
endc
NULL ds.b 4 *
_base ds.b 4 * base of stack
_mbase ds.b 4 * base of memory pool
_mnext ds.b 4 * next available memory location
_msize ds.b 4 * size of memory pool
_tsize ds.b 4 * total size?
_oserr equ *
_OSERR ds.b 4
_FPERR ds.b 4
_SIGFPE ds.b 4
_SIGINT ds.b 4
_ONERR ds.b 4
_ONEXIT ds.b 4
_ONBREAK ds.b 4
curdir ds.b 4
SysBase ds.b 4
WBenchMsg ds.b 4
_StackPtr ds.b 4
stdin ds.b 4
_ProgramName ds.b 4
*JVP--- ontrap storage
_ONTRAP ds.b 4 * my trap handler vector
_TRAPCODE ds.b 4
oldTrapCode ds.b 4
END