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 &timestamp, uint32 address, bool DS24 = false, bool LWC_timing = false);
228  template<typename T> void WriteMemory(pscpu_timestamp_t &timestamp, uint32 address, uint32 value, bool DS24 = false);
229 
230  uint32 ReadInstruction(pscpu_timestamp_t &timestamp, 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