]>
Commit | Line | Data |
---|---|---|
c978b524 CZ |
1 | /* |
2 | * (C) Copyright 2008 - 2013 Tensilica Inc. | |
3 | * (C) Copyright 2014 - 2016 Cadence Design Systems Inc. | |
4 | * | |
5 | * SPDX-License-Identifier: GPL-2.0+ | |
6 | */ | |
7 | ||
8 | #include <config.h> | |
9 | #include <asm/asmmacro.h> | |
10 | #include <asm/cacheasm.h> | |
11 | #include <asm/regs.h> | |
12 | #include <asm/arch/tie.h> | |
13 | #include <asm-offsets.h> | |
14 | ||
15 | /* | |
16 | * Offsets into the the pt_regs struture. | |
17 | * Make sure these always match with the structure defined in ptrace.h! | |
18 | */ | |
19 | ||
20 | #define PT_PC 0 | |
21 | #define PT_PS 4 | |
22 | #define PT_DEPC 8 | |
23 | #define PT_EXCCAUSE 12 | |
24 | #define PT_EXCVADDR 16 | |
25 | #define PT_DEBUGCAUSE 20 | |
26 | #define PT_WMASK 24 | |
27 | #define PT_LBEG 28 | |
28 | #define PT_LEND 32 | |
29 | #define PT_LCOUNT 36 | |
30 | #define PT_SAR 40 | |
31 | #define PT_WINDOWBASE 44 | |
32 | #define PT_WINDOWSTART 48 | |
33 | #define PT_SYSCALL 52 | |
34 | #define PT_ICOUNTLEVEL 56 | |
35 | #define PT_RESERVED 60 | |
36 | #define PT_AREG 64 | |
37 | #define PT_SIZE (64 + 64) | |
38 | ||
39 | /* | |
40 | * Cache attributes are different for full MMU and region protection. | |
41 | */ | |
42 | ||
43 | #if XCHAL_HAVE_PTP_MMU | |
44 | #define CA_WRITEBACK (0x7) | |
45 | #else | |
46 | #define CA_WRITEBACK (0x4) | |
47 | #endif | |
48 | ||
49 | /* | |
50 | * Reset vector. | |
51 | * Only a trampoline to jump to _start | |
52 | * (Note that we have to mark the section writable as the section contains | |
53 | * a relocatable literal) | |
54 | */ | |
55 | ||
56 | .section .ResetVector.text, "awx" | |
57 | .global _ResetVector | |
58 | _ResetVector: | |
59 | ||
60 | j 1f | |
61 | .align 4 | |
62 | 2: .long _start | |
63 | 1: l32r a2, 2b | |
64 | jx a2 | |
65 | ||
66 | ||
67 | /* | |
68 | * Processor initialization. We still run in rom space. | |
69 | * | |
70 | * NOTE: Running in ROM | |
71 | * For Xtensa, we currently don't allow to run some code from ROM but | |
72 | * unpack the data immediately to memory. This requires, for example, | |
73 | * that DDR has been set up before running U-Boot. (See also comments | |
74 | * inline for ways to change it) | |
75 | */ | |
76 | ||
77 | .section .reset.text, "ax" | |
78 | .global _start | |
79 | .align 4 | |
80 | _start: | |
81 | /* Keep a0 = 0 for various initializations */ | |
82 | ||
83 | movi a0, 0 | |
84 | ||
85 | /* | |
86 | * For full MMU cores, put page table at unmapped virtual address. | |
87 | * This ensures that accesses outside the static maps result | |
88 | * in miss exceptions rather than random behaviour. | |
89 | */ | |
90 | ||
91 | #if XCHAL_HAVE_PTP_MMU | |
92 | wsr a0, PTEVADDR | |
93 | #endif | |
94 | ||
95 | /* Disable dbreak debug exceptions */ | |
96 | ||
97 | #if XCHAL_HAVE_DEBUG && XCHAL_NUM_DBREAK > 0 | |
98 | .set _index, 0 | |
99 | .rept XCHAL_NUM_DBREAK | |
100 | wsr a0, DBREAKC + _index | |
101 | .set _index, _index + 1 | |
102 | .endr | |
103 | #endif | |
104 | ||
105 | /* Reset windowbase and windowstart */ | |
106 | ||
107 | #if XCHAL_HAVE_WINDOWED | |
108 | movi a3, 1 | |
109 | wsr a3, windowstart | |
110 | wsr a0, windowbase | |
111 | rsync | |
112 | movi a0, 0 /* windowbase might have changed */ | |
113 | #endif | |
114 | ||
115 | /* | |
116 | * Vecbase in bitstream may differ from header files | |
117 | * set or check it. | |
118 | */ | |
119 | ||
120 | #if XCHAL_HAVE_VECBASE | |
121 | movi a3, XCHAL_VECBASE_RESET_VADDR /* VECBASE reset value */ | |
122 | wsr a3, VECBASE | |
123 | #endif | |
124 | ||
125 | #if XCHAL_HAVE_LOOPS | |
126 | /* Disable loops */ | |
127 | ||
128 | wsr a0, LCOUNT | |
129 | #endif | |
130 | ||
131 | /* Set PS.WOE = 0, PS.EXCM = 0 (for loop), PS.INTLEVEL = EXCM level */ | |
132 | ||
133 | #if XCHAL_HAVE_XEA1 | |
134 | movi a2, 1 | |
135 | #else | |
136 | movi a2, XCHAL_EXCM_LEVEL | |
137 | #endif | |
138 | wsr a2, PS | |
139 | rsync | |
140 | ||
141 | /* Unlock and invalidate caches */ | |
142 | ||
143 | ___unlock_dcache_all a2, a3 | |
144 | ___invalidate_dcache_all a2, a3 | |
145 | ___unlock_icache_all a2, a3 | |
146 | ___invalidate_icache_all a2, a3 | |
147 | ||
148 | isync | |
149 | ||
150 | /* Unpack data sections */ | |
151 | ||
152 | movi a2, __reloc_table_start | |
153 | movi a3, __reloc_table_end | |
154 | ||
155 | 1: beq a2, a3, 3f # no more entries? | |
156 | l32i a4, a2, 0 # start destination (in RAM) | |
157 | l32i a5, a2, 4 # end destination (in RAM) | |
158 | l32i a6, a2, 8 # start source (in ROM) | |
159 | addi a2, a2, 12 # next entry | |
160 | beq a4, a5, 1b # skip, empty entry | |
161 | beq a4, a6, 1b # skip, source and destination are the same | |
162 | ||
163 | /* If there's memory protection option with 512MB TLB regions and | |
164 | * cache attributes in TLB entries and caching is not inhibited, | |
165 | * enable data/instruction cache for relocated image. | |
166 | */ | |
167 | #if XCHAL_HAVE_SPANNING_WAY && \ | |
168 | (!defined(CONFIG_SYS_DCACHE_OFF) || \ | |
169 | !defined(CONFIG_SYS_ICACHE_OFF)) | |
170 | srli a7, a4, 29 | |
171 | slli a7, a7, 29 | |
172 | addi a7, a7, XCHAL_SPANNING_WAY | |
173 | #ifndef CONFIG_SYS_DCACHE_OFF | |
174 | rdtlb1 a8, a7 | |
175 | srli a8, a8, 4 | |
176 | slli a8, a8, 4 | |
177 | addi a8, a8, CA_WRITEBACK | |
178 | wdtlb a8, a7 | |
179 | #endif | |
180 | #ifndef CONFIG_SYS_ICACHE_OFF | |
181 | ritlb1 a8, a7 | |
182 | srli a8, a8, 4 | |
183 | slli a8, a8, 4 | |
184 | addi a8, a8, CA_WRITEBACK | |
185 | witlb a8, a7 | |
186 | #endif | |
187 | isync | |
188 | #endif | |
189 | ||
190 | 2: l32i a7, a6, 0 | |
191 | addi a6, a6, 4 | |
192 | s32i a7, a4, 0 | |
193 | addi a4, a4, 4 | |
194 | bltu a4, a5, 2b | |
195 | j 1b | |
196 | ||
197 | 3: /* All code and initalized data segments have been copied */ | |
198 | ||
199 | /* Setup PS, PS.WOE = 1, PS.EXCM = 0, PS.INTLEVEL = EXCM level. */ | |
200 | ||
201 | #if __XTENSA_CALL0_ABI__ | |
202 | movi a2, XCHAL_EXCM_LEVEL | |
203 | #else | |
204 | movi a2, (1<<PS_WOE_BIT) | XCHAL_EXCM_LEVEL | |
205 | #endif | |
206 | wsr a2, PS | |
207 | rsync | |
208 | ||
209 | /* Writeback */ | |
210 | ||
211 | ___flush_dcache_all a2, a3 | |
212 | ||
213 | #ifdef __XTENSA_WINDOWED_ABI__ | |
214 | /* | |
215 | * In windowed ABI caller and call target need to be within the same | |
216 | * gigabyte. Put the rest of the code into the text segment and jump | |
217 | * there. | |
218 | */ | |
219 | ||
220 | movi a4, .Lboard_init_code | |
221 | jx a4 | |
222 | ||
223 | .text | |
224 | .align 4 | |
225 | .Lboard_init_code: | |
226 | #endif | |
227 | ||
228 | movi a0, 0 | |
10117a29 | 229 | movi sp, (XTENSA_SYS_TEXT_ADDR - 16) & 0xfffffff0 |
c978b524 CZ |
230 | |
231 | #ifdef CONFIG_DEBUG_UART | |
232 | movi a4, debug_uart_init | |
233 | #ifdef __XTENSA_CALL0_ABI__ | |
234 | callx0 a4 | |
235 | #else | |
236 | callx4 a4 | |
237 | #endif | |
238 | #endif | |
239 | ||
240 | movi a4, board_init_f_alloc_reserve | |
241 | ||
242 | #ifdef __XTENSA_CALL0_ABI__ | |
243 | mov a2, sp | |
244 | callx0 a4 | |
245 | mov sp, a2 | |
246 | #else | |
247 | mov a6, sp | |
248 | callx4 a4 | |
249 | movsp sp, a6 | |
250 | #endif | |
251 | ||
252 | movi a4, board_init_f_init_reserve | |
253 | ||
254 | #ifdef __XTENSA_CALL0_ABI__ | |
255 | callx0 a4 | |
256 | #else | |
257 | callx4 a4 | |
258 | #endif | |
259 | ||
260 | /* | |
261 | * Call board initialization routine (never returns). | |
262 | */ | |
263 | ||
264 | movi a4, board_init_f | |
265 | ||
266 | #ifdef __XTENSA_CALL0_ABI__ | |
267 | movi a2, 0 | |
268 | callx0 a4 | |
269 | #else | |
270 | movi a6, 0 | |
271 | callx4 a4 | |
272 | #endif | |
273 | /* Never Returns */ | |
274 | ill | |
275 | ||
276 | /* | |
277 | * void relocate_code (addr_sp, gd, addr_moni) | |
278 | * | |
279 | * This "function" does not return, instead it continues in RAM | |
280 | * after relocating the monitor code. | |
281 | * | |
282 | * a2 = addr_sp | |
283 | * a3 = gd | |
284 | * a4 = destination address | |
285 | */ | |
286 | .text | |
287 | .globl relocate_code | |
288 | .align 4 | |
289 | relocate_code: | |
290 | abi_entry | |
291 | ||
292 | #ifdef __XTENSA_CALL0_ABI__ | |
293 | mov a1, a2 | |
294 | mov a2, a3 | |
295 | mov a3, a4 | |
296 | movi a0, board_init_r | |
297 | callx0 a0 | |
298 | #else | |
299 | /* We can't movsp here, because the chain of stack frames may cross | |
300 | * the now reserved memory. We need to toss all window frames except | |
301 | * the current, create new pristine stack frame and start from scratch. | |
302 | */ | |
303 | rsr a0, windowbase | |
304 | ssl a0 | |
305 | movi a0, 1 | |
306 | sll a0, a0 | |
307 | wsr a0, windowstart | |
308 | rsync | |
309 | ||
310 | movi a0, 0 | |
311 | ||
312 | /* Reserve 16-byte save area */ | |
313 | addi sp, a2, -16 | |
314 | mov a6, a3 | |
315 | mov a7, a4 | |
316 | movi a4, board_init_r | |
317 | callx4 a4 | |
318 | #endif | |
319 | ill | |
320 | ||
321 | #if XCHAL_HAVE_EXCEPTIONS | |
322 | ||
323 | /* | |
324 | * Exception vectors. | |
325 | * | |
326 | * Various notes: | |
327 | * - We currently don't use the user exception vector (PS.UM is always 0), | |
328 | * but do define such a vector, just in case. They both jump to the | |
329 | * same exception handler, though. | |
330 | * - We currently only save the bare minimum number of registers: | |
331 | * a0...a15, sar, loop-registers, exception register (epc1, excvaddr, | |
332 | * exccause, depc) | |
333 | * - WINDOWSTART is only saved to identify if registers have been spilled | |
334 | * to the wrong stack (exception stack) while executing the exception | |
335 | * handler. | |
336 | */ | |
337 | ||
338 | .section .KernelExceptionVector.text, "ax" | |
339 | .global _KernelExceptionVector | |
340 | _KernelExceptionVector: | |
341 | ||
342 | wsr a2, EXCSAVE1 | |
343 | movi a2, ExceptionHandler | |
344 | jx a2 | |
345 | ||
346 | .section .UserExceptionVector.text, "ax" | |
347 | .global _UserExceptionVector | |
348 | _UserExceptionVector: | |
349 | ||
350 | wsr a2, EXCSAVE1 | |
351 | movi a2, ExceptionHandler | |
352 | jx a2 | |
353 | ||
354 | #if !XCHAL_HAVE_XEA1 | |
355 | .section .DoubleExceptionVector.text, "ax" | |
356 | .global _DoubleExceptionVector | |
357 | _DoubleExceptionVector: | |
358 | ||
359 | #ifdef __XTENSA_CALL0_ABI__ | |
360 | wsr a0, EXCSAVE1 | |
361 | movi a0, hang # report and ask user to reset board | |
362 | callx0 a0 | |
363 | #else | |
364 | wsr a4, EXCSAVE1 | |
365 | movi a4, hang # report and ask user to reset board | |
366 | callx4 a4 | |
367 | #endif | |
368 | #endif | |
369 | /* Does not return here */ | |
370 | ||
371 | ||
372 | .text | |
373 | .align 4 | |
374 | ExceptionHandler: | |
375 | ||
376 | rsr a2, EXCCAUSE # find handler | |
377 | ||
378 | #if XCHAL_HAVE_WINDOWED | |
379 | /* Special case for alloca handler */ | |
380 | ||
381 | bnei a2, 5, 1f # jump if not alloca exception | |
382 | ||
383 | addi a1, a1, -16 - 4 # create a small stack frame | |
384 | s32i a3, a1, 0 # and save a3 (a2 still in excsave1) | |
385 | movi a2, fast_alloca_exception | |
386 | jx a2 # jump to fast_alloca_exception | |
387 | #endif | |
388 | /* All other exceptions go here: */ | |
389 | ||
390 | /* Create ptrace stack and save a0...a3 */ | |
391 | ||
392 | 1: addi a2, a1, - PT_SIZE - 16 | |
393 | s32i a0, a2, PT_AREG + 0 * 4 | |
394 | s32i a1, a2, PT_AREG + 1 * 4 | |
395 | s32i a3, a2, PT_AREG + 3 * 4 | |
396 | rsr a3, EXCSAVE1 | |
397 | s32i a3, a2, PT_AREG + 2 * 4 | |
398 | mov a1, a2 | |
399 | ||
400 | /* Save remaining AR registers */ | |
401 | ||
402 | s32i a4, a1, PT_AREG + 4 * 4 | |
403 | s32i a5, a1, PT_AREG + 5 * 4 | |
404 | s32i a6, a1, PT_AREG + 6 * 4 | |
405 | s32i a7, a1, PT_AREG + 7 * 4 | |
406 | s32i a8, a1, PT_AREG + 8 * 4 | |
407 | s32i a9, a1, PT_AREG + 9 * 4 | |
408 | s32i a10, a1, PT_AREG + 10 * 4 | |
409 | s32i a11, a1, PT_AREG + 11 * 4 | |
410 | s32i a12, a1, PT_AREG + 12 * 4 | |
411 | s32i a13, a1, PT_AREG + 13 * 4 | |
412 | s32i a14, a1, PT_AREG + 14 * 4 | |
413 | s32i a15, a1, PT_AREG + 15 * 4 | |
414 | ||
415 | /* Save SRs */ | |
416 | ||
417 | #if XCHAL_HAVE_WINDOWED | |
418 | rsr a2, WINDOWSTART | |
419 | s32i a2, a1, PT_WINDOWSTART | |
420 | #endif | |
421 | ||
422 | rsr a2, SAR | |
423 | rsr a3, EPC1 | |
424 | rsr a4, EXCVADDR | |
425 | s32i a2, a1, PT_SAR | |
426 | s32i a3, a1, PT_PC | |
427 | s32i a4, a1, PT_EXCVADDR | |
428 | ||
429 | #if XCHAL_HAVE_LOOPS | |
430 | movi a2, 0 | |
431 | rsr a3, LBEG | |
432 | xsr a2, LCOUNT | |
433 | s32i a3, a1, PT_LBEG | |
434 | rsr a3, LEND | |
435 | s32i a2, a1, PT_LCOUNT | |
436 | s32i a3, a1, PT_LEND | |
437 | #endif | |
438 | ||
439 | /* Set up C environment and call registered handler */ | |
440 | /* Setup stack, PS.WOE = 1, PS.EXCM = 0, PS.INTLEVEL = EXCM level. */ | |
441 | ||
442 | rsr a2, EXCCAUSE | |
443 | #if XCHAL_HAVE_XEA1 | |
444 | movi a3, (1<<PS_WOE_BIT) | 1 | |
445 | #elif __XTENSA_CALL0_ABI__ | |
446 | movi a3, XCHAL_EXCM_LEVEL | |
447 | #else | |
448 | movi a3, (1<<PS_WOE_BIT) | XCHAL_EXCM_LEVEL | |
449 | #endif | |
450 | xsr a3, PS | |
451 | rsync | |
452 | s32i a2, a1, PT_EXCCAUSE | |
453 | s32i a3, a1, PT_PS | |
454 | ||
455 | movi a0, exc_table | |
456 | addx4 a0, a2, a0 | |
457 | l32i a0, a0, 0 | |
458 | #ifdef __XTENSA_CALL0_ABI__ | |
459 | mov a2, a1 # Provide stack frame as only argument | |
460 | callx0 a0 | |
461 | l32i a3, a1, PT_PS | |
462 | #else | |
463 | mov a6, a1 # Provide stack frame as only argument | |
464 | callx4 a0 | |
465 | #endif | |
466 | ||
467 | /* Restore PS and go to exception mode (PS.EXCM=1) */ | |
468 | ||
469 | wsr a3, PS | |
470 | ||
471 | /* Restore SR registers */ | |
472 | ||
473 | #if XCHAL_HAVE_LOOPS | |
474 | l32i a2, a1, PT_LBEG | |
475 | l32i a3, a1, PT_LEND | |
476 | l32i a4, a1, PT_LCOUNT | |
477 | wsr a2, LBEG | |
478 | wsr a3, LEND | |
479 | wsr a4, LCOUNT | |
480 | #endif | |
481 | ||
482 | l32i a2, a1, PT_SAR | |
483 | l32i a3, a1, PT_PC | |
484 | wsr a2, SAR | |
485 | wsr a3, EPC1 | |
486 | ||
487 | #if XCHAL_HAVE_WINDOWED | |
488 | /* Do we need to simulate a MOVSP? */ | |
489 | ||
490 | l32i a2, a1, PT_WINDOWSTART | |
491 | addi a3, a2, -1 | |
492 | and a2, a2, a3 | |
493 | beqz a2, 1f # Skip if regs were spilled before exc. | |
494 | ||
495 | rsr a2, WINDOWSTART | |
496 | addi a3, a2, -1 | |
497 | and a2, a2, a3 | |
498 | bnez a2, 1f # Skip if registers aren't spilled now | |
499 | ||
500 | addi a2, a1, -16 | |
501 | l32i a4, a2, 0 | |
502 | l32i a5, a2, 4 | |
503 | s32i a4, a1, PT_SIZE + 0 | |
504 | s32i a5, a1, PT_SIZE + 4 | |
505 | l32i a4, a2, 8 | |
506 | l32i a5, a2, 12 | |
507 | s32i a4, a1, PT_SIZE + 8 | |
508 | s32i a5, a1, PT_SIZE + 12 | |
509 | #endif | |
510 | ||
511 | /* Restore address register */ | |
512 | ||
513 | 1: l32i a15, a1, PT_AREG + 15 * 4 | |
514 | l32i a14, a1, PT_AREG + 14 * 4 | |
515 | l32i a13, a1, PT_AREG + 13 * 4 | |
516 | l32i a12, a1, PT_AREG + 12 * 4 | |
517 | l32i a11, a1, PT_AREG + 11 * 4 | |
518 | l32i a10, a1, PT_AREG + 10 * 4 | |
519 | l32i a9, a1, PT_AREG + 9 * 4 | |
520 | l32i a8, a1, PT_AREG + 8 * 4 | |
521 | l32i a7, a1, PT_AREG + 7 * 4 | |
522 | l32i a6, a1, PT_AREG + 6 * 4 | |
523 | l32i a5, a1, PT_AREG + 5 * 4 | |
524 | l32i a4, a1, PT_AREG + 4 * 4 | |
525 | l32i a3, a1, PT_AREG + 3 * 4 | |
526 | l32i a2, a1, PT_AREG + 2 * 4 | |
527 | l32i a0, a1, PT_AREG + 0 * 4 | |
528 | ||
529 | l32i a1, a1, PT_AREG + 1 * 4 # Remove ptrace stack frame | |
530 | ||
531 | rfe | |
532 | ||
533 | #endif /* XCHAL_HAVE_EXCEPTIONS */ | |
534 | ||
535 | #if XCHAL_HAVE_WINDOWED | |
536 | ||
537 | /* | |
538 | * Window overflow and underflow handlers. | |
539 | * The handlers must be 64 bytes apart, first starting with the underflow | |
540 | * handlers underflow-4 to underflow-12, then the overflow handlers | |
541 | * overflow-4 to overflow-12. | |
542 | * | |
543 | * Note: We rerun the underflow handlers if we hit an exception, so | |
544 | * we try to access any page that would cause a page fault early. | |
545 | */ | |
546 | ||
547 | .section .WindowVectors.text, "ax" | |
548 | ||
549 | /* 4-Register Window Overflow Vector (Handler) */ | |
550 | ||
551 | .align 64 | |
552 | .global _WindowOverflow4 | |
553 | _WindowOverflow4: | |
554 | s32e a0, a5, -16 | |
555 | s32e a1, a5, -12 | |
556 | s32e a2, a5, -8 | |
557 | s32e a3, a5, -4 | |
558 | rfwo | |
559 | ||
560 | ||
561 | /* 4-Register Window Underflow Vector (Handler) */ | |
562 | ||
563 | .align 64 | |
564 | .global _WindowUnderflow4 | |
565 | _WindowUnderflow4: | |
566 | l32e a0, a5, -16 | |
567 | l32e a1, a5, -12 | |
568 | l32e a2, a5, -8 | |
569 | l32e a3, a5, -4 | |
570 | rfwu | |
571 | ||
572 | /* | |
573 | * a0: a0 | |
574 | * a1: new stack pointer = a1 - 16 - 4 | |
575 | * a2: available, saved in excsave1 | |
576 | * a3: available, saved on stack *a1 | |
577 | */ | |
578 | ||
579 | /* 15*/ .byte 0xff | |
580 | ||
581 | fast_alloca_exception: /* must be at _WindowUnderflow4 + 16 */ | |
582 | ||
583 | /* 16*/ rsr a2, PS | |
584 | /* 19*/ rsr a3, WINDOWBASE | |
585 | /* 22*/ extui a2, a2, PS_OWB_SHIFT, PS_OWB_SHIFT | |
586 | /* 25*/ xor a2, a2, a3 | |
587 | /* 28*/ rsr a3, PS | |
588 | /* 31*/ slli a2, a2, PS_OWB_SHIFT | |
589 | /* 34*/ xor a2, a3, a2 | |
590 | /* 37*/ wsr a2, PS | |
591 | ||
592 | /* 40*/ _l32i a3, a1, 0 | |
593 | /* 43*/ addi a1, a1, 16 + 4 | |
594 | /* 46*/ rsr a2, EXCSAVE1 | |
595 | ||
596 | /* 49*/ rotw -1 | |
597 | /* 52*/ _bbci.l a4, 31, _WindowUnderflow4 /* 0x: call4 */ | |
598 | /* 55*/ rotw -1 | |
599 | /* 58*/ _bbci.l a8, 30, _WindowUnderflow8 /* 10: call8 */ | |
600 | /* 61*/ _j __WindowUnderflow12 /* 11: call12 */ | |
601 | /* 64*/ | |
602 | ||
603 | /* 8-Register Window Overflow Vector (Handler) */ | |
604 | ||
605 | .align 64 | |
606 | .global _WindowOverflow8 | |
607 | _WindowOverflow8: | |
608 | s32e a0, a9, -16 | |
609 | l32e a0, a1, -12 | |
610 | s32e a2, a9, -8 | |
611 | s32e a1, a9, -12 | |
612 | s32e a3, a9, -4 | |
613 | s32e a4, a0, -32 | |
614 | s32e a5, a0, -28 | |
615 | s32e a6, a0, -24 | |
616 | s32e a7, a0, -20 | |
617 | rfwo | |
618 | ||
619 | /* 8-Register Window Underflow Vector (Handler) */ | |
620 | ||
621 | .align 64 | |
622 | .global _WindowUnderflow8 | |
623 | _WindowUnderflow8: | |
624 | l32e a1, a9, -12 | |
625 | l32e a0, a9, -16 | |
626 | l32e a7, a1, -12 | |
627 | l32e a2, a9, -8 | |
628 | l32e a4, a7, -32 | |
629 | l32e a3, a9, -4 | |
630 | l32e a5, a7, -28 | |
631 | l32e a6, a7, -24 | |
632 | l32e a7, a7, -20 | |
633 | rfwu | |
634 | ||
635 | /* 12-Register Window Overflow Vector (Handler) */ | |
636 | ||
637 | .align 64 | |
638 | .global _WindowOverflow12 | |
639 | _WindowOverflow12: | |
640 | s32e a0, a13, -16 | |
641 | l32e a0, a1, -12 | |
642 | s32e a1, a13, -12 | |
643 | s32e a2, a13, -8 | |
644 | s32e a3, a13, -4 | |
645 | s32e a4, a0, -48 | |
646 | s32e a5, a0, -44 | |
647 | s32e a6, a0, -40 | |
648 | s32e a7, a0, -36 | |
649 | s32e a8, a0, -32 | |
650 | s32e a9, a0, -28 | |
651 | s32e a10, a0, -24 | |
652 | s32e a11, a0, -20 | |
653 | rfwo | |
654 | ||
655 | /* 12-Register Window Underflow Vector (Handler) */ | |
656 | ||
657 | .org _WindowOverflow12 + 64 - 3 | |
658 | __WindowUnderflow12: | |
659 | rotw -1 | |
660 | .global _WindowUnderflow12 | |
661 | _WindowUnderflow12: | |
662 | l32e a1, a13, -12 | |
663 | l32e a0, a13, -16 | |
664 | l32e a11, a1, -12 | |
665 | l32e a2, a13, -8 | |
666 | l32e a4, a11, -48 | |
667 | l32e a8, a11, -32 | |
668 | l32e a3, a13, -4 | |
669 | l32e a5, a11, -44 | |
670 | l32e a6, a11, -40 | |
671 | l32e a7, a11, -36 | |
672 | l32e a9, a11, -28 | |
673 | l32e a10, a11, -24 | |
674 | l32e a11, a11, -20 | |
675 | rfwu | |
676 | ||
677 | #endif /* XCHAL_HAVE_WINDOWED */ |