4 ;** Copyright (C) 1994,95,96,97 Bernardo Innocenti
6 ;** Amiga/m68k startup code for XModule
10 INCLUDE "exec/alerts.i"
11 INCLUDE "exec/nodes.i"
12 INCLUDE "exec/lists.i"
13 INCLUDE "exec/ports.i"
14 INCLUDE "exec/libraries.i"
15 INCLUDE "exec/tasks.i"
16 INCLUDE "exec/memory.i"
17 INCLUDE "exec/macros.i"
18 INCLUDE "exec/execbase.i"
19 INCLUDE "libraries/dos.i"
20 INCLUDE "libraries/dosextens.i"
21 INCLUDE "workbench/startup.i"
26 ;**************************************************************************
27 ; External symbol definitions and references
28 ;**************************************************************************
32 xdef _SysBase,_DOSBase
39 xdef _AsmAllocVecPooled
40 xdef _AsmFreeVecPooled
43 xref _LinkerDB ; linker defined base value
44 xref __BSSBAS ; linker defined base of BSS
45 xref __BSSLEN ; linker defined length of BSS
46 xref ___main ; Name of C entry point
59 ;**************************************************************************
61 ;**************************************************************************
64 PUSH MACRO ; push to stack
65 move.\0 \1,-(sp) ; push.(w|l) <ea>
68 POP MACRO ; pop from stack
69 move.\0 (sp)+,\1 ; pop.(w|l) <ea>
74 ;**************************************************************************
76 ;**************************************************************************
83 lea _LinkerDB,a4 ; load base register
84 move.l AbsExecBase.w,a6
86 ; The BSS segment is being cleared by LoadSeg() starting from V37
88 ; lea __BSSBAS,a3 ; get base of BSS
90 ; move.l #__BSSLEN,d0 ; get length of BSS in longwords
91 ; bra.s .clr_lp ; and clear for length given
97 move.l a7,_StackPtr(a4) ; Save StackPtr
98 move.l a6,_SysBase(a4) ; Save SysBase
101 ; Find our Task (Process) structure
103 JSRLIB FindTask ; FindTask (NULL)
105 move.l d0,_ThisTask(a4)
108 ;**************************************************************************
110 ;**************************************************************************
113 btst.b #AFB_68020,AttnFlags+1(a6)
118 ;**************************************************************************
120 ;**************************************************************************
125 move.l d0,_DOSBase(a4)
129 move.l d0,a6 ; Load DOSBase in A6
130 JSRLIB Output ; Call Output()
131 move.l d0,_StdOut(a4) ; Save result
132 move.l _SysBase(a4),a6 ; Restore SysBase in A6
134 ; are we running as a son of Workbench?
135 move.l pr_CurrentDir(a3),__curdir(a4)
140 ;**************************************************************************
141 ;* Workbench Startup Code: get for startup message
142 ;**************************************************************************
144 lea pr_MsgPort(a3),a0 ; our process message port
146 lea pr_MsgPort(a3),a0 ; our process message port
148 move.l d0,_WBenchMsg(a4)
150 move.l d0,a2 ; get first argument
151 move.l sm_ArgList(a2),d0
154 move.l _DOSBase(a4),a6 ; CurrentDir()
156 move.l wa_Lock(a0),d1
158 move.l d0,__curdir(a4)
161 move.l _SysBase(a4),a6 ; Restore SysBase in A6
163 ; Now calculate the remaining stack size (SP - TC_SPLOWER)
167 sub.l TC_SPLOWER(a3),d0
173 ; get the size of the stack cli_DefaultStack
174 ; D0 still holds process->pr_CLI
176 lsl.l #2,d0 ; Shift BPTR
178 move.l cli_DefaultStack(a0),d0
179 lsl.l #2,d0 ; # longwords -> # bytes
183 ;**************************************************************************
184 ;* Stack swapping code
185 ;**************************************************************************
188 cmpi.l #STKSIZE,d0 ; D0 = current stack size
192 ; current stack is not as big as STKSIZE says it needs
193 ; to be. Allocate a new one.
198 PUSH.l a0 ; push format string
199 jsr _kprintf ; call kprintf()
200 addq #4,sp ; fix stack
203 .msg: dc.b 'Startup.asm: Allocating new stack...',$0A, 0
211 moveq.l #MEMF_PUBLIC,d1
216 moveq #RETURN_FAIL,d7 ; Fail
221 ; Call StackSwap to set up the new stack
223 lea stackswapstruct(a4),a0
224 move.l d0,(a0) ; stk_Lower
225 add.l #STKSIZE,d0 ; SP to top of new stack (base + size)
226 move.l d0,stk_Pointer(a0) ; stk_Pointer
227 move.l d0,stk_Upper(a0) ; stk_Upper
232 ;**************************************************************************
234 ;**************************************************************************
239 ; Fill all free stack space with a magic number to check
240 ; maximum program stack usage later.
243 move.l TC_SPLOWER(a3),a0
253 jsr ___main(pc) ; call C entrypoint
256 @XCEXIT: ; XCEXIT() routine
264 ; Check maximum stack used during execution.
265 ; Search the first longword not containing our magic number.
267 ; <- TC_SPUPPER <- top of stack
269 ; |xxxxxxxx| |- stack used by startup code
271 ; |yyyyyyyy|<- sp \ <- current stack position
274 ; |yyyyyyyy| |- stack used by C program
277 ; |yyyyyyyy|<- Pivot (d0) / <- last used longword
280 ; |DEADF00D| |- unused stack
282 ; |DEADF00D|<- TC_SPLOWER / <- bottom of stack
285 move.l TC_SPLOWER(a3),a0
289 move.l (a0)+,d1 ; read one longword and go on next
290 cmp.l d0,d1 ; is the magic number still there?
291 beq.s .cmpstack ; yes: loop again
293 move.l a0,d0 ; make a copy of the Pivot
295 move.l TC_SPLOWER(a3),d1
296 sub.l d1,d0 ; Pivot - TC_SPLOWER
297 PUSH.l d0 ; push unused stack size (argument 4)
299 move.l TC_SPUPPER(a3),d0
300 sub.l a0,d0 ; TC_SPUPPER - Pivot
301 PUSH.l d0 ; push used stack size (argument 3)
303 move.l TC_SPUPPER(a3),d0
304 sub.l d1,d0 ; TC_SPUPPER - TC_SPLOWER
305 PUSH.l d0 ; push total stack size (argument 2)
307 pea .msg(pc) ; push format string (argument 1)
308 jsr _kprintf ; output debug string with kprintf()
310 lea 16(sp),sp ; fix stack (4 arguments)
313 .msg: dc.b 'Startup.asm: Total stack size: %ld, Used: %ld, Unused: %ld.',$0A, 0
317 move.l d7,d0 ; restore return code
322 ; Swap back to original stack
323 move.l _SysBase(a4),a6
324 lea stackswapstruct(a4),a0
331 move.l stackswapstruct(a4),a1 ; FreeMem (stk_Lower,STKSIZE)
336 move.l _StackPtr(a4),a2 ; restore original StackPtr
338 ; if we ran from CLI, skip workbench cleanup:
341 move.l _DOSBase(a4),a6
342 move.l __curdir(a4),d1
348 ; return the startup message to our parent.
349 ; We Forbid() so Workbench can't UnLoadSeg() us
350 ; before we are done.
352 move.l _SysBase(a4),a6
354 move.l _WBenchMsg(a4),a1
358 move.l _DOSBase(a4),a1 ; Close dos.library
360 move.l d7,d0 ; Put return code in D0
361 rts ; This RTS sends us back to our caller
364 moveq.l #RETURN_FAIL,d0
369 ;**************************************************************************
370 ;* Simple (V)SPrintf routines
371 ;**************************************************************************
374 movem.l a2-a3/a6,-(sp) ; Save registers
376 move.l 4+12(sp),a3 ; Get destination buffer
377 move.l 8+12(sp),a0 ; Get format string
378 lea.l 12+12(sp),a1 ; Get arguments
379 lea.l StuffChar(pc),a2 ; Get formatting routine
381 move.l _SysBase(a4),a6 ; Get ExecBase
382 JSRLIB RawDoFmt ; Format the string
384 movem.l (sp)+,a2-a3/a6 ; Restore registers
391 movem.l a2/a3/a6,-(sp)
398 move.l _SysBase(a4),a6
401 movem.l (sp)+,a2/a3/a6
411 ;**************************************************************************
412 ;* Memory pools support
413 ;**************************************************************************
416 ; AsmAllocVecPooled (Pool, memSize, SysBase)
420 addq.l #4,d0 ; Get space for tracking
421 move.l d0,-(sp) ; Save the size
426 jsr _AsmAllocPooled ; Call pool...
429 move.l (sp)+,d1 ; Get size back...
430 tst.l d0 ; Check for error
431 beq.s .fail ; If NULL, failed!
432 move.l d0,a0 ; Get pointer...
433 move.l d1,(a0)+ ; Store size
434 move.l a0,d0 ; Get result
440 ; AsmFreeVecPooled (Pool, Memory, SysBase)
444 move.l a1,d0 ; Test for NULL
446 move.l -(a1),d0 ; Get size / ajust pointer
458 ; CAllocPooled (Pool, memSize, SysBase)
462 move.l d0,-(sp) ; Save the size
464 JSRLIB AllocPooled ; Allocate memory from pool...
466 jsr _AsmAllocPooled ; Allocate memory from pool...
468 move.l (sp)+,d1 ; Get size back...
470 tst.l d0 ; Check for error
471 beq.s .fail ; If NULL, failed!
473 move.l d0,-(sp) ; Save result
476 moveq #$F,d0 ; Check for odd length (not multiple of 16)
482 subq.w #1,d0 ; DBRA loops once too much for us
484 .clear2 move.b #0,-(a1) ; Clear up to 15 bytes
488 lsr.l #4,d1 ; Divide by 16
489 tst.l d1 ; Check for 0
492 moveq #0,d0 ; D0 will be used to clear our memory buffer
493 subq.l #1,d1 ; DBRA does one cycle more!
495 .clear move.l d0,(a0)+ ; Clear memory block
500 swap d1 ; dbra only works on words
507 move.l (sp)+,d0 ; Get result back...
512 DOSName dc.b 'dos.library',0
516 ;**************************************************************************
518 ;**************************************************************************
530 stackswapstruct ds.b StackSwapStruct_SIZEOF