1 /******************************************************************************/
2 /* Mednafen Sony PS1 Emulation Module                                         */
3 /******************************************************************************/
4 /* cpu.cpp:
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 #pragma GCC optimize ("unroll-loops")
23 
24 #include "psx.h"
25 #include "cpu.h"
26 
27 #if 0
28  #define EXP_ILL_CHECK(n) {n;}
29 #else
30  #define EXP_ILL_CHECK(n) {}
31 #endif
32 
33 #define BIU_ENABLE_ICACHE_S1	0x00000800	// Enable I-cache, set 1
34 #define BIU_ICACHE_FSIZE_MASK	0x00000300      // I-cache fill size mask; 0x000 = 2 words, 0x100 = 4 words, 0x200 = 8 words, 0x300 = 16 words
35 #define BIU_ENABLE_DCACHE	0x00000080	// Enable D-cache
36 #define BIU_DCACHE_SCRATCHPAD	0x00000008	// Enable scratchpad RAM mode of D-cache
37 #define BIU_TAG_TEST_MODE	0x00000004	// Enable TAG test mode(IsC must be set to 1 as well presumably?)
38 #define BIU_INVALIDATE_MODE	0x00000002	// Enable Invalidate mode(IsC must be set to 1 as well presumably?)
39 #define BIU_LOCK_MODE		0x00000001	// Enable Lock mode(IsC must be set to 1 as well presumably?)
40 
41 
42 
43 namespace MDFN_IEN_PSX
44 {
45 
46 
PS_CPU()47 PS_CPU::PS_CPU()
48 {
49  //printf("%zu\n", (size_t)((uintptr_t)ICache - (uintptr_t)this));
50 
51  Halted = false;
52 
53  memset(FastMap, 0, sizeof(FastMap));
54  memset(DummyPage, 0xFF, sizeof(DummyPage));	// 0xFF to trigger an illegal instruction exception, so we'll know what's up when debugging.
55 
56  for(uint64 a = 0x00000000; a < (1ULL << 32); a += FAST_MAP_PSIZE)
57   SetFastMap(DummyPage, a, FAST_MAP_PSIZE);
58 
59  CPUHook = NULL;
60  ADDBT = NULL;
61 
62  GTE_Init();
63 
64  for(unsigned i = 0; i < 24; i++)
65  {
66   uint8 v = 7;
67 
68   if(i < 12)
69    v += 4;
70 
71   if(i < 21)
72    v += 3;
73 
74   MULT_Tab24[i] = v;
75  }
76 }
77 
~PS_CPU()78 PS_CPU::~PS_CPU()
79 {
80 
81 
82 }
83 
SetFastMap(void * region_mem,uint32 region_address,uint32 region_size)84 void PS_CPU::SetFastMap(void *region_mem, uint32 region_address, uint32 region_size)
85 {
86  // FAST_MAP_SHIFT
87  // FAST_MAP_PSIZE
88 
89  for(uint64 A = region_address; A < (uint64)region_address + region_size; A += FAST_MAP_PSIZE)
90  {
91   FastMap[A >> FAST_MAP_SHIFT] = ((uintptr_t)region_mem - region_address);
92  }
93 }
94 
RecalcIPCache(void)95 INLINE void PS_CPU::RecalcIPCache(void)
96 {
97  IPCache = 0;
98 
99  if((CP0.SR & CP0.CAUSE & 0xFF00) && (CP0.SR & 1))
100   IPCache = 0x80;
101 
102  if(Halted)
103   IPCache = 0x80;
104 }
105 
SetHalt(bool status)106 void PS_CPU::SetHalt(bool status)
107 {
108  Halted = status;
109  RecalcIPCache();
110 }
111 
Power(void)112 void PS_CPU::Power(void)
113 {
114  assert(sizeof(ICache) == sizeof(ICache_Bulk));
115 
116  memset(GPR, 0, sizeof(GPR));
117  memset(&CP0, 0, sizeof(CP0));
118  LO = 0;
119  HI = 0;
120 
121  gte_ts_done = 0;
122  muldiv_ts_done = 0;
123 
124  BACKED_PC = 0xBFC00000;
125  BACKED_new_PC = BACKED_PC + 4;
126  BDBT = 0;
127 
128  BACKED_LDWhich = 0x20;
129  BACKED_LDValue = 0;
130  LDAbsorb = 0;
131  memset(ReadAbsorb, 0, sizeof(ReadAbsorb));
132  ReadAbsorbWhich = 0;
133  ReadFudge = 0;
134 
135  CP0.SR |= (1 << 22);	// BEV
136  CP0.SR |= (1 << 21);	// TS
137 
138  CP0.PRID = 0x2;
139 
140  RecalcIPCache();
141 
142 
143  BIU = 0;
144 
145  memset(ScratchRAM.data8, 0, 1024);
146 
147  // Not quite sure about these poweron/reset values:
148  for(unsigned i = 0; i < 1024; i++)
149  {
150   ICache[i].TV = 0x2 | ((BIU & 0x800) ? 0x0 : 0x1);
151   ICache[i].Data = 0;
152  }
153 
154  GTE_Power();
155 }
156 
StateAction(StateMem * sm,const unsigned load,const bool data_only)157 void PS_CPU::StateAction(StateMem *sm, const unsigned load, const bool data_only)
158 {
159  uint32 OPM = BDBT;
160 
161  SFORMAT StateRegs[] =
162  {
163   SFPTR32(GPR, 32),
164   SFVAR(LO),
165   SFVAR(HI),
166   SFVAR(BACKED_PC),
167   SFVAR(BACKED_new_PC),
168   SFVARN(OPM, "BACKED_new_PC_mask"),
169 
170   SFVAR(IPCache),
171   SFVAR(Halted),
172 
173   SFVAR(BACKED_LDWhich),
174   SFVAR(BACKED_LDValue),
175   SFVAR(LDAbsorb),
176 
177   SFVAR(next_event_ts),
178   SFVAR(gte_ts_done),
179   SFVAR(muldiv_ts_done),
180 
181   SFVAR(BIU),
182   SFVAR(ICache_Bulk),
183 
184   SFVAR(CP0.Regs),
185 
186   SFPTR8(ReadAbsorb, 0x20),
187   SFVARN(ReadAbsorb[0x20], "ReadAbsorbDummy"),
188   SFVAR(ReadAbsorbWhich),
189   SFVAR(ReadFudge),
190 
191   SFPTR8(ScratchRAM.data8, 1024),
192 
193   SFEND
194  };
195  MDFNSS_StateAction(sm, load, data_only, StateRegs, "CPU");
196 
197  GTE_StateAction(sm, load, data_only);
198 
199  if(load)
200  {
201   if(load < 0x939)
202   {
203    //
204    // For compatibility with pre-0.9.39 save states.
205    //
206    uint32 NOPM = ~OPM;
207 
208    //printf("Old: new_PC=0x%08x, new_PC_mask=0x%08x\n", BACKED_new_PC, OPM);
209 
210    BDBT = ((NOPM << 1) | (NOPM >> 1)) & 0x3;
211 
212    BACKED_new_PC = (BACKED_PC & OPM) + BACKED_new_PC;
213   }
214   else
215    BDBT = OPM;
216 
217   ReadAbsorbWhich &= 0x1F;
218   BACKED_LDWhich %= 0x21;
219 
220   //printf("PC=0x%08x, new_PC=0x%08x, BDBT=0x%02x\n", BACKED_PC, BACKED_new_PC, BDBT);
221  }
222 }
223 
AssertIRQ(unsigned which,bool asserted)224 void PS_CPU::AssertIRQ(unsigned which, bool asserted)
225 {
226  assert(which <= 5);
227 
228  CP0.CAUSE &= ~(1 << (10 + which));
229 
230  if(asserted)
231   CP0.CAUSE |= 1 << (10 + which);
232 
233  RecalcIPCache();
234 }
235 
SetBIU(uint32 val)236 void PS_CPU::SetBIU(uint32 val)
237 {
238  const uint32 old_BIU = BIU;
239 
240  BIU = val & ~(0x440);
241 
242  if((BIU ^ old_BIU) & 0x800)
243  {
244   if(BIU & 0x800)	// ICache enabled
245   {
246    for(unsigned i = 0; i < 1024; i++)
247     ICache[i].TV &= ~0x1;
248   }
249   else			// ICache disabled
250   {
251    for(unsigned i = 0; i < 1024; i++)
252     ICache[i].TV |= 0x1;
253   }
254  }
255 
256  PSX_DBG(PSX_DBG_SPARSE, "[CPU] Set BIU=0x%08x\n", BIU);
257 }
258 
GetBIU(void)259 uint32 PS_CPU::GetBIU(void)
260 {
261  return BIU;
262 }
263 
264 template<typename T>
PeekMemory(uint32 address)265 INLINE T PS_CPU::PeekMemory(uint32 address)
266 {
267  T ret;
268  address &= addr_mask[address >> 29];
269 
270  if(address >= 0x1F800000 && address <= 0x1F8003FF)
271   return ScratchRAM.Read<T>(address & 0x3FF);
272 
273  //assert(!(CP0.SR & 0x10000));
274 
275  if(sizeof(T) == 1)
276   ret = PSX_MemPeek8(address);
277  else if(sizeof(T) == 2)
278   ret = PSX_MemPeek16(address);
279  else
280   ret = PSX_MemPeek32(address);
281 
282  return(ret);
283 }
284 
285 template<typename T>
PokeMemory(uint32 address,T value)286 void PS_CPU::PokeMemory(uint32 address, T value)
287 {
288  address &= addr_mask[address >> 29];
289 
290  if(address >= 0x1F800000 && address <= 0x1F8003FF)
291   return ScratchRAM.Write<T>(address & 0x3FF, value);
292 
293  if(sizeof(T) == 1)
294   PSX_MemPoke8(address, value);
295  else if(sizeof(T) == 2)
296   PSX_MemPoke16(address, value);
297  else
298   PSX_MemPoke32(address, value);
299 }
300 
301 template<typename T>
ReadMemory(pscpu_timestamp_t & timestamp,uint32 address,bool DS24,bool LWC_timing)302 INLINE T PS_CPU::ReadMemory(pscpu_timestamp_t &timestamp, uint32 address, bool DS24, bool LWC_timing)
303 {
304  T ret;
305 
306  ReadAbsorb[ReadAbsorbWhich] = 0;
307  ReadAbsorbWhich = 0;
308 
309 #if 0
310  if(MDFN_UNLIKELY(CP0.SR & 0x10000))
311  {
312   uint32 tmp = 0;	// TODO(someday): = open bus
313 
314   LDAbsorb = 0;
315 
316   if(BIU & (BIU_TAG_TEST_MODE | BIU_INVALIDATE_MODE | BIU_LOCK_MODE))
317   {
318    if(BIU & BIU_TAG_TEST_MODE)
319    {
320     const __ICache* const ICI = &ICache[((address & 0xFF0) >> 2)];
321 
322     tmp &= ~0x3F;	// bits 0-3 validity, bit 4 tag compare match, bit 5 forced to 0(lock bit apparently unimplemented in the PS1).
323 
324     //
325     // Get validity bits.
326     //
327     for(unsigned i = 0; i < 4; i++)
328      tmp |= (!(ICI[i].TV & 0x02)) << i;
329 
330     //
331     // Tag compare.
332     //
333     if(!((address ^ ICI[0].TV) & 0xFFFFF000))
334      tmp |= 0x10;
335    }
336   }
337   else
338   {
339    tmp = ICache[(address & 0xFFC) >> 2].Data;
340   }
341 
342   return tmp >> ((address & 0x3) * 8);
343  }
344 #endif
345  //
346  //
347  //
348 
349  address &= addr_mask[address >> 29];
350 
351  if(address >= 0x1F800000 && address <= 0x1F8003FF)
352  {
353   LDAbsorb = 0;
354 
355   if(DS24)
356    return ScratchRAM.ReadU24(address & 0x3FF);
357   else
358    return ScratchRAM.Read<T>(address & 0x3FF);
359  }
360 
361  timestamp += (ReadFudge >> 4) & 2;
362 
363  //assert(!(CP0.SR & 0x10000));
364 
365  pscpu_timestamp_t lts = timestamp;
366 
367  if(sizeof(T) == 1)
368   ret = PSX_MemRead8(lts, address);
369  else if(sizeof(T) == 2)
370   ret = PSX_MemRead16(lts, address);
371  else
372  {
373   if(DS24)
374    ret = PSX_MemRead24(lts, address) & 0xFFFFFF;
375   else
376    ret = PSX_MemRead32(lts, address);
377  }
378 
379  if(LWC_timing)
380   lts += 1;
381  else
382   lts += 2;
383 
384  LDAbsorb = (lts - timestamp);
385  timestamp = lts;
386 
387  return(ret);
388 }
389 
390 template<typename T>
WriteMemory(pscpu_timestamp_t & timestamp,uint32 address,uint32 value,bool DS24)391 INLINE void PS_CPU::WriteMemory(pscpu_timestamp_t &timestamp, uint32 address, uint32 value, bool DS24)
392 {
393  if(MDFN_LIKELY(!(CP0.SR & 0x10000)))
394  {
395   address &= addr_mask[address >> 29];
396 
397   if(address >= 0x1F800000 && address <= 0x1F8003FF)
398   {
399    if(DS24)
400     ScratchRAM.WriteU24(address & 0x3FF, value);
401    else
402     ScratchRAM.Write<T>(address & 0x3FF, value);
403 
404    return;
405   }
406 
407   if(sizeof(T) == 1)
408    PSX_MemWrite8(timestamp, address, value);
409   else if(sizeof(T) == 2)
410    PSX_MemWrite16(timestamp, address, value);
411   else
412   {
413    if(DS24)
414     PSX_MemWrite24(timestamp, address, value);
415    else
416     PSX_MemWrite32(timestamp, address, value);
417   }
418  }
419  else
420  {
421   if(BIU & BIU_ENABLE_ICACHE_S1)	// Instruction cache is enabled/active
422   {
423    if(BIU & (BIU_TAG_TEST_MODE | BIU_INVALIDATE_MODE | BIU_LOCK_MODE))
424    {
425     const uint8 valid_bits = (BIU & BIU_TAG_TEST_MODE) ? ((value << ((address & 0x3) * 8)) & 0x0F) : 0x00;
426     __ICache* const ICI = &ICache[((address & 0xFF0) >> 2)];
427 
428     //
429     // Set validity bits and tag.
430     //
431     for(unsigned i = 0; i < 4; i++)
432      ICI[i].TV = ((valid_bits & (1U << i)) ? 0x00 : 0x02) | (address & 0xFFFFFFF0) | (i << 2);
433    }
434    else
435    {
436     ICache[(address & 0xFFC) >> 2].Data = value << ((address & 0x3) * 8);
437    }
438   }
439 
440   if((BIU & 0x081) == 0x080)	// Writes to the scratchpad(TODO test)
441   {
442    if(DS24)
443     ScratchRAM.WriteU24(address & 0x3FF, value);
444    else
445     ScratchRAM.Write<T>(address & 0x3FF, value);
446   }
447   //printf("IsC WRITE%d 0x%08x 0x%08x -- CP0.SR=0x%08x\n", (int)sizeof(T), address, value, CP0.SR);
448  }
449 }
450 
451 //
452 // ICache emulation here is not very accurate.  More accurate emulation had about a 6% performance penalty for simple
453 // code that just looped infinitely, with no tangible known benefit for commercially-released games.
454 //
455 // We do emulate the tag test mode functionality in regards to loading custom tag, valid bits, and instruction word data, as it could
456 // hypothetically be useful for homebrew.  However, due to inaccuracies, it's possible to load a tag for an address in the non-cached
457 // 0xA0000000-0xBFFFFFFF range, jump to the address, and have it execute out of instruction cache, which is wrong and not possible on a PS1.
458 //
459 // The other major inaccuracy here is how the region 0x80000000-0x9FFFFFFF is handled.  On a PS1, when fetching instruction word data
460 // from this region, the upper bit is forced to 0 before the tag compare(though the tag compare IS a full 20 bit compare),
461 // and this address with the upper bit set to 0 is also written to the tag on cache miss.  We don't do the address masking here,
462 // so in addition to the tag test mode implications, a program that jumps from somewhere in 0x00000000-0x1FFFFFFF to the corresponding
463 // location in 0x80000000-0x9FFFFFFF will always cause a cache miss in Mednafen.
464 //
465 // On a PS1, icache miss fill size can be programmed to 2, 4, 8, or 16 words(though 4 words is the nominally-correct setting).  We always emulate the cache
466 // miss fill size as 4-words.  Fill size of 8-words and 16-words are buggy on a PS1, and will write the wrong instruction data values(or read from the wrong
467 // addresses?) to cache when a cache miss occurs on an address that isn't aligned to a 4-word boundary.
468 // Fill size of 2-words seems to work on a PS1, and even behaves as if the line size is 2 words in regards to clearing
469 // the valid bits(when the tag matches, of course), but is obviously not very efficient unless running code that's just endless branching.
470 //
ReadInstruction(pscpu_timestamp_t & timestamp,uint32 address)471 INLINE uint32 PS_CPU::ReadInstruction(pscpu_timestamp_t &timestamp, uint32 address)
472 {
473  uint32 instr;
474 
475  instr = ICache[(address & 0xFFC) >> 2].Data;
476 
477  if(ICache[(address & 0xFFC) >> 2].TV != address)
478  {
479   ReadAbsorb[ReadAbsorbWhich] = 0;
480   ReadAbsorbWhich = 0;
481 
482   if(address >= 0xA0000000 || !(BIU & 0x800))
483   {
484    instr = MDFN_de32lsb<true>((uint8*)(FastMap[address >> FAST_MAP_SHIFT] + address));
485    timestamp += 4;	// Approximate best-case cache-disabled time, per PS1 tests(executing out of 0xA0000000+); it can be 5 in *some* sequences of code(like a lot of sequential "nop"s, probably other simple instructions too).
486   }
487   else
488   {
489    __ICache *ICI = &ICache[((address & 0xFF0) >> 2)];
490    const uint8 *FMP = (uint8*)(FastMap[(address & 0xFFFFFFF0) >> FAST_MAP_SHIFT] + (address & 0xFFFFFFF0));
491 
492    // | 0x2 to simulate (in)validity bits.
493    ICI[0x00].TV = (address & 0xFFFFFFF0) | 0x0 | 0x2;
494    ICI[0x01].TV = (address & 0xFFFFFFF0) | 0x4 | 0x2;
495    ICI[0x02].TV = (address & 0xFFFFFFF0) | 0x8 | 0x2;
496    ICI[0x03].TV = (address & 0xFFFFFFF0) | 0xC | 0x2;
497 
498    timestamp += 3;
499 
500    switch(address & 0xC)
501    {
502     case 0x0:
503 	timestamp++;
504         ICI[0x00].TV &= ~0x2;
505 	ICI[0x00].Data = MDFN_de32lsb<true>(&FMP[0x0]);
506     case 0x4:
507 	timestamp++;
508         ICI[0x01].TV &= ~0x2;
509 	ICI[0x01].Data = MDFN_de32lsb<true>(&FMP[0x4]);
510     case 0x8:
511 	timestamp++;
512         ICI[0x02].TV &= ~0x2;
513 	ICI[0x02].Data = MDFN_de32lsb<true>(&FMP[0x8]);
514     case 0xC:
515 	timestamp++;
516         ICI[0x03].TV &= ~0x2;
517 	ICI[0x03].Data = MDFN_de32lsb<true>(&FMP[0xC]);
518 	break;
519    }
520    instr = ICache[(address & 0xFFC) >> 2].Data;
521   }
522  }
523 
524  return instr;
525 }
526 
Exception(uint32 code,uint32 PC,const uint32 NP,const uint32 instr)527 uint32 NO_INLINE PS_CPU::Exception(uint32 code, uint32 PC, const uint32 NP, const uint32 instr)
528 {
529  uint32 handler = 0x80000080;
530 
531  assert(code < 16);
532 
533  if(code != EXCEPTION_INT && code != EXCEPTION_BP && code != EXCEPTION_SYSCALL)
534  {
535   static const char* exmne[16] =
536   {
537    "INT", "MOD", "TLBL", "TLBS", "ADEL", "ADES", "IBE", "DBE", "SYSCALL", "BP", "RI", "COPU", "OV", NULL, NULL, NULL
538   };
539 
540   PSX_DBG(PSX_DBG_WARNING, "[CPU] Exception %s(0x%02x) @ PC=0x%08x(NP=0x%08x, BDBT=0x%02x), Instr=0x%08x, IPCache=0x%02x, CAUSE=0x%08x, SR=0x%08x, IRQC_Status=0x%04x, IRQC_Mask=0x%04x\n",
541 	exmne[code], code, PC, NP, BDBT, instr, IPCache, CP0.CAUSE, CP0.SR, IRQ_GetRegister(IRQ_GSREG_STATUS, NULL, 0), IRQ_GetRegister(IRQ_GSREG_MASK, NULL, 0));
542  }
543 
544  if(CP0.SR & (1 << 22))	// BEV
545   handler = 0xBFC00180;
546 
547  CP0.EPC = PC;
548  if(BDBT & 2)
549  {
550   CP0.EPC -= 4;
551   CP0.TAR = NP;
552  }
553 
554  if(ADDBT)
555   ADDBT(PC, handler, true);
556 
557  // "Push" IEc and KUc(so that the new IEc and KUc are 0)
558  CP0.SR = (CP0.SR & ~0x3F) | ((CP0.SR << 2) & 0x3F);
559 
560  // Setup cause register
561  CP0.CAUSE &= 0x0000FF00;
562  CP0.CAUSE |= code << 2;
563 
564  CP0.CAUSE |= BDBT << 30;
565  CP0.CAUSE |= (instr << 2) & (0x3 << 28);	// CE
566 
567  //
568  //
569  //
570  RecalcIPCache();
571 
572  BDBT = 0;
573 
574  return(handler);
575 }
576 
577 #define BACKING_TO_ACTIVE			\
578 	PC = BACKED_PC;				\
579 	new_PC = BACKED_new_PC;			\
580 	LDWhich = BACKED_LDWhich;		\
581 	LDValue = BACKED_LDValue;
582 
583 #define ACTIVE_TO_BACKING			\
584 	BACKED_PC = PC;				\
585 	BACKED_new_PC = new_PC;			\
586 	BACKED_LDWhich = LDWhich;		\
587 	BACKED_LDValue = LDValue;
588 
589 //
590 // Should come before DO_LDS() so the EXP_ILL_CHECK() emulator debugging macro in GPR_DEP() will work properly.
591 //
592 #define GPR_DEPRES_BEGIN { uint8 back = ReadAbsorb[0];
593 #define GPR_DEP(n) { unsigned tn = (n); ReadAbsorb[tn] = 0; EXP_ILL_CHECK(if(LDWhich > 0 && LDWhich < 0x20 && LDWhich == tn) { PSX_DBG(PSX_DBG_WARNING, "[CPU] Instruction at PC=0x%08x in load delay slot has dependency on load target register(0x%02x): SR=0x%08x\n", PC, LDWhich, CP0.SR); }) }
594 #define GPR_RES(n) { unsigned tn = (n); ReadAbsorb[tn] = 0; }
595 #define GPR_DEPRES_END ReadAbsorb[0] = back; }
596 
597 template<bool DebugMode, bool BIOSPrintMode, bool ILHMode>
RunReal(pscpu_timestamp_t timestamp_in)598 pscpu_timestamp_t PS_CPU::RunReal(pscpu_timestamp_t timestamp_in)
599 {
600  pscpu_timestamp_t timestamp = timestamp_in;
601 
602  uint32 PC;
603  uint32 new_PC;
604  uint32 LDWhich;
605  uint32 LDValue;
606 
607  //printf("%d %d\n", gte_ts_done, muldiv_ts_done);
608 
609  gte_ts_done += timestamp;
610  muldiv_ts_done += timestamp;
611 
612  BACKING_TO_ACTIVE;
613 
614  do
615  {
616   //printf("Running: %d %d\n", timestamp, next_event_ts);
617   while(MDFN_LIKELY(timestamp < next_event_ts))
618   {
619    uint32 instr;
620    uint32 opf;
621 
622    // Zero must be zero...until the Master Plan is enacted.
623    GPR[0] = 0;
624 
625    if(DebugMode && CPUHook)
626    {
627     ACTIVE_TO_BACKING;
628 
629     // For save states in step mode.
630     gte_ts_done -= timestamp;
631     muldiv_ts_done -= timestamp;
632 
633     CPUHook(timestamp, PC);
634 
635     // For save states in step mode.
636     gte_ts_done += timestamp;
637     muldiv_ts_done += timestamp;
638 
639     BACKING_TO_ACTIVE;
640    }
641 
642    if(BIOSPrintMode)
643    {
644     if(PC == 0xB0)
645     {
646      if(MDFN_UNLIKELY(GPR[9] == 0x3D))
647      {
648       PSX_DBG_BIOS_PUTC(GPR[4]);
649      }
650     }
651    }
652 
653    //
654    // Instruction fetch
655    //
656    if(MDFN_UNLIKELY(PC & 0x3))
657    {
658     // This will block interrupt processing, but since we're going more for keeping broken homebrew/hacks from working
659     // than super-duper-accurate pipeline emulation, it shouldn't be a problem.
660     CP0.BADA = PC;
661     new_PC = Exception(EXCEPTION_ADEL, PC, new_PC, 0);
662     goto OpDone;
663    }
664 
665    instr = ReadInstruction(timestamp, PC);
666 
667 
668    //
669    // Instruction decode
670    //
671    opf = instr & 0x3F;
672 
673    if(instr & (0x3F << 26))
674     opf = 0x40 | (instr >> 26);
675 
676    opf |= IPCache;
677 
678    if(ReadAbsorb[ReadAbsorbWhich])
679     ReadAbsorb[ReadAbsorbWhich]--;
680    else
681     timestamp++;
682 
683    #define DO_LDS() { GPR[LDWhich] = LDValue; ReadAbsorb[LDWhich] = LDAbsorb; ReadFudge = LDWhich; ReadAbsorbWhich |= LDWhich & 0x1F; LDWhich = 0x20; }
684    #define BEGIN_OPF(name) { op_##name:
685    #define END_OPF goto OpDone; }
686 
687    #define DO_BRANCH(arg_cond, arg_offset, arg_mask, arg_dolink, arg_linkreg)\
688 	{							\
689 	 const bool cond = (arg_cond);				\
690 	 const uint32 offset = (arg_offset);			\
691 	 const uint32 mask = (arg_mask);			\
692 	 const uint32 old_PC = PC;				\
693 								\
694 	 EXP_ILL_CHECK(if(BDBT) { PSX_DBG(PSX_DBG_WARNING, "[CPU] Branch instruction at PC=0x%08x in branch delay slot: SR=0x%08x\n", PC, CP0.SR);}) 	\
695 								\
696 	 PC = new_PC;						\
697 	 new_PC += 4;						\
698 	 BDBT = 2;						\
699 								\
700 	 if(arg_dolink)						\
701 	  GPR[(arg_linkreg)] = new_PC;				\
702 								\
703 	 if(cond)						\
704 	 {							\
705 	  if(ILHMode)						\
706 	  {							\
707 	   if(old_PC == (((new_PC - 4) & mask) + offset))	\
708 	   {							\
709 	    if(MDFN_densb<uint32, true>((uint8*)(FastMap[PC >> FAST_MAP_SHIFT] + PC)) == 0)	\
710 	    {							\
711 	     if(next_event_ts > timestamp) /* Necessary since next_event_ts might be set to something like "0" to force a call to the event handler. */		\
712 	     {							\
713 	      timestamp = next_event_ts;			\
714 	     }							\
715 	    }							\
716 	   }							\
717 	  }							\
718 								\
719 	  new_PC = ((new_PC - 4) & mask) + offset;		\
720 	  BDBT = 3;						\
721 								\
722           if(DebugMode && ADDBT)                 		\
723 	  {							\
724            ADDBT(PC, new_PC, false);				\
725 	  }							\
726 	 }							\
727 								\
728 	 goto SkipNPCStuff;					\
729 	}
730 
731    #define ITYPE uint32 rs MDFN_NOWARN_UNUSED = (instr >> 21) & 0x1F; uint32 rt MDFN_NOWARN_UNUSED = (instr >> 16) & 0x1F; uint32 immediate = (int32)(int16)(instr & 0xFFFF); /*printf(" rs=%02x(%08x), rt=%02x(%08x), immediate=(%08x) ", rs, GPR[rs], rt, GPR[rt], immediate);*/
732    #define ITYPE_ZE uint32 rs MDFN_NOWARN_UNUSED = (instr >> 21) & 0x1F; uint32 rt MDFN_NOWARN_UNUSED = (instr >> 16) & 0x1F; uint32 immediate = instr & 0xFFFF; /*printf(" rs=%02x(%08x), rt=%02x(%08x), immediate=(%08x) ", rs, GPR[rs], rt, GPR[rt], immediate);*/
733    #define JTYPE uint32 target = instr & ((1 << 26) - 1); /*printf(" target=(%08x) ", target);*/
734    #define RTYPE uint32 rs MDFN_NOWARN_UNUSED = (instr >> 21) & 0x1F; uint32 rt MDFN_NOWARN_UNUSED = (instr >> 16) & 0x1F; uint32 rd MDFN_NOWARN_UNUSED = (instr >> 11) & 0x1F; uint32 shamt MDFN_NOWARN_UNUSED = (instr >> 6) & 0x1F; /*printf(" rs=%02x(%08x), rt=%02x(%08x), rd=%02x(%08x) ", rs, GPR[rs], rt, GPR[rt], rd, GPR[rd]);*/
735 
736 #if HAVE_COMPUTED_GOTO
737    #if 0
738 	//
739 	// These truncated 32-bit table values apparently can't be calculated at compile/link time by gcc on x86_64, so gcc inserts initialization code, but
740 	// the compare for the initialization code path is placed sub-optimally(near where the table value is used instead of at the beginning of the function).
741 	//
742 	#define CGBEGIN static const uint32 const op_goto_table[256] = {
743 	#define CGE(l) (uint32)(uintptr_t)&&l,
744 	#define CGEND }; goto *(void*)(uintptr_t)op_goto_table[opf];
745    #else
746 	#define CGBEGIN static const void *const op_goto_table[256] = {
747 	#define CGE(l) &&l,
748 	#define CGEND }; goto *op_goto_table[opf];
749    #endif
750 #else
751    /* (uint8) cast for cheaper alternative to generated branch+compare bounds check instructions, but still more
752       expensive than computed goto which needs no masking nor bounds checking.
753    */
754    #define CGBEGIN { enum { CGESB = 1 + __COUNTER__ }; switch((uint8)opf) {
755    #define CGE(l) case __COUNTER__ - CGESB: goto l;
756    #define CGEND } }
757 #endif
758 
759    CGBEGIN
760     CGE(op_SLL)  CGE(op_ILL)   CGE(op_SRL)  CGE(op_SRA)   CGE(op_SLLV)    CGE(op_ILL)   CGE(op_SRLV) CGE(op_SRAV)
761     CGE(op_JR)   CGE(op_JALR)  CGE(op_ILL)  CGE(op_ILL)   CGE(op_SYSCALL) CGE(op_BREAK) CGE(op_ILL)  CGE(op_ILL)
762     CGE(op_MFHI) CGE(op_MTHI)  CGE(op_MFLO) CGE(op_MTLO)  CGE(op_ILL)     CGE(op_ILL)   CGE(op_ILL)  CGE(op_ILL)
763     CGE(op_MULT) CGE(op_MULTU) CGE(op_DIV)  CGE(op_DIVU)  CGE(op_ILL)     CGE(op_ILL)   CGE(op_ILL)  CGE(op_ILL)
764     CGE(op_ADD)  CGE(op_ADDU)  CGE(op_SUB)  CGE(op_SUBU)  CGE(op_AND)     CGE(op_OR)    CGE(op_XOR)  CGE(op_NOR)
765     CGE(op_ILL)  CGE(op_ILL)   CGE(op_SLT)  CGE(op_SLTU)  CGE(op_ILL)     CGE(op_ILL)   CGE(op_ILL)  CGE(op_ILL)
766     CGE(op_ILL)  CGE(op_ILL)   CGE(op_ILL)  CGE(op_ILL)   CGE(op_ILL)     CGE(op_ILL)   CGE(op_ILL)  CGE(op_ILL)
767     CGE(op_ILL)  CGE(op_ILL)   CGE(op_ILL)  CGE(op_ILL)   CGE(op_ILL)     CGE(op_ILL)   CGE(op_ILL)  CGE(op_ILL)
768 
769     CGE(op_ILL)  CGE(op_BCOND) CGE(op_J)    CGE(op_JAL)   CGE(op_BEQ)  CGE(op_BNE) CGE(op_BLEZ) CGE(op_BGTZ)
770     CGE(op_ADDI) CGE(op_ADDIU) CGE(op_SLTI) CGE(op_SLTIU) CGE(op_ANDI) CGE(op_ORI) CGE(op_XORI) CGE(op_LUI)
771     CGE(op_COP0) CGE(op_COP13) CGE(op_COP2) CGE(op_COP13) CGE(op_ILL)  CGE(op_ILL) CGE(op_ILL)  CGE(op_ILL)
772     CGE(op_ILL)  CGE(op_ILL)   CGE(op_ILL)  CGE(op_ILL)   CGE(op_ILL)  CGE(op_ILL) CGE(op_ILL)  CGE(op_ILL)
773     CGE(op_LB)   CGE(op_LH)    CGE(op_LWL)  CGE(op_LW)    CGE(op_LBU)  CGE(op_LHU) CGE(op_LWR)  CGE(op_ILL)
774     CGE(op_SB)   CGE(op_SH)    CGE(op_SWL)  CGE(op_SW)    CGE(op_ILL)  CGE(op_ILL) CGE(op_SWR)  CGE(op_ILL)
775     CGE(op_LWC013) CGE(op_LWC013)  CGE(op_LWC2) CGE(op_LWC013)  CGE(op_ILL)  CGE(op_ILL) CGE(op_ILL)  CGE(op_ILL)
776     CGE(op_SWC013) CGE(op_SWC013)  CGE(op_SWC2) CGE(op_SWC013)  CGE(op_ILL)  CGE(op_ILL) CGE(op_ILL)  CGE(op_ILL)
777 
778     // Interrupt portion of this table is constructed so that an interrupt won't be taken when the PC is pointing to a GTE instruction,
779     // to avoid problems caused by pipeline vs coprocessor nuances that aren't emulated.
780     CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT)
781     CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT)
782     CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT)
783     CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT)
784     CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT)
785     CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT)
786     CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT)
787     CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT)
788 
789     CGE(op_ILL)       CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT)
790     CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT)
791     CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_COP2)      CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT)
792     CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT)
793     CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT)
794     CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT)
795     CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT)
796     CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT) CGE(op_INTERRUPT)
797    CGEND
798 
799    {
800     BEGIN_OPF(ILL);
801 	     DO_LDS();
802 	     new_PC = Exception(EXCEPTION_RI, PC, new_PC, instr);
803     END_OPF;
804 
805     //
806     // ADD - Add Word
807     //
808     BEGIN_OPF(ADD);
809 	RTYPE;
810 
811 	GPR_DEPRES_BEGIN
812 	GPR_DEP(rs);
813 	GPR_DEP(rt);
814  	GPR_RES(rd);
815 	GPR_DEPRES_END
816 
817 	uint32 result = GPR[rs] + GPR[rt];
818 	bool ep = ((~(GPR[rs] ^ GPR[rt])) & (GPR[rs] ^ result)) & 0x80000000;
819 
820 	DO_LDS();
821 
822 	if(MDFN_UNLIKELY(ep))
823 	{
824 	 new_PC = Exception(EXCEPTION_OV, PC, new_PC, instr);
825 	}
826 	else
827 	 GPR[rd] = result;
828 
829     END_OPF;
830 
831     //
832     // ADDI - Add Immediate Word
833     //
834     BEGIN_OPF(ADDI);
835 	ITYPE;
836 
837 	GPR_DEPRES_BEGIN
838 	GPR_DEP(rs);
839 	GPR_RES(rt);
840 	GPR_DEPRES_END
841 
842         uint32 result = GPR[rs] + immediate;
843 	bool ep = ((~(GPR[rs] ^ immediate)) & (GPR[rs] ^ result)) & 0x80000000;
844 
845 	DO_LDS();
846 
847         if(MDFN_UNLIKELY(ep))
848 	{
849 	 new_PC = Exception(EXCEPTION_OV, PC, new_PC, instr);
850 	}
851         else
852          GPR[rt] = result;
853 
854     END_OPF;
855 
856     //
857     // ADDIU - Add Immediate Unsigned Word
858     //
859     BEGIN_OPF(ADDIU);
860 	ITYPE;
861 
862 	GPR_DEPRES_BEGIN
863 	GPR_DEP(rs);
864 	GPR_RES(rt);
865 	GPR_DEPRES_END
866 
867 	uint32 result = GPR[rs] + immediate;
868 
869 	DO_LDS();
870 
871 	GPR[rt] = result;
872 
873     END_OPF;
874 
875     //
876     // ADDU - Add Unsigned Word
877     //
878     BEGIN_OPF(ADDU);
879 	RTYPE;
880 
881 	GPR_DEPRES_BEGIN
882 	GPR_DEP(rs);
883 	GPR_DEP(rt);
884  	GPR_RES(rd);
885 	GPR_DEPRES_END
886 
887 	uint32 result = GPR[rs] + GPR[rt];
888 
889 	DO_LDS();
890 
891 	GPR[rd] = result;
892 
893     END_OPF;
894 
895     //
896     // AND - And
897     //
898     BEGIN_OPF(AND);
899 	RTYPE;
900 
901 	GPR_DEPRES_BEGIN
902 	GPR_DEP(rs);
903 	GPR_DEP(rt);
904  	GPR_RES(rd);
905 	GPR_DEPRES_END
906 
907 	uint32 result = GPR[rs] & GPR[rt];
908 
909 	DO_LDS();
910 
911 	GPR[rd] = result;
912 
913     END_OPF;
914 
915     //
916     // ANDI - And Immediate
917     //
918     BEGIN_OPF(ANDI);
919 	ITYPE_ZE;
920 
921 	GPR_DEPRES_BEGIN
922 	GPR_DEP(rs);
923 	GPR_RES(rt);
924 	GPR_DEPRES_END
925 
926 	uint32 result = GPR[rs] & immediate;
927 
928 	DO_LDS();
929 
930 	GPR[rt] = result;
931 
932     END_OPF;
933 
934     //
935     // BEQ - Branch on Equal
936     //
937     BEGIN_OPF(BEQ);
938 	ITYPE;
939 
940 	GPR_DEPRES_BEGIN
941 	GPR_DEP(rs);
942 	GPR_DEP(rt);
943 	GPR_DEPRES_END
944 
945 	const bool result = (GPR[rs] == GPR[rt]);
946 
947 	DO_LDS();
948 
949 	DO_BRANCH(result, (immediate << 2), ~0U, false, 0);
950     END_OPF;
951 
952     // Bah, why does MIPS encoding have to be funky like this. :(
953     // Handles BGEZ, BGEZAL, BLTZ, BLTZAL
954     BEGIN_OPF(BCOND);
955 	const uint32 tv = GPR[(instr >> 21) & 0x1F];
956 	const uint32 riv = (instr >> 16) & 0x1F;
957 	const uint32 immediate = (int32)(int16)(instr & 0xFFFF);
958 	const bool result = (int32)(tv ^ (riv << 31)) < 0;
959 	const uint32 link = ((riv & 0x1E) == 0x10) ? 31 : 0;
960 
961 	GPR_DEPRES_BEGIN
962 	GPR_DEP((instr >> 21) & 0x1F);
963 	GPR_RES(link);
964 	GPR_DEPRES_END
965 
966 	DO_LDS();
967 
968 	DO_BRANCH(result, (immediate << 2), ~0U, true, link);
969     END_OPF;
970 
971 
972     //
973     // BGTZ - Branch on Greater than Zero
974     //
975     BEGIN_OPF(BGTZ);
976 	ITYPE;
977 
978 	GPR_DEPRES_BEGIN
979 	GPR_DEP(rs);
980 	GPR_DEPRES_END
981 
982 	const bool result = (int32)GPR[rs] > 0;
983 
984 	DO_LDS();
985 
986 	DO_BRANCH(result, (immediate << 2), ~0U, false, 0);
987     END_OPF;
988 
989     //
990     // BLEZ - Branch on Less Than or Equal to Zero
991     //
992     BEGIN_OPF(BLEZ);
993 	ITYPE;
994 
995 	GPR_DEPRES_BEGIN
996 	GPR_DEP(rs);
997 	GPR_DEPRES_END
998 
999 	const bool result = (int32)GPR[rs] <= 0;
1000 
1001 	DO_LDS();
1002 
1003 	DO_BRANCH(result, (immediate << 2), ~0U, false, 0);
1004     END_OPF;
1005 
1006     //
1007     // BNE - Branch on Not Equal
1008     //
1009     BEGIN_OPF(BNE);
1010 	ITYPE;
1011 
1012 	GPR_DEPRES_BEGIN
1013 	GPR_DEP(rs);
1014 	GPR_DEP(rt);
1015 	GPR_DEPRES_END
1016 
1017 	const bool result = GPR[rs] != GPR[rt];
1018 
1019 	DO_LDS();
1020 
1021 	DO_BRANCH(result, (immediate << 2), ~0U, false, 0);
1022     END_OPF;
1023 
1024     //
1025     // BREAK - Breakpoint
1026     //
1027     BEGIN_OPF(BREAK);
1028 	DO_LDS();
1029 	new_PC = Exception(EXCEPTION_BP, PC, new_PC, instr);
1030     END_OPF;
1031 
1032     // Cop "instructions":	CFCz(no CP0), COPz, CTCz(no CP0), LWCz(no CP0), MFCz, MTCz, SWCz(no CP0)
1033     //
1034     // COP0 instructions
1035     //
1036     BEGIN_OPF(COP0);
1037 	const uint32 sub_op = (instr >> 21) & 0x1F;
1038 	const uint32 rt = (instr >> 16) & 0x1F;
1039 	const uint32 rd = (instr >> 11) & 0x1F;
1040 	const uint32 val = GPR[rt];
1041 
1042 	switch(sub_op)
1043 	{
1044 	 default:
1045 		DO_LDS();
1046 		break;
1047 
1048 	 case 0x02:
1049 	 case 0x06:
1050 		DO_LDS();
1051 		new_PC = Exception(EXCEPTION_RI, PC, new_PC, instr);
1052 		break;
1053 
1054 	 case 0x00:		// MFC0	- Move from Coprocessor
1055 		switch(rd)
1056 		{
1057 		 case 0x00:
1058 		 case 0x01:
1059 		 case 0x02:
1060 		 case 0x04:
1061 		 case 0x0A:
1062 			DO_LDS();
1063 		  	new_PC = Exception(EXCEPTION_RI, PC, new_PC, instr);
1064 			break;
1065 
1066 		 case 0x03:
1067 		 case 0x05:
1068 		 case 0x06:
1069 		 case 0x07:
1070 		 case 0x08:
1071 		 case 0x09:
1072 		 case 0x0B:
1073 		 case 0x0C:
1074 		 case 0x0D:
1075 		 case 0x0E:
1076 		 case 0x0F:
1077 			if(MDFN_UNLIKELY(LDWhich == rt))
1078 		 	 LDWhich = 0;
1079 
1080 			DO_LDS();
1081 
1082 			LDAbsorb = 0;
1083 			LDWhich = rt;
1084 			LDValue = CP0.Regs[rd];
1085 			break;
1086 
1087 		 default:
1088 			// Tested to be rather NOPish
1089 			DO_LDS();
1090 			PSX_DBG(PSX_DBG_WARNING, "[CPU] MFC0 from unmapped CP0 register %u.\n", rd);
1091 			break;
1092 		}
1093 		break;
1094 
1095 	 case 0x04:		// MTC0	- Move to Coprocessor
1096 		DO_LDS();
1097 		switch(rd)
1098 		{
1099 		 case 0x00:
1100 		 case 0x01:
1101 		 case 0x02:
1102 		 case 0x04:
1103 		 case 0x0A:
1104 			new_PC = Exception(EXCEPTION_RI, PC, new_PC, instr);
1105 			break;
1106 
1107 		 case CP0REG_BPC:
1108 			CP0.BPC = val;
1109 			break;
1110 
1111 		 case CP0REG_BDA:
1112 			CP0.BDA = val;
1113 			break;
1114 
1115 		 case CP0REG_DCIC:
1116 			if(val)
1117 			{
1118 			 PSX_DBG(PSX_DBG_WARNING, "[CPU] Non-zero write to DCIC: 0x%08x\n", val);
1119 			}
1120 			CP0.DCIC = val & 0xFF80003F;
1121 			break;
1122 
1123   		 case CP0REG_BDAM:
1124 			CP0.BDAM = val;
1125 			break;
1126 
1127   		 case CP0REG_BPCM:
1128 			CP0.BPCM = val;
1129 			break;
1130 
1131 		 case CP0REG_CAUSE:
1132 			CP0.CAUSE &= ~(0x3 << 8);
1133 			CP0.CAUSE |= val & (0x3 << 8);
1134 			RecalcIPCache();
1135 			break;
1136 
1137 		 case CP0REG_SR:
1138 			CP0.SR = val & ~( (0x3 << 26) | (0x3 << 23) | (0x3 << 6));
1139 			RecalcIPCache();
1140 			break;
1141 		}
1142 		break;
1143 
1144 	 case 0x08:	// BC
1145 	 case 0x0C:
1146 		DO_LDS();
1147 		{
1148 		 const uint32 immediate = (int32)(int16)(instr & 0xFFFF);
1149 		 const bool result = (false == (bool)(instr & (1U << 16)));
1150 
1151 		 PSX_DBG(PSX_DBG_WARNING, "[CPU] BC0x instruction(0x%08x) @ PC=0x%08x\n", instr, PC);
1152 
1153 		 DO_BRANCH(result, (immediate << 2), ~0U, false, 0);
1154 		}
1155 		break;
1156 
1157 	 case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
1158 	 case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F:
1159 		DO_LDS();
1160 		{
1161 		 const uint32 cp0_op = instr & 0x1F;	// Not 0x3F
1162 
1163 		 if(MDFN_LIKELY(cp0_op == 0x10))	// RFE
1164 		 {
1165 		  // "Pop"
1166 		  CP0.SR = (CP0.SR & ~0x0F) | ((CP0.SR >> 2) & 0x0F);
1167 		  RecalcIPCache();
1168 		 }
1169 		 else if(cp0_op == 0x01 || cp0_op == 0x02 || cp0_op == 0x06 || cp0_op == 0x08)	// TLBR, TLBWI, TLBWR, TLBP
1170 		 {
1171 		  new_PC = Exception(EXCEPTION_RI, PC, new_PC, instr);
1172 		 }
1173 		}
1174 		break;
1175 	}
1176     END_OPF;
1177 
1178     //
1179     // COP2
1180     //
1181     BEGIN_OPF(COP2);
1182 	const uint32 sub_op = (instr >> 21) & 0x1F;
1183 	const uint32 rt = (instr >> 16) & 0x1F;
1184 	const uint32 rd = (instr >> 11) & 0x1F;
1185 	const uint32 val = GPR[rt];
1186 
1187 	if(MDFN_UNLIKELY(!(CP0.SR & (1U << (28 + 2)))))
1188 	{
1189 	 DO_LDS();
1190          new_PC = Exception(EXCEPTION_COPU, PC, new_PC, instr);
1191 	}
1192 	else switch(sub_op)
1193 	{
1194 	 default:
1195 		DO_LDS();
1196 		break;
1197 
1198 	 case 0x00:		// MFC2	- Move from Coprocessor
1199 		if(MDFN_UNLIKELY(LDWhich == rt))
1200 		 LDWhich = 0;
1201 
1202 		DO_LDS();
1203 
1204 	        if(timestamp < gte_ts_done)
1205 		{
1206 		 LDAbsorb = gte_ts_done - timestamp;
1207 	         timestamp = gte_ts_done;
1208 		}
1209 		else
1210 		 LDAbsorb = 0;
1211 
1212 		LDWhich = rt;
1213 		LDValue = GTE_ReadDR(rd);
1214 		break;
1215 
1216 	 case 0x04:		// MTC2	- Move to Coprocessor
1217 		DO_LDS();
1218 
1219 	        if(timestamp < gte_ts_done)
1220 	         timestamp = gte_ts_done;
1221 
1222 		GTE_WriteDR(rd, val);
1223 		break;
1224 
1225 	 case 0x02:		// CFC2
1226 		if(MDFN_UNLIKELY(LDWhich == rt))
1227 		 LDWhich = 0;
1228 
1229 		DO_LDS();
1230 
1231 	        if(timestamp < gte_ts_done)
1232 		{
1233 		 LDAbsorb = gte_ts_done - timestamp;
1234 	         timestamp = gte_ts_done;
1235 		}
1236 		else
1237 		 LDAbsorb = 0;
1238 
1239 		LDWhich = rt;
1240 		LDValue = GTE_ReadCR(rd);
1241 		break;
1242 
1243 	 case 0x06:		// CTC2
1244 		DO_LDS();
1245 
1246  	        if(timestamp < gte_ts_done)
1247 	         timestamp = gte_ts_done;
1248 
1249 		GTE_WriteCR(rd, val);
1250 		break;
1251 
1252 	 case 0x08:
1253 	 case 0x0C:
1254 		DO_LDS();
1255 		{
1256 		 const uint32 immediate = (int32)(int16)(instr & 0xFFFF);
1257 		 const bool result = (false == (bool)(instr & (1U << 16)));
1258 
1259 		 PSX_DBG(PSX_DBG_WARNING, "[CPU] BC2x instruction(0x%08x) @ PC=0x%08x\n", instr, PC);
1260 
1261 		 DO_BRANCH(result, (immediate << 2), ~0U, false, 0);
1262 		}
1263 		break;
1264 
1265 	 case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
1266 	 case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F:
1267 		DO_LDS();
1268 
1269 	        if(timestamp < gte_ts_done)
1270 	         timestamp = gte_ts_done;
1271 		gte_ts_done = timestamp + GTE_Instruction(instr);
1272 		break;
1273 	}
1274     END_OPF;
1275 
1276     //
1277     // COP1, COP3
1278     //
1279     BEGIN_OPF(COP13);
1280 	DO_LDS();
1281 
1282 	if(!(CP0.SR & (1U << (28 + ((instr >> 26) & 0x3)))))
1283 	{
1284          new_PC = Exception(EXCEPTION_COPU, PC, new_PC, instr);
1285 	}
1286 	else
1287 	{
1288 	 const uint32 sub_op = (instr >> 21) & 0x1F;
1289 
1290 	 PSX_DBG(PSX_DBG_WARNING, "[CPU] COP%u instruction(0x%08x) @ PC=0x%08x\n", (instr >> 26) & 0x3, instr, PC);
1291 
1292 	 if(sub_op == 0x08 || sub_op == 0x0C)
1293 	 {
1294 	  const uint32 immediate = (int32)(int16)(instr & 0xFFFF);
1295 	  const bool result = (false == (bool)(instr & (1U << 16)));
1296 
1297 	  DO_BRANCH(result, (immediate << 2), ~0U, false, 0);
1298 	 }
1299 	}
1300     END_OPF;
1301 
1302     //
1303     // LWC0, LWC1, LWC3
1304     //
1305     BEGIN_OPF(LWC013);
1306         ITYPE;
1307 	const uint32 address = GPR[rs] + immediate;
1308 
1309 	DO_LDS();
1310 
1311 	if(!(CP0.SR & (1U << (28 + ((instr >> 26) & 0x3)))))
1312 	{
1313          new_PC = Exception(EXCEPTION_COPU, PC, new_PC, instr);
1314 	}
1315 	else
1316 	{
1317 	 if(MDFN_UNLIKELY(address & 3))
1318 	 {
1319 	  CP0.BADA = address;
1320           new_PC = Exception(EXCEPTION_ADEL, PC, new_PC, instr);
1321 	 }
1322          else
1323 	 {
1324 	  PSX_DBG(PSX_DBG_WARNING, "[CPU] LWC%u instruction(0x%08x) @ PC=0x%08x\n", (instr >> 26) & 0x3, instr, PC);
1325 
1326           ReadMemory<uint32>(timestamp, address, false, true);
1327 	 }
1328 	}
1329     END_OPF;
1330 
1331     //
1332     // LWC2
1333     //
1334     BEGIN_OPF(LWC2);
1335         ITYPE;
1336 	const uint32 address = GPR[rs] + immediate;
1337 
1338 	DO_LDS();
1339 
1340         if(MDFN_UNLIKELY(address & 3))
1341 	{
1342 	 CP0.BADA = address;
1343          new_PC = Exception(EXCEPTION_ADEL, PC, new_PC, instr);
1344 	}
1345         else
1346 	{
1347          if(timestamp < gte_ts_done)
1348           timestamp = gte_ts_done;
1349 
1350          GTE_WriteDR(rt, ReadMemory<uint32>(timestamp, address, false, true));
1351 	}
1352 	// GTE stuff here
1353     END_OPF;
1354 
1355     //
1356     // SWC0, SWC1, SCW3
1357     //
1358     BEGIN_OPF(SWC013);
1359         ITYPE;
1360 	const uint32 address = GPR[rs] + immediate;
1361 
1362 	DO_LDS();
1363 
1364 	if(!(CP0.SR & (1U << (28 + ((instr >> 26) & 0x3)))))
1365 	{
1366          new_PC = Exception(EXCEPTION_COPU, PC, new_PC, instr);
1367 	}
1368 	else
1369 	{
1370 	 if(MDFN_UNLIKELY(address & 0x3))
1371 	 {
1372 	  CP0.BADA = address;
1373 	  new_PC = Exception(EXCEPTION_ADES, PC, new_PC, instr);
1374 	 }
1375 	 else
1376 	 {
1377 	  PSX_DBG(PSX_DBG_WARNING, "[CPU] SWC%u instruction(0x%08x) @ PC=0x%08x\n", (instr >> 26) & 0x3, instr, PC);
1378 	  //WriteMemory<uint32>(timestamp, address, SOMETHING);
1379 	 }
1380 	}
1381     END_OPF;
1382 
1383     //
1384     // SWC2
1385     //
1386     BEGIN_OPF(SWC2);
1387         ITYPE;
1388 	const uint32 address = GPR[rs] + immediate;
1389 
1390 	if(MDFN_UNLIKELY(address & 0x3))
1391 	{
1392 	 CP0.BADA = address;
1393 	 new_PC = Exception(EXCEPTION_ADES, PC, new_PC, instr);
1394 	}
1395 	else
1396 	{
1397          if(timestamp < gte_ts_done)
1398           timestamp = gte_ts_done;
1399 
1400 	 WriteMemory<uint32>(timestamp, address, GTE_ReadDR(rt));
1401 	}
1402 	DO_LDS();
1403     END_OPF;
1404 
1405     //
1406     // DIV - Divide Word
1407     //
1408     BEGIN_OPF(DIV);
1409 	RTYPE;
1410 
1411 	GPR_DEPRES_BEGIN
1412 	GPR_DEP(rs);
1413 	GPR_DEP(rt);
1414 	GPR_DEPRES_END
1415 
1416         if(!GPR[rt])
1417         {
1418 	 if(GPR[rs] & 0x80000000)
1419 	  LO = 1;
1420 	 else
1421 	  LO = 0xFFFFFFFF;
1422 
1423 	 HI = GPR[rs];
1424         }
1425 	else if(GPR[rs] == 0x80000000 && GPR[rt] == 0xFFFFFFFF)
1426 	{
1427 	 LO = 0x80000000;
1428 	 HI = 0;
1429 	}
1430         else
1431         {
1432          LO = (int32)GPR[rs] / (int32)GPR[rt];
1433          HI = (int32)GPR[rs] % (int32)GPR[rt];
1434         }
1435 	muldiv_ts_done = timestamp + 37;
1436 
1437 	DO_LDS();
1438 
1439     END_OPF;
1440 
1441 
1442     //
1443     // DIVU - Divide Unsigned Word
1444     //
1445     BEGIN_OPF(DIVU);
1446 	RTYPE;
1447 
1448 	GPR_DEPRES_BEGIN
1449 	GPR_DEP(rs);
1450 	GPR_DEP(rt);
1451 	GPR_DEPRES_END
1452 
1453 	if(!GPR[rt])
1454 	{
1455 	 LO = 0xFFFFFFFF;
1456 	 HI = GPR[rs];
1457 	}
1458 	else
1459 	{
1460 	 LO = GPR[rs] / GPR[rt];
1461 	 HI = GPR[rs] % GPR[rt];
1462 	}
1463  	muldiv_ts_done = timestamp + 37;
1464 
1465 	DO_LDS();
1466     END_OPF;
1467 
1468     //
1469     // J - Jump
1470     //
1471     BEGIN_OPF(J);
1472 	JTYPE;
1473 
1474 	DO_LDS();
1475 
1476 	DO_BRANCH(true, target << 2, 0xF0000000, false, 0);
1477     END_OPF;
1478 
1479     //
1480     // JAL - Jump and Link
1481     //
1482     BEGIN_OPF(JAL);
1483 	JTYPE;
1484 
1485 	//GPR_DEPRES_BEGIN
1486 	GPR_RES(31);
1487 	//GPR_DEPRES_END
1488 
1489 	DO_LDS();
1490 
1491 	DO_BRANCH(true, target << 2, 0xF0000000, true, 31);
1492     END_OPF;
1493 
1494     //
1495     // JALR - Jump and Link Register
1496     //
1497     BEGIN_OPF(JALR);
1498 	RTYPE;
1499 
1500 	GPR_DEPRES_BEGIN
1501 	GPR_DEP(rs);
1502  	GPR_RES(rd);
1503 	GPR_DEPRES_END
1504 
1505 	uint32 tmp = GPR[rs];
1506 
1507 	DO_LDS();
1508 
1509 	DO_BRANCH(true, tmp, 0, true, rd);
1510     END_OPF;
1511 
1512     //
1513     // JR - Jump Register
1514     //
1515     BEGIN_OPF(JR);
1516 	RTYPE;
1517 
1518 	GPR_DEPRES_BEGIN
1519 	GPR_DEP(rs);
1520  	GPR_RES(rd);
1521 	GPR_DEPRES_END
1522 
1523 	uint32 bt = GPR[rs];
1524 
1525 	DO_LDS();
1526 
1527 	DO_BRANCH(true, bt, 0, false, 0);
1528     END_OPF;
1529 
1530     //
1531     // LUI - Load Upper Immediate
1532     //
1533     BEGIN_OPF(LUI);
1534 	ITYPE_ZE;		// Actually, probably would be sign-extending...if we were emulating a 64-bit MIPS chip :b
1535 
1536 	GPR_DEPRES_BEGIN
1537 	GPR_RES(rt);
1538 	GPR_DEPRES_END
1539 
1540 	DO_LDS();
1541 
1542 	GPR[rt] = immediate << 16;
1543 
1544     END_OPF;
1545 
1546     //
1547     // MFHI - Move from HI
1548     //
1549     BEGIN_OPF(MFHI);
1550 	RTYPE;
1551 
1552 	GPR_DEPRES_BEGIN
1553  	GPR_RES(rd);
1554 	GPR_DEPRES_END
1555 
1556 	DO_LDS();
1557 
1558 	if(timestamp < muldiv_ts_done)
1559 	{
1560 	 if(timestamp == muldiv_ts_done - 1)
1561 	  muldiv_ts_done--;
1562 	 else
1563 	 {
1564 	  do
1565 	  {
1566 	   if(ReadAbsorb[ReadAbsorbWhich])
1567 	    ReadAbsorb[ReadAbsorbWhich]--;
1568 	   timestamp++;
1569 	  } while(timestamp < muldiv_ts_done);
1570 	 }
1571 	}
1572 
1573 	GPR[rd] = HI;
1574 
1575     END_OPF;
1576 
1577 
1578     //
1579     // MFLO - Move from LO
1580     //
1581     BEGIN_OPF(MFLO);
1582 	RTYPE;
1583 
1584 	GPR_DEPRES_BEGIN
1585  	GPR_RES(rd);
1586 	GPR_DEPRES_END
1587 
1588 	DO_LDS();
1589 
1590 	if(timestamp < muldiv_ts_done)
1591 	{
1592 	 if(timestamp == muldiv_ts_done - 1)
1593 	  muldiv_ts_done--;
1594 	 else
1595 	 {
1596 	  do
1597 	  {
1598 	   if(ReadAbsorb[ReadAbsorbWhich])
1599 	    ReadAbsorb[ReadAbsorbWhich]--;
1600 	   timestamp++;
1601 	  } while(timestamp < muldiv_ts_done);
1602 	 }
1603 	}
1604 
1605 	GPR[rd] = LO;
1606 
1607     END_OPF;
1608 
1609 
1610     //
1611     // MTHI - Move to HI
1612     //
1613     BEGIN_OPF(MTHI);
1614 	RTYPE;
1615 
1616 	GPR_DEPRES_BEGIN
1617 	GPR_DEP(rs);
1618 	GPR_DEPRES_END
1619 
1620 	HI = GPR[rs];
1621 
1622 	DO_LDS();
1623 
1624     END_OPF;
1625 
1626     //
1627     // MTLO - Move to LO
1628     //
1629     BEGIN_OPF(MTLO);
1630 	RTYPE;
1631 
1632 	GPR_DEPRES_BEGIN
1633 	GPR_DEP(rs);
1634 	GPR_DEPRES_END
1635 
1636 	LO = GPR[rs];
1637 
1638 	DO_LDS();
1639 
1640     END_OPF;
1641 
1642 
1643     //
1644     // MULT - Multiply Word
1645     //
1646     BEGIN_OPF(MULT);
1647 	RTYPE;
1648 
1649 	GPR_DEPRES_BEGIN
1650 	GPR_DEP(rs);
1651 	GPR_DEP(rt);
1652 	GPR_DEPRES_END
1653 
1654 	uint64 result;
1655 
1656 	result = (int64)(int32)GPR[rs] * (int32)GPR[rt];
1657 	muldiv_ts_done = timestamp + MULT_Tab24[MDFN_lzcount32((GPR[rs] ^ ((int32)GPR[rs] >> 31)) | 0x400)];
1658 	DO_LDS();
1659 
1660 	LO = result;
1661 	HI = result >> 32;
1662 
1663     END_OPF;
1664 
1665     //
1666     // MULTU - Multiply Unsigned Word
1667     //
1668     BEGIN_OPF(MULTU);
1669 	RTYPE;
1670 
1671 	GPR_DEPRES_BEGIN
1672 	GPR_DEP(rs);
1673 	GPR_DEP(rt);
1674 	GPR_DEPRES_END
1675 
1676 	uint64 result;
1677 
1678 	result = (uint64)GPR[rs] * GPR[rt];
1679 	muldiv_ts_done = timestamp + MULT_Tab24[MDFN_lzcount32(GPR[rs] | 0x400)];
1680 	DO_LDS();
1681 
1682 	LO = result;
1683 	HI = result >> 32;
1684 
1685     END_OPF;
1686 
1687 
1688     //
1689     // NOR - NOR
1690     //
1691     BEGIN_OPF(NOR);
1692 	RTYPE;
1693 
1694 	GPR_DEPRES_BEGIN
1695 	GPR_DEP(rs);
1696 	GPR_DEP(rt);
1697  	GPR_RES(rd);
1698 	GPR_DEPRES_END
1699 
1700 	uint32 result = ~(GPR[rs] | GPR[rt]);
1701 
1702 	DO_LDS();
1703 
1704 	GPR[rd] = result;
1705 
1706     END_OPF;
1707 
1708     //
1709     // OR - OR
1710     //
1711     BEGIN_OPF(OR);
1712 	RTYPE;
1713 
1714 	GPR_DEPRES_BEGIN
1715 	GPR_DEP(rs);
1716 	GPR_DEP(rt);
1717  	GPR_RES(rd);
1718 	GPR_DEPRES_END
1719 
1720 	uint32 result = GPR[rs] | GPR[rt];
1721 
1722 	DO_LDS();
1723 
1724 	GPR[rd] = result;
1725 
1726     END_OPF;
1727 
1728 
1729     //
1730     // ORI - OR Immediate
1731     //
1732     BEGIN_OPF(ORI);
1733 	ITYPE_ZE;
1734 
1735 	GPR_DEPRES_BEGIN
1736 	GPR_DEP(rs);
1737 	GPR_RES(rt);
1738 	GPR_DEPRES_END
1739 
1740 	uint32 result = GPR[rs] | immediate;
1741 
1742 	DO_LDS();
1743 
1744 	GPR[rt] = result;
1745 
1746     END_OPF;
1747 
1748 
1749     //
1750     // SLL - Shift Word Left Logical
1751     //
1752     BEGIN_OPF(SLL);	// SLL
1753 	RTYPE;
1754 
1755 	GPR_DEPRES_BEGIN
1756 	GPR_DEP(rt);
1757  	GPR_RES(rd);
1758 	GPR_DEPRES_END
1759 
1760 	uint32 result = GPR[rt] << shamt;
1761 
1762 	DO_LDS();
1763 
1764 	GPR[rd] = result;
1765 
1766     END_OPF;
1767 
1768 
1769     //
1770     // SLLV - Shift Word Left Logical Variable
1771     //
1772     BEGIN_OPF(SLLV);
1773 	RTYPE;
1774 
1775 	GPR_DEPRES_BEGIN
1776 	GPR_DEP(rs);
1777 	GPR_DEP(rt);
1778  	GPR_RES(rd);
1779 	GPR_DEPRES_END
1780 
1781 	uint32 result = GPR[rt] << (GPR[rs] & 0x1F);
1782 
1783 	DO_LDS();
1784 
1785 	GPR[rd] = result;
1786 
1787     END_OPF;
1788 
1789     //
1790     // SLT - Set on Less Than
1791     //
1792     BEGIN_OPF(SLT);
1793 	RTYPE;
1794 
1795 	GPR_DEPRES_BEGIN
1796 	GPR_DEP(rs);
1797 	GPR_DEP(rt);
1798  	GPR_RES(rd);
1799 	GPR_DEPRES_END
1800 
1801 	uint32 result = (bool)((int32)GPR[rs] < (int32)GPR[rt]);
1802 
1803 	DO_LDS();
1804 
1805 	GPR[rd] = result;
1806 
1807     END_OPF;
1808 
1809 
1810     //
1811     // SLTI - Set on Less Than Immediate
1812     //
1813     BEGIN_OPF(SLTI);
1814 	ITYPE;
1815 
1816 	GPR_DEPRES_BEGIN
1817 	GPR_DEP(rs);
1818 	GPR_RES(rt);
1819 	GPR_DEPRES_END
1820 
1821 	uint32 result = (bool)((int32)GPR[rs] < (int32)immediate);
1822 
1823 	DO_LDS();
1824 
1825 	GPR[rt] = result;
1826 
1827     END_OPF;
1828 
1829 
1830     //
1831     // SLTIU - Set on Less Than Immediate, Unsigned
1832     //
1833     BEGIN_OPF(SLTIU);
1834 	ITYPE;
1835 
1836 	GPR_DEPRES_BEGIN
1837 	GPR_DEP(rs);
1838 	GPR_RES(rt);
1839 	GPR_DEPRES_END
1840 
1841 	uint32 result = (bool)(GPR[rs] < (uint32)immediate);
1842 
1843 	DO_LDS();
1844 
1845 	GPR[rt] = result;
1846 
1847     END_OPF;
1848 
1849 
1850     //
1851     // SLTU - Set on Less Than, Unsigned
1852     //
1853     BEGIN_OPF(SLTU);
1854 	RTYPE;
1855 
1856 	GPR_DEPRES_BEGIN
1857 	GPR_DEP(rs);
1858 	GPR_DEP(rt);
1859  	GPR_RES(rd);
1860 	GPR_DEPRES_END
1861 
1862 	uint32 result = (bool)(GPR[rs] < GPR[rt]);
1863 
1864 	DO_LDS();
1865 
1866 	GPR[rd] = result;
1867 
1868     END_OPF;
1869 
1870 
1871     //
1872     // SRA - Shift Word Right Arithmetic
1873     //
1874     BEGIN_OPF(SRA);
1875 	RTYPE;
1876 
1877 	GPR_DEPRES_BEGIN
1878 	GPR_DEP(rt);
1879  	GPR_RES(rd);
1880 	GPR_DEPRES_END
1881 
1882 	uint32 result = ((int32)GPR[rt]) >> shamt;
1883 
1884 	DO_LDS();
1885 
1886 	GPR[rd] = result;
1887 
1888     END_OPF;
1889 
1890 
1891     //
1892     // SRAV - Shift Word Right Arithmetic Variable
1893     //
1894     BEGIN_OPF(SRAV);
1895 	RTYPE;
1896 
1897 	GPR_DEPRES_BEGIN
1898 	GPR_DEP(rs);
1899 	GPR_DEP(rt);
1900  	GPR_RES(rd);
1901 	GPR_DEPRES_END
1902 
1903 	uint32 result = ((int32)GPR[rt]) >> (GPR[rs] & 0x1F);
1904 
1905 	DO_LDS();
1906 
1907 	GPR[rd] = result;
1908 
1909     END_OPF;
1910 
1911 
1912     //
1913     // SRL - Shift Word Right Logical
1914     //
1915     BEGIN_OPF(SRL);
1916 	RTYPE;
1917 
1918 	GPR_DEPRES_BEGIN
1919 	GPR_DEP(rt);
1920  	GPR_RES(rd);
1921 	GPR_DEPRES_END
1922 
1923 	uint32 result = GPR[rt] >> shamt;
1924 
1925 	DO_LDS();
1926 
1927 	GPR[rd] = result;
1928 
1929     END_OPF;
1930 
1931     //
1932     // SRLV - Shift Word Right Logical Variable
1933     //
1934     BEGIN_OPF(SRLV);
1935 	RTYPE;
1936 
1937 	GPR_DEPRES_BEGIN
1938 	GPR_DEP(rs);
1939 	GPR_DEP(rt);
1940  	GPR_RES(rd);
1941 	GPR_DEPRES_END
1942 
1943 	uint32 result = GPR[rt] >> (GPR[rs] & 0x1F);
1944 
1945 	DO_LDS();
1946 
1947 	GPR[rd] = result;
1948 
1949     END_OPF;
1950 
1951 
1952     //
1953     // SUB - Subtract Word
1954     //
1955     BEGIN_OPF(SUB);
1956 	RTYPE;
1957 
1958 	GPR_DEPRES_BEGIN
1959 	GPR_DEP(rs);
1960 	GPR_DEP(rt);
1961  	GPR_RES(rd);
1962 	GPR_DEPRES_END
1963 
1964 	uint32 result = GPR[rs] - GPR[rt];
1965 	bool ep = (((GPR[rs] ^ GPR[rt])) & (GPR[rs] ^ result)) & 0x80000000;
1966 
1967 	DO_LDS();
1968 
1969 	if(MDFN_UNLIKELY(ep))
1970 	{
1971 	 new_PC = Exception(EXCEPTION_OV, PC, new_PC, instr);
1972 	}
1973 	else
1974 	 GPR[rd] = result;
1975 
1976     END_OPF;
1977 
1978 
1979     //
1980     // SUBU - Subtract Unsigned Word
1981     //
1982     BEGIN_OPF(SUBU);
1983 	RTYPE;
1984 
1985 	GPR_DEPRES_BEGIN
1986 	GPR_DEP(rs);
1987 	GPR_DEP(rt);
1988  	GPR_RES(rd);
1989 	GPR_DEPRES_END
1990 
1991 	uint32 result = GPR[rs] - GPR[rt];
1992 
1993 	DO_LDS();
1994 
1995 	GPR[rd] = result;
1996 
1997     END_OPF;
1998 
1999 
2000     //
2001     // SYSCALL
2002     //
2003     BEGIN_OPF(SYSCALL);
2004 	DO_LDS();
2005 
2006 	new_PC = Exception(EXCEPTION_SYSCALL, PC, new_PC, instr);
2007     END_OPF;
2008 
2009 
2010     //
2011     // XOR
2012     //
2013     BEGIN_OPF(XOR);
2014 	RTYPE;
2015 
2016 	GPR_DEPRES_BEGIN
2017 	GPR_DEP(rs);
2018 	GPR_DEP(rt);
2019  	GPR_RES(rd);
2020 	GPR_DEPRES_END
2021 
2022 	uint32 result = GPR[rs] ^ GPR[rt];
2023 
2024 	DO_LDS();
2025 
2026 	GPR[rd] = result;
2027 
2028     END_OPF;
2029 
2030     //
2031     // XORI - Exclusive OR Immediate
2032     //
2033     BEGIN_OPF(XORI);
2034 	ITYPE_ZE;
2035 
2036 	GPR_DEPRES_BEGIN
2037 	GPR_DEP(rs);
2038 	GPR_RES(rt);
2039 	GPR_DEPRES_END
2040 
2041 	uint32 result = GPR[rs] ^ immediate;
2042 
2043 	DO_LDS();
2044 
2045 	GPR[rt] = result;
2046     END_OPF;
2047 
2048     //
2049     // Memory access instructions(besides the coprocessor ones) follow:
2050     //
2051 
2052     //
2053     // LB - Load Byte
2054     //
2055     BEGIN_OPF(LB);
2056 	ITYPE;
2057 
2058 	GPR_DEPRES_BEGIN
2059 	GPR_DEP(rs);
2060 	GPR_DEPRES_END
2061 
2062 	uint32 address = GPR[rs] + immediate;
2063 
2064 	if(MDFN_UNLIKELY(LDWhich == rt))
2065 	 LDWhich = 0;
2066 
2067 	DO_LDS();
2068 
2069 	LDWhich = rt;
2070 	LDValue = (int32)ReadMemory<int8>(timestamp, address);
2071     END_OPF;
2072 
2073     //
2074     // LBU - Load Byte Unsigned
2075     //
2076     BEGIN_OPF(LBU);
2077         ITYPE;
2078 
2079 	GPR_DEPRES_BEGIN
2080 	GPR_DEP(rs);
2081 	GPR_DEPRES_END
2082 
2083         uint32 address = GPR[rs] + immediate;
2084 
2085 	if(MDFN_UNLIKELY(LDWhich == rt))
2086 	 LDWhich = 0;
2087 
2088 	DO_LDS();
2089 
2090         LDWhich = rt;
2091 	LDValue = ReadMemory<uint8>(timestamp, address);
2092     END_OPF;
2093 
2094     //
2095     // LH - Load Halfword
2096     //
2097     BEGIN_OPF(LH);
2098         ITYPE;
2099 
2100 	GPR_DEPRES_BEGIN
2101 	GPR_DEP(rs);
2102 	GPR_DEPRES_END
2103 
2104         uint32 address = GPR[rs] + immediate;
2105 
2106 	if(MDFN_UNLIKELY(address & 1))
2107 	{
2108 	 DO_LDS();
2109 
2110 	 CP0.BADA = address;
2111 	 new_PC = Exception(EXCEPTION_ADEL, PC, new_PC, instr);
2112 	}
2113 	else
2114 	{
2115 	 if(MDFN_UNLIKELY(LDWhich == rt))
2116 	  LDWhich = 0;
2117 
2118 	 DO_LDS();
2119 
2120 	 LDWhich = rt;
2121          LDValue = (int32)ReadMemory<int16>(timestamp, address);
2122 	}
2123     END_OPF;
2124 
2125     //
2126     // LHU - Load Halfword Unsigned
2127     //
2128     BEGIN_OPF(LHU);
2129         ITYPE;
2130 
2131 	GPR_DEPRES_BEGIN
2132 	GPR_DEP(rs);
2133 	GPR_DEPRES_END
2134 
2135         uint32 address = GPR[rs] + immediate;
2136 
2137         if(MDFN_UNLIKELY(address & 1))
2138 	{
2139 	 DO_LDS();
2140 
2141 	 CP0.BADA = address;
2142          new_PC = Exception(EXCEPTION_ADEL, PC, new_PC, instr);
2143 	}
2144 	else
2145 	{
2146 	 if(MDFN_UNLIKELY(LDWhich == rt))
2147 	  LDWhich = 0;
2148 
2149 	 DO_LDS();
2150 
2151 	 LDWhich = rt;
2152          LDValue = ReadMemory<uint16>(timestamp, address);
2153 	}
2154     END_OPF;
2155 
2156 
2157     //
2158     // LW - Load Word
2159     //
2160     BEGIN_OPF(LW);
2161         ITYPE;
2162 
2163 	GPR_DEPRES_BEGIN
2164 	GPR_DEP(rs);
2165 	GPR_DEPRES_END
2166 
2167         uint32 address = GPR[rs] + immediate;
2168 
2169         if(MDFN_UNLIKELY(address & 3))
2170 	{
2171 	 DO_LDS();
2172 
2173 	 CP0.BADA = address;
2174          new_PC = Exception(EXCEPTION_ADEL, PC, new_PC, instr);
2175 	}
2176         else
2177 	{
2178 	 if(MDFN_UNLIKELY(LDWhich == rt))
2179 	  LDWhich = 0;
2180 
2181 	 DO_LDS();
2182 
2183 	 LDWhich = rt;
2184          LDValue = ReadMemory<uint32>(timestamp, address);
2185 	}
2186     END_OPF;
2187 
2188     //
2189     // SB - Store Byte
2190     //
2191     BEGIN_OPF(SB);
2192 	ITYPE;
2193 
2194 	GPR_DEPRES_BEGIN
2195 	GPR_DEP(rs);
2196 	GPR_DEP(rt);
2197 	GPR_DEPRES_END
2198 
2199 	uint32 address = GPR[rs] + immediate;
2200 
2201 	WriteMemory<uint8>(timestamp, address, GPR[rt]);
2202 
2203 	DO_LDS();
2204     END_OPF;
2205 
2206     //
2207     // SH - Store Halfword
2208     //
2209     BEGIN_OPF(SH);
2210         ITYPE;
2211 
2212 	GPR_DEPRES_BEGIN
2213 	GPR_DEP(rs);
2214 	GPR_DEP(rt);
2215 	GPR_DEPRES_END
2216 
2217         uint32 address = GPR[rs] + immediate;
2218 
2219 	if(MDFN_UNLIKELY(address & 0x1))
2220 	{
2221 	 CP0.BADA = address;
2222 	 new_PC = Exception(EXCEPTION_ADES, PC, new_PC, instr);
2223 	}
2224 	else
2225 	 WriteMemory<uint16>(timestamp, address, GPR[rt]);
2226 
2227 	DO_LDS();
2228     END_OPF;
2229 
2230     //
2231     // SW - Store Word
2232     //
2233     BEGIN_OPF(SW);
2234         ITYPE;
2235 
2236 	GPR_DEPRES_BEGIN
2237 	GPR_DEP(rs);
2238 	GPR_DEP(rt);
2239 	GPR_DEPRES_END
2240 
2241         uint32 address = GPR[rs] + immediate;
2242 
2243 	if(MDFN_UNLIKELY(address & 0x3))
2244 	{
2245 	 CP0.BADA = address;
2246 	 new_PC = Exception(EXCEPTION_ADES, PC, new_PC, instr);
2247 	}
2248 	else
2249 	 WriteMemory<uint32>(timestamp, address, GPR[rt]);
2250 
2251 	DO_LDS();
2252     END_OPF;
2253 
2254     // LWL and LWR load delay slot tomfoolery appears to apply even to MFC0! (and probably MFCn and CFCn as well, though they weren't explicitly tested)
2255 
2256     //
2257     // LWL - Load Word Left
2258     //
2259     BEGIN_OPF(LWL);
2260 	ITYPE;
2261 
2262 	GPR_DEPRES_BEGIN
2263 	GPR_DEP(rs);
2264 	//GPR_DEP(rt);
2265 	GPR_DEPRES_END
2266 
2267 	uint32 address = GPR[rs] + immediate;
2268 	uint32 v = GPR[rt];
2269 
2270 	if(LDWhich == rt)
2271 	{
2272 	 v = LDValue;
2273 	 ReadFudge = 0;
2274 	}
2275 	else
2276 	{
2277 	 DO_LDS();
2278 	}
2279 
2280 	LDWhich = rt;
2281 	switch(address & 0x3)
2282 	{
2283 	 case 0: LDValue = (v & ~(0xFF << 24)) | (ReadMemory<uint8>(timestamp, address & ~3) << 24);
2284 		 break;
2285 
2286 	 case 1: LDValue = (v & ~(0xFFFF << 16)) | (ReadMemory<uint16>(timestamp, address & ~3) << 16);
2287 	         break;
2288 
2289 	 case 2: LDValue = (v & ~(0xFFFFFF << 8)) | (ReadMemory<uint32>(timestamp, address & ~3, true) << 8);
2290 		 break;
2291 
2292 	 case 3: LDValue = (v & ~(0xFFFFFFFF << 0)) | (ReadMemory<uint32>(timestamp, address & ~3) << 0);
2293 		 break;
2294 	}
2295     END_OPF;
2296 
2297     //
2298     // SWL - Store Word Left
2299     //
2300     BEGIN_OPF(SWL);
2301         ITYPE;
2302 
2303 	GPR_DEPRES_BEGIN
2304 	GPR_DEP(rs);
2305 	GPR_DEP(rt);
2306 	GPR_DEPRES_END
2307 
2308         uint32 address = GPR[rs] + immediate;
2309 
2310 	switch(address & 0x3)
2311 	{
2312 	 case 0: WriteMemory<uint8>(timestamp, address & ~3, GPR[rt] >> 24);
2313 		 break;
2314 
2315 	 case 1: WriteMemory<uint16>(timestamp, address & ~3, GPR[rt] >> 16);
2316 	         break;
2317 
2318 	 case 2: WriteMemory<uint32>(timestamp, address & ~3, GPR[rt] >> 8, true);
2319 		 break;
2320 
2321 	 case 3: WriteMemory<uint32>(timestamp, address & ~3, GPR[rt] >> 0);
2322 		 break;
2323 	}
2324 	DO_LDS();
2325 
2326     END_OPF;
2327 
2328     //
2329     // LWR - Load Word Right
2330     //
2331     BEGIN_OPF(LWR);
2332         ITYPE;
2333 
2334 	GPR_DEPRES_BEGIN
2335 	GPR_DEP(rs);
2336 	//GPR_DEP(rt);
2337 	GPR_DEPRES_END
2338 
2339         uint32 address = GPR[rs] + immediate;
2340 	uint32 v = GPR[rt];
2341 
2342 	if(LDWhich == rt)
2343 	{
2344 	 v = LDValue;
2345 	 ReadFudge = 0;
2346 	}
2347 	else
2348 	{
2349 	 DO_LDS();
2350 	}
2351 
2352 	LDWhich = rt;
2353 	switch(address & 0x3)
2354 	{
2355 	 case 0: LDValue = (v & ~(0xFFFFFFFF)) | ReadMemory<uint32>(timestamp, address);
2356 		 break;
2357 
2358 	 case 1: LDValue = (v & ~(0xFFFFFF)) | ReadMemory<uint32>(timestamp, address, true);
2359 		 break;
2360 
2361 	 case 2: LDValue = (v & ~(0xFFFF)) | ReadMemory<uint16>(timestamp, address);
2362 	         break;
2363 
2364 	 case 3: LDValue = (v & ~(0xFF)) | ReadMemory<uint8>(timestamp, address);
2365 		 break;
2366 	}
2367     END_OPF;
2368 
2369     //
2370     // SWR - Store Word Right
2371     //
2372     BEGIN_OPF(SWR);
2373         ITYPE;
2374 
2375 	GPR_DEPRES_BEGIN
2376 	GPR_DEP(rs);
2377 	GPR_DEP(rt);
2378 	GPR_DEPRES_END
2379 
2380         uint32 address = GPR[rs] + immediate;
2381 
2382 	switch(address & 0x3)
2383 	{
2384 	 case 0: WriteMemory<uint32>(timestamp, address, GPR[rt]);
2385 		 break;
2386 
2387 	 case 1: WriteMemory<uint32>(timestamp, address, GPR[rt], true);
2388 		 break;
2389 
2390 	 case 2: WriteMemory<uint16>(timestamp, address, GPR[rt]);
2391 	         break;
2392 
2393 	 case 3: WriteMemory<uint8>(timestamp, address, GPR[rt]);
2394 		 break;
2395 	}
2396 
2397 	DO_LDS();
2398 
2399     END_OPF;
2400 
2401     //
2402     // Mednafen special instruction
2403     //
2404     BEGIN_OPF(INTERRUPT);
2405 	if(Halted)
2406 	{
2407 	 goto SkipNPCStuff;
2408 	}
2409 	else
2410 	{
2411  	 DO_LDS();
2412 
2413 	 new_PC = Exception(EXCEPTION_INT, PC, new_PC, instr);
2414 	}
2415     END_OPF;
2416    }
2417 
2418    OpDone: ;
2419    PC = new_PC;
2420    new_PC = new_PC + 4;
2421    BDBT = 0;
2422 
2423    SkipNPCStuff:	;
2424 
2425    //printf("\n");
2426   }
2427  } while(MDFN_LIKELY(PSX_EventHandler(timestamp)));
2428 
2429  if(gte_ts_done > 0)
2430   gte_ts_done -= timestamp;
2431 
2432  if(muldiv_ts_done > 0)
2433   muldiv_ts_done -= timestamp;
2434 
2435  ACTIVE_TO_BACKING;
2436 
2437  return(timestamp);
2438 }
2439 
Run(pscpu_timestamp_t timestamp_in,bool BIOSPrintMode,bool ILHMode)2440 pscpu_timestamp_t PS_CPU::Run(pscpu_timestamp_t timestamp_in, bool BIOSPrintMode, bool ILHMode)
2441 {
2442  if(CPUHook || ADDBT)
2443   return(RunReal<true, true, false>(timestamp_in));
2444  else
2445  {
2446   if(ILHMode)
2447    return(RunReal<false, false, true>(timestamp_in));
2448   else
2449   {
2450    if(BIOSPrintMode)
2451     return(RunReal<false, true, false>(timestamp_in));
2452    else
2453     return(RunReal<false, false, false>(timestamp_in));
2454   }
2455  }
2456 }
2457 
SetCPUHook(void (* cpuh)(const pscpu_timestamp_t timestamp,uint32 pc),void (* addbt)(uint32 from,uint32 to,bool exception))2458 void PS_CPU::SetCPUHook(void (*cpuh)(const pscpu_timestamp_t timestamp, uint32 pc), void (*addbt)(uint32 from, uint32 to, bool exception))
2459 {
2460  ADDBT = addbt;
2461  CPUHook = cpuh;
2462 }
2463 
GetRegister(unsigned int which,char * special,const uint32 special_len)2464 uint32 PS_CPU::GetRegister(unsigned int which, char *special, const uint32 special_len)
2465 {
2466  uint32 ret = 0;
2467 
2468  if(which >= GSREG_GPR && which < (GSREG_GPR + 32))
2469   ret = GPR[which];
2470  else switch(which)
2471  {
2472   case GSREG_PC:
2473 	ret = BACKED_PC;
2474 	break;
2475 
2476   case GSREG_PC_NEXT:
2477 	ret = BACKED_new_PC;
2478 	break;
2479 
2480   case GSREG_IN_BD_SLOT:
2481 	ret = BDBT;
2482 	break;
2483 
2484   case GSREG_LO:
2485 	ret = LO;
2486 	break;
2487 
2488   case GSREG_HI:
2489 	ret = HI;
2490 	break;
2491 
2492   case GSREG_BPC:
2493 	ret = CP0.BPC;
2494 	break;
2495 
2496   case GSREG_BDA:
2497 	ret = CP0.BDA;
2498 	break;
2499 
2500   case GSREG_TAR:
2501 	ret = CP0.TAR;
2502 	break;
2503 
2504   case GSREG_DCIC:
2505 	ret = CP0.DCIC;
2506 	break;
2507 
2508   case GSREG_BADA:
2509 	ret = CP0.BADA;
2510 	break;
2511 
2512   case GSREG_BDAM:
2513 	ret = CP0.BDAM;
2514 	break;
2515 
2516   case GSREG_BPCM:
2517 	ret = CP0.BPCM;
2518 	break;
2519 
2520   case GSREG_SR:
2521 	ret = CP0.SR;
2522 	break;
2523 
2524   case GSREG_CAUSE:
2525 	ret = CP0.CAUSE;
2526 	if(special)
2527 	{
2528 	 trio_snprintf(special, special_len, "BD: %u, BT: %u, CE: %u, IP: 0x%02x, Sw: %u, ExcCode: 0x%01x",
2529 		(ret >> 31) & 1, (ret >> 30) & 1, (ret >> 28) & 3, (ret >> 10) & 0x3F, (ret >> 8) & 3, (ret >> 2) & 0xF);
2530 	}
2531 	break;
2532 
2533   case GSREG_EPC:
2534 	ret = CP0.EPC;
2535 	break;
2536 
2537  }
2538 
2539  return(ret);
2540 }
2541 
SetRegister(unsigned int which,uint32 value)2542 void PS_CPU::SetRegister(unsigned int which, uint32 value)
2543 {
2544  if(which >= GSREG_GPR && which < (GSREG_GPR + 32))
2545  {
2546   if(which != (GSREG_GPR + 0))
2547    GPR[which] = value;
2548  }
2549  else switch(which)
2550  {
2551   case GSREG_PC:
2552         BACKED_PC = value;
2553         break;
2554 
2555   case GSREG_PC_NEXT:
2556 	BACKED_new_PC = value;
2557 	break;
2558 
2559   case GSREG_IN_BD_SLOT:
2560 	BDBT = value & 0x3;
2561 	break;
2562 
2563   case GSREG_LO:
2564         LO = value;
2565         break;
2566 
2567   case GSREG_HI:
2568         HI = value;
2569         break;
2570 
2571   case GSREG_SR:
2572         CP0.SR = value;		// TODO: mask
2573         break;
2574 
2575   case GSREG_CAUSE:
2576 	CP0.CAUSE = value;
2577 	break;
2578 
2579   case GSREG_EPC:
2580 	CP0.EPC = value & ~0x3U;
2581 	break;
2582 
2583 
2584  }
2585 }
2586 
PeekCheckICache(uint32 PC,uint32 * iw)2587 bool PS_CPU::PeekCheckICache(uint32 PC, uint32 *iw)
2588 {
2589  if(ICache[(PC & 0xFFC) >> 2].TV == PC)
2590  {
2591   *iw = ICache[(PC & 0xFFC) >> 2].Data;
2592   return(true);
2593  }
2594 
2595  return(false);
2596 }
2597 
2598 
PeekMem8(uint32 A)2599 uint8 PS_CPU::PeekMem8(uint32 A)
2600 {
2601  return PeekMemory<uint8>(A);
2602 }
2603 
PeekMem16(uint32 A)2604 uint16 PS_CPU::PeekMem16(uint32 A)
2605 {
2606  return PeekMemory<uint16>(A);
2607 }
2608 
PeekMem32(uint32 A)2609 uint32 PS_CPU::PeekMem32(uint32 A)
2610 {
2611  return PeekMemory<uint32>(A);
2612 }
2613 
PokeMem8(uint32 A,uint8 V)2614 void PS_CPU::PokeMem8(uint32 A, uint8 V)
2615 {
2616  PokeMemory<uint8>(A, V);
2617 }
2618 
PokeMem16(uint32 A,uint16 V)2619 void PS_CPU::PokeMem16(uint32 A, uint16 V)
2620 {
2621  PokeMemory<uint16>(A, V);
2622 }
2623 
PokeMem32(uint32 A,uint32 V)2624 void PS_CPU::PokeMem32(uint32 A, uint32 V)
2625 {
2626  PokeMemory<uint32>(A, V);
2627 }
2628 
2629 #undef BEGIN_OPF
2630 #undef END_OPF
2631 #undef MK_OPF
2632 
2633 #define MK_OPF(op, funct)	((op) ? (0x40 | (op)) : (funct))
2634 #define BEGIN_OPF(op, funct) case MK_OPF(op, funct): {
2635 #define END_OPF } break;
2636 
2637 // FIXME: should we breakpoint on an illegal address?  And with LWC2/SWC2 if CP2 isn't enabled?
CheckBreakpoints(void (* callback)(bool write,uint32 address,unsigned int len),uint32 instr)2638 void PS_CPU::CheckBreakpoints(void (*callback)(bool write, uint32 address, unsigned int len), uint32 instr)
2639 {
2640  uint32 opf;
2641 
2642  opf = instr & 0x3F;
2643 
2644  if(instr & (0x3F << 26))
2645   opf = 0x40 | (instr >> 26);
2646 
2647 
2648  switch(opf)
2649  {
2650   default:
2651 	break;
2652 
2653     //
2654     // LB - Load Byte
2655     //
2656     BEGIN_OPF(0x20, 0);
2657 	ITYPE;
2658 	uint32 address = GPR[rs] + immediate;
2659 
2660         callback(false, address, 1);
2661     END_OPF;
2662 
2663     //
2664     // LBU - Load Byte Unsigned
2665     //
2666     BEGIN_OPF(0x24, 0);
2667         ITYPE;
2668         uint32 address = GPR[rs] + immediate;
2669 
2670         callback(false, address, 1);
2671     END_OPF;
2672 
2673     //
2674     // LH - Load Halfword
2675     //
2676     BEGIN_OPF(0x21, 0);
2677         ITYPE;
2678         uint32 address = GPR[rs] + immediate;
2679 
2680         callback(false, address, 2);
2681     END_OPF;
2682 
2683     //
2684     // LHU - Load Halfword Unsigned
2685     //
2686     BEGIN_OPF(0x25, 0);
2687         ITYPE;
2688         uint32 address = GPR[rs] + immediate;
2689 
2690         callback(false, address, 2);
2691     END_OPF;
2692 
2693 
2694     //
2695     // LW - Load Word
2696     //
2697     BEGIN_OPF(0x23, 0);
2698         ITYPE;
2699         uint32 address = GPR[rs] + immediate;
2700 
2701         callback(false, address, 4);
2702     END_OPF;
2703 
2704     //
2705     // SB - Store Byte
2706     //
2707     BEGIN_OPF(0x28, 0);
2708 	ITYPE;
2709 	uint32 address = GPR[rs] + immediate;
2710 
2711         callback(true, address, 1);
2712     END_OPF;
2713 
2714     //
2715     // SH - Store Halfword
2716     //
2717     BEGIN_OPF(0x29, 0);
2718         ITYPE;
2719         uint32 address = GPR[rs] + immediate;
2720 
2721         callback(true, address, 2);
2722     END_OPF;
2723 
2724     //
2725     // SW - Store Word
2726     //
2727     BEGIN_OPF(0x2B, 0);
2728         ITYPE;
2729         uint32 address = GPR[rs] + immediate;
2730 
2731         callback(true, address, 4);
2732     END_OPF;
2733 
2734     //
2735     // LWL - Load Word Left
2736     //
2737     BEGIN_OPF(0x22, 0);
2738 	ITYPE;
2739 	uint32 address = GPR[rs] + immediate;
2740 
2741 	do
2742 	{
2743          callback(false, address, 1);
2744 	} while((address--) & 0x3);
2745 
2746     END_OPF;
2747 
2748     //
2749     // SWL - Store Word Left
2750     //
2751     BEGIN_OPF(0x2A, 0);
2752         ITYPE;
2753         uint32 address = GPR[rs] + immediate;
2754 
2755         do
2756         {
2757 	 callback(true, address, 1);
2758         } while((address--) & 0x3);
2759 
2760     END_OPF;
2761 
2762     //
2763     // LWR - Load Word Right
2764     //
2765     BEGIN_OPF(0x26, 0);
2766         ITYPE;
2767         uint32 address = GPR[rs] + immediate;
2768 
2769         do
2770         {
2771 	 callback(false, address, 1);
2772         } while((++address) & 0x3);
2773 
2774     END_OPF;
2775 
2776     //
2777     // SWR - Store Word Right
2778     //
2779     BEGIN_OPF(0x2E, 0);
2780         ITYPE;
2781         uint32 address = GPR[rs] + immediate;
2782 
2783         do
2784         {
2785 	 callback(true, address, 1);
2786         } while((++address) & 0x3);
2787 
2788     END_OPF;
2789 
2790     //
2791     // LWC2
2792     //
2793     BEGIN_OPF(0x32, 0);
2794         ITYPE;
2795         uint32 address = GPR[rs] + immediate;
2796 
2797 	callback(false, address, 4);
2798     END_OPF;
2799 
2800     //
2801     // SWC2
2802     //
2803     BEGIN_OPF(0x3A, 0);
2804         ITYPE;
2805         uint32 address = GPR[rs] + immediate;
2806 
2807 	callback(true, address, 4);
2808     END_OPF;
2809 
2810  }
2811 }
2812 
2813 
2814 }
2815