1 // overlay_os_asm.h -- Overlay manager assembly macros for OS use.
2 // $Id$
3 
4 // Copyright (c) 2013 Tensilica Inc.
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the
8 // "Software"), to deal in the Software without restriction, including
9 // without limitation the rights to use, copy, modify, merge, publish,
10 // distribute, sublicense, and/or sell copies of the Software, and to
11 // permit persons to whom the Software is furnished to do so, subject to
12 // the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included
15 // in all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 
25 
26 #ifndef OVERLAY_OS_ASM_H
27 #define OVERLAY_OS_ASM_H
28 
29 // The macros in here are intended to be used by RTOS task switch code
30 // to check overlay status. Such code is usually in assembly and cannot
31 // call C code without penalty. For C code usage, it is best to use the
32 // corresponding C functions from the library.
33 
34 
35 // Inline assembly version of xt_overlay_get_state(). The arguments are
36 // three AR registers (a0-a15):
37 //
38 // "pcreg" - should contain the outgoing task's PC, i.e. the point at
39 //           which the task got interrupted. The return value is also
40 //           returned in this register.
41 // "sr1/2" - Scratch registers. These must be distinct from "pcreg".
42 //
43 // The return value is a 32-bit result that should be saved with the
44 // task context and passed as-is to xt_overlay_check_map.
45 
46         .macro _xt_overlay_get_state    pcreg  sr1  sr2
47 
48         movi    \sr1, _mapping_id
49         movi    \sr2, _ovly_id
50         l16si   \sr1, \sr1, 0
51         l16ui   \sr2, \sr2, 0
52         slli    \sr1, \sr1, 16
53         or      \pcreg, \sr1, \sr2
54 
55         .endm
56 
57 
58 // Inline assembly version of xt_overlay_check_map(). It requires 5 AR
59 // registers (a0-a15) as arguments.
60 //
61 // "pcreg" - should contain the interrupted task's PC, i.e. the point
62 //           at which the task got interrupted. This will be adjusted
63 //           if required.
64 // "psreg" - should contain the interrupted task's PS. This will be
65 //           adjusted if required.
66 // "ovreg" - should contain the overlay state on entry. Contents may
67 //           be clobbered.
68 // "spreg" - should contain the tasks stack pointer on entry.
69 // "sr1"   - Scratch register. Must be distinct from any of the above.
70 //
71 // The return values are "pcreg" and "psreg" and these must be used
72 // to update the task's PC and PS.
73 // Note that this macro may store data below the "spreg" pointer. If
74 // it does, then it will also disable interrupts via the PS, so that
75 // the task resumes with all interrupts disabled (to avoid corrupting
76 // this data).
77 //
78 // (SP - 24)    Overlay ID to restore
79 // (SP - 28)    Task PC
80 // (SP - 32)    Task PS
81 
82         .macro _xt_overlay_check_map    pcreg  psreg ovreg  spreg  sr1
83 
84 // There are four cases to deal with:
85 //
86 // _ovly_id = -1, _mapping_id = -1
87 // No overlay is mapped or mapping, nothing to do.
88 //
89 // _ovly_id >= 0, _mapping_id = -1
90 // An overlay was mapped, check PC to see if we need a restore.
91 //
92 // _ovly_id = -1, _mapping_id >= 0
93 // An overlay is being mapped. Either it belongs to this task, which
94 // implies that the PC is in the mapping function, or it does not
95 // belong to this task. Either way there is nothing to do.
96 //
97 // _ovly_id >= 0, _mapping_id >= 0
98 // Illegal, cannot happen by design. Don't need to handle this.
99 //
100 // So, the logic is to check _ovly_id first. If this is >= 0, then
101 // we check the task PC. If the PC is in the regions of interest then
102 // we'll patch the return PC to invoke xt_overlay_restore.
103 
104 .L1:
105         extui   \sr1, \ovreg, 0, 16             // Extract _ovly_id
106         bbsi.l  \sr1, 15, .Lno                  // If -1 then we're done
107         mov     \ovreg, \sr1                    // Restore this one
108 
109 // Next check the PC to see if it falls within the ranges of interest.
110 
111 .L2:
112         movi    \sr1, _overlay_vma              // Is PC < VMA range ?
113         bltu    \pcreg, \sr1, .L3
114         movi    \sr1, _overlay_vma_end          // Is PC > VMA range ?
115         bgeu    \pcreg, \sr1, .L3
116         j       .L4                             // PC is in VMA range
117 .L3:
118         movi    \sr1, _overlay_call_stubs_start // Is PC < call stubs range ?
119         bltu    \pcreg, \sr1, .Lno
120         movi    \sr1, _overlay_call_stubs_end   // Is PC > call stubs range ?
121         bgeu    \pcreg, \sr1, .Lno
122 
123 // If we get here then a restore is needed. Save the overlay ID, PC and PS.
124 // Return modified PC and PS so that xt_overlay_restore() will execute in
125 // the context of the task when resumed. Note that the OS resumption code
126 // may expect PS.EXCM to be set so we leave it as is in the return value.
127 
128 .L4:
129         s32e    \ovreg, \spreg, -24             // Save overlay ID
130         s32e    \pcreg, \spreg, -28             // Save task PC
131         s32e    \psreg, \spreg, -32             // Save task PS
132         movi    \pcreg, xt_overlay_restore      // Adjust resumption PC
133         movi    \sr1, 15
134         or      \psreg, \psreg, \sr1            // Set intlevel to highest
135 .Lno:
136 
137         .endm
138 
139 #endif // OVERLAY_OS_ASM_H
140 
141