summaryrefslogtreecommitdiffstats
path: root/c/src/lib/start/a29k/crt0.S
blob: 017f2d4cca16d79f9f4a5893cc769594d4c320d2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
; @(#)crt0.s	1.3 96/05/31 14:40:27, AMD
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Copyright 1988, 1989, 1990 Advanced Micro Devices, Inc.
;
; This software is the property of Advanced Micro Devices, Inc	(AMD)  which
; specifically	grants the user the right to modify, use and distribute this
; software provided this notice is not removed or altered.  All other rights
; are reserved by AMD.
;
; AMD MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS
; SOFTWARE.  IN NO EVENT SHALL AMD BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL
; DAMAGES IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, OR
; USE OF THIS SOFTWARE.
;
; So that all may benefit from your experience, please report  any  problems
; or  suggestions about this software to the 29K Technical Support Center at
; 800-29-29-AMD (800-292-9263) in the USA, or 0800-89-1131  in	the  UK,  or
; 0031-11-1129 in Japan, toll free.  The direct dial number is 512-462-4118.
;
; Advanced Micro Devices, Inc.
; 29K Support Products
; Mail Stop 573
; 5900 E. Ben White Blvd.
; Austin, TX 78741
; 800-292-9263
;
;  /* $Id$ */
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	.file	"crt0.s"

; crt0.s version 3.3-0
;
; This module gets control from the OS.
; It saves away the Am29027 Mode register settings and
; then sets up the pointers to the resident spill and fill
; trap handlers. It then establishes argv and argc for passing
; to main. It then calls _main. If main returns, it calls _exit.
;
;	void = start( );
;	NOTE - not C callable (no lead underscore)
;
	.include	"sysmac.h"
;
;
	.extern V_SPILL, V_FILL
;	.comm	__29027Mode, 8	; A shadow of the mode register
	.comm	__LibInit, 4

	.text
	.extern _main, _exit, _atexit

	.word	0			; Terminating tag word
	.global start
start:
	sub	gr1, gr1, 6 * 4
	asgeu	V_SPILL, gr1, rab	; better not ever happen
	add	lr1, gr1, 6 * 4

;
; Save the initial value of the Am29027's Mode register
;
; If your system does not enter crt0 with value for Am29027's Mode 
; register in gr96 and gr97, and also the coprocessor is active 
; uncomment the next 4 instructions.
;
;	const	gr96, 0xfc00820
;	consth	gr96, 0xfc00820
;	const	gr97, 0x1375
;	store	1, 3, gr96, gr97
;
;	const	gr98, __29027Mode
;	consth	gr98, __29027Mode
;	store	0, 0, gr96, gr98
;	add	gr98, gr98, 4
;	store	0, 0, gr97, gr98
;
; Now call the system to setup the spill and fill trap handlers
;
	const	lr3, spill
	consth	lr3, spill
	const	lr2, V_SPILL
	syscall setvec
	const	lr3, fill
	consth	lr3, fill
	const	lr2, V_FILL
	syscall setvec

;
; atexit(_fini)
;
;        const   lr0, _atexit
;        consth  lr0, _atexit
;        const   lr2,__fini
;        calli   lr0,lr0
;        consth  lr2,__fini
;
; Now call _init
;
;        const   lr0, __init
;        consth  lr0, __init
;        calli   lr0,lr0
;        nop

;
; Get the argv base address and calculate argc.
;
	syscall getargs
	add	lr3, v0, 0		; argv
	add	lr4, v0, 0
	constn	lr2, -1
argcloop:				; scan for NULL terminator
	load	0, 0, gr97, lr4
	add	lr4, lr4, 4
	cpeq	gr97, gr97, 0
	jmpf	gr97, argcloop
	add	lr2, lr2, 1
;
; Now call LibInit, if there is one. To aid runtime libraries
; that need to do some startup initialization, we have created
; a bss variable called LibInit. If the library doesn't need
; any run-time initialization, the variable is still 0. If the
; library does need run-time initialization, the library will
; contain a definition like
; void (*_LibInit)(void) = LibInitFunction;
; The linker will match up our bss LibInit with this data LibInit
; and the variable will not be 0.  This results in the LibInit routine
; being called via the calli instruction below.
;
	const	lr0, __LibInit
	consth	lr0, __LibInit
	load	0, 0, lr0, lr0
	cpeq	gr96, lr0, 0
	jmpt	gr96, NoLibInit
	nop
	calli	lr0, lr0
	nop
NoLibInit:

;
; Call RAMInit to initialize the data memory.
; 
; The following code segment was used to create the two flavors of the 
; run-time initialization routines (crt0_1.o, and crt0_2.o) as described
; in the User's Manual.  If osboot is used to create a stand-alone
; application, or the call to RAMInit is made in the start-up routine, 
; then the following is not needed.
;
;       .ifdef ROM_LOAD
;       .extern RAMInit
;
;       const   lr0, RAMInit
;       consth  lr0, RAMInit
;       calli   gr96, lr0
;       nop
;       .else
;       nop
;       nop
;       nop
;       nop
;       .endif

;
; Uncomment the following .comm, if you ARE NOT using osboot as released
; with the High C 29K product, AND plan to use the romcoff utility to
; move code and/or data sections to ROM.
;
;       .comm   RAMInit, 4
; 
; Furthermore, if the above is uncommented, then use the following logic
; to call the RAMInit function, if needed.  
;
;       const   lr0, RAMInit
;       consth  lr0, RAMInit
;       load    0, 0, gr96, lr0
;       cpeq    gr96, gr96, 0           ; nothing there?
;       jmpt    gr96, endRAMInit        ; yes, nothing to init
;       nop
;       calli   gr96, lr0               ; no, then instruction found
;       nop                             ; execute function.
;


;
; call main, passing it 2 arguments. main( argc, argv )
;
	const	lr0, _main
	consth	lr0, _main
	calli	lr0, lr0
	nop
;
; call exit
;
	const	lr0, _exit
	consth	lr0, _exit
	calli	lr0, lr0
	add	lr2, gr96, 0
;
; Should never get here, but just in case
;
loop:
	syscall exit
	jmp	loop
	nop
	.sbttl	"Spill and Fill trap handlers"
	.eject
;
;	SPILL, FILL trap handlers
;
; Note that these Spill and Fill trap handlers allow the OS to
; assume that the only registers of use are between gr1 and rfb.
; Therefore, if the OS desires to, it may simply preserve from
; lr0 for (rfb-gr1)/4 registers when doing a context save.
;
;
; Here is the spill handler
;
; spill registers from [*gr1..*rab)
; and move rab downto where gr1 points
;
; rab must change before rfb for signals to work
;
; On entry:	rfb - rab = windowsize, gr1 < rab
; Near the end: rfb - rab > windowsize, gr1 == rab
; On exit:	rfb - rab = windowsize, gr1 == rab
;
	.global spill
spill:
	sub	tav, rab, gr1	; tav = number of bytes to spill
	srl	tav, tav, 2	; change byte count to word count
	sub	tav, tav, 1	; make count zero based
	mtsr	CR, tav		; set Count Remaining register
	sub	tav, rab, gr1
	sub	tav, rfb, tav	; pull down free bound and save it in rab
	add	rab, gr1, 0	; first pull down allocate bound
	storem	0, 0, lr0, tav	; store lr0..lr(tav) into rfb
	jmpi	tpc		; return...
	add	rfb, tav, 0
;
; Here is the fill handler
;
; fill registers from [*rfb..*lr1)
; and move rfb upto where lr1 points.
;
; rab must change before rfb for signals to work
;
; On entry:	rfb - rab = windowsize, lr1 > rfb
; Near the end: rfb - rab < windowsize, lr1 == rab + windowsize
; On exit:	rfb - rab = windowsize, lr1 == rfb
;
	.global fill
fill:
	const	tav, 0x80 << 2
	or	tav, tav, rfb	; tav = ((rfb>>2) | 0x80)<<2 == [rfb]<<2
	mtsr	IPA, tav	; ipa = [rfb]<<2 == 1st reg to fill
				; gr0 is now the first reg to fill
	sub	tav, lr1, rfb	; tav = number of bytes to fill
	add	rab, rab, tav	; push up allocate bound
	srl	tav, tav, 2	; change byte count to word count
	sub	tav, tav, 1	; make count zero based
	mtsr	CR, tav		; set Count Remaining register
	loadm	0, 0, gr0, rfb	; load registers
	jmpi	tpc		; return...
	add	rfb, lr1, 0	; ... first pushing up free bound

;
; The __init function
;
;        .sect   .init,text
;        .use .init
;        .global __init
;__init:
;        sub     gr1,gr1,16
;        asgeu   V_SPILL,gr1,gr126
;        add     lr1,gr1,24
;
;
; The __fini function
;
;        .sect   .fini,text
;        .use .fini
;        .global __fini
;__fini:
;        sub     gr1,gr1,16
;        asgeu   V_SPILL,gr1,gr126
;        add     lr1,gr1,24
;
	.end