locore.s revision 1.48.6.5 1 1.48.6.5 nathanw /* $NetBSD: locore.s,v 1.48.6.5 2002/11/11 22:05:37 nathanw Exp $ */
2 1.48.6.2 scw
3 1.48.6.2 scw /*
4 1.48.6.2 scw * Copyright (c) 1988 University of Utah.
5 1.48.6.2 scw * Copyright (c) 1980, 1990, 1993
6 1.48.6.2 scw * The Regents of the University of California. All rights reserved.
7 1.48.6.2 scw *
8 1.48.6.2 scw * This code is derived from software contributed to Berkeley by
9 1.48.6.2 scw * the Systems Programming Group of the University of Utah Computer
10 1.48.6.2 scw * Science Department.
11 1.48.6.2 scw *
12 1.48.6.2 scw * Redistribution and use in source and binary forms, with or without
13 1.48.6.2 scw * modification, are permitted provided that the following conditions
14 1.48.6.2 scw * are met:
15 1.48.6.2 scw * 1. Redistributions of source code must retain the above copyright
16 1.48.6.2 scw * notice, this list of conditions and the following disclaimer.
17 1.48.6.2 scw * 2. Redistributions in binary form must reproduce the above copyright
18 1.48.6.2 scw * notice, this list of conditions and the following disclaimer in the
19 1.48.6.2 scw * documentation and/or other materials provided with the distribution.
20 1.48.6.2 scw * 3. All advertising materials mentioning features or use of this software
21 1.48.6.2 scw * must display the following acknowledgement:
22 1.48.6.2 scw * This product includes software developed by the University of
23 1.48.6.2 scw * California, Berkeley and its contributors.
24 1.48.6.2 scw * 4. Neither the name of the University nor the names of its contributors
25 1.48.6.2 scw * may be used to endorse or promote products derived from this software
26 1.48.6.2 scw * without specific prior written permission.
27 1.48.6.2 scw *
28 1.48.6.2 scw * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 1.48.6.2 scw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 1.48.6.2 scw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 1.48.6.2 scw * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 1.48.6.2 scw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 1.48.6.2 scw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 1.48.6.2 scw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 1.48.6.2 scw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 1.48.6.2 scw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 1.48.6.2 scw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 1.48.6.2 scw * SUCH DAMAGE.
39 1.48.6.2 scw *
40 1.48.6.2 scw * from: Utah $Hdr: locore.s 1.66 92/12/22$
41 1.48.6.2 scw * @(#)locore.s 8.6 (Berkeley) 5/27/94
42 1.48.6.2 scw */
43 1.48.6.2 scw
44 1.48.6.2 scw #include "opt_compat_netbsd.h"
45 1.48.6.2 scw #include "opt_compat_svr4.h"
46 1.48.6.2 scw #include "opt_compat_sunos.h"
47 1.48.6.2 scw #include "opt_kgdb.h"
48 1.48.6.2 scw #include "opt_lockdebug.h"
49 1.48.6.2 scw
50 1.48.6.2 scw #include "assym.h"
51 1.48.6.2 scw #include <machine/asm.h>
52 1.48.6.2 scw #include <machine/trap.h>
53 1.48.6.2 scw
54 1.48.6.2 scw | Remember this is a fun project!
55 1.48.6.2 scw
56 1.48.6.2 scw .data
57 1.48.6.2 scw GLOBAL(mon_crp)
58 1.48.6.2 scw .long 0,0
59 1.48.6.2 scw
60 1.48.6.2 scw | This is for kvm_mkdb, and should be the address of the beginning
61 1.48.6.2 scw | of the kernel text segment (not necessarily the same as kernbase).
62 1.48.6.2 scw .text
63 1.48.6.2 scw GLOBAL(kernel_text)
64 1.48.6.2 scw
65 1.48.6.2 scw | This is the entry point, as well as the end of the temporary stack
66 1.48.6.2 scw | used during process switch (one 8K page ending at start)
67 1.48.6.2 scw ASGLOBAL(tmpstk)
68 1.48.6.2 scw ASGLOBAL(start)
69 1.48.6.2 scw
70 1.48.6.2 scw | The first step, after disabling interrupts, is to map enough of the kernel
71 1.48.6.2 scw | into high virtual address space so that we can use position dependent code.
72 1.48.6.2 scw | This is a tricky task on the sun3x because the MMU is already enabled and
73 1.48.6.2 scw | the ROM monitor provides no indication of where the root MMU table is mapped.
74 1.48.6.2 scw | Therefore we must use one of the 68030's 'transparent translation' registers
75 1.48.6.2 scw | to define a range in the address space where the MMU translation is
76 1.48.6.2 scw | turned off. Once this is complete we can modify the MMU table directly
77 1.48.6.2 scw | without the need for it to be mapped into virtual memory.
78 1.48.6.2 scw | All code must be position independent until otherwise noted, as the
79 1.48.6.2 scw | boot loader has loaded us into low memory but all the symbols in this
80 1.48.6.2 scw | code have been linked high.
81 1.48.6.2 scw movw #PSL_HIGHIPL,%sr | no interrupts
82 1.48.6.2 scw movl #KERNBASE,%a5 | for vtop conversion
83 1.48.6.2 scw lea _C_LABEL(mon_crp),%a0 | where to store the CRP
84 1.48.6.2 scw subl %a5,%a0
85 1.48.6.2 scw | Note: borrowing mon_crp for tt0 setup...
86 1.48.6.2 scw movl #0x3F8107,%a0@ | map the low 1GB v=p with the
87 1.48.6.2 scw .long 0xf0100800 | transparent translation reg0
88 1.48.6.2 scw | [ pmove a0@, tt0 ]
89 1.48.6.2 scw | In order to map the kernel into high memory we will copy the root table
90 1.48.6.2 scw | entry which maps the 16 megabytes of memory starting at 0x0 into the
91 1.48.6.2 scw | entry which maps the 16 megabytes starting at KERNBASE.
92 1.48.6.2 scw pmove %crp,%a0@ | Get monitor CPU root pointer
93 1.48.6.2 scw movl %a0@(4),%a1 | 2nd word is PA of level A table
94 1.48.6.2 scw
95 1.48.6.2 scw movl %a1,%a0 | compute the descriptor address
96 1.48.6.2 scw addl #0x3e0,%a1 | for VA starting at KERNBASE
97 1.48.6.2 scw movl %a0@,%a1@ | copy descriptor type
98 1.48.6.2 scw movl %a0@(4),%a1@(4) | copy physical address
99 1.48.6.2 scw
100 1.48.6.2 scw | Kernel is now double mapped at zero and KERNBASE.
101 1.48.6.2 scw | Force a long jump to the relocated code (high VA).
102 1.48.6.2 scw movl #IC_CLEAR,%d0 | Flush the I-cache
103 1.48.6.2 scw movc %d0,%cacr
104 1.48.6.2 scw jmp L_high_code:l | long jump
105 1.48.6.2 scw
106 1.48.6.2 scw L_high_code:
107 1.48.6.2 scw | We are now running in the correctly relocated kernel, so
108 1.48.6.2 scw | we are no longer restricted to position-independent code.
109 1.48.6.2 scw | It is handy to leave transparent translation enabled while
110 1.48.6.2 scw | for the low 1GB while _bootstrap() is doing its thing.
111 1.48.6.2 scw
112 1.48.6.2 scw | Do bootstrap stuff needed before main() gets called.
113 1.48.6.2 scw | Our boot loader leaves a copy of the kernel's exec header
114 1.48.6.2 scw | just before the start of the kernel text segment, so the
115 1.48.6.2 scw | kernel can sanity-check the DDB symbols at [end...esym].
116 1.48.6.2 scw | Pass the struct exec at tmpstk-32 to _bootstrap().
117 1.48.6.2 scw | Also, make sure the initial frame pointer is zero so that
118 1.48.6.2 scw | the backtrace algorithm used by KGDB terminates nicely.
119 1.48.6.2 scw lea _ASM_LABEL(tmpstk)-32,%sp
120 1.48.6.2 scw movl #0,%a6
121 1.48.6.2 scw jsr _C_LABEL(_bootstrap) | See locore2.c
122 1.48.6.2 scw
123 1.48.6.2 scw | Now turn off the transparent translation of the low 1GB.
124 1.48.6.2 scw | (this also flushes the ATC)
125 1.48.6.2 scw clrl %sp@-
126 1.48.6.2 scw .long 0xf0170800 | pmove sp@,tt0
127 1.48.6.2 scw addql #4,%sp
128 1.48.6.2 scw
129 1.48.6.2 scw | Now that _bootstrap() is done using the PROM functions,
130 1.48.6.2 scw | we can safely set the sfc/dfc to something != FC_CONTROL
131 1.48.6.2 scw moveq #FC_USERD,%d0 | make movs access "user data"
132 1.48.6.2 scw movc %d0,%sfc | space for copyin/copyout
133 1.48.6.2 scw movc %d0,%dfc
134 1.48.6.2 scw
135 1.48.6.2 scw | Setup process zero user/kernel stacks.
136 1.48.6.2 scw movl _C_LABEL(proc0paddr),%a1| get lwp0 pcb addr
137 1.48.6.2 scw lea %a1@(USPACE-4),%sp | set SSP to last word
138 1.48.6.2 scw movl #USRSTACK-4,%a2
139 1.48.6.2 scw movl %a2,%usp | init user SP
140 1.48.6.2 scw
141 1.48.6.2 scw | Note curpcb was already set in _bootstrap().
142 1.48.6.2 scw | Will do fpu initialization during autoconfig (see fpu.c)
143 1.48.6.2 scw | The interrupt vector table and stack are now ready.
144 1.48.6.2 scw | Interrupts will be enabled later, AFTER autoconfiguration
145 1.48.6.2 scw | is finished, to avoid spurrious interrupts.
146 1.48.6.2 scw
147 1.48.6.2 scw /*
148 1.48.6.5 nathanw * Create a fake exception frame so that cpu_fork() can copy it.
149 1.48.6.5 nathanw * main() nevers returns; we exit to user mode from a forked process
150 1.48.6.5 nathanw * later on.
151 1.48.6.2 scw */
152 1.48.6.2 scw clrw %sp@- | tf_format,tf_vector
153 1.48.6.2 scw clrl %sp@- | tf_pc (filled in later)
154 1.48.6.2 scw movw #PSL_USER,%sp@- | tf_sr for user mode
155 1.48.6.2 scw clrl %sp@- | tf_stackadj
156 1.48.6.2 scw lea %sp@(-64),%sp | tf_regs[16]
157 1.48.6.5 nathanw lea _C_LABEL(lwp0),%a0 | proc0.p_md.md_regs =
158 1.48.6.2 scw movl %a1,%a0@(L_MD_REGS) | trapframe
159 1.48.6.2 scw jbsr _C_LABEL(main) | main(&trapframe)
160 1.48.6.5 nathanw PANIC("main() returned")
161 1.48.6.2 scw
162 1.48.6.2 scw /*
163 1.48.6.5 nathanw * proc_trampoline: call function in register %a2 with %a3 as an arg
164 1.48.6.5 nathanw * and then rei.
165 1.48.6.2 scw */
166 1.48.6.2 scw GLOBAL(proc_trampoline)
167 1.48.6.5 nathanw movl %a3,%sp@- | push function arg
168 1.48.6.5 nathanw jbsr %a2@ | call function
169 1.48.6.5 nathanw addql #4,%sp | pop arg
170 1.48.6.5 nathanw movl %sp@(FR_SP),%a0 | grab and load
171 1.48.6.5 nathanw movl %a0,%usp | user SP
172 1.48.6.5 nathanw moveml %sp@+,#0x7FFF | restore most user regs
173 1.48.6.5 nathanw addql #8,%sp | toss SP and stack adjust
174 1.48.6.5 nathanw jra _ASM_LABEL(rei) | and return
175 1.48.6.2 scw
176 1.48.6.2 scw | That is all the assembly startup code we need on the sun3x!
177 1.48.6.2 scw | The rest of this is like the hp300/locore.s where possible.
178 1.48.6.2 scw
179 1.48.6.2 scw /*
180 1.48.6.2 scw * Trap/interrupt vector routines
181 1.48.6.2 scw */
182 1.48.6.2 scw #include <m68k/m68k/trap_subr.s>
183 1.48.6.2 scw
184 1.48.6.2 scw GLOBAL(buserr)
185 1.48.6.2 scw tstl _C_LABEL(nofault) | device probe?
186 1.48.6.2 scw jeq _C_LABEL(addrerr) | no, handle as usual
187 1.48.6.2 scw movl _C_LABEL(nofault),%sp@- | yes,
188 1.48.6.2 scw jbsr _C_LABEL(longjmp) | longjmp(nofault)
189 1.48.6.2 scw GLOBAL(addrerr)
190 1.48.6.2 scw clrl %sp@- | stack adjust count
191 1.48.6.2 scw moveml #0xFFFF,%sp@- | save user registers
192 1.48.6.2 scw movl %usp,%a0 | save the user SP
193 1.48.6.2 scw movl %a0,%sp@(FR_SP) | in the savearea
194 1.48.6.2 scw lea %sp@(FR_HW),%a1 | grab base of HW berr frame
195 1.48.6.2 scw moveq #0,%d0
196 1.48.6.2 scw movw %a1@(10),%d0 | grab SSW for fault processing
197 1.48.6.2 scw btst #12,%d0 | RB set?
198 1.48.6.2 scw jeq LbeX0 | no, test RC
199 1.48.6.2 scw bset #14,%d0 | yes, must set FB
200 1.48.6.2 scw movw %d0,%a1@(10) | for hardware too
201 1.48.6.2 scw LbeX0:
202 1.48.6.2 scw btst #13,%d0 | RC set?
203 1.48.6.2 scw jeq LbeX1 | no, skip
204 1.48.6.2 scw bset #15,%d0 | yes, must set FC
205 1.48.6.2 scw movw %d0,%a1@(10) | for hardware too
206 1.48.6.2 scw LbeX1:
207 1.48.6.2 scw btst #8,%d0 | data fault?
208 1.48.6.2 scw jeq Lbe0 | no, check for hard cases
209 1.48.6.2 scw movl %a1@(16),%d1 | fault address is as given in frame
210 1.48.6.2 scw jra Lbe10 | thats it
211 1.48.6.2 scw Lbe0:
212 1.48.6.2 scw btst #4,%a1@(6) | long (type B) stack frame?
213 1.48.6.2 scw jne Lbe4 | yes, go handle
214 1.48.6.2 scw movl %a1@(2),%d1 | no, can use save PC
215 1.48.6.2 scw btst #14,%d0 | FB set?
216 1.48.6.2 scw jeq Lbe3 | no, try FC
217 1.48.6.2 scw addql #4,%d1 | yes, adjust address
218 1.48.6.2 scw jra Lbe10 | done
219 1.48.6.2 scw Lbe3:
220 1.48.6.2 scw btst #15,%d0 | FC set?
221 1.48.6.2 scw jeq Lbe10 | no, done
222 1.48.6.2 scw addql #2,%d1 | yes, adjust address
223 1.48.6.2 scw jra Lbe10 | done
224 1.48.6.2 scw Lbe4:
225 1.48.6.2 scw movl %a1@(36),%d1 | long format, use stage B address
226 1.48.6.2 scw btst #15,%d0 | FC set?
227 1.48.6.2 scw jeq Lbe10 | no, all done
228 1.48.6.2 scw subql #2,%d1 | yes, adjust address
229 1.48.6.2 scw Lbe10:
230 1.48.6.2 scw movl %d1,%sp@- | push fault VA
231 1.48.6.2 scw movl %d0,%sp@- | and padded SSW
232 1.48.6.2 scw movw %a1@(6),%d0 | get frame format/vector offset
233 1.48.6.2 scw andw #0x0FFF,%d0 | clear out frame format
234 1.48.6.2 scw cmpw #12,%d0 | address error vector?
235 1.48.6.2 scw jeq Lisaerr | yes, go to it
236 1.48.6.2 scw
237 1.48.6.2 scw /* MMU-specific code to determine reason for bus error. */
238 1.48.6.2 scw movl %d1,%a0 | fault address
239 1.48.6.2 scw movl %sp@,%d0 | function code from ssw
240 1.48.6.2 scw btst #8,%d0 | data fault?
241 1.48.6.2 scw jne Lbe10a
242 1.48.6.2 scw movql #1,%d0 | user program access FC
243 1.48.6.2 scw | (we dont separate data/program)
244 1.48.6.2 scw btst #5,%a1@ | supervisor mode?
245 1.48.6.2 scw jeq Lbe10a | if no, done
246 1.48.6.2 scw movql #5,%d0 | else supervisor program access
247 1.48.6.2 scw Lbe10a:
248 1.48.6.2 scw ptestr %d0,%a0@,#7 | do a table search
249 1.48.6.2 scw pmove %psr,%sp@ | save result
250 1.48.6.2 scw movb %sp@,%d1
251 1.48.6.2 scw btst #2,%d1 | invalid? (incl. limit viol and berr)
252 1.48.6.2 scw jeq Lmightnotbemerr | no -> wp check
253 1.48.6.2 scw btst #7,%d1 | is it MMU table berr?
254 1.48.6.2 scw jeq Lismerr | no, must be fast
255 1.48.6.2 scw jra Lisberr1 | real bus err needs not be fast
256 1.48.6.2 scw Lmightnotbemerr:
257 1.48.6.2 scw btst #3,%d1 | write protect bit set?
258 1.48.6.2 scw jeq Lisberr1 | no, must be bus error
259 1.48.6.2 scw movl %sp@,%d0 | ssw into low word of d0
260 1.48.6.2 scw andw #0xc0,%d0 | write protect is set on page:
261 1.48.6.2 scw cmpw #0x40,%d0 | was it read cycle?
262 1.48.6.2 scw jeq Lisberr1 | yes, was not WPE, must be bus err
263 1.48.6.2 scw /* End of MMU-specific bus error code. */
264 1.48.6.2 scw
265 1.48.6.2 scw Lismerr:
266 1.48.6.2 scw movl #T_MMUFLT,%sp@- | show that we are an MMU fault
267 1.48.6.2 scw jra _ASM_LABEL(faultstkadj) | and deal with it
268 1.48.6.2 scw Lisaerr:
269 1.48.6.2 scw movl #T_ADDRERR,%sp@- | mark address error
270 1.48.6.2 scw jra _ASM_LABEL(faultstkadj) | and deal with it
271 1.48.6.2 scw Lisberr1:
272 1.48.6.2 scw clrw %sp@ | re-clear pad word
273 1.48.6.2 scw Lisberr:
274 1.48.6.2 scw movl #T_BUSERR,%sp@- | mark bus error
275 1.48.6.2 scw jra _ASM_LABEL(faultstkadj) | and deal with it
276 1.48.6.2 scw
277 1.48.6.2 scw /*
278 1.48.6.2 scw * FP exceptions.
279 1.48.6.2 scw */
280 1.48.6.2 scw GLOBAL(fpfline)
281 1.48.6.2 scw clrl %sp@- | stack adjust count
282 1.48.6.2 scw moveml #0xFFFF,%sp@- | save registers
283 1.48.6.2 scw moveq #T_FPEMULI,%d0 | denote as FP emulation trap
284 1.48.6.2 scw jra _ASM_LABEL(fault) | do it
285 1.48.6.2 scw
286 1.48.6.2 scw GLOBAL(fpunsupp)
287 1.48.6.2 scw clrl %sp@- | stack adjust count
288 1.48.6.2 scw moveml #0xFFFF,%sp@- | save registers
289 1.48.6.2 scw moveq #T_FPEMULD,%d0 | denote as FP emulation trap
290 1.48.6.2 scw jra _ASM_LABEL(fault) | do it
291 1.48.6.2 scw
292 1.48.6.2 scw /*
293 1.48.6.2 scw * Handles all other FP coprocessor exceptions.
294 1.48.6.2 scw * Note that since some FP exceptions generate mid-instruction frames
295 1.48.6.2 scw * and may cause signal delivery, we need to test for stack adjustment
296 1.48.6.2 scw * after the trap call.
297 1.48.6.2 scw */
298 1.48.6.2 scw GLOBAL(fpfault)
299 1.48.6.2 scw clrl %sp@- | stack adjust count
300 1.48.6.2 scw moveml #0xFFFF,%sp@- | save user registers
301 1.48.6.2 scw movl %usp,%a0 | and save
302 1.48.6.2 scw movl %a0,%sp@(FR_SP) | the user stack pointer
303 1.48.6.2 scw clrl %sp@- | no VA arg
304 1.48.6.2 scw movl _C_LABEL(curpcb),%a0 | current pcb
305 1.48.6.2 scw lea %a0@(PCB_FPCTX),%a0 | address of FP savearea
306 1.48.6.2 scw fsave %a0@ | save state
307 1.48.6.2 scw tstb %a0@ | null state frame?
308 1.48.6.2 scw jeq Lfptnull | yes, safe
309 1.48.6.2 scw clrw %d0 | no, need to tweak BIU
310 1.48.6.2 scw movb %a0@(1),%d0 | get frame size
311 1.48.6.2 scw bset #3,%a0@(0,%d0:w) | set exc_pend bit of BIU
312 1.48.6.2 scw Lfptnull:
313 1.48.6.2 scw fmovem %fpsr,%sp@- | push fpsr as code argument
314 1.48.6.2 scw frestore %a0@ | restore state
315 1.48.6.2 scw movl #T_FPERR,%sp@- | push type arg
316 1.48.6.2 scw jra _ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup
317 1.48.6.2 scw
318 1.48.6.2 scw /*
319 1.48.6.2 scw * Other exceptions only cause four and six word stack frame and require
320 1.48.6.2 scw * no post-trap stack adjustment.
321 1.48.6.2 scw */
322 1.48.6.2 scw GLOBAL(badtrap)
323 1.48.6.2 scw clrl %sp@- | stack adjust count
324 1.48.6.2 scw moveml #0xFFFF,%sp@- | save std frame regs
325 1.48.6.2 scw jbsr _C_LABEL(straytrap) | report
326 1.48.6.2 scw moveml %sp@+,#0xFFFF | restore regs
327 1.48.6.2 scw addql #4,%sp | stack adjust count
328 1.48.6.2 scw jra _ASM_LABEL(rei) | all done
329 1.48.6.2 scw
330 1.48.6.2 scw /*
331 1.48.6.2 scw * Trap 0 is for system calls
332 1.48.6.2 scw */
333 1.48.6.2 scw GLOBAL(trap0)
334 1.48.6.2 scw clrl %sp@- | stack adjust count
335 1.48.6.2 scw moveml #0xFFFF,%sp@- | save user registers
336 1.48.6.2 scw movl %usp,%a0 | save the user SP
337 1.48.6.2 scw movl %a0,%sp@(FR_SP) | in the savearea
338 1.48.6.2 scw movl %d0,%sp@- | push syscall number
339 1.48.6.2 scw jbsr _C_LABEL(syscall) | handle it
340 1.48.6.2 scw addql #4,%sp | pop syscall arg
341 1.48.6.2 scw movl %sp@(FR_SP),%a0 | grab and restore
342 1.48.6.2 scw movl %a0,%usp | user SP
343 1.48.6.2 scw moveml %sp@+,#0x7FFF | restore most registers
344 1.48.6.2 scw addql #8,%sp | pop SP and stack adjust
345 1.48.6.2 scw jra _ASM_LABEL(rei) | all done
346 1.48.6.2 scw
347 1.48.6.2 scw /*
348 1.48.6.2 scw * Trap 12 is the entry point for the cachectl "syscall"
349 1.48.6.2 scw * cachectl(command, addr, length)
350 1.48.6.2 scw * command in d0, addr in a1, length in d1
351 1.48.6.2 scw */
352 1.48.6.2 scw GLOBAL(trap12)
353 1.48.6.4 nathanw movl _C_LABEL(curlwp),%a0
354 1.48.6.2 scw movl %a0@(L_PROC),%sp@- | push curproc pointer
355 1.48.6.2 scw movl %d1,%sp@- | push length
356 1.48.6.2 scw movl %a1,%sp@- | push addr
357 1.48.6.2 scw movl %d0,%sp@- | push command
358 1.48.6.2 scw jbsr _C_LABEL(cachectl1) | do it
359 1.48.6.2 scw lea %sp@(16),%sp | pop args
360 1.48.6.2 scw jra _ASM_LABEL(rei) | all done
361 1.48.6.2 scw
362 1.48.6.2 scw /*
363 1.48.6.2 scw * Trace (single-step) trap. Kernel-mode is special.
364 1.48.6.2 scw * User mode traps are simply passed on to trap().
365 1.48.6.2 scw */
366 1.48.6.2 scw GLOBAL(trace)
367 1.48.6.2 scw clrl %sp@- | stack adjust count
368 1.48.6.2 scw moveml #0xFFFF,%sp@-
369 1.48.6.2 scw moveq #T_TRACE,%d0
370 1.48.6.2 scw
371 1.48.6.2 scw | Check PSW and see what happen.
372 1.48.6.2 scw | T=0 S=0 (should not happen)
373 1.48.6.2 scw | T=1 S=0 trace trap from user mode
374 1.48.6.2 scw | T=0 S=1 trace trap on a trap instruction
375 1.48.6.2 scw | T=1 S=1 trace trap from system mode (kernel breakpoint)
376 1.48.6.2 scw
377 1.48.6.2 scw movw %sp@(FR_HW),%d1 | get PSW
378 1.48.6.2 scw notw %d1 | XXX no support for T0 on 680[234]0
379 1.48.6.2 scw andw #PSL_TS,%d1 | from system mode (T=1, S=1)?
380 1.48.6.2 scw jeq _ASM_LABEL(kbrkpt) | yes, kernel brkpt
381 1.48.6.2 scw jra _ASM_LABEL(fault) | no, user-mode fault
382 1.48.6.2 scw
383 1.48.6.2 scw /*
384 1.48.6.2 scw * Trap 15 is used for:
385 1.48.6.2 scw * - GDB breakpoints (in user programs)
386 1.48.6.2 scw * - KGDB breakpoints (in the kernel)
387 1.48.6.2 scw * - trace traps for SUN binaries (not fully supported yet)
388 1.48.6.2 scw * User mode traps are simply passed to trap().
389 1.48.6.2 scw */
390 1.48.6.2 scw GLOBAL(trap15)
391 1.48.6.2 scw clrl %sp@- | stack adjust count
392 1.48.6.2 scw moveml #0xFFFF,%sp@-
393 1.48.6.2 scw moveq #T_TRAP15,%d0
394 1.48.6.2 scw btst #5,%sp@(FR_HW) | was supervisor mode?
395 1.48.6.2 scw jne _ASM_LABEL(kbrkpt) | yes, kernel brkpt
396 1.48.6.2 scw jra _ASM_LABEL(fault) | no, user-mode fault
397 1.48.6.2 scw
398 1.48.6.2 scw ASLOCAL(kbrkpt)
399 1.48.6.2 scw | Kernel-mode breakpoint or trace trap. (%d0=trap_type)
400 1.48.6.2 scw | Save the system sp rather than the user sp.
401 1.48.6.2 scw movw #PSL_HIGHIPL,%sr | lock out interrupts
402 1.48.6.2 scw lea %sp@(FR_SIZE),%a6 | Save stack pointer
403 1.48.6.2 scw movl %a6,%sp@(FR_SP) | from before trap
404 1.48.6.2 scw
405 1.48.6.2 scw | If we are not on tmpstk switch to it.
406 1.48.6.2 scw | (so debugger can change the stack pointer)
407 1.48.6.2 scw movl %a6,%d1
408 1.48.6.2 scw cmpl #_ASM_LABEL(tmpstk),%d1
409 1.48.6.2 scw jls Lbrkpt2 | already on tmpstk
410 1.48.6.2 scw | Copy frame to the temporary stack
411 1.48.6.2 scw movl %sp,%a0 | %a0=src
412 1.48.6.2 scw lea _ASM_LABEL(tmpstk)-96,%a1 | %a1=dst
413 1.48.6.2 scw movl %a1,%sp | sp=new frame
414 1.48.6.2 scw moveq #FR_SIZE,%d1
415 1.48.6.2 scw Lbrkpt1:
416 1.48.6.2 scw movl %a0@+,%a1@+
417 1.48.6.2 scw subql #4,%d1
418 1.48.6.2 scw bgt Lbrkpt1
419 1.48.6.2 scw
420 1.48.6.2 scw Lbrkpt2:
421 1.48.6.2 scw | Call the trap handler for the kernel debugger.
422 1.48.6.2 scw | Do not call trap() to handle it, so that we can
423 1.48.6.2 scw | set breakpoints in trap() if we want. We know
424 1.48.6.2 scw | the trap type is either T_TRACE or T_BREAKPOINT.
425 1.48.6.2 scw movl %d0,%sp@- | push trap type
426 1.48.6.2 scw jbsr _C_LABEL(trap_kdebug)
427 1.48.6.2 scw addql #4,%sp | pop args
428 1.48.6.2 scw
429 1.48.6.2 scw | The stack pointer may have been modified, or
430 1.48.6.2 scw | data below it modified (by kgdb push call),
431 1.48.6.2 scw | so push the hardware frame at the current sp
432 1.48.6.2 scw | before restoring registers and returning.
433 1.48.6.2 scw movl %sp@(FR_SP),%a0 | modified sp
434 1.48.6.2 scw lea %sp@(FR_SIZE),%a1 | end of our frame
435 1.48.6.2 scw movl %a1@-,%a0@- | copy 2 longs with
436 1.48.6.2 scw movl %a1@-,%a0@- | ... predecrement
437 1.48.6.2 scw movl %a0,%sp@(FR_SP) | sp = h/w frame
438 1.48.6.2 scw moveml %sp@+,#0x7FFF | restore all but sp
439 1.48.6.2 scw movl %sp@,%sp | ... and sp
440 1.48.6.2 scw rte | all done
441 1.48.6.2 scw
442 1.48.6.2 scw /* Use common m68k sigreturn */
443 1.48.6.2 scw #include <m68k/m68k/sigreturn.s>
444 1.48.6.2 scw
445 1.48.6.2 scw /*
446 1.48.6.2 scw * Interrupt handlers. Most are auto-vectored,
447 1.48.6.2 scw * and hard-wired the same way on all sun3 models.
448 1.48.6.2 scw * Format in the stack is:
449 1.48.6.2 scw * %d0,%d1,%a0,%a1, sr, pc, vo
450 1.48.6.2 scw */
451 1.48.6.2 scw
452 1.48.6.2 scw #define INTERRUPT_SAVEREG \
453 1.48.6.2 scw moveml #0xC0C0,%sp@-
454 1.48.6.2 scw
455 1.48.6.2 scw #define INTERRUPT_RESTORE \
456 1.48.6.2 scw moveml %sp@+,#0x0303
457 1.48.6.2 scw
458 1.48.6.2 scw /*
459 1.48.6.2 scw * This is the common auto-vector interrupt handler,
460 1.48.6.2 scw * for which the CPU provides the vector=0x18+level.
461 1.48.6.2 scw * These are installed in the interrupt vector table.
462 1.48.6.2 scw */
463 1.48.6.2 scw #ifdef __ELF__
464 1.48.6.2 scw .align 4
465 1.48.6.2 scw #else
466 1.48.6.2 scw .align 2
467 1.48.6.2 scw #endif
468 1.48.6.2 scw GLOBAL(_isr_autovec)
469 1.48.6.2 scw INTERRUPT_SAVEREG
470 1.48.6.2 scw jbsr _C_LABEL(isr_autovec)
471 1.48.6.2 scw INTERRUPT_RESTORE
472 1.48.6.2 scw jra _ASM_LABEL(rei)
473 1.48.6.2 scw
474 1.48.6.2 scw /* clock: see clock.c */
475 1.48.6.2 scw #ifdef __ELF__
476 1.48.6.2 scw .align 4
477 1.48.6.2 scw #else
478 1.48.6.2 scw .align 2
479 1.48.6.2 scw #endif
480 1.48.6.2 scw GLOBAL(_isr_clock)
481 1.48.6.2 scw INTERRUPT_SAVEREG
482 1.48.6.2 scw jbsr _C_LABEL(clock_intr)
483 1.48.6.2 scw INTERRUPT_RESTORE
484 1.48.6.2 scw jra _ASM_LABEL(rei)
485 1.48.6.2 scw
486 1.48.6.2 scw | Handler for all vectored interrupts (i.e. VME interrupts)
487 1.48.6.2 scw #ifdef __ELF__
488 1.48.6.2 scw .align 4
489 1.48.6.2 scw #else
490 1.48.6.2 scw .align 2
491 1.48.6.2 scw #endif
492 1.48.6.2 scw GLOBAL(_isr_vectored)
493 1.48.6.2 scw INTERRUPT_SAVEREG
494 1.48.6.2 scw jbsr _C_LABEL(isr_vectored)
495 1.48.6.2 scw INTERRUPT_RESTORE
496 1.48.6.2 scw jra _ASM_LABEL(rei)
497 1.48.6.2 scw
498 1.48.6.2 scw #undef INTERRUPT_SAVEREG
499 1.48.6.2 scw #undef INTERRUPT_RESTORE
500 1.48.6.2 scw
501 1.48.6.2 scw /* interrupt counters (needed by vmstat) */
502 1.48.6.2 scw GLOBAL(intrnames)
503 1.48.6.2 scw .asciz "spur" | 0
504 1.48.6.2 scw .asciz "lev1" | 1
505 1.48.6.2 scw .asciz "lev2" | 2
506 1.48.6.2 scw .asciz "lev3" | 3
507 1.48.6.2 scw .asciz "lev4" | 4
508 1.48.6.2 scw .asciz "clock" | 5
509 1.48.6.2 scw .asciz "lev6" | 6
510 1.48.6.2 scw .asciz "nmi" | 7
511 1.48.6.2 scw GLOBAL(eintrnames)
512 1.48.6.2 scw
513 1.48.6.2 scw .data
514 1.48.6.2 scw .even
515 1.48.6.2 scw GLOBAL(intrcnt)
516 1.48.6.2 scw .long 0,0,0,0,0,0,0,0,0,0
517 1.48.6.2 scw GLOBAL(eintrcnt)
518 1.48.6.2 scw .text
519 1.48.6.2 scw
520 1.48.6.2 scw /*
521 1.48.6.2 scw * Emulation of VAX REI instruction.
522 1.48.6.2 scw *
523 1.48.6.2 scw * This code is (mostly) un-altered from the hp300 code,
524 1.48.6.2 scw * except that sun machines do not need a simulated SIR
525 1.48.6.2 scw * because they have a real software interrupt register.
526 1.48.6.2 scw *
527 1.48.6.2 scw * This code deals with checking for and servicing ASTs
528 1.48.6.2 scw * (profiling, scheduling) and software interrupts (network, softclock).
529 1.48.6.2 scw * We check for ASTs first, just like the VAX. To avoid excess overhead
530 1.48.6.2 scw * the T_ASTFLT handling code will also check for software interrupts so we
531 1.48.6.2 scw * do not have to do it here. After identifying that we need an AST we
532 1.48.6.2 scw * drop the IPL to allow device interrupts.
533 1.48.6.2 scw *
534 1.48.6.2 scw * This code is complicated by the fact that sendsig may have been called
535 1.48.6.2 scw * necessitating a stack cleanup.
536 1.48.6.2 scw */
537 1.48.6.2 scw
538 1.48.6.2 scw ASGLOBAL(rei)
539 1.48.6.2 scw #ifdef DIAGNOSTIC
540 1.48.6.2 scw tstl _C_LABEL(panicstr) | have we paniced?
541 1.48.6.2 scw jne Ldorte | yes, do not make matters worse
542 1.48.6.2 scw #endif
543 1.48.6.2 scw tstl _C_LABEL(astpending) | AST pending?
544 1.48.6.2 scw jeq Ldorte | no, done
545 1.48.6.2 scw Lrei1:
546 1.48.6.2 scw btst #5,%sp@ | yes, are we returning to user mode?
547 1.48.6.2 scw jne Ldorte | no, done
548 1.48.6.2 scw movw #PSL_LOWIPL,%sr | lower SPL
549 1.48.6.2 scw clrl %sp@- | stack adjust
550 1.48.6.2 scw moveml #0xFFFF,%sp@- | save all registers
551 1.48.6.2 scw movl %usp,%a1 | including
552 1.48.6.2 scw movl %a1,%sp@(FR_SP) | the users SP
553 1.48.6.2 scw clrl %sp@- | VA == none
554 1.48.6.2 scw clrl %sp@- | code == none
555 1.48.6.2 scw movl #T_ASTFLT,%sp@- | type == async system trap
556 1.48.6.2 scw jbsr _C_LABEL(trap) | go handle it
557 1.48.6.2 scw lea %sp@(12),%sp | pop value args
558 1.48.6.2 scw movl %sp@(FR_SP),%a0 | restore user SP
559 1.48.6.2 scw movl %a0,%usp | from save area
560 1.48.6.2 scw movw %sp@(FR_ADJ),%d0 | need to adjust stack?
561 1.48.6.2 scw jne Laststkadj | yes, go to it
562 1.48.6.2 scw moveml %sp@+,#0x7FFF | no, restore most user regs
563 1.48.6.2 scw addql #8,%sp | toss SP and stack adjust
564 1.48.6.2 scw rte | and do real RTE
565 1.48.6.2 scw Laststkadj:
566 1.48.6.2 scw lea %sp@(FR_HW),%a1 | pointer to HW frame
567 1.48.6.2 scw addql #8,%a1 | source pointer
568 1.48.6.2 scw movl %a1,%a0 | source
569 1.48.6.2 scw addw %d0,%a0 | + hole size = dest pointer
570 1.48.6.2 scw movl %a1@-,%a0@- | copy
571 1.48.6.2 scw movl %a1@-,%a0@- | 8 bytes
572 1.48.6.2 scw movl %a0,%sp@(FR_SP) | new SSP
573 1.48.6.2 scw moveml %sp@+,#0x7FFF | restore user registers
574 1.48.6.2 scw movl %sp@,%sp | and our SP
575 1.48.6.2 scw Ldorte:
576 1.48.6.2 scw rte | real return
577 1.48.6.2 scw
578 1.48.6.2 scw /*
579 1.48.6.2 scw * Initialization is at the beginning of this file, because the
580 1.48.6.2 scw * kernel entry point needs to be at zero for compatibility with
581 1.48.6.2 scw * the Sun boot loader. This works on Sun machines because the
582 1.48.6.2 scw * interrupt vector table for reset is NOT at address zero.
583 1.48.6.2 scw * (The MMU has a "boot" bit that forces access to the PROM)
584 1.48.6.2 scw */
585 1.48.6.2 scw
586 1.48.6.2 scw /*
587 1.48.6.2 scw * Use common m68k sigcode.
588 1.48.6.2 scw */
589 1.48.6.2 scw #include <m68k/m68k/sigcode.s>
590 1.48.6.2 scw #ifdef COMPAT_SUNOS
591 1.48.6.2 scw #include <m68k/m68k/sunos_sigcode.s>
592 1.48.6.2 scw #endif
593 1.48.6.2 scw #ifdef COMPAT_SVR4
594 1.48.6.2 scw #include <m68k/m68k/svr4_sigcode.s>
595 1.48.6.2 scw #endif
596 1.48.6.2 scw
597 1.48.6.2 scw .text
598 1.48.6.2 scw
599 1.48.6.2 scw /*
600 1.48.6.2 scw * Primitives
601 1.48.6.2 scw */
602 1.48.6.2 scw
603 1.48.6.2 scw /*
604 1.48.6.2 scw * Use common m68k support routines.
605 1.48.6.2 scw */
606 1.48.6.2 scw #include <m68k/m68k/support.s>
607 1.48.6.2 scw
608 1.48.6.2 scw BSS(want_resched,4)
609 1.48.6.2 scw
610 1.48.6.2 scw /*
611 1.48.6.2 scw * Use common m68k process manipulation routines.
612 1.48.6.2 scw */
613 1.48.6.2 scw #include <m68k/m68k/proc_subr.s>
614 1.48.6.2 scw
615 1.48.6.2 scw /*
616 1.48.6.2 scw * Use common m68k process/lwp switch and context save subroutines.
617 1.48.6.2 scw */
618 1.48.6.2 scw #define FPCOPROC /* XXX: Temp. Reqd. */
619 1.48.6.2 scw #include <m68k/m68k/switch_subr.s>
620 1.48.6.2 scw
621 1.48.6.2 scw
622 1.48.6.2 scw /* suline() */
623 1.48.6.2 scw
624 1.48.6.2 scw #ifdef DEBUG
625 1.48.6.2 scw .data
626 1.48.6.2 scw ASGLOBAL(fulltflush)
627 1.48.6.2 scw .long 0
628 1.48.6.2 scw ASGLOBAL(fullcflush)
629 1.48.6.2 scw .long 0
630 1.48.6.2 scw .text
631 1.48.6.2 scw #endif
632 1.48.6.2 scw
633 1.48.6.2 scw ENTRY(ecacheon)
634 1.48.6.2 scw rts
635 1.48.6.2 scw
636 1.48.6.2 scw ENTRY(ecacheoff)
637 1.48.6.2 scw rts
638 1.48.6.2 scw
639 1.48.6.2 scw /*
640 1.48.6.2 scw * Get callers current SP value.
641 1.48.6.2 scw * Note that simply taking the address of a local variable in a C function
642 1.48.6.2 scw * doesn't work because callee saved registers may be outside the stack frame
643 1.48.6.2 scw * defined by A6 (e.g. GCC generated code).
644 1.48.6.2 scw *
645 1.48.6.2 scw * [I don't think the ENTRY() macro will do the right thing with this -- glass]
646 1.48.6.2 scw */
647 1.48.6.2 scw GLOBAL(getsp)
648 1.48.6.2 scw movl %sp,%d0 | get current SP
649 1.48.6.2 scw addql #4,%d0 | compensate for return address
650 1.48.6.2 scw movl %d0,%a0
651 1.48.6.2 scw rts
652 1.48.6.2 scw
653 1.48.6.2 scw ENTRY(getsfc)
654 1.48.6.2 scw movc %sfc,%d0
655 1.48.6.2 scw movl %d0,%a0
656 1.48.6.2 scw rts
657 1.48.6.2 scw
658 1.48.6.2 scw ENTRY(getdfc)
659 1.48.6.2 scw movc %dfc,%d0
660 1.48.6.2 scw movl %d0,%a0
661 1.48.6.2 scw rts
662 1.48.6.2 scw
663 1.48.6.2 scw ENTRY(getvbr)
664 1.48.6.2 scw movc %vbr,%d0
665 1.48.6.2 scw movl %d0,%a0
666 1.48.6.2 scw rts
667 1.48.6.2 scw
668 1.48.6.2 scw ENTRY(setvbr)
669 1.48.6.2 scw movl %sp@(4),%d0
670 1.48.6.2 scw movc %d0,%vbr
671 1.48.6.2 scw rts
672 1.48.6.2 scw
673 1.48.6.2 scw /*
674 1.48.6.2 scw * Load a new CPU Root Pointer (CRP) into the MMU.
675 1.48.6.2 scw * void loadcrp(struct mmu_rootptr *);
676 1.48.6.2 scw */
677 1.48.6.2 scw ENTRY(loadcrp)
678 1.48.6.2 scw movl %sp@(4),%a0 | arg1: &CRP
679 1.48.6.2 scw movl #CACHE_CLR,%d0
680 1.48.6.2 scw movc %d0,%cacr | invalidate cache(s)
681 1.48.6.2 scw pflusha | flush entire TLB
682 1.48.6.2 scw pmove %a0@,%crp | load new user root pointer
683 1.48.6.2 scw rts
684 1.48.6.2 scw
685 1.48.6.2 scw ENTRY(getcrp)
686 1.48.6.2 scw movl %sp@(4),%a0 | arg1: &crp
687 1.48.6.2 scw pmove %crp,%a0@ | *crpp = %crp
688 1.48.6.2 scw rts
689 1.48.6.2 scw
690 1.48.6.2 scw /*
691 1.48.6.2 scw * Get the physical address of the PTE for a given VA.
692 1.48.6.2 scw */
693 1.48.6.2 scw ENTRY(ptest_addr)
694 1.48.6.2 scw movl %sp@(4),%a1 | VA
695 1.48.6.2 scw ptestr #5,%a1@,#7,%a0 | %a0 = addr of PTE
696 1.48.6.2 scw movl %a0,%d0 | Result in %d0 (not a pointer return)
697 1.48.6.2 scw rts
698 1.48.6.2 scw
699 1.48.6.2 scw /*
700 1.48.6.2 scw * Set processor priority level calls. Most are implemented with
701 1.48.6.2 scw * inline asm expansions. However, we need one instantiation here
702 1.48.6.2 scw * in case some non-optimized code makes external references.
703 1.48.6.2 scw * Most places will use the inlined functions param.h supplies.
704 1.48.6.2 scw */
705 1.48.6.2 scw
706 1.48.6.2 scw ENTRY(_getsr)
707 1.48.6.2 scw clrl %d0
708 1.48.6.2 scw movw %sr,%d0
709 1.48.6.2 scw movl %a1,%d0
710 1.48.6.2 scw rts
711 1.48.6.2 scw
712 1.48.6.2 scw ENTRY(_spl)
713 1.48.6.2 scw clrl %d0
714 1.48.6.2 scw movw %sr,%d0
715 1.48.6.2 scw movl %sp@(4),%d1
716 1.48.6.2 scw movw %d1,%sr
717 1.48.6.2 scw rts
718 1.48.6.2 scw
719 1.48.6.2 scw ENTRY(_splraise)
720 1.48.6.2 scw clrl %d0
721 1.48.6.2 scw movw %sr,%d0
722 1.48.6.2 scw movl %d0,%d1
723 1.48.6.2 scw andl #PSL_HIGHIPL,%d1 | old &= PSL_HIGHIPL
724 1.48.6.2 scw cmpl %sp@(4),%d1 | (old - new)
725 1.48.6.2 scw bge Lsplr
726 1.48.6.2 scw movl %sp@(4),%d1
727 1.48.6.2 scw movw %d1,%sr
728 1.48.6.2 scw Lsplr:
729 1.48.6.2 scw rts
730 1.48.6.2 scw
731 1.48.6.2 scw /*
732 1.48.6.2 scw * Save and restore 68881 state.
733 1.48.6.2 scw */
734 1.48.6.2 scw ENTRY(m68881_save)
735 1.48.6.2 scw movl %sp@(4),%a0 | save area pointer
736 1.48.6.2 scw fsave %a0@ | save state
737 1.48.6.2 scw tstb %a0@ | null state frame?
738 1.48.6.2 scw jeq Lm68881sdone | yes, all done
739 1.48.6.2 scw fmovem %fp0-%fp7,%a0@(FPF_REGS) | save FP general regs
740 1.48.6.2 scw fmovem %fpcr/%fpsr/%fpi,%a0@(FPF_FPCR) | save FP control regs
741 1.48.6.2 scw Lm68881sdone:
742 1.48.6.2 scw rts
743 1.48.6.2 scw
744 1.48.6.2 scw ENTRY(m68881_restore)
745 1.48.6.2 scw movl %sp@(4),%a0 | save area pointer
746 1.48.6.2 scw tstb %a0@ | null state frame?
747 1.48.6.2 scw jeq Lm68881rdone | yes, easy
748 1.48.6.2 scw fmovem %a0@(FPF_FPCR),%fpcr/%fpsr/%fpi | restore FP control regs
749 1.48.6.2 scw fmovem %a0@(FPF_REGS),%fp0-%fp7 | restore FP general regs
750 1.48.6.2 scw Lm68881rdone:
751 1.48.6.2 scw frestore %a0@ | restore state
752 1.48.6.2 scw rts
753 1.48.6.2 scw
754 1.48.6.2 scw /*
755 1.48.6.2 scw * _delay(unsigned N)
756 1.48.6.2 scw * Delay for at least (N/256) microseconds.
757 1.48.6.2 scw * This routine depends on the variable: delay_divisor
758 1.48.6.2 scw * which should be set based on the CPU clock rate.
759 1.48.6.2 scw * XXX: Currently this is set based on the CPU model,
760 1.48.6.2 scw * XXX: but this should be determined at run time...
761 1.48.6.2 scw */
762 1.48.6.2 scw GLOBAL(_delay)
763 1.48.6.2 scw | %d0 = arg = (usecs << 8)
764 1.48.6.2 scw movl %sp@(4),%d0
765 1.48.6.2 scw | %d1 = delay_divisor;
766 1.48.6.2 scw movl _C_LABEL(delay_divisor),%d1
767 1.48.6.2 scw jra L_delay /* Jump into the loop! */
768 1.48.6.2 scw
769 1.48.6.2 scw /*
770 1.48.6.2 scw * Align the branch target of the loop to a half-line (8-byte)
771 1.48.6.2 scw * boundary to minimize cache effects. This guarantees both
772 1.48.6.2 scw * that there will be no prefetch stalls due to cache line burst
773 1.48.6.2 scw * operations and that the loop will run from a single cache
774 1.48.6.2 scw * half-line.
775 1.48.6.2 scw */
776 1.48.6.2 scw #ifdef __ELF__
777 1.48.6.2 scw .align 8
778 1.48.6.2 scw #else
779 1.48.6.2 scw .align 3
780 1.48.6.2 scw #endif
781 1.48.6.2 scw L_delay:
782 1.48.6.2 scw subl %d1,%d0
783 1.48.6.2 scw jgt L_delay
784 1.48.6.2 scw rts
785 1.48.6.2 scw
786 1.48.6.2 scw | Define some addresses, mostly so DDB can print useful info.
787 1.48.6.2 scw | Not using _C_LABEL() here because these symbols are never
788 1.48.6.2 scw | referenced by any C code, and if the leading underscore
789 1.48.6.2 scw | ever goes away, these lines turn into syntax errors...
790 1.48.6.2 scw .set _KERNBASE,KERNBASE
791 1.48.6.2 scw .set _MONSTART,SUN3X_MONSTART
792 1.48.6.2 scw .set _PROM_BASE,SUN3X_PROM_BASE
793 1.48.6.2 scw .set _MONEND,SUN3X_MONEND
794 1.48.6.2 scw
795 1.48.6.2 scw |The end!
796