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