blob: 1294744649e3bf0860a0fd596a2de3e28bb1ca55 [file] [log] [blame]
Reid Spencercbad7012004-09-11 04:59:30 +00001//===- Memory.cpp - Memory Handling Support ---------------------*- C++ -*-===//
Misha Brukmanf976c852005-04-21 22:55:34 +00002//
Reid Spencercbad7012004-09-11 04:59:30 +00003// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Misha Brukmanf976c852005-04-21 22:55:34 +00007//
Reid Spencercbad7012004-09-11 04:59:30 +00008//===----------------------------------------------------------------------===//
9//
10// This file defines some helpful functions for allocating memory and dealing
11// with memory mapped files
12//
13//===----------------------------------------------------------------------===//
14
Michael J. Spencer1f6efa32010-11-29 18:16:10 +000015#include "llvm/Support/Memory.h"
16#include "llvm/Support/Valgrind.h"
Reid Spencerce799952004-12-27 06:15:57 +000017#include "llvm/Config/config.h"
Reid Spencercbad7012004-09-11 04:59:30 +000018
19namespace llvm {
20using namespace sys;
Reid Spencercbad7012004-09-11 04:59:30 +000021}
22
23// Include the platform-specific parts of this class.
Reid Spencerce799952004-12-27 06:15:57 +000024#ifdef LLVM_ON_UNIX
Reid Spencerbccc8ab2005-01-09 23:29:00 +000025#include "Unix/Memory.inc"
Reid Spencerce799952004-12-27 06:15:57 +000026#endif
27#ifdef LLVM_ON_WIN32
Michael J. Spencer1f6efa32010-11-29 18:16:10 +000028#include "Windows/Memory.inc"
Reid Spencerce799952004-12-27 06:15:57 +000029#endif
Chris Lattner93bb4aa2008-06-25 17:14:10 +000030
Chris Lattner95f39002008-06-25 17:17:53 +000031extern "C" void sys_icache_invalidate(const void *Addr, size_t len);
32
Bruno Cardoso Lopesc4cc40c2011-09-14 03:00:41 +000033/// ClearMipsCache - Invalidates instruction cache for Mips. This assembly code
34/// is copied from the MIPS32 Instruction Set Reference. Since the code ends
35/// with the return instruction "jr.hb ra" (Jump Register with Hazard Barrier),
36/// it must be implemented as a function (which is called from the
37/// InvalidateInstructionCache function). It cannot be directly inlined into
38/// InvalidateInstructionCache function, because in that case the epilog of
39/// InvalidateInstructionCache will not be executed.
40#if defined(__mips__)
41extern "C" void ClearMipsCache(const void* Addr, size_t Size);
42 asm volatile(
43 ".text\n"
44 ".align 2\n"
45 ".globl ClearMipsCache\n"
46 "ClearMipsCache:\n"
47 ".set noreorder\n"
48 "beq $a1, $zero, 20f\n" /* If size==0, branch around */
49 "nop\n"
50 "addu $a1, $a0, $a1\n" /* Calculate end address + 1 */
51 "rdhwr $v0, $1\n" /* Get step size for SYNCI */
52 /* $1 is $HW_SYNCI_Step */
53 "beq $v0, $zero, 20f\n" /* If no caches require synchronization, */
54 /* branch around */
55 "nop\n"
56 "10: synci 0($a0)\n" /* Synchronize all caches around address */
57 "sltu $v1, $a0, $a1\n" /* Compare current with end address */
58 "bne $v1, $zero, 10b\n" /* Branch if more to do */
59 "addu $a0, $a0, $v0\n" /* Add step size in delay slot */
60 "sync\n" /* Clear memory hazards */
61 "20: jr.hb $ra\n" /* Return, clearing instruction hazards */
62 "nop\n"
63 );
64#endif
65
Chris Lattner93bb4aa2008-06-25 17:14:10 +000066/// InvalidateInstructionCache - Before the JIT can run a block of code
67/// that has been emitted it must invalidate the instruction cache on some
68/// platforms.
69void llvm::sys::Memory::InvalidateInstructionCache(const void *Addr,
70 size_t Len) {
Michael J. Spencer1f6efa32010-11-29 18:16:10 +000071
Evan Chengc663bee2008-11-14 02:33:17 +000072// icache invalidation for PPC and ARM.
73#if defined(__APPLE__)
Daniel Dunbar299f11f2009-09-12 23:29:02 +000074
75# if (defined(__POWERPC__) || defined (__ppc__) || \
Evan Chengc663bee2008-11-14 02:33:17 +000076 defined(_POWER) || defined(_ARCH_PPC)) || defined(__arm__)
77 sys_icache_invalidate(Addr, Len);
Daniel Dunbar299f11f2009-09-12 23:29:02 +000078# endif
79
Evan Chengc663bee2008-11-14 02:33:17 +000080#else
Daniel Dunbar299f11f2009-09-12 23:29:02 +000081
82# if (defined(__POWERPC__) || defined (__ppc__) || \
83 defined(_POWER) || defined(_ARCH_PPC)) && defined(__GNUC__)
Evan Chengc663bee2008-11-14 02:33:17 +000084 const size_t LineSize = 32;
Chris Lattner93bb4aa2008-06-25 17:14:10 +000085
Evan Chengc663bee2008-11-14 02:33:17 +000086 const intptr_t Mask = ~(LineSize - 1);
87 const intptr_t StartLine = ((intptr_t) Addr) & Mask;
88 const intptr_t EndLine = ((intptr_t) Addr + Len + LineSize - 1) & Mask;
Chris Lattner93bb4aa2008-06-25 17:14:10 +000089
Evan Chengc663bee2008-11-14 02:33:17 +000090 for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
91 asm volatile("dcbf 0, %0" : : "r"(Line));
92 asm volatile("sync");
Chris Lattner93bb4aa2008-06-25 17:14:10 +000093
Evan Chengc663bee2008-11-14 02:33:17 +000094 for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
95 asm volatile("icbi 0, %0" : : "r"(Line));
96 asm volatile("isync");
Daniel Dunbar299f11f2009-09-12 23:29:02 +000097# elif defined(__arm__) && defined(__GNUC__)
98 // FIXME: Can we safely always call this for __GNUC__ everywhere?
99 char *Start = (char*) Addr;
100 char *End = Start + Len;
101 __clear_cache(Start, End);
Bruno Cardoso Lopesc4cc40c2011-09-14 03:00:41 +0000102# elif defined(__mips__)
103 ClearMipsCache(Addr, Len);
Daniel Dunbar299f11f2009-09-12 23:29:02 +0000104# endif
105
Evan Chengc663bee2008-11-14 02:33:17 +0000106#endif // end apple
Jeffrey Yasskinf28411f2010-03-15 04:57:55 +0000107
108 ValgrindDiscardTranslations(Addr, Len);
Chris Lattner95f39002008-06-25 17:17:53 +0000109}