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