aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/libgcc/config/mep/tramp.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/libgcc/config/mep/tramp.c')
-rw-r--r--gcc-4.9/libgcc/config/mep/tramp.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/gcc-4.9/libgcc/config/mep/tramp.c b/gcc-4.9/libgcc/config/mep/tramp.c
new file mode 100644
index 000000000..4b294c6df
--- /dev/null
+++ b/gcc-4.9/libgcc/config/mep/tramp.c
@@ -0,0 +1,103 @@
+/* Trampoline support for MeP
+ Copyright (C) 2004-2014 Free Software Foundation, Inc.
+ Contributed by Red Hat Inc.
+
+This file 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 3 of the License, or (at your
+option) any later version.
+
+This file 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+/*
+ 7a0a ldc $10,$pc
+ c0ae000a lw $0,10($10)
+ caae000e lw $10,14($10)
+ 10ae jmp $10
+ 00000000 static chain
+ 00000000 function address
+*/
+
+static inline int
+cache_config_register(void) {
+ int rv;
+ asm ("ldc\t%0, $ccfg" : "=r" (rv));
+ return rv;
+}
+
+#define ICACHE_SIZE ((cache_config_register() >> 16) & 0x7f)
+#define DCACHE_SIZE (cache_config_register() & 0x7f)
+
+#define ICACHE_DATA_BASE 0x00300000
+#define ICACHE_TAG_BASE 0x00310000
+#define DCACHE_DATA_BASE 0x00320000
+#define DCACHE_TAG_BASE 0x00330000
+
+static inline void
+flush_dcache (int addr)
+{
+ asm volatile ("cache\t0, (%0)" : : "r" (addr));
+}
+
+void
+__mep_trampoline_helper (unsigned long *tramp,
+ int function_address,
+ int static_chain);
+
+void
+__mep_trampoline_helper (unsigned long *tramp,
+ int function_address,
+ int static_chain)
+{
+ int dsize, isize;
+
+#ifdef __LITTLE_ENDIAN__
+ tramp[0] = 0xc0ae7a0a;
+ tramp[1] = 0xcaae000a;
+ tramp[2] = 0x10ae000e;
+#else
+ tramp[0] = 0x7a0ac0ae;
+ tramp[1] = 0x000acaae;
+ tramp[2] = 0x000e10ae;
+#endif
+ tramp[3] = static_chain;
+ tramp[4] = function_address;
+
+ dsize = DCACHE_SIZE;
+ isize = ICACHE_SIZE;
+
+ if (dsize)
+ {
+ flush_dcache ((int)tramp);
+ flush_dcache ((int)tramp+16);
+ }
+
+ if (isize)
+ {
+ int imask = (isize * 1024) - 1;
+ int tmask = ~imask;
+ unsigned int i;
+ volatile unsigned int *tags;
+
+ imask &= 0xffe0;
+
+ for (i=(unsigned int)tramp; i<(unsigned int)tramp+20; i+=16)
+ {
+ tags = (unsigned int *)(ICACHE_TAG_BASE + (i & imask));
+ if ((*tags & tmask) == (i & tmask))
+ *tags &= ~1;
+ }
+ }
+}