1/* Assembly functions for libgcc2. 2 Copyright (C) 2001-2013 Free Software Foundation, Inc. 3 Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free 9Software Foundation; either version 3, or (at your option) any later 10version. 11 12GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or 14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15for more details. 16 17Under Section 7 of GPL version 3, you are granted additional 18permissions described in the GCC Runtime Library Exception, version 193.1, as published by the Free Software Foundation. 20 21You should have received a copy of the GNU General Public License and 22a copy of the GCC Runtime Library Exception along with this program; 23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24<http://www.gnu.org/licenses/>. */ 25 26#include "xtensa-config.h" 27 28/* __xtensa_libgcc_window_spill: This function flushes out all but the 29 current register window. This is used to set up the stack so that 30 arbitrary frames can be accessed. */ 31 32 .align 4 33 .global __xtensa_libgcc_window_spill 34 .type __xtensa_libgcc_window_spill,@function 35__xtensa_libgcc_window_spill: 36 entry sp, 32 37 movi a2, 0 38 syscall 39 retw 40 .size __xtensa_libgcc_window_spill, .-__xtensa_libgcc_window_spill 41 42 43/* __xtensa_nonlocal_goto: This code does all the hard work of a 44 nonlocal goto on Xtensa. It is here in the library to avoid the 45 code size bloat of generating it in-line. There are two 46 arguments: 47 48 a2 = frame pointer for the procedure containing the label 49 a3 = goto handler address 50 51 This function never returns to its caller but instead goes directly 52 to the address of the specified goto handler. */ 53 54 .align 4 55 .global __xtensa_nonlocal_goto 56 .type __xtensa_nonlocal_goto,@function 57__xtensa_nonlocal_goto: 58 entry sp, 32 59 60 /* Flush registers. */ 61 mov a5, a2 62 movi a2, 0 63 syscall 64 mov a2, a5 65 66 /* Because the save area for a0-a3 is stored one frame below 67 the one identified by a2, the only way to restore those 68 registers is to unwind the stack. If alloca() were never 69 called, we could just unwind until finding the sp value 70 matching a2. However, a2 is a frame pointer, not a stack 71 pointer, and may not be encountered during the unwinding. 72 The solution is to unwind until going _past_ the value 73 given by a2. This involves keeping three stack pointer 74 values during the unwinding: 75 76 next = sp of frame N-1 77 cur = sp of frame N 78 prev = sp of frame N+1 79 80 When next > a2, the desired save area is stored relative 81 to prev. At this point, cur will be the same as a2 82 except in the alloca() case. 83 84 Besides finding the values to be restored to a0-a3, we also 85 need to find the current window size for the target 86 function. This can be extracted from the high bits of the 87 return address, initially in a0. As the unwinding 88 proceeds, the window size is taken from the value of a0 89 saved _two_ frames below the current frame. */ 90 91 addi a5, sp, -16 /* a5 = prev - save area */ 92 l32i a6, a5, 4 93 addi a6, a6, -16 /* a6 = cur - save area */ 94 mov a8, a0 /* a8 = return address (for window size) */ 95 j .Lfirstframe 96 97.Lnextframe: 98 l32i a8, a5, 0 /* next return address (for window size) */ 99 mov a5, a6 /* advance prev */ 100 addi a6, a7, -16 /* advance cur */ 101.Lfirstframe: 102 l32i a7, a6, 4 /* a7 = next */ 103 bgeu a2, a7, .Lnextframe 104 105 /* At this point, prev (a5) points to the save area with the saved 106 values of a0-a3. Copy those values into the save area at the 107 current sp so they will be reloaded when the return from this 108 function underflows. We don't have to worry about exceptions 109 while updating the current save area, because the windows have 110 already been flushed. */ 111 112 addi a4, sp, -16 /* a4 = save area of this function */ 113 l32i a6, a5, 0 114 l32i a7, a5, 4 115 s32i a6, a4, 0 116 s32i a7, a4, 4 117 l32i a6, a5, 8 118 l32i a7, a5, 12 119 s32i a6, a4, 8 120 s32i a7, a4, 12 121 122 /* Set return address to goto handler. Use the window size bits 123 from the return address two frames below the target. */ 124 extui a8, a8, 30, 2 /* get window size from return addr. */ 125 slli a3, a3, 2 /* get goto handler addr. << 2 */ 126 ssai 2 127 src a0, a8, a3 /* combine them with a funnel shift */ 128 129 retw 130 .size __xtensa_nonlocal_goto, .-__xtensa_nonlocal_goto 131 132 133/* __xtensa_sync_caches: This function is called after writing a trampoline 134 on the stack to force all the data writes to memory and invalidate the 135 instruction cache. a2 is the address of the new trampoline. 136 137 After the trampoline data is written out, it must be flushed out of 138 the data cache into memory. We use DHWB in case we have a writeback 139 cache. At least one DHWB instruction is needed for each data cache 140 line which may be touched by the trampoline. An ISYNC instruction 141 must follow the DHWBs. 142 143 We have to flush the i-cache to make sure that the new values get used. 144 At least one IHI instruction is needed for each i-cache line which may 145 be touched by the trampoline. An ISYNC instruction is also needed to 146 make sure that the modified instructions are loaded into the instruction 147 fetch buffer. */ 148 149/* Use the maximum trampoline size. Flushing a bit extra is OK. */ 150#define TRAMPOLINE_SIZE 60 151 152 .text 153 .align 4 154 .global __xtensa_sync_caches 155 .type __xtensa_sync_caches,@function 156__xtensa_sync_caches: 157 entry sp, 32 158#if XCHAL_DCACHE_SIZE > 0 159 /* Flush the trampoline from the data cache. */ 160 extui a4, a2, 0, XCHAL_DCACHE_LINEWIDTH 161 addi a4, a4, TRAMPOLINE_SIZE 162 addi a4, a4, (1 << XCHAL_DCACHE_LINEWIDTH) - 1 163 srli a4, a4, XCHAL_DCACHE_LINEWIDTH 164 mov a3, a2 165.Ldcache_loop: 166 dhwb a3, 0 167 addi a3, a3, (1 << XCHAL_DCACHE_LINEWIDTH) 168 addi a4, a4, -1 169 bnez a4, .Ldcache_loop 170 isync 171#endif 172#if XCHAL_ICACHE_SIZE > 0 173 /* Invalidate the corresponding lines in the instruction cache. */ 174 extui a4, a2, 0, XCHAL_ICACHE_LINEWIDTH 175 addi a4, a4, TRAMPOLINE_SIZE 176 addi a4, a4, (1 << XCHAL_ICACHE_LINEWIDTH) - 1 177 srli a4, a4, XCHAL_ICACHE_LINEWIDTH 178.Licache_loop: 179 ihi a2, 0 180 addi a2, a2, (1 << XCHAL_ICACHE_LINEWIDTH) 181 addi a4, a4, -1 182 bnez a4, .Licache_loop 183#endif 184 isync 185 retw 186 .size __xtensa_sync_caches, .-__xtensa_sync_caches 187