1 |
148 |
jeremybenn |
; @(#)crt0.s 2.7 90/10/15 13:17:57, 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 |
|
|
.file "crt0.s"
|
28 |
|
|
; crt0.s version 2.1-7
|
29 |
|
|
;
|
30 |
|
|
; This module gets control from the OS.
|
31 |
|
|
; It saves away the Am29027 Mode register settings and
|
32 |
|
|
; then sets up the pointers to the resident spill and fill
|
33 |
|
|
; trap handlers. It then establishes argv and argc for passing
|
34 |
|
|
; to main. It then calls _main. If main returns, it calls _exit.
|
35 |
|
|
;
|
36 |
|
|
; void = start( );
|
37 |
|
|
; NOTE - not C callable (no lead underscore)
|
38 |
|
|
;
|
39 |
|
|
.include "sys/sysmac.h"
|
40 |
|
|
;
|
41 |
|
|
;
|
42 |
|
|
.extern V_SPILL, V_FILL
|
43 |
|
|
.comm __29027Mode, 8 ; A shadow of the mode register
|
44 |
|
|
.comm __LibInit, 4
|
45 |
|
|
.comm __environ, 4 ; Environment variables, currently none.
|
46 |
|
|
.text
|
47 |
|
|
.extern _main, _exit
|
48 |
|
|
.extern _memset
|
49 |
|
|
|
50 |
|
|
.word 0 ; Terminating tag word
|
51 |
|
|
.global start
|
52 |
|
|
start:
|
53 |
|
|
sub gr1, gr1, 6 * 4
|
54 |
|
|
asgeu V_SPILL, gr1, rab ; better not ever happen
|
55 |
|
|
add lr1, gr1, 6 * 4
|
56 |
|
|
;
|
57 |
|
|
; Initialize the .bss section to zero by using the memset library function.
|
58 |
|
|
; The .bss initialization section below has been commented out as it breaks
|
59 |
|
|
; XRAY29K that has been released. The operators sizeof and startof create
|
60 |
|
|
; new sections that are not recognized by XRAY29k, but will be implemented
|
61 |
|
|
; in the next release (2.0).
|
62 |
|
|
;
|
63 |
|
|
; const lr4, $sizeof(.bss) ; get size of .bss section to zero out
|
64 |
|
|
; consth lr4, $sizeof(.bss)
|
65 |
|
|
; const lr2, $startof(.bss) ; Get start address of .bss section
|
66 |
|
|
; consth lr2, $startof(.bss)
|
67 |
|
|
; const lr0, _memset ; address of memset function
|
68 |
|
|
; consth lr0, _memset
|
69 |
|
|
; calli lr0, lr0 ; call memset function
|
70 |
|
|
; const lr3, 0
|
71 |
|
|
|
72 |
|
|
; Save the initial value of the Am29027's Mode register
|
73 |
|
|
; 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
|
74 |
|
|
; in gr96 and gr97, and also if the coprocessor is active uncomment the
|
75 |
|
|
; next 4 lines.
|
76 |
|
|
; const gr96, 0xfc00820
|
77 |
|
|
; consth gr96, 0xfc00820
|
78 |
|
|
; const gr97, 0x1375
|
79 |
|
|
; store 1, 3, gr96, gr97
|
80 |
|
|
;
|
81 |
|
|
const gr98, __29027Mode
|
82 |
|
|
consth gr98, __29027Mode
|
83 |
|
|
store 0, 0, gr96, gr98
|
84 |
|
|
add gr98, gr98, 4
|
85 |
|
|
store 0, 0, gr97, gr98
|
86 |
|
|
;
|
87 |
|
|
; 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
|
88 |
|
|
;
|
89 |
|
|
const lr3, spill
|
90 |
|
|
consth lr3, spill
|
91 |
|
|
const lr2, V_SPILL
|
92 |
|
|
const tav,HIF_setvec @ asneq V_SYSCALL,gr1,gr1
|
93 |
|
|
const lr3, fill
|
94 |
|
|
consth lr3, fill
|
95 |
|
|
const lr2, V_FILL
|
96 |
|
|
const tav,HIF_setvec @ asneq V_SYSCALL,gr1,gr1
|
97 |
|
|
;
|
98 |
|
|
; Set up dividu handler, since native one don't work?!
|
99 |
|
|
; Set it up by hand (FIXME) since HIF_settrap doesn't work either!
|
100 |
|
|
;
|
101 |
|
|
; const lr3,Edividu
|
102 |
|
|
; consth lr3,Edividu
|
103 |
|
|
;
|
104 |
|
|
; const lr2,35
|
105 |
|
|
; const tav,HIF_settrap @ asneq V_SYSCALL,gr1,gr1
|
106 |
|
|
; asge 0x50,gr121,0 ; check whether it failed
|
107 |
|
|
; const lr2,0x8000008c ; abs addr of dividu trap handler on EB
|
108 |
|
|
; consth lr2,0x8000008c
|
109 |
|
|
; store 0,0,lr3,lr2 ; Clobber vector FIXME
|
110 |
|
|
|
111 |
|
|
;
|
112 |
|
|
; Get the argv base address and calculate argc.
|
113 |
|
|
;
|
114 |
|
|
const tav,HIF_getargs @ asneq V_SYSCALL,gr1,gr1
|
115 |
|
|
add lr3, v0, 0 ; argv
|
116 |
|
|
add lr4, v0, 0
|
117 |
|
|
constn lr2, -1
|
118 |
|
|
argcloop: ; scan for NULL terminator
|
119 |
|
|
load 0, 0, gr97, lr4
|
120 |
|
|
add lr4, lr4, 4
|
121 |
|
|
cpeq gr97, gr97, 0
|
122 |
|
|
jmpf gr97, argcloop
|
123 |
|
|
add lr2, lr2, 1
|
124 |
|
|
;
|
125 |
|
|
; Now call LibInit, if there is one. To aid runtime libraries
|
126 |
|
|
; that need to do some startup initialization, we have created
|
127 |
|
|
; a bss variable called LibInit. If the library doesn't need
|
128 |
|
|
; any run-time initialization, the variable is still 0. If the
|
129 |
|
|
; library does need run-time initialization, the library will
|
130 |
|
|
; contain a definition like
|
131 |
|
|
; void (*_LibInit)(void) = LibInitFunction;
|
132 |
|
|
; The linker will match up our bss LibInit with this data LibInit
|
133 |
|
|
; and the variable will not be 0.
|
134 |
|
|
;
|
135 |
|
|
const lr0, __LibInit
|
136 |
|
|
consth lr0, __LibInit
|
137 |
|
|
load 0, 0, lr0, lr0
|
138 |
|
|
cpeq gr96, lr0, 0
|
139 |
|
|
jmpt gr96, NoLibInit
|
140 |
|
|
nop
|
141 |
|
|
calli lr0, lr0
|
142 |
|
|
nop
|
143 |
|
|
NoLibInit:
|
144 |
|
|
;
|
145 |
|
|
; call main, passing it 2 arguments. main( argc, argv )
|
146 |
|
|
;
|
147 |
|
|
const lr0, _main
|
148 |
|
|
consth lr0, _main
|
149 |
|
|
calli lr0, lr0
|
150 |
|
|
nop
|
151 |
|
|
;
|
152 |
|
|
; call exit
|
153 |
|
|
;
|
154 |
|
|
const lr0, _exit
|
155 |
|
|
consth lr0, _exit
|
156 |
|
|
calli lr0, lr0
|
157 |
|
|
add lr2, gr96, 0
|
158 |
|
|
;
|
159 |
|
|
; Should never get here, but just in case
|
160 |
|
|
;
|
161 |
|
|
loop:
|
162 |
|
|
const tav,HIF_exit @ asneq V_SYSCALL,gr1,gr1
|
163 |
|
|
jmp loop
|
164 |
|
|
nop
|
165 |
|
|
.sbttl "Spill and Fill trap handlers"
|
166 |
|
|
.eject
|
167 |
|
|
;
|
168 |
|
|
; SPILL, FILL trap handlers
|
169 |
|
|
;
|
170 |
|
|
; Note that these Spill and Fill trap handlers allow the OS to
|
171 |
|
|
; assume that the only registers of use are between gr1 and rfb.
|
172 |
|
|
; Therefore, if the OS desires to, it may simply preserve from
|
173 |
|
|
; lr0 for (rfb-gr1)/4 registers when doing a context save.
|
174 |
|
|
;
|
175 |
|
|
;
|
176 |
|
|
; Here is the spill handler
|
177 |
|
|
;
|
178 |
|
|
; spill registers from [*gr1..*rab)
|
179 |
|
|
; and move rab downto where gr1 points
|
180 |
|
|
;
|
181 |
|
|
; rab must change before rfb for signals to work
|
182 |
|
|
;
|
183 |
|
|
; On entry: rfb - rab = windowsize, gr1 < rab
|
184 |
|
|
; Near the end: rfb - rab > windowsize, gr1 == rab
|
185 |
|
|
; On exit: rfb - rab = windowsize, gr1 == rab
|
186 |
|
|
;
|
187 |
|
|
.global spill
|
188 |
|
|
spill:
|
189 |
|
|
sub tav, rab, gr1 ; tav = number of bytes to spill
|
190 |
|
|
srl tav, tav, 2 ; change byte count to word count
|
191 |
|
|
sub tav, tav, 1 ; make count zero based
|
192 |
|
|
mtsr cr, tav ; set Count Remaining register
|
193 |
|
|
sub tav, rab, gr1
|
194 |
|
|
sub tav, rfb, tav ; pull down free bound and save it in rab
|
195 |
|
|
add rab, gr1, 0 ; first pull down allocate bound
|
196 |
|
|
storem 0, 0, lr0, tav ; store lr0..lr(tav) into rfb
|
197 |
|
|
jmpi tpc ; return...
|
198 |
|
|
add rfb, tav, 0
|
199 |
|
|
;
|
200 |
|
|
; Here is the fill handler
|
201 |
|
|
;
|
202 |
|
|
; fill registers from [*rfb..*lr1)
|
203 |
|
|
; and move rfb upto where lr1 points.
|
204 |
|
|
;
|
205 |
|
|
; rab must change before rfb for signals to work
|
206 |
|
|
;
|
207 |
|
|
; On entry: rfb - rab = windowsize, lr1 > rfb
|
208 |
|
|
; Near the end: rfb - rab < windowsize, lr1 == rab + windowsize
|
209 |
|
|
; On exit: rfb - rab = windowsize, lr1 == rfb
|
210 |
|
|
;
|
211 |
|
|
.global fill
|
212 |
|
|
fill:
|
213 |
|
|
const tav, 0x80 << 2
|
214 |
|
|
or tav, tav, rfb ; tav = ((rfb>>2) | 0x80)<<2 == [rfb]<<2
|
215 |
|
|
mtsr ipa, tav ; ipa = [rfb]<<2 == 1st reg to fill
|
216 |
|
|
; gr0 is now the first reg to spill
|
217 |
|
|
sub tav, lr1, rfb ; tav = number of bytes to spill
|
218 |
|
|
add rab, rab, tav ; push up allocate bound
|
219 |
|
|
srl tav, tav, 2 ; change byte count to word count
|
220 |
|
|
sub tav, tav, 1 ; make count zero based
|
221 |
|
|
mtsr cr, tav ; set Count Remaining register
|
222 |
|
|
loadm 0, 0, gr0, rfb ; load registers
|
223 |
|
|
jmpi tpc ; return...
|
224 |
|
|
add rfb, lr1, 0 ; ... first pushing up free bound
|
225 |
|
|
|
226 |
|
|
.end
|