aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/xtensa/lib2funcs.S
diff options
context:
space:
mode:
authorBob Wilson <bob.wilson@acm.org>2002-01-23 21:03:53 +0000
committerBob Wilson <bwilson@gcc.gnu.org>2002-01-23 21:03:53 +0000
commit039843087a884e96058fd0fcde72339974d49e81 (patch)
tree474190a92649d5af6ccd7a6f3ed51d377009630f /gcc/config/xtensa/lib2funcs.S
parent5b1a76105bb377230a838ddeb0c94d384b33e97b (diff)
downloadgcc-039843087a884e96058fd0fcde72339974d49e81.zip
gcc-039843087a884e96058fd0fcde72339974d49e81.tar.gz
gcc-039843087a884e96058fd0fcde72339974d49e81.tar.bz2
elf.h: New file.
* config/xtensa/elf.h: New file. * config/xtensa/lib1funcs.asm: New file. * config/xtensa/lib2funcs.S: New file. * config/xtensa/linux.h: New file. * config/xtensa/t-xtensa: New file. * config/xtensa/xtensa-config.h: New file. * config/xtensa/xtensa-protos.h: New file. * config/xtensa/xtensa.c: New file. * config/xtensa/xtensa.h: New file. * config/xtensa/xtensa.md: New file. * config.gcc (xtensa-*-elf*): New target. (xtensa-*-linux*): New target. * cse.c (canon_hash): Compare rtx pointers instead of register numbers. This is required for the Xtensa port. * integrate.c (copy_insn_list): Handle case where the static chain is in memory and the memory address has to be copied to a register. * doc/invoke.texi (Option Summary): Add Xtensa options. (Xtensa Options): New node. * doc/md.texi (Machine Constraints): Add Xtensa machine constraints. * gcc.c-torture/compile/20001226-1.x: xfail for Xtensa. From-SVN: r49155
Diffstat (limited to 'gcc/config/xtensa/lib2funcs.S')
-rw-r--r--gcc/config/xtensa/lib2funcs.S205
1 files changed, 205 insertions, 0 deletions
diff --git a/gcc/config/xtensa/lib2funcs.S b/gcc/config/xtensa/lib2funcs.S
new file mode 100644
index 0000000..82679e6
--- /dev/null
+++ b/gcc/config/xtensa/lib2funcs.S
@@ -0,0 +1,205 @@
+/* Assembly functions for libgcc2.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#include "xtensa/xtensa-config.h"
+
+/* __xtensa_libgcc_window_spill: This function uses a series of nested
+ calls to flush out all but the current register window. This is
+ used to set up the stack so that arbitrary frames can be accessed.
+ The functions used for the nested calls are also reused by the
+ nonlocal goto function below. */
+
+ .align 4
+ .global __xtensa_libgcc_window_spill
+ .type __xtensa_libgcc_window_spill,@function
+__xtensa_libgcc_window_spill:
+ entry sp, 48
+ call4 .L__wdwspill_assist52 // called with call8, only need a call4
+ retw
+ .size __xtensa_libgcc_window_spill,.-__xtensa_libgcc_window_spill
+
+ .align 4
+.L__wdwspill_assist56:
+ entry sp, 16
+ call4 .L__wdwspill_assist52
+ retw
+ .align 4
+.L__wdwspill_assist52:
+ entry sp, 48
+ call12 .L__wdwspill_assist40
+ retw
+ .align 4
+.L__wdwspill_assist40:
+ entry sp, 48
+ call12 .L__wdwspill_assist28
+ retw
+ .align 4
+.L__wdwspill_assist28:
+ entry sp, 48
+ call12 .L__wdwspill_assist16
+ retw
+ .align 4
+.L__wdwspill_assist16:
+ entry sp, 16
+ movi a15, 0
+ retw
+
+
+/* __xtensa_nonlocal_goto: This code does all the hard work of a
+ nonlocal goto on Xtensa. It is here in the library to avoid the
+ code size bloat of generating it in-line. There are two
+ arguments:
+
+ a2 = frame pointer for the procedure containing the label
+ a3 = goto handler address
+
+ This function never returns to its caller but instead goes directly
+ to the address of the specified goto handler. */
+
+ .align 4
+ .global __xtensa_nonlocal_goto
+ .type __xtensa_nonlocal_goto,@function
+__xtensa_nonlocal_goto:
+ entry sp, 32
+
+ /* flush registers */
+ call8 .L__wdwspill_assist56
+
+ /* Because the save area for a0-a3 is stored one frame below
+ the one identified by a2, the only way to restore those
+ registers is to unwind the stack. If alloca() were never
+ called, we could just unwind until finding the sp value
+ matching a2. However, a2 is a frame pointer, not a stack
+ pointer, and may not be encountered during the unwinding.
+ The solution is to unwind until going _past_ the value
+ given by a2. This involves keeping three stack pointer
+ values during the unwinding:
+
+ next = sp of frame N-1
+ cur = sp of frame N
+ prev = sp of frame N+1
+
+ When next > a2, the desired save area is stored relative
+ to prev. At this point, cur will be the same as a2
+ except in the alloca() case.
+
+ Besides finding the values to be restored to a0-a3, we also
+ need to find the current window size for the target
+ function. This can be extracted from the high bits of the
+ return address, initially in a0. As the unwinding
+ proceeds, the window size is taken from the value of a0
+ saved _two_ frames below the current frame. */
+
+ addi a5, sp, -16 # a5 = prev - save area
+ l32i a6, a5, 4
+ addi a6, a6, -16 # a6 = cur - save area
+ mov a8, a0 # a8 = return address (for window size)
+ j .Lfirstframe
+
+.Lnextframe:
+ l32i a8, a5, 0 # next return address (for window size)
+ mov a5, a6 # advance prev
+ addi a6, a7, -16 # advance cur
+.Lfirstframe:
+ l32i a7, a6, 4 # a7 = next
+ bge a2, a7, .Lnextframe
+
+ /* At this point, prev (a5) points to the save area with the saved
+ values of a0-a3. Copy those values into the save area at the
+ current sp so they will be reloaded when the return from this
+ function underflows. We don't have to worry about exceptions
+ while updating the current save area, because the windows have
+ already been flushed. */
+
+ addi a4, sp, -16 # a4 = save area of this function
+ l32i a6, a5, 0
+ l32i a7, a5, 4
+ s32i a6, a4, 0
+ s32i a7, a4, 4
+ l32i a6, a5, 8
+ l32i a7, a5, 12
+ s32i a6, a4, 8
+ s32i a7, a4, 12
+
+ /* Set return address to goto handler. Use the window size bits
+ from the return address two frames below the target. */
+ extui a8, a8, 30, 2 # get window size from return addr.
+ slli a3, a3, 2 # get goto handler addr. << 2
+ ssai 2
+ src a0, a8, a3 # combine them with a funnel shift
+
+ retw
+ .size __xtensa_nonlocal_goto,.-__xtensa_nonlocal_goto
+
+
+/* __xtensa_sync_caches: This function is called after writing a trampoline
+ on the stack to force all the data writes to memory and invalidate the
+ instruction cache. a2 is the address of the new trampoline.
+
+ After the trampoline data is written out, it must be flushed out of
+ the data cache into memory. We use DHWB in case we have a writeback
+ cache. At least one DHWB instruction is needed for each data cache
+ line which may be touched by the trampoline. An ISYNC instruction
+ must follow the DHWBs.
+
+ We have to flush the i-cache to make sure that the new values get used.
+ At least one IHI instruction is needed for each i-cache line which may
+ be touched by the trampoline. An ISYNC instruction is also needed to
+ make sure that the modified instructions are loaded into the instruction
+ fetch buffer. */
+
+#define TRAMPOLINE_SIZE 49
+
+ .text
+ .align 4
+ .global __xtensa_sync_caches
+ .type __xtensa_sync_caches,@function
+__xtensa_sync_caches:
+ entry sp, 32
+#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK
+ # Flush the trampoline from the data cache
+ extui a4, a2, 0, XCHAL_DCACHE_LINEWIDTH
+ addi a4, a4, TRAMPOLINE_SIZE
+ addi a4, a4, (1 << XCHAL_DCACHE_LINEWIDTH) - 1
+ srli a4, a4, XCHAL_DCACHE_LINEWIDTH
+ mov a3, a2
+.Ldcache_loop:
+ dhwb a3, 0
+ addi a3, a3, (1 << XCHAL_DCACHE_LINEWIDTH)
+ addi a4, a4, -1
+ bnez a4, .Ldcache_loop
+ isync
+#endif
+#if XCHAL_ICACHE_SIZE > 0
+ # Invalidate the corresponding lines in the instruction cache
+ extui a4, a2, 0, XCHAL_ICACHE_LINEWIDTH
+ addi a4, a4, TRAMPOLINE_SIZE
+ addi a4, a4, (1 << XCHAL_ICACHE_LINEWIDTH) - 1
+ srli a4, a4, XCHAL_ICACHE_LINEWIDTH
+.Licache_loop:
+ ihi a2, 0
+ addi a2, a2, (1 << XCHAL_ICACHE_LINEWIDTH)
+ addi a4, a4, -1
+ bnez a4, .Licache_loop
+ isync
+#endif
+ retw
+ .size __xtensa_sync_caches,.-__xtensa_sync_caches