|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdint.h> |
|
|
#if ENABLE_VALGRIND_SUPPORT |
|
|
# include <valgrind/valgrind.h> |
|
|
#endif |
|
|
#if defined _WIN32 && !defined __CYGWIN__ |
|
|
# define WIN32_LEAN_AND_MEAN |
|
|
# include <windows.h> |
|
|
#endif |
|
|
#if defined __APPLE__ && defined __MACH__ |
|
|
# include <libkern/OSCacheControl.h> |
|
|
#endif |
|
|
#if defined _AIX |
|
|
# include <sys/cache.h> |
|
|
#endif |
|
|
#if defined __sun |
|
|
# include <stddef.h> |
|
|
#endif |
|
|
|
|
|
#ifdef __cplusplus |
|
|
extern "C" { |
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static inline void |
|
|
clear_cache (void *start, void *end) |
|
|
{ |
|
|
#if ENABLE_VALGRIND_SUPPORT |
|
|
|
|
|
|
|
|
VALGRIND_DISCARD_TRANSLATIONS (start, (char *) end - (char *) start); |
|
|
#endif |
|
|
#if (defined __x86_64__ || defined _M_X64) || (defined __i386 || defined _M_IX86) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#elif defined _WIN32 && !defined __CYGWIN__ |
|
|
|
|
|
|
|
|
|
|
|
HANDLE process = GetCurrentProcess (); |
|
|
while (!FlushInstructionCache (process, start, (char *) end - (char *) start)) |
|
|
; |
|
|
#elif defined __APPLE__ && defined __MACH__ |
|
|
|
|
|
sys_icache_invalidate (start, (char *) end - (char *) start); |
|
|
#elif defined _AIX |
|
|
|
|
|
_sync_cache_range (start, (char *) end - (char *) start); |
|
|
#elif defined __sun |
|
|
|
|
|
extern void sync_instruction_memory (char *, size_t); |
|
|
sync_instruction_memory (start, (char *) end - (char *) start); |
|
|
|
|
|
|
|
|
#elif (defined __GNUC__ || defined __clang__) && defined __powerpc__ |
|
|
|
|
|
uintptr_t addr = (uintptr_t) start & ~(intptr_t)3; |
|
|
uintptr_t end_addr = (uintptr_t) end; |
|
|
do |
|
|
{ |
|
|
asm volatile ("icbi 0,%0; dcbf 0,%0" : : "r" (addr)); |
|
|
addr += 4; |
|
|
} |
|
|
while (addr < end_addr); |
|
|
asm volatile ("sync; isync"); |
|
|
#elif (defined __GNUC__ || defined __clang__) && defined __sparc |
|
|
|
|
|
|
|
|
uintptr_t addr = (uintptr_t) start & ~(intptr_t)7; |
|
|
uintptr_t end_addr = (uintptr_t) end; |
|
|
do |
|
|
{ |
|
|
asm volatile ("flush %0+0" : : "r" (addr)); |
|
|
addr += 8; |
|
|
} |
|
|
while (addr < end_addr); |
|
|
#elif (defined __GNUC__ || defined __clang__) && defined __hppa |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
intptr_t cache_line_size = 16; |
|
|
uintptr_t addr = (uintptr_t) start & ~cache_line_size; |
|
|
uintptr_t end_addr = (uintptr_t) end; |
|
|
do |
|
|
{ |
|
|
asm volatile ("fdc 0(0,%0)" |
|
|
"\n\t" "sync" |
|
|
"\n\t" "fic 0(0,%0)" |
|
|
"\n\t" "sync" : : "r" (addr)); |
|
|
addr += cache_line_size; |
|
|
} |
|
|
while (addr < end_addr); |
|
|
asm volatile ("nop" |
|
|
"\n\t" "nop" |
|
|
"\n\t" "nop" |
|
|
"\n\t" "nop" |
|
|
"\n\t" "nop" |
|
|
"\n\t" "nop"); |
|
|
#elif (defined __GNUC__ || defined __clang__) && defined __ia64 |
|
|
|
|
|
|
|
|
|
|
|
intptr_t cache_line_size = 32; |
|
|
uintptr_t addr = (uintptr_t) start & ~cache_line_size; |
|
|
uintptr_t end_addr = (uintptr_t) end; |
|
|
do |
|
|
{ |
|
|
|
|
|
asm volatile ("fc %0" : : "r" (addr)); |
|
|
addr += cache_line_size; |
|
|
} |
|
|
while (addr < end_addr); |
|
|
|
|
|
|
|
|
asm volatile ("sync.i"); |
|
|
|
|
|
|
|
|
asm volatile ("srlz.i"); |
|
|
#elif (defined __GNUC__ || defined __clang__) && defined __m68k__ && defined __linux__ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
register uintptr_t addr __asm__ ("%d1") = (uintptr_t) start; |
|
|
register uintptr_t len __asm__ ("%d4") = (uintptr_t) end - addr; |
|
|
__asm__ __volatile__ ( |
|
|
"move%.l %#123,%/d0" |
|
|
"\n\t" "move%.l %#1,%/d2" |
|
|
"\n\t" "move%.l %#3,%/d3" |
|
|
"\n\t" "trap %#0" |
|
|
: |
|
|
: "d" (addr), "d" (len) |
|
|
: "%d0", "%d2", "%d3" |
|
|
); |
|
|
#elif (__GNUC__ + (__GNUC_MINOR__ >= 3) > 4 && !defined __clang__) \ |
|
|
|| ((__clang_major__ + (__clang_minor__ >= 4) > 3) \ |
|
|
&& (defined __aarch64__ || defined __arm__)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
__builtin___clear_cache (start, end); |
|
|
#elif HAVE___CLEAR_CACHE |
|
|
|
|
|
|
|
|
extern void __clear_cache (char *, char *); |
|
|
__clear_cache (start, end); |
|
|
#else |
|
|
# error "Don't know how to implement clear_cache on this platform." |
|
|
#endif |
|
|
} |
|
|
|
|
|
|
|
|
#ifdef __cplusplus |
|
|
} |
|
|
#endif |
|
|
|