source: rtems/c/src/lib/start/a29k/crt0.s @ d2632274

4.104.114.84.95
Last change on this file since d2632274 was d6b2bba, checked in by Joel Sherrill <joel.sherrill@…>, on Sep 18, 1996 at 8:56:35 PM

new files submitted by Craig Lebakken (lebakken@…) and Derrick Ostertag
(ostertag@…)

  • Property mode set to 100644
File size: 7.6 KB
Line 
1; @(#)crt0.s    1.3 96/05/31 14:40:27, AMD
2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3; Copyright 1988, 1989, 1990 Advanced Micro Devices, Inc.
4;
5; This software is the property of Advanced Micro Devices, Inc  (AMD)  which
6; specifically  grants the user the right to modify, use and distribute this
7; software provided this notice is not removed or altered.  All other rights
8; are reserved by AMD.
9;
10; AMD MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS
11; SOFTWARE.  IN NO EVENT SHALL AMD BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL
12; DAMAGES IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, OR
13; USE OF THIS SOFTWARE.
14;
15; So that all may benefit from your experience, please report  any  problems
16; or  suggestions about this software to the 29K Technical Support Center at
17; 800-29-29-AMD (800-292-9263) in the USA, or 0800-89-1131  in  the  UK,  or
18; 0031-11-1129 in Japan, toll free.  The direct dial number is 512-462-4118.
19;
20; Advanced Micro Devices, Inc.
21; 29K Support Products
22; Mail Stop 573
23; 5900 E. Ben White Blvd.
24; Austin, TX 78741
25; 800-292-9263
26;
27;  /* $Id$ */
28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
29
30        .file   "crt0.s"
31
32; crt0.s version 3.3-0
33;
34; This module gets control from the OS.
35; It saves away the Am29027 Mode register settings and
36; then sets up the pointers to the resident spill and fill
37; trap handlers. It then establishes argv and argc for passing
38; to main. It then calls _main. If main returns, it calls _exit.
39;
40;       void = start( );
41;       NOTE - not C callable (no lead underscore)
42;
43        .include        "sysmac.h"
44;
45;
46        .extern V_SPILL, V_FILL
47;       .comm   __29027Mode, 8  ; A shadow of the mode register
48        .comm   __LibInit, 4
49
50        .text
51        .extern _main, _exit, _atexit
52
53        .word   0                       ; Terminating tag word
54        .global start
55start:
56        sub     gr1, gr1, 6 * 4
57        asgeu   V_SPILL, gr1, rab       ; better not ever happen
58        add     lr1, gr1, 6 * 4
59
60;
61; Save the initial value of the Am29027's Mode register
62;
63; If your system does not enter crt0 with value for Am29027's Mode
64; register in gr96 and gr97, and also the coprocessor is active
65; uncomment the next 4 instructions.
66;
67;       const   gr96, 0xfc00820
68;       consth  gr96, 0xfc00820
69;       const   gr97, 0x1375
70;       store   1, 3, gr96, gr97
71;
72;       const   gr98, __29027Mode
73;       consth  gr98, __29027Mode
74;       store   0, 0, gr96, gr98
75;       add     gr98, gr98, 4
76;       store   0, 0, gr97, gr98
77;
78; Now call the system to setup the spill and fill trap handlers
79;
80        const   lr3, spill
81        consth  lr3, spill
82        const   lr2, V_SPILL
83        syscall setvec
84        const   lr3, fill
85        consth  lr3, fill
86        const   lr2, V_FILL
87        syscall setvec
88
89;
90; atexit(_fini)
91;
92;        const   lr0, _atexit
93;        consth  lr0, _atexit
94;        const   lr2,__fini
95;        calli   lr0,lr0
96;        consth  lr2,__fini
97;
98; Now call _init
99;
100;        const   lr0, __init
101;        consth  lr0, __init
102;        calli   lr0,lr0
103;        nop
104
105;
106; Get the argv base address and calculate argc.
107;
108        syscall getargs
109        add     lr3, v0, 0              ; argv
110        add     lr4, v0, 0
111        constn  lr2, -1
112argcloop:                               ; scan for NULL terminator
113        load    0, 0, gr97, lr4
114        add     lr4, lr4, 4
115        cpeq    gr97, gr97, 0
116        jmpf    gr97, argcloop
117        add     lr2, lr2, 1
118;
119; Now call LibInit, if there is one. To aid runtime libraries
120; that need to do some startup initialization, we have created
121; a bss variable called LibInit. If the library doesn't need
122; any run-time initialization, the variable is still 0. If the
123; library does need run-time initialization, the library will
124; contain a definition like
125; void (*_LibInit)(void) = LibInitFunction;
126; The linker will match up our bss LibInit with this data LibInit
127; and the variable will not be 0.  This results in the LibInit routine
128; being called via the calli instruction below.
129;
130        const   lr0, __LibInit
131        consth  lr0, __LibInit
132        load    0, 0, lr0, lr0
133        cpeq    gr96, lr0, 0
134        jmpt    gr96, NoLibInit
135        nop
136        calli   lr0, lr0
137        nop
138NoLibInit:
139
140;
141; Call RAMInit to initialize the data memory.
142;
143; The following code segment was used to create the two flavors of the
144; run-time initialization routines (crt0_1.o, and crt0_2.o) as described
145; in the User's Manual.  If osboot is used to create a stand-alone
146; application, or the call to RAMInit is made in the start-up routine, 
147; then the following is not needed.
148;
149;       .ifdef ROM_LOAD
150;       .extern RAMInit
151;
152;       const   lr0, RAMInit
153;       consth  lr0, RAMInit
154;       calli   gr96, lr0
155;       nop
156;       .else
157;       nop
158;       nop
159;       nop
160;       nop
161;       .endif
162
163;
164; Uncomment the following .comm, if you ARE NOT using osboot as released
165; with the High C 29K product, AND plan to use the romcoff utility to
166; move code and/or data sections to ROM.
167;
168;       .comm   RAMInit, 4
169; 
170; Furthermore, if the above is uncommented, then use the following logic
171; to call the RAMInit function, if needed. 
172;
173;       const   lr0, RAMInit
174;       consth  lr0, RAMInit
175;       load    0, 0, gr96, lr0
176;       cpeq    gr96, gr96, 0           ; nothing there?
177;       jmpt    gr96, endRAMInit        ; yes, nothing to init
178;       nop
179;       calli   gr96, lr0               ; no, then instruction found
180;       nop                             ; execute function.
181;
182
183
184;
185; call main, passing it 2 arguments. main( argc, argv )
186;
187        const   lr0, _main
188        consth  lr0, _main
189        calli   lr0, lr0
190        nop
191;
192; call exit
193;
194        const   lr0, _exit
195        consth  lr0, _exit
196        calli   lr0, lr0
197        add     lr2, gr96, 0
198;
199; Should never get here, but just in case
200;
201loop:
202        syscall exit
203        jmp     loop
204        nop
205        .sbttl  "Spill and Fill trap handlers"
206        .eject
207;
208;       SPILL, FILL trap handlers
209;
210; Note that these Spill and Fill trap handlers allow the OS to
211; assume that the only registers of use are between gr1 and rfb.
212; Therefore, if the OS desires to, it may simply preserve from
213; lr0 for (rfb-gr1)/4 registers when doing a context save.
214;
215;
216; Here is the spill handler
217;
218; spill registers from [*gr1..*rab)
219; and move rab downto where gr1 points
220;
221; rab must change before rfb for signals to work
222;
223; On entry:     rfb - rab = windowsize, gr1 < rab
224; Near the end: rfb - rab > windowsize, gr1 == rab
225; On exit:      rfb - rab = windowsize, gr1 == rab
226;
227        .global spill
228spill:
229        sub     tav, rab, gr1   ; tav = number of bytes to spill
230        srl     tav, tav, 2     ; change byte count to word count
231        sub     tav, tav, 1     ; make count zero based
232        mtsr    CR, tav         ; set Count Remaining register
233        sub     tav, rab, gr1
234        sub     tav, rfb, tav   ; pull down free bound and save it in rab
235        add     rab, gr1, 0     ; first pull down allocate bound
236        storem  0, 0, lr0, tav  ; store lr0..lr(tav) into rfb
237        jmpi    tpc             ; return...
238        add     rfb, tav, 0
239;
240; Here is the fill handler
241;
242; fill registers from [*rfb..*lr1)
243; and move rfb upto where lr1 points.
244;
245; rab must change before rfb for signals to work
246;
247; On entry:     rfb - rab = windowsize, lr1 > rfb
248; Near the end: rfb - rab < windowsize, lr1 == rab + windowsize
249; On exit:      rfb - rab = windowsize, lr1 == rfb
250;
251        .global fill
252fill:
253        const   tav, 0x80 << 2
254        or      tav, tav, rfb   ; tav = ((rfb>>2) | 0x80)<<2 == [rfb]<<2
255        mtsr    IPA, tav        ; ipa = [rfb]<<2 == 1st reg to fill
256                                ; gr0 is now the first reg to fill
257        sub     tav, lr1, rfb   ; tav = number of bytes to fill
258        add     rab, rab, tav   ; push up allocate bound
259        srl     tav, tav, 2     ; change byte count to word count
260        sub     tav, tav, 1     ; make count zero based
261        mtsr    CR, tav         ; set Count Remaining register
262        loadm   0, 0, gr0, rfb  ; load registers
263        jmpi    tpc             ; return...
264        add     rfb, lr1, 0     ; ... first pushing up free bound
265
266;
267; The __init function
268;
269;        .sect   .init,text
270;        .use .init
271;        .global __init
272;__init:
273;        sub     gr1,gr1,16
274;        asgeu   V_SPILL,gr1,gr126
275;        add     lr1,gr1,24
276;
277;
278; The __fini function
279;
280;        .sect   .fini,text
281;        .use .fini
282;        .global __fini
283;__fini:
284;        sub     gr1,gr1,16
285;        asgeu   V_SPILL,gr1,gr126
286;        add     lr1,gr1,24
287;
288        .end
Note: See TracBrowser for help on using the repository browser.