]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/sparc64/sparc64/support.S
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / sparc64 / sparc64 / support.S
1 /*-
2  * Copyright (c) 2001 Jake Burkholder.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <machine/asm.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/errno.h>
31
32 #include <machine/asi.h>
33 #include <machine/asmacros.h>
34 #include <machine/fsr.h>
35 #include <machine/intr_machdep.h>
36 #include <machine/ktr.h>
37 #include <machine/pcb.h>
38 #include <machine/pstate.h>
39 #include <machine/wstate.h>
40
41 #include "assym.s"
42
43         .register %g2, #ignore
44         .register %g3, #ignore
45         .register %g6, #ignore
46
47 #define E       /* empty */
48
49 /*
50  * Generate load and store instructions for the corresponding width and asi
51  * (or not).  Note that we want to evaluate the macro args before
52  * concatenating, so that E really turns into nothing.
53  */
54 #define _LD(w, a)       ld ## w ## a
55 #define _ST(w, a)       st ## w ## a
56
57 #define LD(w, a)        _LD(w, a)
58 #define ST(w, a)        _ST(w, a)
59
60 /*
61  * Common code for copy routines.
62  *
63  * We use large macros to generate functions for each of the copy routines.
64  * This allows the load and store instructions to be generated for the right
65  * operation, asi or not.  It is possible to write an asi independent function
66  * but this would require 2 expensive wrs in the main loop to switch %asi.
67  * It would also screw up profiling (if we ever get it), but may save some I$.
68  * We assume that either one of dasi and sasi is empty, or that they are both
69  * the same (empty or non-empty).  It is up to the caller to set %asi.
70  */
71
72 /*
73  * ASI independent implementation of copystr(9).
74  * Used to implement copyinstr() and copystr().
75  *
76  * Return value is in %g1.
77  */
78 #define _COPYSTR(src, dst, len, done, sa, sasi, da, dasi) \
79         brz     len, 4f ; \
80          mov    src, %g2 ; \
81 1:      deccc   1, len ; \
82         bl,a,pn %xcc, 3f ; \
83          nop ; \
84         LD(ub, sa) [src] sasi, %g1 ; \
85         ST(b, da) %g1, [dst] dasi ; \
86         brz,pn  %g1, 3f ; \
87          inc    src ; \
88         ba      %xcc, 1b ; \
89          inc    dst ; \
90 2:      mov     ENAMETOOLONG, %g1 ; \
91 3:      sub     src, %g2, %g2 ; \
92         brnz,a  done, 4f ; \
93          stx    %g2, [done] ; \
94 4:
95
96 /*
97  * ASI independent implementation of memset(3).
98  * Used to implement bzero(), memset() and aszero().
99  *
100  * If the pattern is non-zero, duplicate it to fill 64 bits.
101  * Store bytes until dst is 8-byte aligned, then store 8 bytes.
102  * It has yet to be determined how much unrolling is beneficial.
103  * Could also read and compare before writing to minimize snoop traffic.
104  *
105  * XXX bzero() should be implemented as
106  * #define bzero(dst, len) (void)memset((dst), 0, (len))
107  * if at all.
108  */
109 #define _MEMSET(dst, pat, len, da, dasi) \
110         brlez,pn len, 5f ; \
111          and    pat, 0xff, pat ; \
112         brz,pt  pat, 1f ; \
113          sllx   pat, 8, %g1 ; \
114         or      pat, %g1, pat ; \
115         sllx    pat, 16, %g1 ; \
116         or      pat, %g1, pat ; \
117         sllx    pat, 32, %g1 ; \
118         or      pat, %g1, pat ; \
119         .align 16 ; \
120 1:      deccc   1, len ; \
121         bl,pn   %xcc, 5f ; \
122          btst   7, dst ; \
123         bz,a,pt %xcc, 2f ; \
124          inc    1, len ; \
125         ST(b, da) pat, [dst] dasi ; \
126         ba      %xcc, 1b ; \
127          inc    dst ; \
128         .align 16 ; \
129 2:      deccc   32, len ; \
130         bl,a,pn %xcc, 3f ; \
131          inc    32, len ; \
132         ST(x, da) pat, [dst] dasi ; \
133         ST(x, da) pat, [dst + 8] dasi ; \
134         ST(x, da) pat, [dst + 16] dasi ; \
135         ST(x, da) pat, [dst + 24] dasi ; \
136         ba      %xcc, 2b ; \
137          inc    32, dst ; \
138         .align 16 ; \
139 3:      deccc   8, len ; \
140         bl,a,pn %xcc, 4f ; \
141          inc    8, len ; \
142         ST(x, da) pat, [dst] dasi ; \
143         ba      %xcc, 3b ; \
144          inc    8, dst ; \
145         .align 16 ; \
146 4:      deccc   1, len ; \
147         bl,a,pn %xcc, 5f ; \
148          nop ; \
149         ST(b, da) pat, [dst] dasi ; \
150         ba      %xcc, 4b ; \
151          inc    1, dst ; \
152 5:
153
154 /*
155  * ASI independent implementation of memcpy(3).
156  * Used to implement bcopy(), copyin(), copyout(), memcpy(), ascopy(),
157  * ascopyfrom() and ascopyto().
158  *
159  * Transfer bytes until dst is 8-byte aligned.  If src is then also 8 byte
160  * aligned, transfer 8 bytes, otherwise finish with bytes.  The unaligned
161  * case could be optimized, but it is expected that this is the uncommon
162  * case and of questionable value.  The code to do so is also rather large
163  * and ugly.  It has yet to be determined how much unrolling is beneficial.
164  *
165  * XXX bcopy() must also check for overlap.  This is stupid.
166  * XXX bcopy() should be implemented as
167  * #define bcopy(src, dst, len) (void)memcpy((dst), (src), (len))
168  * if at all.
169  */
170 #define _MEMCPY(dst, src, len, da, dasi, sa, sasi) \
171 1:      deccc   1, len ; \
172         bl,pn   %xcc, 6f ; \
173          btst   7, dst ; \
174         bz,a,pt %xcc, 2f ; \
175          inc    1, len ; \
176         LD(ub, sa) [src] sasi, %g1 ; \
177         ST(b, da) %g1, [dst] dasi ; \
178         inc     1, src ; \
179         ba      %xcc, 1b ; \
180          inc    1, dst ; \
181         .align 16 ; \
182 2:      btst    7, src ; \
183         bz,a,pt %xcc, 3f ; \
184          nop ; \
185         ba,a    %xcc, 5f ; \
186         .align 16 ; \
187 3:      deccc   32, len ; \
188         bl,a,pn %xcc, 4f ; \
189          inc    32, len ; \
190         LD(x, sa) [src] sasi, %g1 ; \
191         LD(x, sa) [src + 8] sasi, %g2 ; \
192         LD(x, sa) [src + 16] sasi, %g3 ; \
193         LD(x, sa) [src + 24] sasi, %g4 ; \
194         ST(x, da) %g1, [dst] dasi ; \
195         ST(x, da) %g2, [dst + 8] dasi ; \
196         ST(x, da) %g3, [dst + 16] dasi ; \
197         ST(x, da) %g4, [dst + 24] dasi ; \
198         inc     32, src ; \
199         ba      %xcc, 3b ; \
200          inc    32, dst ; \
201         .align 16 ; \
202 4:      deccc   8, len ; \
203         bl,a,pn %xcc, 5f ; \
204          inc    8, len ; \
205         LD(x, sa) [src] sasi, %g1 ; \
206         ST(x, da) %g1, [dst] dasi ; \
207         inc     8, src ; \
208         ba      %xcc, 4b ; \
209          inc    8, dst ; \
210         .align 16 ; \
211 5:      deccc   1, len ; \
212         bl,a,pn %xcc, 6f ; \
213          nop ; \
214         LD(ub, sa) [src] sasi, %g1 ; \
215         ST(b, da) %g1, [dst] dasi ; \
216         inc     src ; \
217         ba      %xcc, 5b ; \
218          inc    dst ; \
219 6:
220
221 /*
222  * void ascopy(u_long asi, vm_offset_t src, vm_offset_t dst, size_t len)
223  */
224 ENTRY(ascopy)
225         wr      %o0, 0, %asi
226         _MEMCPY(%o2, %o1, %o3, a, %asi, a, %asi)
227         retl
228          nop
229 END(ascopy)
230
231 /*
232  * void ascopyfrom(u_long sasi, vm_offset_t src, caddr_t dst, size_t len)
233  */
234 ENTRY(ascopyfrom)
235         wr      %o0, 0, %asi
236         _MEMCPY(%o2, %o1, %o3, E, E, a, %asi)
237         retl
238          nop
239 END(ascopyfrom)
240
241 /*
242  * void ascopyto(caddr_t src, u_long dasi, vm_offset_t dst, size_t len)
243  */
244 ENTRY(ascopyto)
245         wr      %o1, 0, %asi
246         _MEMCPY(%o2, %o0, %o3, a, %asi, E, E)
247         retl
248          nop
249 END(ascopyto)
250
251 /*
252  * void aszero(u_long asi, vm_offset_t pa, size_t len)
253  */
254 ENTRY(aszero)
255         wr      %o0, 0, %asi
256         _MEMSET(%o1, %g0, %o2, a, %asi)
257         retl
258          nop
259 END(aszero)
260
261 /*
262  * int bcmp(const void *b1, const void *b2, size_t len)
263  */
264 ENTRY(bcmp)
265         brz,pn  %o2, 2f
266          clr    %o3
267 1:      ldub    [%o0 + %o3], %o4
268         ldub    [%o1 + %o3], %o5
269         cmp     %o4, %o5
270         bne,pn  %xcc, 2f
271          inc    %o3
272         deccc   %o2
273         bne,pt  %xcc, 1b
274          nop
275 2:      retl
276          mov    %o2, %o0
277 END(bcmp)
278
279 /*
280  * void bcopy(const void *src, void *dst, size_t len)
281  */
282 ENTRY(bcopy)
283         /*
284          * Check for overlap, and copy backwards if so.
285          */
286         sub     %o1, %o0, %g1
287         cmp     %g1, %o2
288         bgeu,a,pt %xcc, 3f
289          nop
290
291         /*
292          * Copy backwards.
293          */
294         add     %o0, %o2, %o0
295         add     %o1, %o2, %o1
296 1:      deccc   1, %o2
297         bl,a,pn %xcc, 2f
298          nop
299         dec     1, %o0
300         ldub    [%o0], %g1
301         dec     1, %o1
302         ba      %xcc, 1b
303          stb    %g1, [%o1]
304 2:      retl
305          nop
306
307         /*
308          * Do the fast version.
309          */
310 3:      _MEMCPY(%o1, %o0, %o2, E, E, E, E)
311         retl
312          nop
313 END(bcopy)
314
315 /*
316  * void bzero(void *b, size_t len)
317  */
318 ENTRY(bzero)
319         _MEMSET(%o0, %g0, %o1, E, E)
320         retl
321          nop
322 END(bzero)
323
324 /*
325  * int copystr(const void *src, void *dst, size_t len, size_t *done)
326  */
327 ENTRY(copystr)
328         _COPYSTR(%o0, %o1, %o2, %o3, E, E, E, E)
329         retl
330          mov    %g1, %o0
331 END(copystr)
332
333 /*
334  * void *memcpy(void *dst, const void *src, size_t len)
335  */
336 ENTRY(memcpy)
337         mov     %o0, %o3
338         _MEMCPY(%o3, %o1, %o2, E, E, E, E)
339         retl
340          nop
341 END(memcpy)
342
343 /*
344  * void *memset(void *b, int c, size_t len)
345  */
346 ENTRY(memset)
347         mov     %o0, %o3
348         _MEMSET(%o3, %o1, %o2, E, E)
349         retl
350          nop
351 END(memset)
352
353         .globl  copy_nofault_begin
354 copy_nofault_begin:
355         nop
356
357 /*
358  * int copyin(const void *uaddr, void *kaddr, size_t len)
359  */
360 ENTRY(copyin)
361         wr      %g0, ASI_AIUP, %asi
362         _MEMCPY(%o1, %o0, %o2, E, E, a, %asi)
363         retl
364          clr    %o0
365 END(copyin)
366
367 /*
368  * int copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
369  */
370 ENTRY(copyinstr)
371         wr      %g0, ASI_AIUP, %asi
372         _COPYSTR(%o0, %o1, %o2, %o3, a, %asi, E, E)
373         retl
374          mov    %g1, %o0
375 END(copyinstr)
376
377 /*
378  * int copyout(const void *kaddr, void *uaddr, size_t len)
379  */
380 ENTRY(copyout)
381         wr      %g0, ASI_AIUP, %asi
382         _MEMCPY(%o1, %o0, %o2, a, %asi, E, E)
383         retl
384          clr    %o0
385 END(copyout)
386
387         .globl  copy_nofault_end
388 copy_nofault_end:
389         nop
390
391 ENTRY(copy_fault)
392         retl
393          mov    EFAULT, %o0
394 END(copy_fault)
395
396         .globl  fs_nofault_begin
397 fs_nofault_begin:
398         nop
399
400 /*
401  * Chatty aliases for fetch, store functions.
402  */
403         .globl  fubyte, fusword, fuword, subyte, susword, suword
404         .set    fubyte, fuword8
405         .set    fusword, fuword16
406         .set    fuword, fuword64
407         .set    subyte, suword8
408         .set    susword, suword16
409         .set    suword, suword64
410
411         .globl  casuword32, casuword, fuptr, suptr
412         .set    casuword, casuword64
413         .set    fuptr, fuword64
414         .set    suptr, suword64
415
416 /*
417  * int32_t casuword32(volatile int32_t *p, int32_t e, int32_t s)
418  */
419 ENTRY(casuword32)
420         casa    [%o0] ASI_AIUP, %o1, %o2
421         retl
422          mov    %o2, %o0
423 END(casuword32)
424
425 /*
426  * int64_t casuword64(volatile int64_t *p, int64_t e, int64_t s)
427  */
428 ENTRY(casuword64)
429         casxa   [%o0] ASI_AIUP, %o1, %o2
430         retl
431          mov    %o2, %o0
432 END(casuword64)
433
434 /*
435  * int fuword8(const void *base)
436  */
437 ENTRY(fuword8)
438         retl
439          lduba  [%o0] ASI_AIUP, %o0
440 END(fuword8)
441
442 /*
443  * int fuword16(const void *base)
444  */
445 ENTRY(fuword16)
446         retl
447          lduha  [%o0] ASI_AIUP, %o0
448 END(fuword16)
449
450 /*
451  * int32_t fuword32(const void *base)
452  */
453 ENTRY(fuword32)
454         retl
455          lduwa  [%o0] ASI_AIUP, %o0
456 END(fuword32)
457
458 /*
459  * int64_t fuword64(const void *base)
460  */
461 ENTRY(fuword64)
462         retl
463          ldxa   [%o0] ASI_AIUP, %o0
464 END(fuword64)
465
466 /*
467  * int suword8(const void *base, int word)
468  */
469 ENTRY(suword8)
470         stba    %o1, [%o0] ASI_AIUP
471         retl
472          clr    %o0
473 END(suword8)
474
475 /*
476  * int suword16(const void *base, int word)
477  */
478 ENTRY(suword16)
479         stha    %o1, [%o0] ASI_AIUP
480         retl
481          clr    %o0
482 END(suword16)
483
484 /*
485  * int suword32(const void *base, int32_t word)
486  */
487 ENTRY(suword32)
488         stwa    %o1, [%o0] ASI_AIUP
489         retl
490          clr    %o0
491 END(suword32)
492
493 /*
494  * int suword64(const void *base, int64_t word)
495  */
496 ENTRY(suword64)
497         stxa    %o1, [%o0] ASI_AIUP
498         retl
499          clr    %o0
500 END(suword64)
501
502         .globl  fs_nofault_intr_begin
503 fs_nofault_intr_begin:
504         nop
505
506 /*
507  * int fuswintr(const void *base)
508  */
509 ENTRY(fuswintr)
510         retl
511          lduha  [%o0] ASI_AIUP, %o0
512 END(fuswintr)
513
514 /*
515  * int suswintr(const void *base, int word)
516  */
517 ENTRY(suswintr)
518         stha    %o1, [%o0] ASI_AIUP
519         retl
520          clr    %o0
521 END(suswintr)
522
523         .globl  fs_nofault_intr_end
524 fs_nofault_intr_end:
525         nop
526
527         .globl  fs_nofault_end
528 fs_nofault_end:
529         nop
530
531 ENTRY(fs_fault)
532         retl
533          mov    -1, %o0
534 END(fsfault)
535
536         .globl  fas_nofault_begin
537 fas_nofault_begin:
538
539 /*
540  * int fasword8(u_long asi, uint64_t addr, uint8_t *val)
541  */
542 ENTRY(fasword8)
543         wr      %o0, 0, %asi
544         membar  #Sync
545         lduba   [%o1] %asi, %o3
546         membar  #Sync
547         stb     %o3, [%o2]
548         retl
549          clr    %o0
550 END(fasword8)
551
552 /*
553  * int fasword16(u_long asi, uint64_t addr, uint16_t *val)
554  */
555 ENTRY(fasword16)
556         wr      %o0, 0, %asi
557         membar  #Sync
558         lduha   [%o1] %asi, %o3
559         membar  #Sync
560         sth     %o3, [%o2]
561         retl
562          clr    %o0
563 END(fasword16)
564
565 /*
566  * int fasword32(u_long asi, uint64_t addr, uint32_t *val)
567  */
568 ENTRY(fasword32)
569         wr      %o0, 0, %asi
570         membar  #Sync
571         lduwa   [%o1] %asi, %o3
572         membar  #Sync
573         stw     %o3, [%o2]
574         retl
575          clr    %o0
576 END(fasword32)
577
578         .globl  fas_nofault_end
579 fas_nofault_end:
580         nop
581
582         .globl  fas_fault
583 ENTRY(fas_fault)
584         retl
585          mov    -1, %o0
586 END(fas_fault)
587
588         .globl  fpu_fault_begin
589 fpu_fault_begin:
590         nop
591
592 /*
593  * void spitfire_block_copy(void *src, void *dst, size_t len)
594  */
595 ENTRY(spitfire_block_copy)
596         rdpr    %pil, %o3
597         wrpr    %g0, PIL_TICK, %pil
598
599         wr      %g0, ASI_BLK_S, %asi
600         wr      %g0, FPRS_FEF, %fprs
601
602         sub     PCB_REG, TF_SIZEOF, %o4
603         ldx     [%o4 + TF_FPRS], %o5
604         andcc   %o5, FPRS_FEF, %g0
605         bz,a,pt %xcc, 1f
606          nop
607         stda    %f0, [PCB_REG + PCB_UFP + (0 * 64)] %asi
608         stda    %f16, [PCB_REG + PCB_UFP + (1 * 64)] %asi
609         stda    %f32, [PCB_REG + PCB_UFP + (2 * 64)] %asi
610         stda    %f48, [PCB_REG + PCB_UFP + (3 * 64)] %asi
611         membar  #Sync
612
613         andn    %o5, FPRS_FEF, %o5
614         stx     %o5, [%o4 + TF_FPRS]
615         ldx     [PCB_REG + PCB_FLAGS], %o4
616         or      %o4, PCB_FEF, %o4
617         stx     %o4, [PCB_REG + PCB_FLAGS]
618
619 1:      wrpr    %o3, 0, %pil
620
621         ldda    [%o0] %asi, %f0
622         add     %o0, 64, %o0
623         sub     %o2, 64, %o2
624
625 2:      ldda    [%o0] %asi, %f16
626         fsrc1   %f0, %f32
627         fsrc1   %f2, %f34
628         fsrc1   %f4, %f36
629         fsrc1   %f6, %f38
630         fsrc1   %f8, %f40
631         fsrc1   %f10, %f42
632         fsrc1   %f12, %f44
633         fsrc1   %f14, %f46
634         stda    %f32, [%o1] %asi
635         add     %o0, 64, %o0
636         subcc   %o2, 64, %o2
637         bz,pn   %xcc, 3f
638          add    %o1, 64, %o1
639         ldda    [%o0] %asi, %f0
640         fsrc1   %f16, %f32
641         fsrc1   %f18, %f34
642         fsrc1   %f20, %f36
643         fsrc1   %f22, %f38
644         fsrc1   %f24, %f40
645         fsrc1   %f26, %f42
646         fsrc1   %f28, %f44
647         fsrc1   %f30, %f46
648         stda    %f32, [%o1] %asi
649         add     %o0, 64, %o0
650         sub     %o2, 64, %o2
651         ba,pt   %xcc, 2b
652          add    %o1, 64, %o1
653
654 3:      membar  #Sync
655
656         stda    %f16, [%o1] %asi
657         membar  #Sync
658
659         retl
660          wr     %g0, 0, %fprs
661 END(spitfire_block_copy)
662
663 /*
664  * void spitfire_block_zero(void *dst, size_t len)
665  */
666 ENTRY(spitfire_block_zero)
667         rdpr    %pil, %o3
668         wrpr    %g0, PIL_TICK, %pil
669
670         wr      %g0, ASI_BLK_S, %asi
671         wr      %g0, FPRS_FEF, %fprs
672
673         sub     PCB_REG, TF_SIZEOF, %o4
674         ldx     [%o4 + TF_FPRS], %o5
675         andcc   %o5, FPRS_FEF, %g0
676         bz,a,pt %xcc, 1f
677          nop
678         stda    %f0, [PCB_REG + PCB_UFP + (0 * 64)] %asi
679         stda    %f16, [PCB_REG + PCB_UFP + (1 * 64)] %asi
680         stda    %f32, [PCB_REG + PCB_UFP + (2 * 64)] %asi
681         stda    %f48, [PCB_REG + PCB_UFP + (3 * 64)] %asi
682         membar  #Sync
683
684         andn    %o5, FPRS_FEF, %o5
685         stx     %o5, [%o4 + TF_FPRS]
686         ldx     [PCB_REG + PCB_FLAGS], %o4
687         or      %o4, PCB_FEF, %o4
688         stx     %o4, [PCB_REG + PCB_FLAGS]
689
690 1:      wrpr    %o3, 0, %pil
691
692         fzero   %f0
693         fzero   %f2
694         fzero   %f4
695         fzero   %f6
696         fzero   %f8
697         fzero   %f10
698         fzero   %f12
699         fzero   %f14
700
701 1:      stda    %f0, [%o0] %asi
702         stda    %f0, [%o0 + 64] %asi
703         stda    %f0, [%o0 + 128] %asi
704         stda    %f0, [%o0 + 192] %asi
705         sub     %o1, 256, %o1
706         brnz,pt %o1, 1b
707          add    %o0, 256, %o0
708         membar  #Sync
709
710         retl
711          wr     %g0, 0, %fprs
712 END(spitfire_block_zero)
713
714         .globl  fpu_fault_end
715 fpu_fault_end:
716         nop
717
718         .globl  fpu_fault_size
719         .set    fpu_fault_size, fpu_fault_end - fpu_fault_begin
720
721 ENTRY(longjmp)
722         set     1, %g3
723         movrz   %o1, %o1, %g3
724         mov     %o0, %g1
725         ldx     [%g1 + _JB_FP], %g2
726 1:      cmp     %fp, %g2
727         bl,a,pt %xcc, 1b
728          restore
729         bne,pn  %xcc, 2f
730          ldx    [%g1 + _JB_SP], %o2
731         cmp     %o2, %sp
732         blt,pn  %xcc, 2f
733          movge  %xcc, %o2, %sp
734         ldx     [%g1 + _JB_PC], %o7
735         retl
736          mov    %g3, %o0
737 2:      PANIC("longjmp botch", %l1)
738 END(longjmp)
739
740 ENTRY(setjmp)
741         stx     %sp, [%o0 + _JB_SP]
742         stx     %o7, [%o0 + _JB_PC]
743         stx     %fp, [%o0 + _JB_FP]
744         retl
745          clr    %o0
746 END(setjmp)
747
748 /*
749  * void ofw_entry(cell_t args[])
750  */
751 ENTRY(ofw_entry)
752         save    %sp, -CCFSZ, %sp
753         SET(ofw_vec, %l7, %l6)
754         ldx     [%l6], %l6
755         rdpr    %pstate, %l7
756         andn    %l7, PSTATE_AM | PSTATE_IE, %l5
757         wrpr    %l5, 0, %pstate
758         SET(tba_taken_over, %l5, %l4)
759         brz,pn  %l4, 1f
760          rdpr   %wstate, %l5
761         andn    %l5, WSTATE_PROM_MASK, %l3
762         wrpr    %l3, WSTATE_PROM_KMIX, %wstate
763 1:      call    %l6
764          mov    %i0, %o0
765         brz,pn  %l4, 1f
766          nop
767         wrpr    %g0, %l5, %wstate
768 1:      wrpr    %l7, 0, %pstate
769         ret
770          restore %o0, %g0, %o0
771 END(ofw_entry)
772
773 /*
774  * void ofw_exit(cell_t args[])
775  */
776 ENTRY(ofw_exit)
777         save    %sp, -CCFSZ, %sp
778         flushw
779         SET(ofw_tba, %l7, %l5)
780         ldx     [%l5], %l5
781         rdpr    %pstate, %l7
782         andn    %l7, PSTATE_AM | PSTATE_IE, %l7
783         wrpr    %l7, 0, %pstate
784         rdpr    %wstate, %l7
785         andn    %l7, WSTATE_PROM_MASK, %l7
786         wrpr    %l7, WSTATE_PROM_KMIX, %wstate
787         wrpr    %l5, 0, %tba                    ! restore the OFW trap table
788         SET(ofw_vec, %l7, %l6)
789         ldx     [%l6], %l6
790         SET(kstack0 + KSTACK_PAGES * PAGE_SIZE - PCB_SIZEOF, %l7, %l0)
791         sub     %l0, SPOFF, %fp                 ! setup a stack in a locked page
792         sub     %l0, SPOFF + CCFSZ, %sp
793         mov     AA_DMMU_PCXR, %l3               ! force primary DMMU context 0
794         sethi   %hi(KERNBASE), %l5
795         stxa    %g0, [%l3] ASI_DMMU
796         flush   %l5
797         wrpr    %g0, 0, %tl                     ! force trap level 0
798         call    %l6
799          mov    %i0, %o0
800         ! never to return
801 END(ofw_exit)
802
803 #ifdef GPROF
804
805 ENTRY(user)
806         nop
807
808 ENTRY(btrap)
809         nop
810
811 ENTRY(etrap)
812         nop
813
814 ENTRY(bintr)
815         nop
816
817 ENTRY(eintr)
818         nop
819
820 /*
821  * XXX including sys/gmon.h in genassym.c is not possible due to uintfptr_t
822  * badness.
823  */
824 #define GM_STATE        0x0
825 #define GMON_PROF_OFF   3
826 #define GMON_PROF_HIRES 4
827
828         .globl  _mcount
829         .set    _mcount, __cyg_profile_func_enter
830
831 ENTRY(__cyg_profile_func_enter)
832         SET(_gmonparam, %o3, %o2)
833         lduw    [%o2 + GM_STATE], %o3
834         cmp     %o3, GMON_PROF_OFF
835         be,a,pn %icc, 1f
836          nop
837         SET(mcount, %o3, %o2)
838         jmpl    %o2, %g0
839          nop
840 1:      retl
841          nop
842 END(__cyg_profile_func_enter)
843
844 #ifdef GUPROF
845
846 ENTRY(__cyg_profile_func_exit)
847         SET(_gmonparam, %o3, %o2)
848         lduw    [%o2 + GM_STATE], %o3
849         cmp     %o3, GMON_PROF_HIRES
850         be,a,pn %icc, 1f
851          nop
852         SET(mexitcount, %o3, %o2)
853         jmpl    %o2, %g0
854          nop
855 1:      retl
856          nop
857 END(__cyg_profile_func_exit)
858
859 #endif /* GUPROF */
860
861 #endif /* GPROF */