1 /******************************************************************************/ 2 /* Mednafen Sony PS1 Emulation Module */ 3 /******************************************************************************/ 4 /* cpu.h: 5 ** Copyright (C) 2011-2016 Mednafen Team 6 ** 7 ** This program is free software; you can redistribute it and/or 8 ** modify it under the terms of the GNU General Public License 9 ** as published by the Free Software Foundation; either version 2 10 ** of the License, or (at your option) any later version. 11 ** 12 ** This program is distributed in the hope that it will be useful, 13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 ** GNU General Public License for more details. 16 ** 17 ** You should have received a copy of the GNU General Public License 18 ** along with this program; if not, write to the Free Software Foundation, Inc., 19 ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 */ 21 22 #ifndef __MDFN_PSX_CPU_H 23 #define __MDFN_PSX_CPU_H 24 25 /* 26 Load delay notes: 27 28 // Takes 1 less 29 ".set noreorder\n\t" 30 ".set nomacro\n\t" 31 "lw %0, 0(%2)\n\t" 32 "nop\n\t" 33 "nop\n\t" 34 "or %0, %1, %1\n\t" 35 36 // cycle than this: 37 ".set noreorder\n\t" 38 ".set nomacro\n\t" 39 "lw %0, 0(%2)\n\t" 40 "nop\n\t" 41 "or %0, %1, %1\n\t" 42 "nop\n\t" 43 44 45 // Both of these 46 ".set noreorder\n\t" 47 ".set nomacro\n\t" 48 "lw %0, 0(%2)\n\t" 49 "nop\n\t" 50 "nop\n\t" 51 "or %1, %0, %0\n\t" 52 53 // take same...(which is kind of odd). 54 ".set noreorder\n\t" 55 ".set nomacro\n\t" 56 "lw %0, 0(%2)\n\t" 57 "nop\n\t" 58 "or %1, %0, %0\n\t" 59 "nop\n\t" 60 */ 61 62 #include "gte.h" 63 64 namespace MDFN_IEN_PSX 65 { 66 67 class PS_CPU 68 { 69 public: 70 71 PS_CPU() MDFN_COLD; 72 ~PS_CPU() MDFN_COLD; 73 74 // FAST_MAP_* enums are in BYTES(8-bit), not in 32-bit units("words" in MIPS context), but the sizes 75 // will always be multiples of 4. 76 enum { FAST_MAP_SHIFT = 16 }; 77 enum { FAST_MAP_PSIZE = 1 << FAST_MAP_SHIFT }; 78 79 void SetFastMap(void *region_mem, uint32 region_address, uint32 region_size); 80 SetEventNT(const pscpu_timestamp_t next_event_ts_arg)81 INLINE void SetEventNT(const pscpu_timestamp_t next_event_ts_arg) 82 { 83 next_event_ts = next_event_ts_arg; 84 } 85 86 pscpu_timestamp_t Run(pscpu_timestamp_t timestamp_in, bool BIOSPrintMode, bool ILHMode); 87 88 void Power(void) MDFN_COLD; 89 90 // which ranges 0-5, inclusive 91 void AssertIRQ(unsigned which, bool asserted); 92 93 void SetHalt(bool status); 94 95 // TODO eventually: factor BIU address decoding directly in the CPU core somehow without hurting speed. 96 void SetBIU(uint32 val); 97 uint32 GetBIU(void); 98 99 void StateAction(StateMem *sm, const unsigned load, const bool data_only); 100 101 private: 102 103 uint32 GPR[32 + 1]; // GPR[32] Used as dummy in load delay simulation(indexing past the end of real GPR) 104 105 uint32 LO; 106 uint32 HI; 107 108 109 uint32 BACKED_PC; 110 uint32 BACKED_new_PC; 111 112 uint32 IPCache; 113 uint8 BDBT; 114 115 uint8 ReadAbsorb[0x20 + 1]; 116 uint8 ReadAbsorbWhich; 117 uint8 ReadFudge; 118 119 void RecalcIPCache(void); 120 bool Halted; 121 122 uint32 BACKED_LDWhich; 123 uint32 BACKED_LDValue; 124 uint32 LDAbsorb; 125 126 pscpu_timestamp_t next_event_ts; 127 pscpu_timestamp_t gte_ts_done; 128 pscpu_timestamp_t muldiv_ts_done; 129 130 uint32 BIU; 131 132 const uint32 addr_mask[8] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0x1FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; 133 134 enum 135 { 136 CP0REG_BPC = 3, // PC breakpoint address. 137 CP0REG_BDA = 5, // Data load/store breakpoint address. 138 CP0REG_TAR = 6, // Target address(???) 139 CP0REG_DCIC = 7, // Cache control 140 CP0REG_BADA = 8, 141 CP0REG_BDAM = 9, // Data load/store address mask. 142 CP0REG_BPCM = 11, // PC breakpoint address mask. 143 CP0REG_SR = 12, 144 CP0REG_CAUSE = 13, 145 CP0REG_EPC = 14, 146 CP0REG_PRID = 15 // Product ID 147 }; 148 149 struct 150 { 151 union 152 { 153 uint32 Regs[32]; 154 struct 155 { 156 uint32 Unused00; 157 uint32 Unused01; 158 uint32 Unused02; 159 uint32 BPC; // RW 160 uint32 Unused04; 161 uint32 BDA; // RW 162 uint32 TAR; // R 163 uint32 DCIC; // RW 164 uint32 BADA; // R 165 uint32 BDAM; // R/W 166 uint32 Unused0A; 167 uint32 BPCM; // R/W 168 uint32 SR; // R/W 169 uint32 CAUSE; // R/W(partial) 170 uint32 EPC; // R 171 uint32 PRID; // R 172 }; 173 }; 174 } CP0; 175 176 uint8 MULT_Tab24[24]; 177 178 struct __ICache 179 { 180 /* 181 TV: 182 Mask 0x00000001: 0x0 = icache enabled((BIU & 0x800) == 0x800), 0x1 = icache disabled(changed in bulk on BIU value changes; preserve everywhere else!) 183 Mask 0x00000002: 0x0 = valid, 0x2 = invalid 184 Mask 0x00000FFC: Always 0 185 Mask 0xFFFFF000: Tag. 186 */ 187 uint32 TV; 188 uint32 Data; 189 }; 190 191 union 192 { 193 __ICache ICache[1024]; 194 uint32 ICache_Bulk[2048]; 195 }; 196 197 MultiAccessSizeMem<1024, false> ScratchRAM; 198 199 //PS_GTE GTE; 200 201 uintptr_t FastMap[1 << (32 - FAST_MAP_SHIFT)]; 202 uint8 DummyPage[FAST_MAP_PSIZE]; 203 204 enum 205 { 206 EXCEPTION_INT = 0, 207 EXCEPTION_MOD = 1, 208 EXCEPTION_TLBL = 2, 209 EXCEPTION_TLBS = 3, 210 EXCEPTION_ADEL = 4, // Address error on load 211 EXCEPTION_ADES = 5, // Address error on store 212 EXCEPTION_IBE = 6, // Instruction bus error 213 EXCEPTION_DBE = 7, // Data bus error 214 EXCEPTION_SYSCALL = 8, // System call 215 EXCEPTION_BP = 9, // Breakpoint 216 EXCEPTION_RI = 10, // Reserved instruction 217 EXCEPTION_COPU = 11, // Coprocessor unusable 218 EXCEPTION_OV = 12 // Arithmetic overflow 219 }; 220 221 uint32 Exception(uint32 code, uint32 PC, const uint32 NP, const uint32 instr) MDFN_WARN_UNUSED_RESULT; 222 223 template<bool DebugMode, bool BIOSPrintMode, bool ILHMode> NO_INLINE pscpu_timestamp_t RunReal(pscpu_timestamp_t timestamp_in); 224 225 template<typename T> T PeekMemory(uint32 address) MDFN_COLD; 226 template<typename T> void PokeMemory(uint32 address, T value) MDFN_COLD; 227 template<typename T> T ReadMemory(pscpu_timestamp_t ×tamp, uint32 address, bool DS24 = false, bool LWC_timing = false); 228 template<typename T> void WriteMemory(pscpu_timestamp_t ×tamp, uint32 address, uint32 value, bool DS24 = false); 229 230 uint32 ReadInstruction(pscpu_timestamp_t ×tamp, uint32 address); 231 232 // 233 // Mednafen debugger stuff follows: 234 // 235 public: 236 void SetCPUHook(void (*cpuh)(const pscpu_timestamp_t timestamp, uint32 pc), void (*addbt)(uint32 from, uint32 to, bool exception)); 237 void CheckBreakpoints(void (*callback)(bool write, uint32 address, unsigned int len), uint32 instr); 238 239 enum 240 { 241 GSREG_GPR = 0, 242 GSREG_PC = 32, 243 GSREG_PC_NEXT, 244 GSREG_IN_BD_SLOT, 245 GSREG_LO, 246 GSREG_HI, 247 // 248 // 249 GSREG_BPC, 250 GSREG_BDA, 251 GSREG_TAR, 252 GSREG_DCIC, 253 GSREG_BADA, 254 GSREG_BDAM, 255 GSREG_BPCM, 256 GSREG_SR, 257 GSREG_CAUSE, 258 GSREG_EPC 259 }; 260 261 uint32 GetRegister(unsigned int which, char *special, const uint32 special_len); 262 void SetRegister(unsigned int which, uint32 value); 263 bool PeekCheckICache(uint32 PC, uint32 *iw); 264 265 uint8 PeekMem8(uint32 A); 266 uint16 PeekMem16(uint32 A); 267 uint32 PeekMem32(uint32 A); 268 269 void PokeMem8(uint32 A, uint8 V); 270 void PokeMem16(uint32 A, uint16 V); 271 void PokeMem32(uint32 A, uint32 V); 272 273 private: 274 void (*CPUHook)(const pscpu_timestamp_t timestamp, uint32 pc); 275 void (*ADDBT)(uint32 from, uint32 to, bool exception); 276 }; 277 278 } 279 280 #endif 281