1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     fnd_DetailHeapCommonImpl.h
4   Copyright (C)2009 Nintendo Co., Ltd.  All rights reserved.
5   These coded instructions, statements, and computer programs contain
6   proprietary information of Nintendo of America Inc. and/or Nintendo
7   Company Ltd., and are protected by Federal copyright law. They may
8   not be disclosed to third parties or copied or duplicated in any form,
9   in whole or in part, without the prior written consent of Nintendo.
10   $Rev: 12449 $
11  *---------------------------------------------------------------------------
12 
13 
14 */
15 
16 #ifndef NN_FND_DETAIL_FND_DETAIL_HEAPCOMMONIMPL_H_
17 #define NN_FND_DETAIL_FND_DETAIL_HEAPCOMMONIMPL_H_
18 
19 #include <nn/types.h>
20 
21 #ifdef __cplusplus
22 
23 namespace nn { namespace fnd { namespace detail {
24 //
25 
26 /* =======================================================================
27     Type Definitions
28    ======================================================================== */
29 
30 typedef s32 NNSiIntPtr;     // signed integer type mutually convertible with void* pointer
31 typedef u32 NNSiUIntPtr;    // unsigned integer type mutually convertible with void* pointer
32 
33 
34 /* ========================================================================
35     Macro Functions
36    ======================================================================== */
37 
38 /*---------------------------------------------------------------------------*
39   Name:         NNSi_FndRoundUp
40   Description:  Rounds up to align with specified alignment.
41   Arguments:    value:      target data
42                 alignment:  alignment value
43   Returns:      Returns a value that has been rounded up to the specified alignment value.
44  *---------------------------------------------------------------------------
45 
46 
47 */
48 #define NNSi_FndRoundUp(value, alignment) \
49     (((value) + (alignment-1)) & ~(alignment-1))
50 
51 #define NNSi_FndRoundUpPtr(ptr, alignment) \
52     ((void*)NNSi_FndRoundUp(NNSiGetUIntPtr(ptr), alignment))
53 
54 /*---------------------------------------------------------------------------*
55   Name:         NNSi_FndRoundDown
56   Description:  Rounds down to align for a specified alignment value.
57   Arguments:    value:      target data
58                 alignment:  alignment value
59   Returns:      Returns a value that has been rounded down to the specified alignment.
60  *---------------------------------------------------------------------------
61 
62 
63 */
64 #define NNSi_FndRoundDown(value, alignment) \
65     ((value) & ~(alignment-1))
66 
67 #define NNSi_FndRoundDownPtr(ptr, alignment) \
68     ((void*)NNSi_FndRoundDown(NNSiGetUIntPtr(ptr), alignment))
69 
70 /*---------------------------------------------------------------------------*
71   Name:         NNSi_FndGetBitValue
72   Description:  Gets a value at a specific bit position.
73   Arguments:    data:  Data that contains the bit data to be gotten.
74                 st:    Start bit (start from 0)
75                 bits:  Number of bits (maximum 31)
76   Returns:      Returns the value at a specific bit position.
77  *---------------------------------------------------------------------------
78 
79 
80 */
81 #define     NNSi_FndGetBitValue(data, st, bits) \
82     (((data) >>(st)) & ((1 <<(bits)) -1))
83 
84 /*---------------------------------------------------------------------------*
85   Name:         NNSi_FndSetBitValue
86   Description:  Sets a value at a specific bit position.
87   Arguments:    data:  Variable that holds the bit data that is to be set
88                 st:    Start bit (start from 0)
89                 bits:  Number of bits (maximum 31)
90                 val:   Bit data to set.
91   Returns:      None.
92  *---------------------------------------------------------------------------
93 
94 
95 */
96 #define     NNSi_FndSetBitValue(data, st, bits, val)                        \
97                 do                                                          \
98                 {                                                           \
99                     u32 maskBits = (u32)((1 <<(bits)) -1);                   \
100                     u32 newVal = (val) & maskBits; /* mask for safety */    \
101                     (void)(maskBits <<= st);                                 \
102                     (data) &= ~maskBits; /* clears the region to set */        \
103                     (data) |= newVal <<(st);                                 \
104                 } while(false);
105 
106 
107 /* ========================================================================
108     Inline Functions
109    ======================================================================== */
110 
111 /* ------------------------------------------------------------------------
112     Pointer operations
113    ------------------------------------------------------------------------ */
114 
115 inline NNSiUIntPtr
NNSiGetUIntPtr(const void * ptr)116 NNSiGetUIntPtr(const void* ptr)
117 {
118     return (NNSiUIntPtr)ptr;
119 }
120 
121 inline u32
GetOffsetFromPtr(const void * start,const void * end)122 GetOffsetFromPtr(const void* start, const void* end)
123 {
124     return NNSiGetUIntPtr(end) - NNSiGetUIntPtr(start);
125 }
126 
127 inline void*
AddU32ToPtr(void * ptr,u32 val)128 AddU32ToPtr(void* ptr, u32 val)
129 {
130     return (void*)( NNSiGetUIntPtr(ptr) + val );
131 }
132 
133 inline const void*
AddU32ToCPtr(const void * ptr,u32 val)134 AddU32ToCPtr(const void* ptr, u32 val)
135 {
136     return (const void*)( NNSiGetUIntPtr(ptr) + val );
137 }
138 
139 inline void*
SubU32ToPtr(void * ptr,u32 val)140 SubU32ToPtr(void* ptr, u32 val)
141 {
142     return (void*)( NNSiGetUIntPtr(ptr) - val );
143 }
144 
145 inline const void*
SubU32ToCPtr(const void * ptr,u32 val)146 SubU32ToCPtr(const void* ptr, u32 val)
147 {
148     return (const void*)( NNSiGetUIntPtr(ptr) - val );
149 }
150 
151 inline int
ComparePtr(const void * a,const void * b)152 ComparePtr(const void* a, const void* b)
153 {
154     const u8* wa = reinterpret_cast<const u8*>(a);
155     const u8* wb = reinterpret_cast<const u8*>(b);
156 
157     return wa - wb;
158 }
159 
160 
161 inline u16
GetOptForHeap(const NNSiFndHeapHead * pHeapHd)162 GetOptForHeap(const NNSiFndHeapHead* pHeapHd)
163 {
164     return (u16)NNSi_FndGetBitValue(pHeapHd->attribute, 0, 8);
165 }
166 
167 inline void
SetOptForHeap(NNSiFndHeapHead * pHeapHd,u16 optFlag)168 SetOptForHeap(
169     NNSiFndHeapHead*    pHeapHd,
170     u16                 optFlag
171 )
172 {
173     NNSi_FndSetBitValue(pHeapHd->attribute, 0, 8, optFlag);
174 }
175 
176 
177 /* ------------------------------------------------------------------------
178     Fill memory
179    ------------------------------------------------------------------------ */
180 
181 
182 //  Tentative memset
MI_CpuFill32(void * dest,u32 data,u32 size)183 inline void MI_CpuFill32(void* dest, u32 data, u32 size)
184 {
185     u32* pDest = reinterpret_cast<u32*>(dest);
186     NN_TASSERT_(((u32)pDest & 0xfffffffc) == (u32)pDest);  // dest should be 4-byte aligned
187     NN_TASSERT_((size & 0xfffffffc) == size);  // size should be 4-byte aligned
188     for(int i = 0; i < size / 4; ++i)
189     {
190         pDest[i] = data;
191     }
192 }
193 
194 inline void
FillAllocMemory(NNSiFndHeapHead * pHeapHd,void * address,u32 size)195 FillAllocMemory(
196     NNSiFndHeapHead*    pHeapHd,
197     void*               address,
198     u32                 size
199 )
200 {
201 
202     if (GetOptForHeap(pHeapHd) & NN_OS_HEAP_OPT_0_CLEAR)
203     {
204         MI_CpuFill32(address, 0, size);
205     }
206     else
207     {
208         #if ! defined(NN_SWITCH_DISABLE_DEBUG_PRINT)
209             if (GetOptForHeap(pHeapHd) & NN_OS_HEAP_OPT_DEBUG_FILL)
210             {
211                 MI_CpuFill32(address, GetFillValForHeap(NN_OS_HEAP_FILL_ALLOC), size);
212             }
213         #endif
214     }
215 }
216 
217 #if defined(NN_SWITCH_DISABLE_DEBUG_PRINT)
218     #define FillFreeMemory(pHeapHd, address, size)  ((void) 0)
219 #else
220     inline void
FillFreeMemory(NNSiFndHeapHead * pHeapHd,void * address,u32 size)221     FillFreeMemory(
222         NNSiFndHeapHead*    pHeapHd,
223         void*               address,
224         u32                 size
225     )
226     {
227         if (GetOptForHeap(pHeapHd) & NN_OS_HEAP_OPT_DEBUG_FILL)
228         {
229             MI_CpuFill32(address, GetFillValForHeap(NN_OS_HEAP_FILL_FREE), size);
230         }
231     }
232 #endif
233 
234 #if defined(NN_SWITCH_DISABLE_DEBUG_PRINT)
235     #define FillNoUseMemory(pHeapHd, address, size)  ((void) 0)
236 #else
237     inline void
FillNoUseMemory(NNSiFndHeapHead * pHeapHd,void * address,u32 size)238     FillNoUseMemory(
239         NNSiFndHeapHead*    pHeapHd,
240         void*               address,
241         u32                 size
242     )
243     {
244         if (GetOptForHeap(pHeapHd) & NN_OS_HEAP_OPT_DEBUG_FILL)
245         {
246             MI_CpuFill32(address, GetFillValForHeap(NN_OS_HEAP_FILL_NOUSE), size);
247         }
248     }
249 #endif
250 
251 
252 /* =======================================================================
253     Function Prototypes
254    ======================================================================== */
255 
256 void        NNSi_FndInitHeapHead(
257                 NNSiFndHeapHead*    pHeapHd,
258                 u32                 signature,
259                 void*               heapStart,
260                 void*               heapEnd,
261                 u16                 optFlag);
262 
263 void        NNSi_FndFinalizeHeap(
264                 NNSiFndHeapHead* pHeapHd);
265 
266 void        NNSi_FndDumpHeapHead(
267                 NNSiFndHeapHead const* pHeapHd);
268 
269 //
270 
271 }}} // namespace nn::os
272 
273 #endif // __cplusplus
274 
275 /* NN_OS_HEAPCOMMONI_H_ */
276 #endif /* NN_OS_OS_HEAPCOMMONIMPL_H_ */
277