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
|
; @(#)crt0.s 2.7 90/10/15 13:17:57, 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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.file "crt0.s"
; crt0.s version 2.1-7
;
; 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 "sys/sysmac.h"
;
;
.extern V_SPILL, V_FILL
.comm __29027Mode, 8 ; A shadow of the mode register
.comm __LibInit, 4
.comm __environ, 4 ; Environment variables, currently none.
.text
.extern _main, _exit
.extern _memset
.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
;
; Initialize the .bss section to zero by using the memset library function.
; The .bss initialization section below has been commented out as it breaks
; XRAY29K that has been released. The operators sizeof and startof create
; new sections that are not recognized by XRAY29k, but will be implemented
; in the next release (2.0).
;
; const lr4, $sizeof(.bss) ; get size of .bss section to zero out
; consth lr4, $sizeof(.bss)
; const lr2, $startof(.bss) ; Get start address of .bss section
; consth lr2, $startof(.bss)
; const lr0, _memset ; address of memset function
; consth lr0, _memset
; calli lr0, lr0 ; call memset function
; const lr3, 0
; Save the initial value of the Am29027's Mode register
; If your const tav,HIF_does @ asneq V_SYSCALL,gr1,gr1 @ jmpti tav,lr0 @ const tpc,_errno @ consth tpc,_errno @ store 0,0,tav,tpc @ jmpi lr0 @ constn v0,-1 not enter crt0 with value for Am29027's Mode register
; in gr96 and gr97, and also if the coprocessor is active uncomment the
; next 4 lines.
; 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 const tav,HIF_to @ asneq V_SYSCALL,gr1,gr1 @ jmpti tav,lr0 @ const tpc,_errno @ consth tpc,_errno @ store 0,0,tav,tpc @ jmpi lr0 @ constn v0,-1 setup the spill and fill trap handlers
;
const lr3, spill
consth lr3, spill
const lr2, V_SPILL
const tav,HIF_setvec @ asneq V_SYSCALL,gr1,gr1
const lr3, fill
consth lr3, fill
const lr2, V_FILL
const tav,HIF_setvec @ asneq V_SYSCALL,gr1,gr1
;
; Set up dividu handler, since native one don't work?!
; Set it up by hand (FIXME) since HIF_settrap doesn't work either!
;
; const lr3,Edividu
; consth lr3,Edividu
;
; const lr2,35
; const tav,HIF_settrap @ asneq V_SYSCALL,gr1,gr1
; asge 0x50,gr121,0 ; check whether it failed
; const lr2,0x8000008c ; abs addr of dividu trap handler on EB
; consth lr2,0x8000008c
; store 0,0,lr3,lr2 ; Clobber vector FIXME
;
; Get the argv base address and calculate argc.
;
const tav,HIF_getargs @ asneq V_SYSCALL,gr1,gr1
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.
;
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 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:
const tav,HIF_exit @ asneq V_SYSCALL,gr1,gr1
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 spill
sub tav, lr1, rfb ; tav = number of bytes to spill
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
.end
|