Setting up repository
[linux-libre-firmware.git] / ath9k_htc / sboot / magpie_1_1 / sboot / athos / src / xtos / exc-return.S
1 // exc-return.S - Shared exception/interrupt return code
2
3 // Copyright (c) 2002-2004, 2006-2007, 2010 Tensilica Inc.
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining
6 // a copy of this software and associated documentation files (the
7 // "Software"), to deal in the Software without restriction, including
8 // without limitation the rights to use, copy, modify, merge, publish,
9 // distribute, sublicense, and/or sell copies of the Software, and to
10 // permit persons to whom the Software is furnished to do so, subject to
11 // the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be included
14 // in all copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24 #include <xtensa/coreasm.h>
25 #include <xtensa/corebits.h>
26 #include <xtensa/config/specreg.h>
27 #include "xtos-internal.h"
28
29 #if XCHAL_HAVE_EXCEPTIONS
30
31         .text
32         .align  4
33         .global _xtos_return_from_exc
34 _xtos_return_from_exc:
35
36 #ifdef __XTENSA_CALL0_ABI__
37
38         l32i    a0, a1, UEXC_a0         // restore general registers, pc, ps
39         l32i    a4, a1, UEXC_a4
40         l32i    a5, a1, UEXC_a5
41         l32i    a6, a1, UEXC_a6
42         l32i    a7, a1, UEXC_a7
43         l32i    a8, a1, UEXC_a8
44         l32i    a9, a1, UEXC_a9
45         l32i    a10, a1, UEXC_a10
46         l32i    a11, a1, UEXC_a11
47         l32i    a12, a1, UEXC_a12
48         l32i    a13, a1, UEXC_a13
49         l32i    a14, a1, UEXC_a14
50         l32i    a15, a1, UEXC_a15
51
52         l32i    a2, a1, UEXC_pc
53         l32i    a3, a1, UEXC_ps
54         wsr     a2, EPC_1
55         wsr     a3, PS
56
57         l32i    a2, a1, UEXC_a2
58         l32i    a3, a1, UEXC_a3
59         
60         rsync                           // wait for WSR to PS to complete
61
62         addi    a1, a1, ESF_TOTALSIZE   // restore sp
63
64         rfe
65
66 #else /* ! __XTENSA_CALL0_ABI__ */
67         
68         
69         //  Here we rotated back by N registers, to the interrupted code's register window.
70         //  NOTA: a2 and a3 might contain something useful, but we haven't determined
71         //  what that might be yet (for now, a2 contains nested-C-func call-chain ptr).
72
73         //  NOTE:  a5 still contains the exception window's exception stack frame pointer.
74
75 # if XTOS_CNEST
76         s32i    a2, a5, ESF_TOTALSIZE-20        // restore nested-C-func call-chain ptr
77 # endif
78         l32i    a2, a5, UEXC_ps
79         l32i    a3, a5, UEXC_pc
80         wsr     a2, PS          // for XEA2, this sets EXCM; for XEA1, this sets INTLEVEL to 1; ...
81
82 # if XCHAL_HAVE_XEA1 && XCHAL_HAVE_INTERRUPTS
83         l32i    a4, a5, UEXC_sar        // load INTENABLE value that restores original vpri
84         l32i    a2, a5, UEXC_a2
85         rsync                           // wait for WSR to PS to complete
86         wsr     a4, INTENABLE           // update INTENABLE to restore original vpri (PS.INTLEVEL=1 here)
87         l32i    a4, a5, UEXC_a4
88 # else
89         l32i    a2, a5, UEXC_a2
90         l32i    a4, a5, UEXC_a4
91         rsync                           // wait for WSR to PS to complete
92 # endif
93
94         /* FIXME: Enabling this here may break task-engine builds
95          * because task engines have exceptions (sort of), but they do
96          * not have the EPC_1 special register.  XCHAL_HAVE_INTERRUPTS
97          * is incorrect for normal configs without interrupts but with
98          * exceptions (we still need to restore EPC_1).  The correct
99          * solution is to define XCHAL_HAVE_EXCEPTIONS more strictly
100          * to mean something like "Have exceptions with
101          * user/kernel/double vectors" so that task engines are
102          * excluded. This would be a change to
103          * <xtensa/config/core.h>.  */
104
105         wsr     a3, EPC_1
106         //  HERE:
107         //      - we cannot get window overflows anymore -- we're NOT in a valid windowed context
108         //      - low-priority interrupts are still disabled
109
110         //  NOTE:  we don't restore EXCCAUSE or EXCVADDR, not needed.
111
112         //  Restore a3, a5:
113         l32i    a3, a5, UEXC_a3
114         l32i    a5, a5, UEXC_a5
115
116         rfe_rfue
117
118 #endif /* __XTENSA_CALL0_ABI__ */
119
120         .size   _xtos_return_from_exc, . - _xtos_return_from_exc
121
122 #endif /* XCHAL_HAVE_EXCEPTIONS */
123