aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/libgcc/config/aarch64/sync-cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/libgcc/config/aarch64/sync-cache.c')
-rw-r--r--gcc-4.9/libgcc/config/aarch64/sync-cache.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/gcc-4.9/libgcc/config/aarch64/sync-cache.c b/gcc-4.9/libgcc/config/aarch64/sync-cache.c
new file mode 100644
index 000000000..8d206c913
--- /dev/null
+++ b/gcc-4.9/libgcc/config/aarch64/sync-cache.c
@@ -0,0 +1,72 @@
+/* Machine description for AArch64 architecture.
+ Copyright (C) 2012-2014 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+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 3, 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.
+
+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/>. */
+
+void __aarch64_sync_cache_range (const void *, const void *);
+
+void
+__aarch64_sync_cache_range (const void *base, const void *end)
+{
+ unsigned icache_lsize;
+ unsigned dcache_lsize;
+ static unsigned int cache_info = 0;
+ const char *address;
+
+ if (! cache_info)
+ /* CTR_EL0 [3:0] contains log2 of icache line size in words.
+ CTR_EL0 [19:16] contains log2 of dcache line size in words. */
+ asm volatile ("mrs\t%0, ctr_el0":"=r" (cache_info));
+
+ icache_lsize = 4 << (cache_info & 0xF);
+ dcache_lsize = 4 << ((cache_info >> 16) & 0xF);
+
+ /* Loop over the address range, clearing one cache line at once.
+ Data cache must be flushed to unification first to make sure the
+ instruction cache fetches the updated data. 'end' is exclusive,
+ as per the GNU definition of __clear_cache. */
+
+ /* Make the start address of the loop cache aligned. */
+ address = (const char*) ((__UINTPTR_TYPE__) base
+ & ~ (__UINTPTR_TYPE__) (dcache_lsize - 1));
+
+ for (; address < (const char *) end; address += dcache_lsize)
+ asm volatile ("dc\tcvau, %0"
+ :
+ : "r" (address)
+ : "memory");
+
+ asm volatile ("dsb\tish" : : : "memory");
+
+ /* Make the start address of the loop cache aligned. */
+ address = (const char*) ((__UINTPTR_TYPE__) base
+ & ~ (__UINTPTR_TYPE__) (icache_lsize - 1));
+
+ for (; address < (const char *) end; address += icache_lsize)
+ asm volatile ("ic\tivau, %0"
+ :
+ : "r" (address)
+ : "memory");
+
+ asm volatile ("dsb\tish; isb" : : : "memory");
+}