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 git repository and contact information can be found at
16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
18 #include "Common/Common.h"
19 #include "Common/Atomics.h"
21 #include "Core/Core.h"
22 #include "Core/MemMap.h"
23 #include "Core/Config.h"
24 #include "Core/Host.h"
25 #include "Core/Reporting.h"
27 #include "Core/MIPS/MIPS.h"
32 // =================================
36 // Read and write shortcuts
38 // GetPointer must always return an address in the bottom 32 bits of address space, so that 64-bit
39 // programs don't have problems directly addressing any part of memory.
41 u8
*GetPointer(const u32 address
)
43 if ((address
& 0x3E000000) == 0x08000000) {
45 return GetPointerUnchecked(address
);
46 } else if ((address
& 0x3F800000) == 0x04000000) {
48 return GetPointerUnchecked(address
);
49 } else if ((address
& 0xBFFF0000) == 0x00010000) {
51 return GetPointerUnchecked(address
);
52 } else if ((address
& 0x3F000000) >= 0x08000000 && (address
& 0x3F000000) < 0x08000000 + g_MemorySize
) {
53 // More RAM (remasters, etc.)
54 return GetPointerUnchecked(address
);
56 ERROR_LOG(MEMMAP
, "Unknown GetPointer %08x PC %08x LR %08x", address
, currentMIPS
->pc
, currentMIPS
->r
[MIPS_REG_RA
]);
57 static bool reported
= false;
59 Reporting::ReportMessage("Unknown GetPointer %08x PC %08x LR %08x", address
, currentMIPS
->pc
, currentMIPS
->r
[MIPS_REG_RA
]);
62 if (!g_Config
.bIgnoreBadMemAccess
) {
63 Core_EnableStepping(true);
64 host
->SetDebugMode(true);
71 inline void ReadFromHardware(T
&var
, const u32 address
)
73 // TODO: Figure out the fastest order of tests for both read and write (they are probably different).
74 // TODO: Make sure this represents the mirrors in a correct way.
76 // Could just do a base-relative read, too.... TODO
78 if ((address
& 0x3E000000) == 0x08000000) {
80 var
= *((const T
*)GetPointerUnchecked(address
));
81 } else if ((address
& 0x3F800000) == 0x04000000) {
83 var
= *((const T
*)GetPointerUnchecked(address
));
84 } else if ((address
& 0xBFFF0000) == 0x00010000) {
86 var
= *((const T
*)GetPointerUnchecked(address
));
87 } else if ((address
& 0x3F000000) >= 0x08000000 && (address
& 0x3F000000) < 0x08000000 + g_MemorySize
) {
88 // More RAM (remasters, etc.)
89 var
= *((const T
*)GetPointerUnchecked(address
));
91 // In jit, we only flush PC when bIgnoreBadMemAccess is off.
92 if (g_Config
.bJit
&& g_Config
.bIgnoreBadMemAccess
) {
93 WARN_LOG(MEMMAP
, "ReadFromHardware: Invalid address %08x", address
);
95 WARN_LOG(MEMMAP
, "ReadFromHardware: Invalid address %08x PC %08x LR %08x", address
, currentMIPS
->pc
, currentMIPS
->r
[MIPS_REG_RA
]);
97 static bool reported
= false;
99 Reporting::ReportMessage("ReadFromHardware: Invalid address %08x near PC %08x LR %08x", address
, currentMIPS
->pc
, currentMIPS
->r
[MIPS_REG_RA
]);
102 if (!g_Config
.bIgnoreBadMemAccess
) {
103 Core_EnableStepping(true);
104 host
->SetDebugMode(true);
110 template <typename T
>
111 inline void WriteToHardware(u32 address
, const T data
)
113 // Could just do a base-relative write, too.... TODO
115 if ((address
& 0x3E000000) == 0x08000000) {
117 *(T
*)GetPointerUnchecked(address
) = data
;
118 } else if ((address
& 0x3F800000) == 0x04000000) {
120 *(T
*)GetPointerUnchecked(address
) = data
;
121 } else if ((address
& 0xBFFF0000) == 0x00010000) {
123 *(T
*)GetPointerUnchecked(address
) = data
;
124 } else if ((address
& 0x3F000000) >= 0x08000000 && (address
& 0x3F000000) < 0x08000000 + g_MemorySize
) {
125 // More RAM (remasters, etc.)
126 *(T
*)GetPointerUnchecked(address
) = data
;
128 // In jit, we only flush PC when bIgnoreBadMemAccess is off.
129 if (g_Config
.bJit
&& g_Config
.bIgnoreBadMemAccess
) {
130 WARN_LOG(MEMMAP
, "WriteToHardware: Invalid address %08x", address
);
132 WARN_LOG(MEMMAP
, "WriteToHardware: Invalid address %08x PC %08x LR %08x", address
, currentMIPS
->pc
, currentMIPS
->r
[MIPS_REG_RA
]);
134 static bool reported
= false;
136 Reporting::ReportMessage("WriteToHardware: Invalid address %08x near PC %08x LR %08x", address
, currentMIPS
->pc
, currentMIPS
->r
[MIPS_REG_RA
]);
139 if (!g_Config
.bIgnoreBadMemAccess
) {
140 Core_EnableStepping(true);
141 host
->SetDebugMode(true);
146 // =====================
148 bool IsRAMAddress(const u32 address
) {
149 if ((address
& 0x3E000000) == 0x08000000) {
151 } else if ((address
& 0x3F000000) >= 0x08000000 && (address
& 0x3F000000) < 0x08000000 + g_MemorySize
) {
158 bool IsVRAMAddress(const u32 address
) {
159 return ((address
& 0x3F800000) == 0x04000000);
162 bool IsScratchpadAddress(const u32 address
) {
163 return (address
& 0xBFFF0000) == 0x00010000;
166 u8
Read_U8(const u32 _Address
)
169 ReadFromHardware
<u8
>(_var
, _Address
);
173 u16
Read_U16(const u32 _Address
)
176 ReadFromHardware
<u16_le
>(_var
, _Address
);
180 u32
Read_U32(const u32 _Address
)
183 ReadFromHardware
<u32_le
>(_var
, _Address
);
187 u64
Read_U64(const u32 _Address
)
190 ReadFromHardware
<u64_le
>(_var
, _Address
);
194 u32
Read_U8_ZX(const u32 _Address
)
196 return (u32
)Read_U8(_Address
);
199 u32
Read_U16_ZX(const u32 _Address
)
201 return (u32
)Read_U16(_Address
);
204 void Write_U8(const u8 _Data
, const u32 _Address
)
206 WriteToHardware
<u8
>(_Address
, _Data
);
209 void Write_U16(const u16 _Data
, const u32 _Address
)
211 WriteToHardware
<u16_le
>(_Address
, _Data
);
214 void Write_U32(const u32 _Data
, const u32 _Address
)
216 WriteToHardware
<u32_le
>(_Address
, _Data
);
219 void Write_U64(const u64 _Data
, const u32 _Address
)
221 WriteToHardware
<u64_le
>(_Address
, _Data
);
226 u8
ReadUnchecked_U8(const u32 _Address
)
229 ReadFromHardware
<u8
>(_var
, _Address
);
233 u16
ReadUnchecked_U16(const u32 _Address
)
236 ReadFromHardware
<u16_le
>(_var
, _Address
);
240 u32
ReadUnchecked_U32(const u32 _Address
)
243 ReadFromHardware
<u32_le
>(_var
, _Address
);
247 void WriteUnchecked_U8(const u8 _iValue
, const u32 _Address
)
249 WriteToHardware
<u8
>(_Address
, _iValue
);
252 void WriteUnchecked_U16(const u16 _iValue
, const u32 _Address
)
254 WriteToHardware
<u16_le
>(_Address
, _iValue
);
257 void WriteUnchecked_U32(const u32 _iValue
, const u32 _Address
)
259 WriteToHardware
<u32_le
>(_Address
, _iValue
);
264 } // namespace Memory