1527d72a6d79e9838b92064572b643ad205cfc4e
[oweals/u-boot.git] / arch / sparc / cpu / leon3 / start.S
1 /* This is where the SPARC/LEON3 starts
2  *
3  * Copyright (C) 2007, 2015
4  * Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #include <asm-offsets.h>
10 #include <config.h>
11 #include <asm/asmmacro.h>
12 #include <asm/winmacro.h>
13 #include <asm/psr.h>
14 #include <asm/stack.h>
15 #include <asm/leon.h>
16 #include <ambapp.h>
17
18 /* Default Plug&Play I/O area */
19 #ifndef CONFIG_AMBAPP_IOAREA
20 #define CONFIG_AMBAPP_IOAREA AMBA_DEFAULT_IOAREA
21 #endif
22
23 /* Default number of SPARC register windows */
24 #ifndef CONFIG_SYS_SPARC_NWINDOWS
25 #define CONFIG_SYS_SPARC_NWINDOWS 8
26 #endif
27
28 /* Entry for traps which jump to a programmer-specified trap handler.  */
29 #define TRAPR(H)  \
30         wr      %g0, 0xfe0, %psr; \
31         mov     %g0, %tbr; \
32         ba      (H); \
33         mov     %g0, %wim;
34
35 #define TRAP(H) \
36         mov     %psr, %l0; \
37         ba      (H); \
38         nop; nop;
39
40 #define TRAPI(ilevel) \
41         mov     ilevel, %l7; \
42         mov     %psr, %l0; \
43         b       _irq_entry; \
44         mov     %wim, %l3
45
46 /* Unexcpected trap will halt the processor by forcing it to error state */
47 #undef BAD_TRAP
48 #define BAD_TRAP ta 0; nop; nop; nop;
49
50 /* Software trap. Treat as BAD_TRAP for the time being... */
51 #define SOFT_TRAP TRAP(_hwerr)
52
53 #define PSR_INIT   0x1FC0       /* Disable traps, set s and ps */
54 #define WIM_INIT   2
55
56 /* All traps low-level code here must end with this macro. */
57 #define RESTORE_ALL b ret_trap_entry; clr %l6;
58
59 #define WRITE_PAUSE nop;nop;nop
60
61 WINDOWSIZE = (16 * 4)
62 ARGPUSHSIZE = (6 * 4)
63 ARGPUSH = (WINDOWSIZE + 4)
64 MINFRAME = (WINDOWSIZE + ARGPUSHSIZE + 4)
65
66 /* Number of register windows */
67 #ifndef CONFIG_SYS_SPARC_NWINDOWS
68 #error Must define number of SPARC register windows, default is 8
69 #endif
70
71 /* Macros to load address into a register. Uses GOT table for PIC */
72 #ifdef __PIC__
73
74 #define SPARC_PIC_THUNK_CALL(reg) \
75         sethi   %pc22(_GLOBAL_OFFSET_TABLE_-4), %##reg; \
76         call    __sparc_get_pc_thunk.reg; \
77          add    %##reg, %pc10(_GLOBAL_OFFSET_TABLE_+4), %##reg;
78
79 #define SPARC_LOAD_ADDRESS(sym, got, reg) \
80         sethi   %gdop_hix22(sym), %##reg; \
81         xor     %##reg, %gdop_lox10(sym), %##reg; \
82         ld      [%##got + %##reg], %##reg, %gdop(sym);
83
84 #else
85
86 #define SPARC_PIC_THUNK_CALL(reg)
87 #define SPARC_LOAD_ADDRESS(sym, got, tmp) \
88         set     sym, %##reg;
89
90 #endif
91
92 #define STACK_ALIGN     8
93 #define SA(X)   (((X)+(STACK_ALIGN-1)) & ~(STACK_ALIGN-1))
94
95         .section ".start", "ax"
96         .globl  _start, start, _trap_table
97         .globl  _irq_entry, nmi_trap
98         .globl  _reset_reloc
99
100 /* at address 0
101  * Hardware traps
102  */
103 start:
104 _start:
105 _trap_table:
106         TRAPR(_hardreset);              ! 00 reset trap
107         BAD_TRAP;                       ! 01 instruction_access_exception
108         BAD_TRAP;                       ! 02 illegal_instruction
109         BAD_TRAP;                       ! 03 priveleged_instruction
110         BAD_TRAP;                       ! 04 fp_disabled
111         TRAP(_window_overflow);         ! 05 window_overflow
112         TRAP(_window_underflow);        ! 06 window_underflow
113         BAD_TRAP;                       ! 07 Memory Address Not Aligned
114         BAD_TRAP;                       ! 08 Floating Point Exception
115         BAD_TRAP;                       ! 09 Data Miss Exception
116         BAD_TRAP;                       ! 0a Tagged Instruction Ovrflw
117         BAD_TRAP;                       ! 0b Watchpoint Detected
118         BAD_TRAP;                       ! 0c
119         BAD_TRAP;                       ! 0d
120         BAD_TRAP;                       ! 0e
121         BAD_TRAP;                       ! 0f
122         BAD_TRAP;                       ! 10
123         TRAPI(1);                       ! 11 IRQ level 1
124         TRAPI(2);                       ! 12 IRQ level 2
125         TRAPI(3);                       ! 13 IRQ level 3
126         TRAPI(4);                       ! 14 IRQ level 4
127         TRAPI(5);                       ! 15 IRQ level 5
128         TRAPI(6);                       ! 16 IRQ level 6
129         TRAPI(7);                       ! 17 IRQ level 7
130         TRAPI(8);                       ! 18 IRQ level 8
131         TRAPI(9);                       ! 19 IRQ level 9
132         TRAPI(10);                      ! 1a IRQ level 10
133         TRAPI(11);                      ! 1b IRQ level 11
134         TRAPI(12);                      ! 1c IRQ level 12
135         TRAPI(13);                      ! 1d IRQ level 13
136         TRAPI(14);                      ! 1e IRQ level 14
137         TRAP(_nmi_trap);                ! 1f IRQ level 15 /
138                                         ! NMI (non maskable interrupt)
139         BAD_TRAP;                       ! 20 r_register_access_error
140         BAD_TRAP;                       ! 21 instruction access error
141         BAD_TRAP;                       ! 22
142         BAD_TRAP;                       ! 23
143         BAD_TRAP;                       ! 24 co-processor disabled
144         BAD_TRAP;                       ! 25 uniplemented FLUSH
145         BAD_TRAP;                       ! 26
146         BAD_TRAP;                       ! 27
147         BAD_TRAP;                       ! 28 co-processor exception
148         BAD_TRAP;                       ! 29 data access error
149         BAD_TRAP;                       ! 2a division by zero
150         BAD_TRAP;                       ! 2b data store error
151         BAD_TRAP;                       ! 2c data access MMU miss
152         BAD_TRAP;                       ! 2d
153         BAD_TRAP;                       ! 2e
154         BAD_TRAP;                       ! 2f
155         BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 30-33
156         BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 34-37
157         BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 38-3b
158         BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 3c-3f
159         BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 40-43
160         BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 44-47
161         BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 48-4b
162         BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 4c-4f
163         BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 50-53
164         BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 54-57
165         BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 58-5b
166         BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 5c-5f
167
168         /* implementaion dependent */
169         BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 60-63
170         BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 64-67
171         BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 68-6b
172         BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 6c-6f
173         BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 70-73
174         BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 74-77
175         BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 78-7b
176         BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 7c-7f
177
178         /* Software traps, not handled */
179         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! 80-83
180         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! 84-87
181         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! 88-8b
182         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! 8c-8f
183         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! 90-93
184         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! 94-97
185         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! 98-9b
186         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! 9c-9f
187         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! a0-a3
188         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! a4-a7
189         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! a8-ab
190         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! ac-af
191         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! b0-b3
192         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! b4-b7
193         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! b8-bb
194         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! bc-bf
195         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! c0-c3
196         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! c4-c7
197         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! c8-cb
198         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! cc-cf
199         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! d0-d3
200         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! d4-d7
201         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! d8-db
202         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! dc-df
203         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! e0-e3
204         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! e4-e7
205         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! e8-eb
206         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! ec-ef
207         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! f0-f3
208         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! f4-f7
209         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! f8-fb
210         SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;     ! fc-ff
211
212         .section        ".text"
213         .extern _nomem_amba_init, _nomem_memory_ctrl_init
214         .align 4
215
216 _hardreset:
217 1000:
218         flush
219
220         /* Enable I/D-Cache and Snooping */
221         set     0x0081000f, %g2
222         sta     %g2, [%g0] 2
223
224         mov     %g0, %y
225         clr     %g1
226         clr     %g2
227         clr     %g3
228         clr     %g4
229         clr     %g5
230         clr     %g6
231         clr     %g7
232
233         mov     %asr17, %g3
234         and     %g3, 0x1f, %g3
235 clear_window:
236         mov     %g0, %l0
237         mov     %g0, %l1
238         mov     %g0, %l2
239         mov     %g0, %l3
240         mov     %g0, %l4
241         mov     %g0, %l5
242         mov     %g0, %l6
243         mov     %g0, %l7
244         mov     %g0, %o0
245         mov     %g0, %o1
246         mov     %g0, %o2
247         mov     %g0, %o3
248         mov     %g0, %o4
249         mov     %g0, %o5
250         mov     %g0, %o6
251         mov     %g0, %o7
252         subcc   %g3, 1, %g3
253         bge     clear_window
254         save
255
256 wiminit:
257         set     WIM_INIT, %g3
258         mov     %g3, %wim
259
260 stackinit:
261         set     CONFIG_SYS_INIT_SP_OFFSET, %fp
262         andn    %fp, 0x0f, %fp
263         sub     %fp, 64, %sp
264
265 tbrinit:
266         set     CONFIG_SYS_TEXT_BASE, %g2
267         wr      %g0, %g2, %tbr
268         nop
269         nop
270         nop
271
272 /* Obtain the address of _GLOBAL_OFFSET_TABLE_ */
273         SPARC_PIC_THUNK_CALL(l7)
274
275 /* Scan AMBA Bus for AMBA buses using PnP information. All found
276  * AMBA buses I/O area will be located in i0-i5 upon return.
277  * The i0-i5 registers are later used by _nomem_amba_init2
278  */
279 ambainit:
280         call    _nomem_amba_init
281          sethi  %hi(CONFIG_AMBAPP_IOAREA), %o0
282
283 /* Scan AMBA Buses for memory controllers, then initialize the
284  * memory controllers. Note that before setting up the memory controller
285  * the stack can not be used.
286  */
287 memory_ctrl_init:
288         SPARC_LOAD_ADDRESS(grlib_mctrl_handlers, l7, o0)
289
290         call    _nomem_memory_ctrl_init
291          nop
292
293 /* The return valu indicate how many memory controllers where found and
294  * initialized, if no memory controller was initialized, we can not continue
295  * because from here on we expect memory to be working.
296  */
297         cmp     %o0, 0
298 memory_ctrl_init_failed:
299         beq     memory_ctrl_init_failed
300          nop
301
302 /*** From now on the stack can be used. ***/
303
304 cpu_init_unreloc:
305         call    cpu_init_f
306          nop
307
308 board_init_unreloc:
309         call    board_init_f
310          clr    %o0                     ! boot_flags
311
312 dead_unreloc:
313         mov     1, %g1                  ! For GRMON2 to exit normally.
314         ta 0                            ! If board_init_f call returns.. (unlikely)
315          nop
316         nop
317         ba      dead_unreloc            ! infinte loop
318          nop
319
320 !-------------------------------------------------------------------------------
321
322 /* void relocate_code (addr_sp, gd, addr_moni)
323  *
324  * This "function" does not return, instead it continues in RAM after
325  * relocating the monitor code.
326  *
327  * %o0 = Relocated stack pointer
328  * %o1 = Relocated global data pointer
329  * %o2 = Relocated text pointer
330  *
331  * %l7 = _GLOBAL_OFFSET_TABLE_ address
332  */
333         .globl  relocate_code
334         .type   relocate_code, #function
335         .align  4
336 relocate_code:
337         !SPARC_PIC_THUNK_CALL(l7)
338 reloc:
339         SPARC_LOAD_ADDRESS(_text, l7, g2)       ! start address of monitor
340         SPARC_LOAD_ADDRESS(__init_end, l7, g3)  ! end address of monitor
341         mov     %o2, %g4                ! relocation address
342         sub     %g4, %g2, %g6           ! relocation offset
343         /* copy .text & .data to relocated address */
344 10:     ldd     [%g2], %l0
345         ldd     [%g2+8], %l2
346         std     %l0, [%g4]
347         std     %l2, [%g4+8]
348         inc     16, %g2                 ! src += 16
349         cmp     %g2, %g3
350         bcs     10b                     ! while (src < end)
351          inc    16, %g4                 ! dst += 16
352
353         clr     %l0
354         clr     %l1
355         clr     %l2
356         clr     %l3
357         clr     %g2
358
359 /* register g4 contain address to start
360  * This means that BSS must be directly after data and code segments
361  *
362  * g3 is length of bss = (__bss_end-__bss_start)
363  *
364  */
365
366         /* clear the relocated .bss area */
367 clr_bss:
368         SPARC_LOAD_ADDRESS(__bss_start, l7, g2)
369         SPARC_LOAD_ADDRESS(__bss_end, l7, g3)
370         sub     %g3,%g2,%g3             ! length of .bss area
371         add     %g3,%g4,%g3
372         /* clearing 16byte a time ==> linker script need to align to 16 byte offset */
373         clr     %g1     /* std %g0 uses g0 and g1 */
374 20:
375         std     %g0, [%g4]
376         std     %g0, [%g4+8]
377         inc     16, %g4                 ! ptr += 16
378         cmp     %g4, %g3
379         bcs     20b                     ! while (ptr < end)
380          nop
381
382         /* add offsets to GOT table */
383 fixup_got:
384         SPARC_LOAD_ADDRESS(__got_start, l7, g4)
385         add     %g4, %g6, %g4
386         SPARC_LOAD_ADDRESS(__got_end, l7, g3)
387         add     %g3, %g6, %g3
388 30:     ld      [%g4], %l0
389 #ifdef CONFIG_RELOC_GOT_SKIP_NULL
390         cmp     %l0, 0
391         be      32f
392 #endif
393         add     %l0, %g6, %l0           ! relocate GOT pointer
394         st      %l0, [%g4]
395 32:     inc     4, %g4                  ! ptr += 4
396         cmp     %g4, %g3
397         bcs     30b                     ! while (ptr < end)
398          nop
399
400 prom_relocate:
401         SPARC_LOAD_ADDRESS(__prom_start, l7, g2)
402         SPARC_LOAD_ADDRESS(__prom_end, l7, g3)
403         /*
404          * Calculated addres is stored in this variable by
405          * reserve_prom() function in common/board_f.c
406          */
407         SPARC_LOAD_ADDRESS(__prom_start_reloc, l7, g4)
408         ld      [%g4], %g4
409
410 40:     ldd     [%g2], %l0
411         ldd     [%g2+8], %l2
412         std     %l0, [%g4]
413         std     %l2, [%g4+8]
414         inc     16, %g2
415         cmp     %g2, %g3
416         bcs     40b
417          inc    16, %g4
418
419 ! %o0 = stack pointer (relocated)
420 ! %o1 = global data pointer (relocated)
421 ! %o2 = text pointer (relocated)
422
423 ! %g6 = relocation offset
424 ! %l7 = _GLOBAL_OFFSET_TABLE_
425
426 /* Trap table has been moved, lets tell CPU about
427  * the new trap table address
428  */
429 update_trap_table_address:
430         wr      %g0, %o2, %tbr
431         nop
432         nop
433         nop
434
435 update_stack_pointers:
436         mov     %o0, %fp
437         andn    %fp, 0x0f, %fp  ! align to 16 bytes
438         add     %fp, -64, %fp   ! make space for a window push
439         mov     %fp, %sp        ! setup stack pointer
440
441 jump_board_init_r:
442         mov     %o1, %o0        ! relocated global data pointer
443         mov     %o2, %o1        ! relocated text pointer
444         SPARC_LOAD_ADDRESS(board_init_r, l7, o3)
445         add     %o3, %g6, %o3   ! add relocation offset
446         call    %o3
447          nop
448
449 dead:
450         mov     1, %g1                  ! For GRMON2 to exit normally.
451         ta 0                            ! if call returns.. (unlikely)
452          nop
453         b       dead                    ! infinte loop
454          nop
455
456 !------------------------------------------------------------------------------
457
458 /* Interrupt handler caller,
459  * reg L7: interrupt number
460  * reg L0: psr after interrupt
461  * reg L1: PC
462  * reg L2: next PC
463  * reg L3: wim
464  */
465 _irq_entry:
466         SAVE_ALL
467
468         or      %l0, PSR_PIL, %g2
469         wr      %g2, 0x0, %psr
470         WRITE_PAUSE
471         wr      %g2, PSR_ET, %psr
472         WRITE_PAUSE
473         mov     %l7, %o0                ! irq level
474         set     handler_irq, %o1
475         set     (CONFIG_SYS_RELOC_MONITOR_BASE-CONFIG_SYS_TEXT_BASE), %o2
476         add     %o1, %o2, %o1
477         call    %o1
478         add     %sp, SF_REGS_SZ, %o1    ! pt_regs ptr
479         or      %l0, PSR_PIL, %g2       ! restore PIL after handler_irq
480         wr      %g2, PSR_ET, %psr       ! keep ET up
481         WRITE_PAUSE
482
483         RESTORE_ALL
484
485 !------------------------------------------------------------------------------
486
487 /*
488  * Window overflow trap handler
489  */
490         .global _window_overflow
491
492 _window_overflow:
493
494         mov     %wim, %l3               ! Calculate next WIM
495         mov     %g1, %l7
496         srl     %l3, 1, %g1
497         sll     %l3, (CONFIG_SYS_SPARC_NWINDOWS-1), %l4
498         or      %g1, %l4, %g1
499         save                            ! Get into window to be saved.
500         mov     %g1, %wim
501         nop; nop; nop
502         st      %l0, [%sp + 0]          ! Save window to the stack
503         st      %l1, [%sp + 4]
504         st      %l2, [%sp + 8]
505         st      %l3, [%sp + 12]
506         st      %l4, [%sp + 16]
507         st      %l5, [%sp + 20]
508         st      %l6, [%sp + 24]
509         st      %l7, [%sp + 28]
510         st      %i0, [%sp + 32]
511         st      %i1, [%sp + 36]
512         st      %i2, [%sp + 40]
513         st      %i3, [%sp + 44]
514         st      %i4, [%sp + 48]
515         st      %i5, [%sp + 52]
516         st      %i6, [%sp + 56]
517         st      %i7, [%sp + 60]
518         restore                         ! Go back to trap window.
519         mov     %l7, %g1
520         jmp     %l1                     ! Re-execute save.
521          rett   %l2
522
523 /*
524  * Window underflow trap handler
525  */
526         .global  _window_underflow
527
528 _window_underflow:
529
530         mov     %wim, %l3               ! Calculate next WIM
531         srl     %l3, (CONFIG_SYS_SPARC_NWINDOWS-1), %l5
532         sll     %l3, 1, %l4
533         or      %l5, %l4, %l5
534         mov     %l5, %wim
535         nop; nop; nop
536         restore                         ! Two restores to get into the
537         restore                         ! window to restore
538         ld      [%sp + 0], %l0;         ! Restore window from the stack
539         ld      [%sp + 4], %l1;
540         ld      [%sp + 8], %l2;
541         ld      [%sp + 12], %l3;
542         ld      [%sp + 16], %l4;
543         ld      [%sp + 20], %l5;
544         ld      [%sp + 24], %l6;
545         ld      [%sp + 28], %l7;
546         ld      [%sp + 32], %i0;
547         ld      [%sp + 36], %i1;
548         ld      [%sp + 40], %i2;
549         ld      [%sp + 44], %i3;
550         ld      [%sp + 48], %i4;
551         ld      [%sp + 52], %i5;
552         ld      [%sp + 56], %i6;
553         ld      [%sp + 60], %i7;
554         save                            ! Get back to the trap window.
555         save
556         jmp     %l1                     ! Re-execute restore.
557          rett   %l2
558
559 !------------------------------------------------------------------------------
560
561 _nmi_trap:
562         nop
563         jmp %l1
564         rett %l2
565
566 _hwerr:
567         ta 0
568         nop
569         nop
570         b _hwerr                        ! loop infinite
571         nop
572
573 /* Registers to not touch at all. */
574 #define t_psr      l0 /* Set by caller */
575 #define t_pc       l1 /* Set by caller */
576 #define t_npc      l2 /* Set by caller */
577 #define t_wim      l3 /* Set by caller */
578 #define t_twinmask l4 /* Set at beginning of this entry routine. */
579 #define t_kstack   l5 /* Set right before pt_regs frame is built */
580 #define t_retpc    l6 /* If you change this, change winmacro.h header file */
581 #define t_systable l7 /* Never touch this, could be the syscall table ptr. */
582 #define curptr     g6 /* Set after pt_regs frame is built */
583
584 trap_setup:
585 /* build a pt_regs trap frame. */
586         sub     %fp, (SF_REGS_SZ + PT_REGS_SZ), %t_kstack
587         PT_STORE_ALL(t_kstack, t_psr, t_pc, t_npc, g2)
588
589         /* See if we are in the trap window. */
590         mov     1, %t_twinmask
591         sll     %t_twinmask, %t_psr, %t_twinmask ! t_twinmask = (1 << psr)
592         andcc   %t_twinmask, %t_wim, %g0
593         beq     1f              ! in trap window, clean up
594         nop
595
596         /*-------------------------------------------------
597          * Spill , adjust %wim and go.
598          */
599         srl     %t_wim, 0x1, %g2                ! begin computation of new %wim
600
601         set     (CONFIG_SYS_SPARC_NWINDOWS-1), %g3      !NWINDOWS-1
602
603         sll     %t_wim, %g3, %t_wim     ! NWINDOWS-1
604         or      %t_wim, %g2, %g2
605         and     %g2, 0xff, %g2
606
607         save    %g0, %g0, %g0           ! get in window to be saved
608
609         /* Set new %wim value */
610         wr      %g2, 0x0, %wim
611
612         /* Save the kernel window onto the corresponding stack. */
613         RW_STORE(sp)
614
615         restore %g0, %g0, %g0
616         /*-------------------------------------------------*/
617
618 1:
619         /* Trap from kernel with a window available.
620          * Just do it...
621          */
622         jmpl    %t_retpc + 0x8, %g0     ! return to caller
623          mov    %t_kstack, %sp          ! jump onto new stack
624
625 #define twin_tmp1 l4
626 #define glob_tmp  g4
627 #define curptr    g6
628 ret_trap_entry:
629         wr      %t_psr, 0x0, %psr       ! enable nesting again, clear ET
630
631         /* Will the rett land us in the invalid window? */
632         mov     2, %g1
633         sll     %g1, %t_psr, %g1
634
635         set     CONFIG_SYS_SPARC_NWINDOWS, %g2  !NWINDOWS
636
637         srl     %g1, %g2, %g2
638         or      %g1, %g2, %g1
639         rd      %wim, %g2
640         andcc   %g2, %g1, %g0
641         be      1f              ! Nope, just return from the trap
642          sll    %g2, 0x1, %g1
643
644         /* We have to grab a window before returning. */
645         set     (CONFIG_SYS_SPARC_NWINDOWS-1), %g3      !NWINDOWS-1
646
647         srl     %g2, %g3,  %g2
648         or      %g1, %g2, %g1
649         and     %g1, 0xff, %g1
650
651         wr      %g1, 0x0, %wim
652
653         /* Grrr, make sure we load from the right %sp... */
654         PT_LOAD_ALL(sp, t_psr, t_pc, t_npc, g1)
655
656         restore %g0, %g0, %g0
657         RW_LOAD(sp)
658         b       2f
659         save    %g0, %g0, %g0
660
661         /* Reload the entire frame in case this is from a
662          * kernel system call or whatever...
663          */
664 1:
665         PT_LOAD_ALL(sp, t_psr, t_pc, t_npc, g1)
666 2:
667         wr      %t_psr, 0x0, %psr
668         nop;
669         nop;
670         nop
671
672         jmp     %t_pc
673         rett    %t_npc
674
675 /* This is called from relocated C-code.
676  * It resets the system by jumping to _start
677  */
678 _reset_reloc:
679         set     start, %l0
680         call    %l0
681         nop