1 // Copyright (C) 2003 Dolphin Project / 2012 PPSSPP Project.
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0 or later versions.
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License 2.0 for more details.
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
15 // Official SVN repository and contact information can be found at
16 // http://code.google.com/p/dolphin-emu/
29 #include "Common/Common.h"
30 #include "Common/CommonTypes.h"
31 #include "Core/Opcode.h"
33 // PPSSPP is very aggressive about trying to do memory accesses directly, for speed.
34 // This can be a problem when debugging though, as stray memory reads and writes will
35 // crash the whole emulator.
36 // If safe memory is enabled and JIT is disabled, all memory access will go through the proper
37 // memory access functions, and thus won't crash the emu when they go out of bounds.
42 // Global declarations
45 typedef void (*writeFn8
)(const u8
, const u32
);
46 typedef void (*writeFn16
)(const u16
,const u32
);
47 typedef void (*writeFn32
)(const u32
,const u32
);
48 typedef void (*writeFn64
)(const u64
,const u32
);
50 typedef void (*readFn8
)(u8
&, const u32
);
51 typedef void (*readFn16
)(u16
&, const u32
);
52 typedef void (*readFn32
)(u32
&, const u32
);
53 typedef void (*readFn64
)(u64
&, const u32
);
57 // Base is a pointer to the base of the memory map. Yes, some MMU tricks
58 // are used to set up a full GC or Wii memory map in process memory. on
59 // 32-bit, you have to mask your offsets with 0x3FFFFFFF. This means that
60 // some things are mirrored too many times, but eh... it works.
62 // In 64-bit, this might point to "high memory" (above the 32-bit limit),
63 // so be sure to load it into a 64-bit register.
66 // These are guaranteed to point to "low memory" addresses (sub-32-bit).
67 // 64-bit: Pointers to low-mem (sub-0x10000000) mirror
68 // 32-bit: Same as the corresponding physical/virtual pointers.
69 // Broken into three chunks to workaround 32-bit mmap() limits.
73 extern u8
*m_pScratchPad
;
76 // 64-bit: Pointers to high-mem mirrors
77 // 32-bit: Same as above
78 extern u8
*m_pPhysicalRAM
;
79 extern u8
*m_pUncachedRAM
;
81 // This replaces RAM_NORMAL_SIZE at runtime.
82 extern u32 g_MemorySize
;
83 extern u32 g_PSPModel
;
87 // This may be adjusted by remaster games.
88 RAM_NORMAL_SIZE
= 0x02000000,
89 // Used if the PSP model is PSP-2000 (Slim).
90 RAM_DOUBLE_SIZE
= RAM_NORMAL_SIZE
* 2,
92 VRAM_SIZE
= 0x00200000,
94 SCRATCHPAD_SIZE
= 0x00004000,
97 // This wraparound should work for PSP too.
98 MEMVIEW32_MASK
= 0x3FFFFFFF,
103 MV_MIRROR_PREVIOUS
= 1,
106 MV_IS_PRIMARY_RAM
= 0x100,
107 MV_IS_EXTRA1_RAM
= 0x200,
108 MV_IS_EXTRA2_RAM
= 0x400,
120 // Uses a memory arena to set up an emulator-friendly memory map
121 void MemoryMap_Setup(u32 flags
);
122 void MemoryMap_Shutdown(u32 flags
);
127 void DoState(PointerWrap
&p
);
130 class MemoryInitedLock
137 // This doesn't lock memory access or anything, it just makes sure memory isn't freed.
138 // Use it when accessing PSP memory from external threads.
139 MemoryInitedLock
Lock();
141 // used by JIT to read instructions. Does not resolve replacements.
142 Opcode
Read_Opcode_JIT(const u32 _Address
);
143 // used by JIT. Reads in the "Locked cache" mode
144 void Write_Opcode_JIT(const u32 _Address
, const Opcode
& _Value
);
146 // Should be used by analyzers, disassemblers etc. Does resolve replacements.
147 Opcode
Read_Instruction(const u32 _Address
, bool resolveReplacements
= false);
148 Opcode
ReadUnchecked_Instruction(const u32 _Address
, bool resolveReplacements
= false);
150 u8
Read_U8(const u32 _Address
);
151 u16
Read_U16(const u32 _Address
);
152 u32
Read_U32(const u32 _Address
);
153 u64
Read_U64(const u32 _Address
);
155 #if (defined(ARM) || defined(_ARM)) && !defined(_M_ARM)
159 inline u8
* GetPointerUnchecked(const u32 address
) {
161 return (u8
*)(base
+ (address
& MEMVIEW32_MASK
));
163 return (u8
*)(base
+ address
);
168 u32
ReadUnchecked_U32(const u32 _Address
);
169 // ONLY for use by GUI and fast interpreter
170 u8
ReadUnchecked_U8(const u32 _Address
);
171 u16
ReadUnchecked_U16(const u32 _Address
);
172 void WriteUnchecked_U8(const u8 _Data
, const u32 _Address
);
173 void WriteUnchecked_U16(const u16 _Data
, const u32 _Address
);
174 void WriteUnchecked_U32(const u32 _Data
, const u32 _Address
);
177 inline u32
ReadUnchecked_U32(const u32 address
) {
179 return *(u32_le
*)(base
+ (address
& MEMVIEW32_MASK
));
181 return *(u32_le
*)(base
+ address
);
185 inline u16
ReadUnchecked_U16(const u32 address
) {
187 return *(u16_le
*)(base
+ (address
& MEMVIEW32_MASK
));
189 return *(u16_le
*)(base
+ address
);
193 inline u8
ReadUnchecked_U8(const u32 address
) {
195 return (*(u8
*)(base
+ (address
& MEMVIEW32_MASK
)));
197 return (*(u8
*)(base
+ address
));
201 inline void WriteUnchecked_U32(u32 data
, u32 address
) {
203 *(u32_le
*)(base
+ (address
& MEMVIEW32_MASK
)) = data
;
205 *(u32_le
*)(base
+ address
) = data
;
209 inline void WriteUnchecked_U16(u16 data
, u32 address
) {
211 *(u16_le
*)(base
+ (address
& MEMVIEW32_MASK
)) = data
;
213 *(u16_le
*)(base
+ address
) = data
;
217 inline void WriteUnchecked_U8(u8 data
, u32 address
) {
219 (*(u8
*)(base
+ (address
& MEMVIEW32_MASK
))) = data
;
221 (*(u8
*)(base
+ address
)) = data
;
227 inline float Read_Float(u32 address
)
229 u32 ifloat
= Read_U32(address
);
231 memcpy(&f
, &ifloat
, sizeof(float));
235 // used by JIT. Return zero-extended 32bit values
236 u32
Read_U8_ZX(const u32 address
);
237 u32
Read_U16_ZX(const u32 address
);
239 void Write_U8(const u8 data
, const u32 address
);
240 void Write_U16(const u16 data
, const u32 address
);
241 void Write_U32(const u32 data
, const u32 address
);
242 void Write_U64(const u64 data
, const u32 address
);
244 inline void Write_Float(float f
, u32 address
)
247 memcpy(&u
, &f
, sizeof(float));
248 Write_U32(u
, address
);
251 u8
* GetPointer(const u32 address
);
252 bool IsRAMAddress(const u32 address
);
253 bool IsVRAMAddress(const u32 address
);
254 bool IsScratchpadAddress(const u32 address
);
256 inline const char* GetCharPointer(const u32 address
) {
257 return (const char *)GetPointer(address
);
260 inline void MemcpyUnchecked(void *to_data
, const u32 from_address
, const u32 len
)
262 memcpy(to_data
, GetPointerUnchecked(from_address
), len
);
265 inline void MemcpyUnchecked(const u32 to_address
, const void *from_data
, const u32 len
)
267 memcpy(GetPointerUnchecked(to_address
), from_data
, len
);
270 inline void MemcpyUnchecked(const u32 to_address
, const u32 from_address
, const u32 len
)
272 MemcpyUnchecked(GetPointer(to_address
), from_address
, len
);
275 inline bool IsValidAddress(const u32 address
) {
276 if ((address
& 0x3E000000) == 0x08000000) {
278 } else if ((address
& 0x3F800000) == 0x04000000) {
280 } else if ((address
& 0xBFFF0000) == 0x00010000) {
282 } else if ((address
& 0x3F000000) >= 0x08000000 && (address
& 0x3F000000) < 0x08000000 + g_MemorySize
) {
289 inline u32
ValidSize(const u32 address
, const u32 requested_size
) {
291 if ((address
& 0x3E000000) == 0x08000000) {
292 max_size
= 0x08000000 + g_MemorySize
- address
;
294 else if ((address
& 0x3F800000) == 0x04000000) {
295 max_size
= 0x04800000 - address
;
297 else if ((address
& 0xBFFF0000) == 0x00010000) {
298 max_size
= 0x00014000 - address
;
300 else if ((address
& 0x3F000000) >= 0x08000000 && (address
& 0x3F000000) < 0x08000000 + g_MemorySize
) {
301 max_size
= 0x08000000 + g_MemorySize
- address
;
306 if (requested_size
> max_size
) {
309 return requested_size
;
312 inline bool IsValidRange(const u32 address
, const u32 size
) {
313 return IsValidAddress(address
) && ValidSize(address
, size
) == size
;
318 template <typename T
>
323 inline T
&operator*() const
326 return *(T
*)(Memory::base
+ (ptr
& Memory::MEMVIEW32_MASK
));
328 return *(T
*)(Memory::base
+ ptr
);
332 inline T
&operator[](int i
) const
335 return *((T
*)(Memory::base
+ (ptr
& Memory::MEMVIEW32_MASK
)) + i
);
337 return *((T
*)(Memory::base
+ ptr
) + i
);
341 inline T
*operator->() const
344 return (T
*)(Memory::base
+ (ptr
& Memory::MEMVIEW32_MASK
));
346 return (T
*)(Memory::base
+ ptr
);
350 inline PSPPointer
<T
> operator+(int i
) const
353 other
.ptr
= ptr
+ i
* sizeof(T
);
357 inline PSPPointer
<T
> &operator=(u32 p
)
363 inline PSPPointer
<T
> &operator+=(int i
)
365 ptr
= ptr
+ i
* sizeof(T
);
369 inline PSPPointer
<T
> operator-(int i
) const
372 other
.ptr
= ptr
- i
* sizeof(T
);
376 inline PSPPointer
<T
> &operator-=(int i
)
378 ptr
= ptr
- i
* sizeof(T
);
382 inline PSPPointer
<T
> &operator++()
388 inline PSPPointer
<T
> operator++(int i
)
396 inline PSPPointer
<T
> &operator--()
402 inline PSPPointer
<T
> operator--(int i
)
413 return (T
*)(Memory::base
+ (ptr
& Memory::MEMVIEW32_MASK
));
415 return (T
*)(Memory::base
+ ptr
);
419 inline operator const T
*() const
422 return (const T
*)(Memory::base
+ (ptr
& Memory::MEMVIEW32_MASK
));
424 return (const T
*)(Memory::base
+ ptr
);
430 return Memory::IsValidAddress(ptr
);
433 static PSPPointer
<T
> Create(u32 ptr
) {
441 inline u32
PSP_GetScratchpadMemoryBase() { return 0x00010000;}
442 inline u32
PSP_GetScratchpadMemoryEnd() { return 0x00014000;}
444 inline u32
PSP_GetKernelMemoryBase() { return 0x08000000;}
445 inline u32
PSP_GetUserMemoryEnd() { return PSP_GetKernelMemoryBase() + Memory::g_MemorySize
;}
446 inline u32
PSP_GetKernelMemoryEnd() { return 0x08400000;}
447 // "Volatile" RAM is between 0x08400000 and 0x08800000, can be requested by the
448 // game through sceKernelVolatileMemTryLock.
450 inline u32
PSP_GetUserMemoryBase() { return 0x08800000;}
452 inline u32
PSP_GetDefaultLoadAddress() { return 0;}
453 //inline u32 PSP_GetDefaultLoadAddress() { return 0x0898dab0;}
454 inline u32
PSP_GetVidMemBase() { return 0x04000000;}
455 inline u32
PSP_GetVidMemEnd() { return 0x04800000;}
457 template <typename T
>
458 inline bool operator==(const PSPPointer
<T
> &lhs
, const PSPPointer
<T
> &rhs
)
460 return lhs
.ptr
== rhs
.ptr
;
463 template <typename T
>
464 inline bool operator!=(const PSPPointer
<T
> &lhs
, const PSPPointer
<T
> &rhs
)
466 return lhs
.ptr
!= rhs
.ptr
;
469 template <typename T
>
470 inline bool operator<(const PSPPointer
<T
> &lhs
, const PSPPointer
<T
> &rhs
)
472 return lhs
.ptr
< rhs
.ptr
;
475 template <typename T
>
476 inline bool operator>(const PSPPointer
<T
> &lhs
, const PSPPointer
<T
> &rhs
)
478 return lhs
.ptr
> rhs
.ptr
;
481 template <typename T
>
482 inline bool operator<=(const PSPPointer
<T
> &lhs
, const PSPPointer
<T
> &rhs
)
484 return lhs
.ptr
<= rhs
.ptr
;
487 template <typename T
>
488 inline bool operator>=(const PSPPointer
<T
> &lhs
, const PSPPointer
<T
> &rhs
)
490 return lhs
.ptr
>= rhs
.ptr
;