1/******************************************************************************/
2/* Mednafen Sega Saturn Emulation Module                                      */
3/******************************************************************************/
4/* sh7095.inc - Hitachi SH7095 Emulation
5**  Copyright (C) 2015-2019 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/*
23   Instruction cache emulation shouldn't be enabled globally for all games until we resolve timestamp vs mem_timestamp issues
24   in regards to bus contention and time sharing, or else emulated dual-CPU programs may run slower
25   than they should and probably glitch out(and also until 5GHz desktop CPUs are the norm ;)).
26*/
27
28/*
29 Emulation implementation notes/deficiencies:
30	Cache multiple-way tag collisions (ostensibly an illegal condition) during reads/writes are not handled accurately.
31
32	Overall timing is extremely approximate.
33
34	DMA timing is very rough.  DMA burst mode probably isn't handled totally correctly, especially in
35	relation to the other CPU and the SCU(is DMA burst mode even legal on the Saturn?).
36
37	DMA channel bus priority handling is not correct(at least not for non-burst mode transfers).
38
39	Misaligned memory accesses(that cause address errors) aren't emulated correctly(for
40	future reference, there's a difference between how cache versus external bus is accessed
41	for misaligned addresses, and perhaps a difference between 32-bit and 16-bit spaces as
42	defined by the BSC too; and then there's misaligned OPM register access semantics...).
43
44	Address errors occur one instruction too soon.
45
46	SLEEP instruction, standby mode, and DMA burst stalls are handled by thoroughly (ab)using the
47	IF/ID pipeline emulation and opcode dispatch mechanism.
48
49	Individual module clocking disabling functionality of SBYCR isn't handled.
50
51	Interrupts are typically delayed by one instruction, but when the interrupt is handled,
52	the current interrupt state is used instead of the previous interrupt state.
53	This can result in the exception-handling pseudo-op code being called when there's
54	no "current" exception to process, which is a quasi-error condition; there's code to log
55	this condition and recover from it.  An SH-2 code sequence that can cause this condition
56	if there's currently a pending/unacked interrupt:
57		<interrupt-enabling instruction>
58		<interrupt-acknowledging instruction>
59	This cooouuuld turn out to be a problem, and if it does, it can be fixed by having two interrupt-pending variables,
60	with one being copied to the other in DoIDIF().
61
62	Instruction fetches don't go through the cache emulation, for performance reasons(getting the instruction fetches timed right
63	versus the instruction data read/write would be critical, to avoid causing inaccurate cache miss patterns which could cause code
64	to run slower than on the real thing, which is arguably worse than having it run faster).
65
66	SCI, UBC, and BSC are mostly unemulated.
67*/
68
69// Address error exception order, sleep versus exceptions.
70
71/*
72 TODO: PC-relative addressing, uses instruction or data fetches?
73*/
74
75/*
76 TODO: Make sure RecalcPendingIntPEX() is called in all places it needs to be called(which is arguably too many...).
77*/
78
79/*
80 TODO: Penalize slave CPU external bus access if we ever figure out a solution to the timestamp vs mem_timestamp problem that doesn't murder
81       performance.
82*/
83
84#ifdef MSB_FIRST
85 #define NE32ASU8_IDX_ADJ(T, idx) (idx)
86#else
87 #define NE32ASU8_IDX_ADJ(T, idx) ( ((idx) & ~(sizeof(T) - 1)) ^ (4 - (sizeof(T))) )
88#endif
89
90SH7095::SH7095(const char* const name_arg, const unsigned event_id_dma_arg, uint8 (*exivecfn_arg)(void)) : event_id_dma(event_id_dma_arg), cpu_name(name_arg), ExIVecFetch(exivecfn_arg)
91{
92 Init(false);
93}
94
95template<unsigned which, typename T, unsigned region, bool CacheEnabled, bool TwoWayMode, bool IsInstr, bool CacheBypassHack>
96static NO_INLINE MDFN_FASTCALL T C_MemReadRT(uint32 A);
97
98template<unsigned which, typename T, unsigned region, bool CacheEnabled>
99static NO_INLINE MDFN_FASTCALL void C_MemWriteRT(uint32 A, T V);
100
101void SH7095::Init(const bool cbh)
102{
103 CBH_Setting = cbh;
104 //
105 #define MAHL_P(w, region) {									\
106		  MRFP8[region]  = C_MemReadRT<w, uint8,  region, false, false, false, false>;	\
107		  MRFP16[region] = C_MemReadRT<w, uint16, region, false, false, false, false>;	\
108		  MRFP32[region] = C_MemReadRT<w, uint32, region, false, false, false, false>;	\
109		  MRFPI[region]  = C_MemReadRT<w, uint32, region, false, false, true, false>;	\
110		  MWFP8[region]  = C_MemWriteRT<w, uint8,  region, false>;	\
111		  MWFP16[region] = C_MemWriteRT<w, uint16, region, false>;	\
112		  MWFP32[region] = C_MemWriteRT<w, uint32, region, false>;	\
113		  }
114
115 #define MAHL(region)			\
116		  if(this == &CPU[0])	\
117		  { MAHL_P(0, region) }	\
118		  else			\
119		  { MAHL_P(1, region) }
120
121 MAHL(1)
122 MAHL(2)
123 MAHL(3)
124 MAHL(4)
125 MAHL(5)
126 MAHL(6)
127 MAHL(7)
128
129 #undef MAHL
130 #undef MAHL_P
131 //
132 //
133 //
134
135 //
136 // Initialize variables that won't be initialized elsewhere since they reflect the overall emulator timing state, or are cache variables
137 // for signal inputs.
138 //
139 timestamp = 0;
140 write_finish_timestamp = 0;
141 divide_finish_timestamp = 0;
142 FRT.lastts = 0;
143 dma_lastts = 0;
144
145 FRT.FTI = false;
146 FRT.FTCI = false;
147 IRL = 0;
148 NMILevel = false;
149 BSC.BCR1 &= 0x7FFF; //MD5Level = false;
150 ExtHalt = false;
151
152 TruePowerOn();
153}
154
155SH7095::~SH7095()
156{
157
158}
159
160void SH7095::AdjustTS(int32 delta, bool force_set)
161{
162 if(force_set)
163 {
164  timestamp = delta;
165
166  MA_until = delta;
167  MM_until = delta;
168
169#if 0
170  for(unsigned i = 0; i < 16; i++)
171   WB_until[i] = delta;
172#endif
173
174  write_finish_timestamp = delta;
175  divide_finish_timestamp = delta;
176
177  FRT.lastts = delta;
178  dma_lastts = delta;
179 }
180 else
181 {
182  if(!(timestamp & 0x40000000))
183   timestamp += delta;
184
185  if(!(MA_until & 0x40000000))
186   MA_until += delta;
187
188  if(!(MM_until & 0x40000000))
189   MM_until += delta;
190
191#if 0
192  for(unsigned i = 0; i < 16; i++)
193  {
194   if(!(WB_until[i] & 0x40000000))
195    WB_until[i] += delta;
196  }
197#endif
198
199  if(!(write_finish_timestamp & 0x40000000))
200   write_finish_timestamp += delta;
201
202  if(!(divide_finish_timestamp & 0x40000000))
203   divide_finish_timestamp += delta;
204
205  FRT.lastts += delta;
206  dma_lastts += delta;
207 }
208
209 FRT_WDT_ClockDivider &= 0x00FFFFFF;
210 FRT_WDT_Recalc_NET();
211}
212
213//
214// Initialize everything for determinism, especially state left "undefined" by reset/power exception handling.
215//
216void SH7095::TruePowerOn(void)
217{
218 for(unsigned i = 0; i < 16; i++)
219  R[i] = 0;
220
221#if 0
222 for(unsigned i = 0; i < 16; i++)
223  WB_until[i] = 0;
224#endif
225
226 PC = 0;
227
228 SR = 0;
229 GBR = 0;
230 VBR = 0;
231
232 MACH = 0;
233 MACL = 0;
234 PR = 0;
235
236 EPending = 0;
237 Pipe_ID = 0;
238 Pipe_IF = 0;
239
240 PC_IF = PC_ID = 0;
241
242 memset(Cache, 0, sizeof(Cache));
243 CCR = 0;
244
245 MA_until = 0;
246 MM_until = 0;
247 //
248 //
249 //
250 IPRA = 0;
251 IPRB = 0;
252 VCRWDT = 0;
253 VCRA = 0;
254 VCRB = 0;
255 VCRC = 0;
256 VCRD = 0;
257 ICR = 0;
258
259 //
260 //
261 //
262 FRT.FRC = 0;
263 FRT.OCR[0] = FRT.OCR[1] = 0;
264 FRT.FICR = 0;
265 FRT.TIER = 0;
266 FRT.FTCSR = 0;
267 FRT.FTCSRM = 0;
268 FRT.TCR = 0;
269 FRT.TOCR = 0;
270 FRT.RW_Temp = 0;
271
272 FRT_WDT_ClockDivider = 0;
273
274 WDT.WTCSR = 0;
275 WDT.WTCSRM = 0;
276 WDT.WTCNT = 0;
277 WDT.RSTCSR = 0;
278 WDT.RSTCSRM = 0;
279
280 FRT_WDT_Recalc_NET();
281 //
282 //
283 //
284 DMA_ClockCounter = 0;
285 DMA_SGCounter = 0;
286 DMA_RoundRobinRockinBoppin = 0;
287 DMA_PenaltyKludgeAmount = 0;
288 DMA_PenaltyKludgeAccum = 0;
289 memset(DMACH, 0, sizeof(DMACH));
290 DMAOR = 0;
291 DMAORM = 0;
292 DMA_RecalcRunning();
293 //
294 //
295 //
296 DVSR = 0;
297 DVDNT = 0;
298 DVDNTH = 0;
299 DVDNTL = 0;
300 DVDNTH_Shadow = 0;
301 DVDNTL_Shadow = 0;
302 VCRDIV = 0;
303 DVCR = 0;
304 //
305 //
306 //
307}
308
309
310
311
312
313// de=1, dme=1, te=0, nmif=0, ae=0
314INLINE bool SH7095::DMA_RunCond(unsigned ch)
315{
316 return ((DMAOR & 0x07) == 0x01) && ((DMACH[ch].CHCR & 0x03) == 0x01);
317}
318
319bool SH7095::DMA_InBurst(void)
320{
321 if((DMAOR & 0x08) && DMA_RunCond(0) && DMA_RunCond(1))
322  return ((DMACH[0].CHCR | DMACH[1].CHCR) & 0x10);
323
324 if(DMA_RunCond(0))
325  return (DMACH[0].CHCR & 0x10);
326 else if(DMA_RunCond(1))
327  return (DMACH[1].CHCR & 0x10);
328
329 return false;
330}
331
332void SH7095::DMA_CheckEnterBurstHack(void)
333{
334 if(DMA_InBurst())
335  SetPEX(PEX_PSEUDO_DMABURST);
336}
337
338
339// RecalcPendingIntPEX() will be called higher up, at the end of DMA_Update()
340//
341// Call SH7095_Bus* directly instead of through ExtBusRead, at least until we can work
342// out all this disparate timestamp nonsense properly(maybe around the time we add proper bus controller emulation? ;)).
343//
344INLINE void SH7095::DMA_DoTransfer(unsigned ch)
345{
346 static const int8 ainc[3][4] =
347 {
348  { 0, 1, -1, -1 },
349  { 0, 2, -2, -2 },
350  { 0, 4, -4, -4 },
351 };
352 const unsigned ts = (DMACH[ch].CHCR >> 10) & 3;
353 const unsigned sm = (DMACH[ch].CHCR >> 12) & 3;
354 const unsigned dm = (DMACH[ch].CHCR >> 14) & 3;
355 uint32 sar = DMACH[ch].SAR;
356 uint32 dar = DMACH[ch].DAR;
357 uint32 tcr = DMACH[ch].TCR;
358
359 switch(ts)
360 {
361  case 0x00:	// 8-bit
362	{
363	 uint8 buffer;
364
365	 buffer = SH7095_BusRead<uint8>(sar & 0x07FFFFFF, false, &DMA_ClockCounter);
366	 SH7095_BusWrite<uint8>(dar & 0x07FFFFFF, buffer, false, &DMA_ClockCounter);
367
368	 sar += ainc[0][sm];
369 	 dar += ainc[0][dm];
370	 tcr = (tcr - 1) & 0xFFFFFF;
371	}
372	break;
373
374  case 0x01:	// 16-bit
375	{
376	 uint16 buffer;
377
378	 buffer = SH7095_BusRead<uint16>(sar & 0x07FFFFFE, false, &DMA_ClockCounter);
379	 SH7095_BusWrite<uint16>(dar & 0x07FFFFFE, buffer, false, &DMA_ClockCounter);
380
381	 if(MDFN_UNLIKELY((sar | dar) & 0x1))
382	 {
383	  DMAOR |= 4;
384	  DMAORM |= 4;
385	  DMA_RecalcRunning();
386	  SetPEX(PEX_DMAADDR);
387	 }
388
389	 sar += ainc[1][sm];
390 	 dar += ainc[1][dm];
391	 tcr = (tcr - 1) & 0xFFFFFF;
392	}
393	break;
394
395  case 0x02:	// 32-bit
396	{
397	 uint32 buffer;
398
399	 buffer = SH7095_BusRead<uint32>(sar & 0x07FFFFFC, false, &DMA_ClockCounter);
400	 SH7095_BusWrite<uint32>(dar & 0x07FFFFFC, buffer, false, &DMA_ClockCounter);
401
402	 if(MDFN_UNLIKELY((sar | dar) & 0x3))
403	 {
404	  DMAOR |= 4;
405	  DMAORM |= 4;
406          DMA_RecalcRunning();
407	  SetPEX(PEX_DMAADDR);
408	 }
409
410	 sar += ainc[2][sm];
411 	 dar += ainc[2][dm];
412	 tcr = (tcr - 1) & 0xFFFFFF;
413	}
414	break;
415
416  case 0x03:	// 4 * 32-bit, a mess...
417	{
418	 uint32 buffer[4];
419
420	 if(MDFN_UNLIKELY((sar | dar) & 0x3))
421	 {
422	  DMAOR |= 4;
423	  DMAORM |= 4;
424	  DMA_RecalcRunning();
425	  SetPEX(PEX_DMAADDR);
426	 }
427
428	 for(unsigned i = 0; i < 4; i++)
429	 {
430	  buffer[i] = SH7095_BusRead<uint32>((sar + (i << 2)) & 0x07FFFFFC, (bool)i, &DMA_ClockCounter);
431	 }
432
433	 sar += 0x10;
434
435	 for(unsigned i = 0; i < 4; i++)
436	 {
437	  SH7095_BusWrite<uint32>(dar & 0x07FFFFFC, buffer[i], false, &DMA_ClockCounter);
438	  dar += ainc[2][dm];
439	  tcr = (tcr - 1) & 0xFFFFFF;
440	  if(MDFN_UNLIKELY(!tcr))
441	   break;
442	 }
443	}
444	break;
445 }
446
447 if(!tcr)
448 {
449#ifdef HAVE_DEBUG
450  SS_DBGTI(SS_DBG_SH2, "[%s] DMA %d finished.", cpu_name, ch);
451#endif
452
453  DMACH[ch].CHCR |= 2;
454  DMACH[ch].CHCRM |= 2;
455  DMA_RecalcRunning();
456 }
457
458 DMACH[ch].SAR = sar;
459 DMACH[ch].DAR = dar;
460 DMACH[ch].TCR = tcr;
461}
462
463sscpu_timestamp_t SH7095::DMA_Update(sscpu_timestamp_t et)
464{
465#ifdef HAVE_DEBUG
466 if(MDFN_UNLIKELY(et < dma_lastts))
467 {
468  // et < dma_lastts may happen...look into it.
469  if(et < dma_lastts)
470   SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] DMA_Update called with et(%u) < dma_lastts(%u).\n", cpu_name, et, dma_lastts);
471 }
472 else
473#else
474 if(MDFN_UNLIKELY(et < dma_lastts)) { }
475#endif
476 if(MDFN_UNLIKELY(ExtHalt))
477 {
478  dma_lastts = et;
479  return dma_lastts + 128;
480 }
481 else
482 {
483  uint32 clocks = et - dma_lastts;
484  dma_lastts = et;
485
486  //
487  //
488  //
489  bool rr = DMA_RoundRobinRockinBoppin;
490
491  DMA_ClockCounter += clocks;
492  DMA_SGCounter += clocks;
493
494  if(DMAOR & 0x08) 	// Round robin
495  {
496   while(DMA_RunCond(0) || DMA_RunCond(1))
497   {
498    if(DMA_RunCond(rr))
499    {
500     if(DMA_ClockCounter <= 0)
501      goto TimeOver;
502
503     DMA_DoTransfer(rr);
504    }
505    rr = !rr;
506   }
507  }
508  else	// ch 0 > ch1
509  {
510   while(DMA_RunCond(0))
511   {
512    if(DMA_ClockCounter <= 0)
513     goto TimeOver;
514
515    DMA_DoTransfer(0);
516   }
517
518   while(DMA_RunCond(1))
519   {
520    if(DMA_ClockCounter <= 0)
521     goto TimeOver;
522
523    DMA_DoTransfer(1);
524   }
525  }
526  //
527  //
528  //
529  TimeOver:;
530
531  DMA_RoundRobinRockinBoppin = rr;
532  DMA_ClockCounter = std::min<int32>(DMA_ClockCounter, 128);
533  DMA_SGCounter = std::min<int32>(DMA_SGCounter, 0);
534
535  DMA_CheckEnterBurstHack();
536  RecalcPendingIntPEX();	// TODO: conditionalize(or make RecalcPendingIntPEX() less expensive).
537 }
538
539 return dma_lastts + ((DMA_SGCounter < 0) ? 32 : 128);
540}
541
542// DMA_StartSG() must be paired with a DMA_Update(SH7095_mem_timestamp) somewhere before.
543void SH7095::DMA_StartSG(void)
544{
545 DMA_SGCounter = DMA_ClockCounter - 128;
546 SS_SetEventNT(&events[event_id_dma], SH7095_mem_timestamp + 32);	// fixed + 32, don't evaluate DMA_SGCounter here.
547
548 DMA_CheckEnterBurstHack();
549}
550
551// Must be called after DMACH[0].CHCR or DMACH[1].CHCR or DMAOR changes.
552INLINE void SH7095::DMA_RecalcRunning(void)
553{
554 DMA_PenaltyKludgeAmount = 0;
555
556 if(DMA_RunCond(0) || DMA_RunCond(1))
557  DMA_PenaltyKludgeAmount = 18;
558}
559
560INLINE void SH7095::DMA_BusTimingKludge(void)
561{
562 timestamp += DMA_PenaltyKludgeAccum;
563 DMA_PenaltyKludgeAccum = 0;
564}
565
566
567//
568//
569//
570void NO_INLINE SH7095::FRT_Reset(void)
571{
572 FRT.FRC = 0x00;
573 FRT.OCR[0] = FRT.OCR[1] = 0x00;
574 FRT.FICR = 0x00;
575 FRT.TIER = 0x00;
576 FRT.FTCSR = 0x00;
577 FRT.FTCSRM = 0x00;
578 FRT.TCR = 0x00;
579 FRT.TOCR = 0x00;
580 FRT.RW_Temp = 0x00;	// Reset or not?
581
582 FRT_WDT_Recalc_NET();
583 RecalcPendingIntPEX();
584}
585
586INLINE void SH7095::FRT_CheckOCR(void)
587{
588 if(FRT.FRC == FRT.OCR[0]) // OCRA
589 {
590  if(FRT.FTCSR & 0x0001)
591   FRT.FRC = 0;
592
593  if(!(FRT.FTCSR & 0x08))
594  {
595   FRT.FTCSR |= 0x08;
596   FRT.FTCSRM |= 0x08;
597   RecalcPendingIntPEX();
598  }
599 }
600
601 if(FRT.FRC == FRT.OCR[1]) // OCRB
602 {
603  if(!(FRT.FTCSR & 0x04))
604  {
605   FRT.FTCSR |= 0x04;
606   FRT.FTCSRM |= 0x04;
607   RecalcPendingIntPEX();
608  }
609 }
610}
611
612INLINE void SH7095::FRT_ClockFRC(void)
613{
614 FRT.FRC++;
615 if(!FRT.FRC)
616 {
617  if(!(FRT.FTCSR & 0x02))
618  {
619   FRT.FTCSR |= 0x02;	// OVF
620   FRT.FTCSRM |= 0x02;
621   RecalcPendingIntPEX();
622  }
623 }
624 //
625 //
626 //
627 FRT_CheckOCR();
628}
629
630
631static const uint8 wdt_cstab[8] = { 1, /**/ 6, 7, 8, 9, 10, /**/ 12, 13 };
632
633//
634// Call after:
635//	WDT.WTCSR, WDT.WTCNT, FRT.TCR, FRT.OCR[0], FRT.OCR[1] changes due to register write or similar.
636//	timestamp >= FRT_WDT_NextTS (after call to FRT_WDT_Update())
637//
638void SH7095::FRT_WDT_Recalc_NET(void)
639{
640 int32 rt = 1000;
641
642 if((FRT.TCR & 0x3) != 0x3)	// when == 3, count on rising edge of external clock(not handled here).
643 {
644  const uint32 frt_clockshift = 3 + ((FRT.TCR & 0x3) << 1);	// /8, /32, /128, count at falling edge
645  int32 next_frc = 0x10000;
646
647  if(FRT.OCR[0] > FRT.FRC)
648   next_frc = FRT.OCR[0];
649
650  if(FRT.OCR[1] > FRT.FRC)
651   next_frc = FRT.OCR[1];
652
653  rt = ((next_frc - FRT.FRC) << frt_clockshift) - (FRT_WDT_ClockDivider & ((1 << frt_clockshift) - 1));
654 }
655
656 if(WDT.WTCSR & 0x28)	// TME(0x20) and internal use standby NMI recover bit(0x08)
657 {
658  const unsigned wdt_clockshift = wdt_cstab[WDT.WTCSR & 0x7];
659  int32 wdt_rt;
660
661  wdt_rt = ((0x100 - WDT.WTCNT) << wdt_clockshift) - (FRT_WDT_ClockDivider & ((1 << wdt_clockshift) - 1));
662  rt = std::min<int32>(rt, wdt_rt);
663 }
664
665 assert(rt > 0);
666
667 FRT_WDT_NextTS = timestamp + rt;
668}
669
670void SH7095::FRT_WDT_Update(void)
671{
672 assert(timestamp >= FRT.lastts);
673
674 uint32 clocks = timestamp - FRT.lastts;
675
676 //if(clocks >= 1000)
677 // printf("%u, %d %d\n", clocks, timestamp, FRT.lastts);
678 //assert(clocks < 1000);
679
680 FRT.lastts = timestamp;
681
682 //
683 //
684 //
685 const uint32 PreAddCD = FRT_WDT_ClockDivider;
686 FRT_WDT_ClockDivider += clocks;
687
688 if((FRT.TCR & 0x3) != 0x3)	// when == 3, count on rising edge of external clock(not handled here).
689 {
690  const uint32 frt_clockshift = 3 + ((FRT.TCR & 0x3) << 1);	// /8, /32, /128, count at falling edge
691  uint32 divided_clocks = (FRT_WDT_ClockDivider >> frt_clockshift) - (PreAddCD >> frt_clockshift);
692
693  while(divided_clocks-- > 0)
694  {
695   FRT_ClockFRC();
696  }
697 }
698
699 // WDT:
700 if(WDT.WTCSR & 0x28)	// TME(0x20) and internal use standby NMI recover bit(0x08)
701 {
702  const unsigned wdt_clockshift = wdt_cstab[WDT.WTCSR & 0x7];
703  uint32 divided_clocks = (FRT_WDT_ClockDivider >> wdt_clockshift) - (PreAddCD >> wdt_clockshift);
704  uint32 tmp_counter = WDT.WTCNT;
705
706  tmp_counter += divided_clocks;
707  WDT.WTCNT = tmp_counter;
708  //
709  //
710  if(MDFN_UNLIKELY(tmp_counter >= 0x100))
711  {
712   if(MDFN_UNLIKELY(WDT.WTCSR & 0x08))
713   {
714    Standby = false;
715    WDT.WTCNT = 0x00;
716    WDT.WTCSR &= ~0x08;
717   }
718   else if(MDFN_UNLIKELY(WDT.WTCSR & 0x40))	// Watchdog timer mode
719   {
720#ifdef HAVE_DEBUG
721    SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] WDT overflow in WDT mode!\n", cpu_name);
722#endif
723    WDT.RSTCSR |= 0x80;
724
725    WDT.WTCNT = 0;
726    WDT.WTCSR = 0;
727
728    if(WDT.RSTCSR & 0x40)	// RSTE
729     Reset(!(WDT.RSTCSR & 0x20), true);
730   }
731   else
732   {
733    if(!(WDT.WTCSR & 0x80))
734    {
735     WDT.WTCSR |= 0x80;
736     WDT.WTCSRM |= 0x80;
737     RecalcPendingIntPEX();
738    }
739   }
740  }
741 }
742}
743
744void SH7095::SetFTI(bool state)
745{
746 FRT_WDT_Update();
747 //
748 //
749 bool prev = FRT.FTI;
750 FRT.FTI = state;
751
752 if((prev ^ state) & (prev ^ (FRT.TCR >> 7)))
753 {
754#ifdef HAVE_DEBUG
755  SS_DBGTI(SS_DBG_SH2, "[%s] FTI input capture triggered.", cpu_name);
756  if((FRT.FTCSR & 0x80) || (FRT.FTCSRM & 0x80))
757  {
758   SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] FTI Input capture interrupt while software not ready? FTCSR=0x%02x, FTCSRM=0x%02x\n", cpu_name, FRT.FTCSR, FRT.FTCSRM);
759  }
760#endif
761
762  FRT.FICR = FRT.FRC;
763  if(!(FRT.FTCSR & 0x80))
764  {
765   FRT.FTCSR |= 0x80;
766   FRT.FTCSRM |= 0x80;
767  }
768  RecalcPendingIntPEX();
769 }
770}
771
772void SH7095::SetFTCI(bool state)
773{
774 bool prev = FRT.FTCI;
775 FRT.FTCI = state;
776
777 if((FRT.TCR & 0x3) == 0x3)
778 {
779  if(!prev && state)
780   FRT_ClockFRC();
781 }
782}
783
784void NO_INLINE SH7095::WDT_Reset(bool from_internal_wdt)
785{
786 WDT.WTCSR = 0x00;
787 WDT.WTCSRM = 0x00;
788
789 WDT.WTCNT = 0x00;
790
791 if(!from_internal_wdt)
792 {
793  WDT.RSTCSR = 0x00;
794  WDT.RSTCSRM = 0x00;
795 }
796
797 FRT_WDT_Recalc_NET();
798 RecalcPendingIntPEX();
799}
800
801void NO_INLINE SH7095::WDT_StandbyReset(void)
802{
803 WDT.WTCSR &= 0x1F;
804 WDT.WTCSRM &= 0x1F;
805
806 WDT.RSTCSR = 0x00;
807 WDT.RSTCSRM = 0x00;
808
809 FRT_WDT_Recalc_NET();
810 RecalcPendingIntPEX();
811}
812
813//
814//
815//
816//
817//
818
819static INLINE uint64 DIVU64_Partial(uint64 dividend, uint32 divisor)
820{
821 bool M, Q;
822
823 Q = dividend >> 63;
824 M = divisor >> 31;
825
826 for(unsigned x = 0; x < 3; x++)
827 {
828	if(!(Q ^ M))
829	 dividend -= (uint64)divisor << 32;
830	else
831	 dividend += (uint64)divisor << 32;
832
833	Q = dividend >> 63;
834        dividend <<= 1;
835	dividend |= Q ^ 1 ^ M;
836 }
837
838 return dividend;
839}
840
841INLINE void SH7095::DIVU_S32_S32(void)
842{
843 if(!DVSR)
844 {
845  divide_finish_timestamp = MA_until + 2 + 6;
846
847  DVCR |= 1;
848  RecalcPendingIntPEX();
849
850  DVDNTH = (int32)DVDNT >> 29;
851
852  if(!(DVCR & 2))
853   DVDNT = DVDNTL = 0x7FFFFFFF + ((int32)DVDNT < 0);
854  else
855   DVDNT = DVDNTL = (DVDNT << 3) | (((int32)~DVDNT >> 31) & 7);
856 }
857 else
858 {
859  divide_finish_timestamp = MA_until + 1 + 39;
860
861  if(DVSR == 0xFFFFFFFF && DVDNTL == 0x80000000)
862  {
863   DVDNT = DVDNTL = 0x80000000;
864   DVDNTH = 0;
865  }
866  else
867  {
868   DVDNTH = (int32)DVDNTL % (int32)DVSR;
869   DVDNT = DVDNTL = (int32)DVDNTL / (int32)DVSR;
870  }
871 }
872 DVDNTH_Shadow = DVDNTH;
873 DVDNTL_Shadow = DVDNTL;
874}
875
876INLINE void SH7095::DIVU_S64_S32(void)
877{
878 const int32 divisor = DVSR;
879 const int64 dividend = ((int64)DVDNTH << 32) | DVDNTL;
880 int64 quotient;
881
882 if(!divisor)
883  goto Overflow;
884
885 if((uint64)dividend == (1ULL << 63) && (uint32)divisor == ~(uint32)0)
886  goto Overflow;
887
888 quotient = dividend / divisor;
889
890 //printf("Divisor=%08x, Dividend=%016llx, Quotient=%016llx\n", divisor, dividend, quotient);
891
892 if(quotient == 2147483648LL && divisor < 0 && (dividend % divisor) == 0)	// Ugh, maybe we should just implement it properly the long way...
893  goto SkipOVCheck;
894
895 if(quotient < -2147483647LL || quotient > 2147483647LL)
896 {
897  Overflow:
898  divide_finish_timestamp = timestamp + 6;
899  DVCR |= 1;
900  RecalcPendingIntPEX();
901  //
902  uint64 tmp = DIVU64_Partial(dividend, divisor);
903  DVDNTH = tmp >> 32;
904
905  if(DVCR & 2)
906   DVDNT = DVDNTL = tmp;
907  else
908   DVDNT = DVDNTL = 0x7FFFFFFF + ((int32)((dividend >> 32) ^ divisor) < 0);
909 }
910 else
911 {
912  SkipOVCheck:
913  divide_finish_timestamp = timestamp + 39;
914  DVDNTH = dividend % divisor;
915  DVDNT = DVDNTL = quotient;
916 }
917 DVDNTH_Shadow = DVDNTH;
918 DVDNTL_Shadow = DVDNTL;
919}
920
921//
922//
923// Begin SCI
924//
925//
926void SH7095::SCI_Reset(void)
927{
928 SCI.SMR = 0x00;
929 SCI.BRR = 0xFF;
930 SCI.SCR = 0x00;
931 SCI.TDR = 0xFF;
932 SCI.SSR = 0x84;
933 SCI.SSRM = 0x00;
934 SCI.RDR = 0x00;
935 //
936 SCI.RSR = 0x00;
937 SCI.TSR = 0x00;
938
939 RecalcPendingIntPEX();
940}
941
942
943//
944//
945// End SCI
946//
947//
948
949//
950// Misaligned/wrong-sized accesses aren't handled correctly, it's a mess, but probably doesn't matter.
951//
952template<typename T>
953NO_INLINE void SH7095::OnChipRegWrite(uint32 A, uint32 V)
954{
955 //SS_DBG(SS_DBG_SH2_REGW, "[%s] %zu-byte write to on-chip register area; address=0x%08x value=0x%08x\n", cpu_name, sizeof(T), A, V);
956
957 if(A & 0x100)
958 {
959  if(sizeof(T) == 2)
960   A &= 0xFE;
961  else
962   A &= 0xFC;
963
964  if(sizeof(T) == 1)
965  {
966   SetPEX(PEX_CPUADDR);
967   V |= (uint8)V << 8;
968  }
969
970  switch(A)
971  {
972   default:
973#ifdef HAVE_DEBUG
974	SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Unhandled %zu-byte write to on-chip high register area; address=0x%08x value=0x%08x\n", cpu_name, sizeof(T), A, V);
975#endif
976	break;
977
978   //
979   // Division Unit registers
980   //
981   case 0x20:
982   case 0x00:
983	DVSR = V;
984	break;
985
986   case 0x24:
987   case 0x04:
988	DVDNT = V;
989	DVDNTL = V;
990	DVDNTH = (int32)V >> 31;
991	DIVU_S32_S32();
992	break;
993
994   case 0x28:
995   case 0x08:
996	DVCR = V & 0x3;
997	break;
998
999   case 0x2C:
1000   case 0x0C:
1001	VCRDIV = V;
1002	break;
1003
1004   case 0x30:
1005   case 0x10:
1006	DVDNTH = V;
1007	break;
1008
1009   case 0x34:
1010   case 0x14:
1011	DVDNTL = V;
1012	DIVU_S64_S32();
1013	break;
1014
1015   // ?
1016   case 0x38:
1017   case 0x18:
1018	DVDNTH_Shadow = V;
1019	break;
1020
1021   case 0x3C:
1022   case 0x1C:
1023	DVDNTL_Shadow = V;
1024	break;
1025   //
1026   //
1027   //
1028
1029   //
1030   // DMA registers
1031   //
1032   case 0x80:
1033   case 0x90:
1034	DMACH[(A >> 4) & 1].SAR = V;
1035	break;
1036
1037   case 0x84:
1038   case 0x94:
1039	DMACH[(A >> 4) & 1].DAR = V;
1040	break;
1041
1042   case 0x88:
1043   case 0x98:
1044	DMACH[(A >> 4) & 1].TCR = V & 0xFFFFFF;
1045	break;
1046
1047   case 0x8C:
1048   case 0x9C:
1049	DMA_Update(SH7095_mem_timestamp);
1050	{
1051	 const unsigned ch = (A >> 4) & 1;
1052
1053	 DMACH[ch].CHCR = (V & ~2) | (DMACH[ch].CHCR & (V | DMACH[ch].CHCRM) & 2);
1054#ifdef HAVE_DEBUG
1055	 SS_DBGTI(SS_DBG_SH2, "[%s] DMA %d CHCR Write: CHCR=0x%04x SAR=0x%08x DAR=0x%08x TCR=0x%04x", cpu_name, ch, DMACH[ch].CHCR, DMACH[ch].SAR, DMACH[ch].DAR, DMACH[ch].TCR);
1056
1057	 if((DMACH[ch].CHCR & 0x1) && (DMACH[ch].CHCR & 0x3E8) != 0x200)
1058	 {
1059	  SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Unhandled CHCR on DMA channel %u: 0x%08x\n", cpu_name, ch, DMACH[ch].CHCR);
1060	 }
1061#endif
1062	}
1063	DMA_RecalcRunning();
1064	DMA_StartSG();
1065	RecalcPendingIntPEX();
1066	break;
1067
1068   case 0xA0:
1069   case 0xA8:
1070	DMACH[(A >> 3) & 1].VCR = V;
1071	break;
1072
1073   case 0xB0:
1074	DMA_Update(SH7095_mem_timestamp);
1075	DMAOR = (V & 0x9) | (DMAOR & (V | DMAORM) & 0x6);
1076	DMA_RecalcRunning();
1077	DMA_StartSG();
1078	break;
1079
1080   //
1081   // BSC registers
1082   //
1083   case 0xE0:	// BCR1
1084	if(sizeof(T) == 4 && (V & 0xFFFF0000) == 0xA55A0000)
1085	{
1086 	 BSC.BCR1 = (BSC.BCR1 & 0x8000) | (V & 0x1FF7);
1087
1088#ifdef HAVE_DEBUG
1089	 if((BSC.BCR1 & 0x7FFF) != 0x3F1)
1090	 {
1091	  SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Unusual BCR1 register value: 0x%04x\n", cpu_name, BSC.BCR1);
1092	 }
1093#endif
1094	}
1095	break;
1096
1097   case 0xE4:	// BCR2
1098	if(sizeof(T) == 4 && (V & 0xFFFF0000) == 0xA55A0000)
1099	{
1100 	 BSC.BCR2 = V & 0xFC;
1101
1102#ifdef HAVE_DEBUG
1103	 if(BSC.BCR2 != 0xFC)
1104	 {
1105	  SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Unusual BCR2 register value: 0x%02x\n", cpu_name, BSC.BCR2);
1106	 }
1107#endif
1108	}
1109	break;
1110
1111   case 0xE8:	// WCR
1112	if(sizeof(T) == 4 && (V & 0xFFFF0000) == 0xA55A0000)
1113	{
1114 	 BSC.WCR = V & 0xFFFF;
1115
1116#ifdef HAVE_DEBUG
1117	 if(BSC.WCR != 0x5555)
1118	 {
1119	  SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Unusual WCR register value: 0x%04x\n", cpu_name, BSC.WCR);
1120	 }
1121#endif
1122	}
1123	break;
1124
1125   case 0xEC:	// MCR
1126	if(sizeof(T) == 4 && (V & 0xFFFF0000) == 0xA55A0000)
1127	{
1128 	 BSC.MCR = V & 0xFEFC;
1129
1130#ifdef HAVE_DEBUG
1131	 if(BSC.MCR != 0x0078 && BSC.MCR != 0x0070)
1132	 {
1133	  SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Unusual MCR register value: 0x%04x\n", cpu_name, BSC.MCR);
1134	 }
1135#endif
1136	}
1137	break;
1138
1139   case 0xF0:	// RTCSR
1140	if(sizeof(T) == 4 && (V & 0xFFFF0000) == 0xA55A0000)
1141	{
1142 	 BSC.RTCSR = (V & 0x78) | (BSC.RTCSR & 0x80 & (V | ~BSC.RTCSRM));
1143
1144#ifdef HAVE_DEBUG
1145	 if((BSC.RTCSR & 0x78) != 0x08)
1146	 {
1147	  SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Unusual RTCSR register value: 0x%02x\n", cpu_name, BSC.RTCSR);
1148	 }
1149#endif
1150	}
1151	break;
1152
1153   case 0xF4:	// RTCNT
1154	if(sizeof(T) == 4 && (V & 0xFFFF0000) == 0xA55A0000)
1155	{
1156 	 BSC.RTCNT = V & 0xFF;
1157
1158#ifdef HAVE_DEBUG
1159	 SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] RTCNT written with: 0x%02x\n", cpu_name, BSC.RTCNT);
1160#endif
1161	}
1162	break;
1163
1164   case 0xF8: // RTCOR
1165	if(sizeof(T) == 4 && (V & 0xFFFF0000) == 0xA55A0000)
1166	{
1167 	 BSC.RTCOR = V & 0xFF;
1168
1169#ifdef HAVE_DEBUG
1170	 if(BSC.RTCOR != 0x36)
1171	 {
1172	  SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Unusual RTCOR register value: 0x%02x\n", cpu_name, BSC.RTCOR);
1173	 }
1174#endif
1175	}
1176	break;
1177  }
1178 }
1179 else
1180 {
1181  unsigned mask = 0xFFFF;
1182  unsigned shift = 0;
1183
1184  if(sizeof(T) != 2)
1185  {
1186   shift = ((A & 1) ^ 1) << 3;
1187   mask = 0xFF << shift;
1188
1189   if(sizeof(T) == 4)
1190    shift ^= 8;
1191  }
1192
1193  if(sizeof(T) == 4)
1194   SetPEX(PEX_CPUADDR);
1195
1196  switch(A & 0xFF)
1197  {
1198   default:
1199#ifdef HAVE_DEBUG
1200	SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Unhandled %zu-byte write to on-chip low register area; address=0x%08x value=0x%08x\n", cpu_name, sizeof(T), A, V);
1201#endif
1202	break;
1203
1204#if 0
1205   //
1206   // SCI registers.
1207   //
1208   case 0x00:
1209	SCI.SMR = V;
1210	break;
1211
1212   case 0x01:
1213	SCI.BRR = V;
1214	break;
1215
1216   case 0x02:
1217	SCI.SCR = V;
1218	RecalcPendingIntPEX();
1219	break;
1220
1221   case 0x03:
1222	SCI.TDR = V;
1223	break;
1224
1225   case 0x04:
1226	SCI.SSR = (SCI.SSR & ~SCI.SSRM & 0xF8) | (SCI.SSR & 0x06) | (V & 0x01);
1227	SCI.SSRM = 0;
1228	RecalcPendingIntPEX();
1229	break;
1230#endif
1231   //
1232   // Free-running timer registers.
1233   //
1234   //
1235   // TIER
1236   case 0x10:
1237	FRT_WDT_Update();
1238	//
1239	FRT.TIER = V;
1240	RecalcPendingIntPEX();
1241	break;
1242
1243   // FTCSR
1244   case 0x11:
1245	FRT_WDT_Update();
1246	//
1247	FRT.FTCSR = (FRT.FTCSR & (FRT.FTCSRM | V) & 0x8E) | (V & 0x01);
1248	RecalcPendingIntPEX();
1249	FRT_CheckOCR();
1250	break;
1251
1252   // FRCH
1253   case 0x12:
1254	FRT.RW_Temp = V;
1255	break;
1256
1257   // FRCL
1258   case 0x13:
1259	FRT_WDT_Update();
1260	//
1261	FRT.FRC = (FRT.RW_Temp << 8) | (V & 0xFF);
1262	FRT_CheckOCR();
1263	FRT_WDT_Recalc_NET();
1264	break;
1265
1266   // OCRA/B H
1267   case 0x14:
1268	FRT.RW_Temp = V;
1269	break;
1270
1271   // OCRA/B L
1272   case 0x15:
1273	FRT_WDT_Update();
1274	//
1275	FRT.OCR[(FRT.TOCR >> 4) & 1] = (FRT.RW_Temp << 8) | V;
1276	FRT_CheckOCR();
1277	FRT_WDT_Recalc_NET();
1278	break;
1279
1280   // TCR
1281   case 0x16:
1282	{
1283	 FRT_WDT_Update();
1284	 //
1285	 //const uint8 old_TCR = FRT.TCR;
1286 	 FRT.TCR = V;
1287#if 0
1288	 //
1289 	 // Maybe not worth emulating?:
1290	 //
1291	 if((old_TCR ^ FRT.TCR) & 3)
1292	 {
1293	  bool old_cs;
1294	  bool clock;
1295
1296	  if((old_TCR & 0x3) == 3)
1297	   old_cs = FRT.FTCI;
1298	  else
1299	   old_cs = (FRT_WDT_.ClockDivider >> (3 - 1 + ((old_TCR & 0x3) << 1))) & 1;
1300
1301	  if((V & 0x3) == 3)
1302	   clock = (!old_cs && FRT.FTCI);
1303	  else
1304	  {
1305	   bool new_cs = (FRT_WDT_ClockDivider >> (3 - 1 + ((FRT.TCR & 0x3) << 1))) & 1;
1306
1307	   clock = (old_cs && !new_cs);
1308	  }
1309
1310	  if(clock)
1311	   FRT_ClockFRC();
1312	 }
1313#endif
1314	 //
1315	 //
1316	 //
1317	 FRT_WDT_Recalc_NET();
1318	}
1319	break;
1320
1321   // TOCR
1322   case 0x17:
1323	FRT.TOCR = V & 0x1F;
1324	break;
1325
1326   //
1327   //
1328   //
1329   case 0x71:
1330   case 0x72:
1331	DMACH[(A & 1) ^ 1].DRCR = V & 0x3;
1332	break;
1333
1334
1335   //
1336   // WDT registers
1337   //
1338   case 0x80:
1339   case 0x88:
1340	FRT_WDT_Update();
1341	if(sizeof(T) == 2)
1342	{
1343	 if((V & 0xFF00) == 0x5A00)
1344	 {
1345	  if(WDT.WTCSR & 0x20)
1346	   WDT.WTCNT = V;
1347	 }
1348	 else if((V & 0xFF00) == 0xA500)
1349	 {
1350	  WDT.WTCSR = (WDT.WTCSR & (WDT.WTCSRM | V) & 0x80) | (V & 0x67);
1351
1352	  if(WDT.WTCSR & 0x20)
1353	   SBYCR &= 0x7F;
1354	  else
1355	  {
1356	   WDT.WTCSR &= ~0x80;	// Seemingly undocumented...
1357	   WDT.WTCNT = 0;
1358	  }
1359	 }
1360	}
1361	WDT.RSTCSRM = 0;
1362	FRT_WDT_Recalc_NET();
1363	RecalcPendingIntPEX();
1364	break;
1365
1366   case 0x82:
1367   case 0x8A:
1368	FRT_WDT_Update();
1369	if(sizeof(T) == 2)
1370	{
1371	 if(V == 0xA500)
1372	 {
1373	  // Clear OVF bit
1374	  WDT.RSTCSR &= ~WDT.RSTCSRM;
1375	 }
1376	 else if((V & 0xFF00) == 0x5A00)
1377	 {
1378	  // Write RSTE and RSTS bits
1379	  WDT.RSTCSR = (WDT.RSTCSR & 0x80) | (V & 0x60);
1380	 }
1381	}
1382	WDT.RSTCSRM = 0;
1383	break;
1384
1385   case 0x81:
1386   case 0x83:
1387   case 0x84:
1388   case 0x85:
1389   case 0x86:
1390   case 0x87:
1391   case 0x89:
1392   case 0x8B:
1393   case 0x8C:
1394   case 0x8D:
1395   case 0x8E:
1396   case 0x8F:
1397	WDT.RSTCSRM = 0;
1398	break;
1399
1400   //
1401   //
1402   //
1403   case 0x91:
1404	SBYCR = V;
1405
1406	if(WDT.WTCSR & 0x20)
1407	 SBYCR &= 0x7F;
1408
1409#ifdef HAVE_DEBUG
1410	if(SBYCR != 0)
1411	{
1412	 SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] SBYCR set to non-zero value: 0x%02x\n", cpu_name, V);
1413	}
1414#endif
1415	break;
1416
1417   case 0x92: case 0x93: case 0x94: case 0x95:
1418   case 0x96: case 0x97: case 0x98: case 0x99:
1419   case 0x9A: case 0x9B: case 0x9C: case 0x9D:
1420   case 0x9E:
1421	SetCCR(V);
1422	break;
1423
1424
1425   //
1426   //
1427   //
1428   case 0x60:
1429   case 0x61:
1430	IPRB = (IPRB &~ mask) | ((V << shift) & mask & 0xFF00);
1431	RecalcPendingIntPEX();
1432	break;
1433
1434   case 0x62:
1435   case 0x63:
1436	VCRA = (VCRA &~ mask) | ((V << shift) & mask & 0x7F7F);
1437	break;
1438
1439   case 0x64:
1440   case 0x65:
1441	VCRB = (VCRB &~ mask) | ((V << shift) & mask & 0x7F7F);
1442	break;
1443
1444   case 0x66:
1445   case 0x67:
1446	VCRC = (VCRC &~ mask) | ((V << shift) & mask & 0x7F7F);
1447	break;
1448
1449   case 0x68:
1450   case 0x69:
1451	VCRD = (VCRD &~ mask) | ((V << shift) & mask & 0x7F00);
1452	break;
1453
1454   case 0xE0:
1455   case 0xE1:
1456	ICR = (ICR &~ mask) | ((V << shift) & mask & 0x0101);
1457#ifdef HAVE_DEBUG
1458	if(ICR & 0x0100)
1459	{
1460	 SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] NMIE=1\n", cpu_name);
1461	}
1462#endif
1463	RecalcPendingIntPEX();
1464	break;
1465
1466   case 0xE2:
1467   case 0xE3:
1468	IPRA = (IPRA &~ mask) | ((V << shift) & mask & 0xFFF0);
1469	RecalcPendingIntPEX();
1470	break;
1471
1472   case 0xE4:
1473   case 0xE5:
1474	VCRWDT = (VCRWDT &~ mask) | ((V << shift) & mask & 0x7F7F);
1475	break;
1476  }
1477 }
1478}
1479
1480template<typename T>
1481INLINE T SH7095::OnChipRegRead(uint32 A)
1482{
1483 if(A & 0x100)
1484 {
1485  uint32 ret = 0;
1486
1487  MA_until++;
1488
1489  if(sizeof(T) == 2)
1490   A &= 0xFE;
1491  else
1492   A &= 0xFC;
1493
1494  if(sizeof(T) == 1)
1495   SetPEX(PEX_CPUADDR);
1496
1497  switch(A)
1498  {
1499   default:
1500#ifdef HAVE_DEBUG
1501	SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Unhandled %zu-byte read from on-chip high register area; address=0x%08x\n", cpu_name, sizeof(T), A);
1502#endif
1503	break;
1504
1505   //
1506   // Division Unit registers
1507   //
1508   case 0x20:
1509   case 0x22:
1510   case 0x00:
1511   case 0x02:
1512	MA_until = std::max<sscpu_timestamp_t>(MA_until, divide_finish_timestamp);
1513	ret = DVSR;
1514	break;
1515
1516   case 0x24:
1517   case 0x26:
1518   case 0x04:
1519   case 0x06:
1520	MA_until = std::max<sscpu_timestamp_t>(MA_until, divide_finish_timestamp);
1521	ret = DVDNT;
1522	break;
1523
1524   case 0x28:
1525   case 0x2A:
1526   case 0x08:
1527   case 0x0A:
1528	MA_until = std::max<sscpu_timestamp_t>(MA_until, divide_finish_timestamp);
1529	ret = DVCR;
1530	break;
1531
1532   case 0x2C:
1533   case 0x2E:
1534   case 0x0C:
1535   case 0x0E:
1536	MA_until = std::max<sscpu_timestamp_t>(MA_until, divide_finish_timestamp);
1537	ret = VCRDIV;
1538	break;
1539
1540   case 0x30:
1541   case 0x32:
1542   case 0x10:
1543   case 0x12:
1544	MA_until = std::max<sscpu_timestamp_t>(MA_until, divide_finish_timestamp);
1545	ret = DVDNTH;
1546	break;
1547
1548   case 0x34:
1549   case 0x36:
1550   case 0x14:
1551   case 0x16:
1552	MA_until = std::max<sscpu_timestamp_t>(MA_until, divide_finish_timestamp);
1553	ret = DVDNTL;
1554	break;
1555
1556   // ?
1557   case 0x38:
1558   case 0x3A:
1559   case 0x18:
1560   case 0x1A:
1561	MA_until = std::max<sscpu_timestamp_t>(MA_until, divide_finish_timestamp);
1562	ret = DVDNTH_Shadow;
1563	break;
1564
1565   case 0x3C:
1566   case 0x3E:
1567   case 0x1C:
1568   case 0x1E:
1569	MA_until = std::max<sscpu_timestamp_t>(MA_until, divide_finish_timestamp);
1570	ret = DVDNTL_Shadow;
1571	break;
1572   //
1573   //
1574   //
1575
1576   //
1577   // DMA registers
1578   //
1579   case 0x80:
1580   case 0x90:
1581	ret = DMACH[(A >> 4) & 1].SAR;
1582	break;
1583
1584   case 0x84:
1585   case 0x94:
1586	ret = DMACH[(A >> 4) & 1].DAR;
1587	break;
1588
1589   case 0x88:
1590   case 0x98:
1591	ret = DMACH[(A >> 4) & 1].TCR;
1592	break;
1593
1594   case 0x8C:
1595   case 0x9C:
1596	{
1597	 const unsigned ch = (A >> 4) & 1;
1598
1599	 ret = DMACH[ch].CHCR;
1600	 DMACH[ch].CHCRM = 0;
1601	}
1602	break;
1603
1604   case 0xA0:
1605   case 0xA8:
1606	ret = DMACH[(A >> 3) & 1].VCR;
1607	break;
1608
1609   case 0xB0:
1610	ret = DMAOR;
1611	DMAORM = 0;
1612	break;
1613
1614   //
1615   // BSC registers
1616   //
1617   case 0xE0:	// BCR1
1618   case 0xE2:
1619	ret = BSC.BCR1;
1620	break;
1621
1622   case 0xE4:	// BCR2
1623   case 0xE6:
1624	ret = BSC.BCR2;
1625	break;
1626
1627   case 0xE8:	// WCR
1628   case 0xEA:
1629	ret = BSC.WCR;
1630	break;
1631
1632   case 0xEC:	// MCR
1633   case 0xEE:
1634	ret = BSC.MCR;
1635	break;
1636
1637   case 0xF0:	// RTCSR
1638   case 0xF2:
1639	ret = BSC.RTCSR;
1640	BSC.RTCSRM = BSC.RTCSR & 0x80;
1641
1642#ifdef HAVE_DEBUG
1643	SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Read from RTCSR\n", cpu_name);
1644#endif
1645	break;
1646
1647   case 0xF4:	// RTCNT
1648   case 0xF6:
1649	ret = BSC.RTCNT;
1650
1651#ifdef HAVE_DEBUG
1652	SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Read from RTCNT\n", cpu_name);
1653#endif
1654	break;
1655
1656   case 0xF8:	// RTCOR
1657   case 0xFA:
1658	ret = BSC.RTCOR;
1659	break;
1660  }
1661
1662  if(sizeof(T) == 1)
1663   ret >>= ((A & 1) ^ 1) << 3;
1664
1665  return ret;
1666 }
1667 else
1668 {
1669  const unsigned Am = (uint8)A;
1670  const unsigned shift = ((sizeof(T) != 2) ? (((A & 1) ^ 1) << 3) : 0);
1671  uint16 ret = 0;
1672
1673  if(Am < 0x20)
1674   MA_until = (MA_until + 11) &~ 1; // FIXME: not quite right. //3;
1675  else if((Am >= 0x60 && Am < 0xA0) || Am >= 0xE0)
1676   MA_until += 3;
1677  else
1678   MA_until += 1;
1679
1680  if(sizeof(T) == 4)
1681   SetPEX(PEX_CPUADDR);
1682
1683  else switch(Am)
1684  {
1685   default:
1686#ifdef HAVE_DEBUG
1687	SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Unhandled %zu-byte read from on-chip low register area; address=0x%08x\n", cpu_name, sizeof(T), A);
1688#endif
1689	break;
1690
1691#if 0
1692   //
1693   // SCI registers.
1694   //
1695   case 0x00:
1696	ret = SCI.SMR;
1697	break;
1698
1699   case 0x01:
1700	ret = SCI.BRR;
1701	break;
1702
1703   case 0x02:
1704	ret = SCI.SCR;
1705	break;
1706
1707   case 0x03:
1708	ret = SCI.TDR;
1709	break;
1710
1711   case 0x04:
1712	ret = SCI.SSR;
1713	SCI.SSRM = SCI.SSR & 0xF8;
1714	break;
1715
1716   case 0x05:
1717	ret = SCI.RDR;
1718	break;
1719#endif
1720   //
1721   // FRT registers.  Some weirdness with 16-bit reads duplicating the lower 8 bits in the upper 8-bits, but the upper 8-bits are masked
1722   // with the last data written to the FRT area or something...not emulated here.
1723   //
1724   case 0x10:
1725	ret = FRT.TIER | 1;
1726	break;
1727
1728   case 0x11:
1729	FRT_WDT_Update();
1730	//
1731	ret = FRT.FTCSR;
1732	FRT.FTCSRM = 0x00;
1733	break;
1734
1735   case 0x12:
1736	FRT_WDT_Update();
1737	//
1738	FRT.RW_Temp = FRT.FRC;
1739	ret = FRT.FRC >> 8;
1740	break;
1741
1742   case 0x13:
1743	ret = FRT.RW_Temp;
1744	break;
1745
1746   case 0x14:
1747	ret = FRT.OCR[(FRT.TOCR >> 4) & 1] >> 8;
1748	break;
1749
1750   case 0x15:
1751	ret = FRT.OCR[(FRT.TOCR >> 4) & 1] & 0xFF;
1752	break;
1753
1754   case 0x16:
1755	ret = FRT.TCR;
1756	break;
1757
1758   case 0x17:
1759	ret = FRT.TOCR | 0xE0;
1760	break;
1761
1762   case 0x18:
1763	FRT.RW_Temp = FRT.FICR;
1764	ret = FRT.FICR >> 8;
1765	break;
1766
1767   case 0x19:
1768	ret = FRT.RW_Temp;
1769	break;
1770
1771   //
1772   //
1773   //
1774   case 0x71:
1775   case 0x72:
1776	ret = DMACH[(A & 1) ^ 1].DRCR;
1777	break;
1778
1779
1780   //
1781   // WDT registers
1782   //
1783   case 0x80:
1784   case 0x88:
1785	FRT_WDT_Update();
1786	ret = WDT.WTCSR | 0x18;
1787	WDT.WTCSRM = 0x00;
1788	break;
1789
1790   case 0x81:
1791   case 0x89:
1792	FRT_WDT_Update();
1793	ret = WDT.WTCNT;
1794	break;
1795
1796   case 0x82:
1797   case 0x85:
1798   case 0x86:
1799   case 0x87:
1800   case 0x8A:
1801   case 0x8D:
1802   case 0x8E:
1803   case 0x8F:
1804	ret = 0xFF;
1805	break;
1806
1807   case 0x83:
1808   case 0x8B:
1809	FRT_WDT_Update();
1810	ret = WDT.RSTCSR | 0x1F;
1811	WDT.RSTCSRM = (WDT.RSTCSR & 0x80);
1812	break;
1813
1814   // FIXME: WDT open bus of a sort.
1815   // case 0x84:
1816   // case 0x8C:
1817
1818   //
1819   //
1820   //
1821
1822   case 0x91:
1823	ret = SBYCR;
1824	break;
1825
1826   case 0x92: case 0x93: case 0x94: case 0x95:
1827   case 0x96: case 0x97: case 0x98: case 0x99:
1828   case 0x9A: case 0x9B: case 0x9C: case 0x9D:
1829   case 0x9E:
1830	ret = CCR | (CCR << 8);
1831	break;
1832   //
1833   //
1834   //
1835   case 0x60:
1836   case 0x61:
1837	ret = IPRB >> shift;
1838	break;
1839
1840   case 0x62:
1841   case 0x63:
1842	ret = VCRA >> shift;
1843	break;
1844
1845   case 0x64:
1846   case 0x65:
1847	ret = VCRB >> shift;
1848	break;
1849
1850   case 0x66:
1851   case 0x67:
1852	ret = VCRC >> shift;
1853	break;
1854
1855   case 0x68:
1856   case 0x69:
1857	ret = VCRD >> shift;
1858	break;
1859
1860   case 0x6A: case 0x6B: case 0x6C: case 0x6D: case 0x6E: case 0x6F:
1861	ret = 0xFFFF >> shift;
1862	break;
1863
1864   case 0xE0:
1865   case 0xE1:
1866	ret = (ICR | (NMILevel << 15)) >> shift;
1867	break;
1868
1869   case 0xE2:
1870   case 0xE3:
1871	ret = IPRA >> shift;
1872	break;
1873
1874   case 0xE4:
1875   case 0xE5:
1876	ret = VCRWDT >> shift;
1877	break;
1878
1879   case 0xE6: case 0xE7:
1880   case 0xE8: case 0xE9: case 0xEA: case 0xEB: case 0xEC: case 0xED: case 0xEE: case 0xEF:
1881   case 0xF0: case 0xF1: case 0xF2: case 0xF3: case 0xF4: case 0xF5: case 0xF6: case 0xF7:
1882   case 0xF8: case 0xF9: case 0xFA: case 0xFB: case 0xFC: case 0xFD: case 0xFE: case 0xFF:
1883	ret = 0xFFFF >> shift;
1884	break;
1885  }
1886
1887  return ret;
1888 }
1889}
1890
1891template<typename T, bool BurstHax>
1892INLINE T SH7095::ExtBusRead(uint32 A)
1893{
1894 T ret;
1895
1896 A &= (1U << 27) - 1;
1897
1898 if(timestamp > SH7095_mem_timestamp)
1899  SH7095_mem_timestamp = timestamp;
1900
1901 //
1902 if(!BurstHax)
1903 {
1904  DMA_PenaltyKludgeAccum += DMA_PenaltyKludgeAmount;
1905 }
1906 //
1907
1908 ret = SH7095_BusRead<T>(A, BurstHax, NULL);
1909
1910 return ret;
1911}
1912
1913template<typename T>
1914INLINE void SH7095::ExtBusWrite(uint32 A, T V)
1915{
1916 A &= (1U << 27) - 1;
1917
1918 if(timestamp > SH7095_mem_timestamp)
1919  SH7095_mem_timestamp = timestamp;
1920
1921 //
1922 {
1923  DMA_PenaltyKludgeAccum += DMA_PenaltyKludgeAmount;
1924 }
1925 //
1926
1927 SH7095_BusWrite<T>(A, V, false, NULL);
1928
1929 write_finish_timestamp = SH7095_mem_timestamp;
1930}
1931
1932
1933//
1934//
1935//
1936static const struct
1937{
1938 uint8 AND;
1939 uint8 OR;
1940} LRU_Update_Tab[4] =
1941{
1942 { (1 << 2) | (1 << 1) | (1 << 0), /**/ (0 << 5) | (0 << 4) | (0 << 3) },	// Way 0
1943 { (1 << 4) | (1 << 3) | (1 << 0), /**/ (1 << 5) | (0 << 2) | (0 << 1) },	// Way 1
1944 { (1 << 5) | (1 << 3) | (1 << 1), /**/ (1 << 4) | (1 << 2) | (0 << 0) },	// Way 2
1945 { (1 << 5) | (1 << 4) | (1 << 2), /**/ (1 << 3) | (1 << 1) | (1 << 0) },	// Way 3
1946};
1947
1948static const int8 LRU_Replace_Tab[0x40] =
1949{
1950 /* 0x00 */ 0x03, 0x02,   -1, 0x02, 0x03,   -1, 0x01, 0x01,   -1, 0x02,   -1, 0x02,   -1,   -1, 0x01, 0x01,
1951 /* 0x10 */ 0x03,   -1,   -1,   -1, 0x03,   -1, 0x01, 0x01,   -1,   -1,   -1,   -1,   -1,   -1, 0x01, 0x01,
1952 /* 0x20 */ 0x03, 0x02,   -1, 0x02, 0x03,   -1,   -1,   -1,   -1, 0x02,   -1, 0x02,   -1,   -1,   -1,   -1,
1953 /* 0x30 */ 0x03,   -1,   -1,   -1, 0x03,   -1,   -1,   -1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1954};
1955
1956static INLINE uint32 cmov_eq_thing(const uint32 reg_compval, const uint32 mem_compval, uint32 var, const uint32 repl_var)
1957{
1958 #ifdef ARCH_X86
1959 asm(	"cmpl %1, %2\n\t"
1960	"cmove %3,%0\n\t"
1961	: "+r"(var)
1962	: "r"(reg_compval), "g"(mem_compval), "r"(repl_var)
1963	: "cc");
1964 #else
1965  #ifdef __GNUC__
1966   #warning "Conditional move inline assembly not being used."
1967  #endif
1968 var = ((reg_compval == mem_compval) ? repl_var : var);
1969 #endif
1970
1971 return var;
1972}
1973
1974INLINE void SH7095::AssocPurge(const uint32 A)
1975{
1976 const uint32 ATM = A & (0x7FFFF << 10);
1977 auto* cent = &Cache[(A >> 4) & 0x3F];
1978
1979 // Ignore two-way-mode bit in CCR here.
1980 if(ATM == cent->Tag[0]) cent->Tag[0] |= 1U << 31;	// Set invalid bit to 1.
1981 if(ATM == cent->Tag[1]) cent->Tag[1] |= 1U << 31;
1982 if(ATM == cent->Tag[2]) cent->Tag[2] |= 1U << 31;
1983 if(ATM == cent->Tag[3]) cent->Tag[3] |= 1U << 31;
1984}
1985
1986template<typename T, unsigned region, bool CacheEnabled, bool TwoWayMode, bool IsInstr, bool CacheBypassHack>
1987INLINE T SH7095::MemReadRT(uint32 A)
1988{
1989 static_assert(region < 0x8, "Wrong region argument.");
1990 const uint32 unmasked_A = A;
1991
1992 if(!IsInstr)
1993 {
1994  if(MDFN_UNLIKELY(A & (sizeof(T) - 1)))
1995  {
1996#ifdef HAVE_DEBUG
1997   SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Misaligned %zu-byte read from 0x%08x\n", cpu_name, sizeof(T), A);
1998#endif
1999   A &= ~(sizeof(T) - 1);
2000   SetPEX(PEX_CPUADDR);
2001  }
2002 }
2003
2004 if(!IsInstr)
2005  MA_until = std::max<sscpu_timestamp_t>(MA_until, timestamp + 1);
2006 else
2007  timestamp = std::max<sscpu_timestamp_t>(MA_until, timestamp);
2008
2009#ifdef MDFN_SS_DEV_BUILD
2010  if((A & 0xC7FFFFFF) >= 0x06000200 && (A & 0xC7FFFFFF) <= 0x060003FF)
2011  {
2012   const uint32 pcm = PC & 0x07FFFFFF;
2013   bool match = (pcm >= 0x100000) && (pcm < 0x06000600 || pcm >= 0x06000A00);
2014
2015#ifdef HAVE_DEBUG
2016   if(match && !BWMIgnoreAddr[0][A & 0x1FF])
2017   {
2018    SS_DBG(SS_DBG_BIOS, "[%s] Read from BIOS area of RAM 0x%08x; PC=0x%08x\n", cpu_name, A, PC);
2019   }
2020#endif
2021  }
2022
2023  if((A & 0xC7FFFFFF) >= 0x00000200/*0x00000004*//*0x00000000*/ && (A & 0xC7FFFFFF) <= 0x000FFFFF)
2024  {
2025   const uint32 pcm = PC & 0x07FFFFFF;
2026   bool match = (pcm >= 0x100000) && (pcm < 0x06000600 || pcm >= 0x06000A00);
2027
2028   if(match)
2029    SS_DBG(SS_DBG_BIOS, "[%s] Read from BIOS ROM 0x%06x; PC=0x%08x\n", cpu_name, A, PC);
2030  }
2031#endif
2032
2033 //
2034 // WARNING: Template arguments CacheEnabled and TwoWayMode are only valid for region==0.  In addition, TwoWayMode is only valid for CacheEnabled==true.
2035 //
2036 switch(region)	// A >> 29
2037 {
2038  case 0:
2039	if(CacheEnabled)
2040	{
2041	 const uint32 ATM = A & (0x7FFFF << 10);
2042	 auto* cent = &Cache[(A >> 4) & 0x3F];
2043	 int way_match = -1;
2044
2045	 way_match = cmov_eq_thing(ATM, cent->Tag[0], way_match, 0);
2046	 way_match = cmov_eq_thing(ATM, cent->Tag[1], way_match, 1);
2047	 way_match = cmov_eq_thing(ATM, cent->Tag[2], way_match, 2);
2048	 way_match = cmov_eq_thing(ATM, cent->Tag[3], way_match, 3);
2049
2050	 if(MDFN_UNLIKELY(way_match < 0)) // Cache miss!
2051	 {
2052	  if(IsInstr)
2053	  {
2054	   if(MDFN_UNLIKELY(CCR & CCR_ID))
2055	    goto EBRCase;
2056	  }
2057	  else
2058	  {
2059	   if(MDFN_UNLIKELY(CCR & CCR_OD))
2060	    goto EBRCase;
2061	  }
2062
2063	  if(TwoWayMode)
2064	   way_match = 3 ^ (cent->LRU & 0x1);
2065	  else
2066	   way_match = LRU_Replace_Tab[cent->LRU];
2067
2068	  if(MDFN_UNLIKELY(way_match < 0))
2069	   goto EBRCase;
2070
2071	  //
2072	  // Load cache line.
2073	  //
2074	  //printf("Cache load line: %08x\n", A);
2075	  cent->Tag[way_match] = ATM;
2076
2077	  {
2078	   unsigned di = (A + 4 + 0) & 0xC; MDFN_ennsb<uint32, true>(&cent->Data[way_match][di], ExtBusRead<uint32, false>((A &~ 0xF) + di));
2079	  }
2080	  for(unsigned i = 4; i < 16; i += 4)
2081	  {
2082	   unsigned di = (A + 4 + i) & 0xC; MDFN_ennsb<uint32, true>(&cent->Data[way_match][di], ExtBusRead<uint32,  true>((A &~ 0xF) + di));
2083	  }
2084	  if(!IsInstr)
2085	   MA_until = std::max<sscpu_timestamp_t>(MA_until, SH7095_mem_timestamp + 1);
2086	  else
2087	   timestamp = SH7095_mem_timestamp;
2088	 }
2089
2090	 if((SH7095_FastMap[A >> SH7095_EXT_MAP_GRAN_BITS] + (A & ~((1U << SH7095_EXT_MAP_GRAN_BITS) - 1))) == (uintptr_t)fmap_dummy)
2091	  SS_DBG(SS_DBG_WARNING | SS_DBG_SH2_CACHE, "[%s] Cacheable %zu-byte read from non-RAM address 0x%08x!\n", cpu_name, sizeof(T), A);
2092	 else if(ne16_rbo_be<T>(SH7095_FastMap[A >> SH7095_EXT_MAP_GRAN_BITS], A) != MDFN_densb<T, true>(&cent->Data[way_match][NE32ASU8_IDX_ADJ(T, A & 0x0F)]))
2093	  SS_DBG(SS_DBG_WARNING | SS_DBG_SH2_CACHE, "[%s] Cache incoherency for %zu-byte read from address 0x%08x!\n", cpu_name, sizeof(T), A);
2094
2095	 cent->LRU = (cent->LRU & LRU_Update_Tab[way_match].AND) | LRU_Update_Tab[way_match].OR;
2096
2097	 // Ugggghhhh....
2098	 if(CacheBypassHack && FMIsWriteable[A >> SH7095_EXT_MAP_GRAN_BITS])
2099	  return ne16_rbo_be<T>(SH7095_FastMap[A >> SH7095_EXT_MAP_GRAN_BITS], A);
2100
2101  	 return MDFN_densb<T, true>(&cent->Data[way_match][NE32ASU8_IDX_ADJ(T, A & 0x0F)]);
2102	}
2103	// Fall-through, no break here
2104  case 1:
2105	EBRCase:
2106	{
2107	 T ret = ExtBusRead<T, false>(A);
2108
2109	 if(!IsInstr)
2110	  MA_until = std::max<sscpu_timestamp_t>(MA_until, SH7095_mem_timestamp + 1);
2111	 else
2112	  timestamp = SH7095_mem_timestamp;
2113
2114	 return ret;
2115	}
2116
2117  case 2:
2118  case 5:
2119	//
2120	// Associative purge(apparently returns open bus of some sort)
2121	//
2122	//SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] %zu-byte read from associative purge area; address=0x%08x\n", cpu_name, sizeof(T), A);
2123	AssocPurge(A);
2124	return ~0;
2125
2126  case 3:
2127	//
2128	// Direct cache address/tag access
2129	//
2130	// Note: bits 0, 1, 3, 29, 30, 31 are some sort of open-bus(unemulated).
2131	//
2132	// SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] %zu-byte read from cache address array area; address=0x%08x\n", cpu_name, sizeof(T), A);
2133	{
2134	 const unsigned way = (CCR >> 6) & 0x3;
2135	 const unsigned ena = (A >> 4) & 0x3F;
2136
2137	 return (Cache[ena].Tag[way] & (0x7FFFF << 10)) | (((int32)~Cache[ena].Tag[way] >> 31) & 0x4) | (Cache[ena].LRU << 4);
2138	}
2139
2140  case 4:
2141  case 6:
2142	//
2143	// Direct cache data access
2144	//
2145	//SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] %zu-byte read from cache data array area; address=0x%08x\n", cpu_name, sizeof(T), A);
2146	{
2147	 const unsigned way = (A >> 10) & 0x3;
2148	 const unsigned ena = (A >> 4) & 0x3F;
2149
2150	 return MDFN_densb<T, true>(&Cache[ena].Data[way][NE32ASU8_IDX_ADJ(T, A & 0x0F)]);
2151	}
2152
2153  case 7:
2154	return OnChipRegRead<T>(unmasked_A);
2155 }
2156}
2157
2158template<typename T>
2159INLINE T SH7095::MemRead(uint32 A)
2160{
2161 if(sizeof(T) == 1)
2162  return MRFP8[A >> 29](A);
2163 else if(sizeof(T) == 2)
2164  return MRFP16[A >> 29](A);
2165 else
2166  return MRFP32[A >> 29](A);
2167}
2168
2169template<typename T>
2170INLINE void SH7095::Write_UpdateCache(uint32 A, T V)
2171{
2172 const uint32 ATM = A & (0x7FFFF << 10);
2173 auto* cent = &Cache[(A >> 4) & 0x3F];
2174 int way_match = -1;
2175
2176 way_match = cmov_eq_thing(ATM, cent->Tag[0], way_match, 0);
2177 way_match = cmov_eq_thing(ATM, cent->Tag[1], way_match, 1);
2178 way_match = cmov_eq_thing(ATM, cent->Tag[2], way_match, 2);
2179 way_match = cmov_eq_thing(ATM, cent->Tag[3], way_match, 3);
2180
2181 if(MDFN_LIKELY(way_match >= 0)) // Cache hit!
2182 {
2183  cent->LRU = (cent->LRU & LRU_Update_Tab[way_match].AND) | LRU_Update_Tab[way_match].OR;
2184  MDFN_ennsb<T, true>(&cent->Data[way_match][NE32ASU8_IDX_ADJ(T, A & 0x0F)], V);	// Ignore CCR OD bit here.
2185 }
2186}
2187
2188template<typename T, unsigned region, bool CacheEnabled>
2189INLINE void SH7095::MemWriteRT(uint32 A, T V)
2190{
2191 static_assert(region < 0x8, "Wrong region argument.");
2192 const uint32 unmasked_A = A;
2193
2194 if(MDFN_UNLIKELY(A & (sizeof(T) - 1)))
2195 {
2196  SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Misaligned %zu-byte write of 0x%08x to 0x%08x\n", cpu_name, sizeof(T), V, A);
2197  A &= ~(sizeof(T) - 1);
2198  SetPEX(PEX_CPUADDR);
2199 }
2200
2201 MA_until = std::max<sscpu_timestamp_t>(MA_until, timestamp + 1);
2202
2203#ifdef MDFN_SS_DEV_BUILD
2204  if((A & 0xC7FFFFFF) >= 0x06000200 && (A & 0xC7FFFFFF) <= 0x060003FF)
2205  {
2206   const uint32 pcm = PC & 0x07FFFFFF;
2207   bool match = (pcm >= 0x100000) && (pcm < 0x06000600 || pcm >= 0x06000800);
2208
2209   if(match && !BWMIgnoreAddr[1][A & 0x1FF])
2210   {
2211    SS_DBG(SS_DBG_BIOS, "[%s] Write to BIOS area of RAM 0x%08x; PC=0x%08x\n", cpu_name, A, PC);
2212   }
2213  }
2214#endif
2215
2216 //
2217 // WARNING: Template argument CacheEnabled is only valid for region==0.
2218 //
2219 switch(region)	// A >> 29
2220 {
2221  case 0:
2222	if(CacheEnabled)
2223	 Write_UpdateCache<T>(A, V);
2224	// Fall-through, no break
2225  case 1:
2226  	MA_until = std::max<sscpu_timestamp_t>(MA_until, write_finish_timestamp + 1);
2227
2228	ExtBusWrite<T>(A, V);
2229	return;
2230
2231  case 2:
2232  case 5:
2233	//
2234	// Associative purge.
2235	//
2236	//SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] %zu-byte write to associative purge area; address=0x%08x value=0x%x\n", cpu_name, sizeof(T), A, V);
2237	AssocPurge(A);
2238	return;
2239
2240  case 3:
2241	//
2242	// Direct cache address/tag access
2243	//
2244	// TODO: Check non-32 bit access
2245	//SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] %zu-byte write to cache address array area; address=0x%08x value=0x%x\n", cpu_name, sizeof(T), A, V);
2246	timestamp++;
2247	MA_until = std::max<sscpu_timestamp_t>(MA_until, timestamp + 1);
2248	{
2249	 const unsigned way = (CCR >> 6) & 0x3;
2250	 const unsigned ena = (A >> 4) & 0x3F;
2251
2252	 Cache[ena].Tag[way] = (A & (0x7FFFF << 10)) | ((!(A & 0x4)) << 31);
2253	 Cache[ena].LRU = (V >> 4) & 0x3F;
2254	}
2255	return;
2256
2257  case 4:
2258  case 6:
2259	//
2260	// Direct cache data access
2261	//
2262	//SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] %zu-byte write to cache data array area; address=0x%08x value=0x%x\n", cpu_name, sizeof(T), A, V);
2263	{
2264	 const unsigned way = (A >> 10) & 0x3;
2265	 const unsigned ena = (A >> 4) & 0x3F;
2266
2267	 MDFN_ennsb<T, true>(&Cache[ena].Data[way][NE32ASU8_IDX_ADJ(T, A & 0x0F)], V);
2268	}
2269	return;
2270
2271  case 7:
2272	OnChipRegWrite<T>(unmasked_A, V);
2273	return;
2274 }
2275}
2276
2277template<typename T>
2278INLINE void SH7095::MemWrite(uint32 A, T V)
2279{
2280 if(sizeof(T) == 1)
2281  MWFP8[A >> 29](A, V);
2282 else if(sizeof(T) == 2)
2283  MWFP16[A >> 29](A, V);
2284 else
2285  MWFP32[A >> 29](A, V);
2286}
2287
2288
2289template<unsigned which, typename T, unsigned region, bool CacheEnabled, bool TwoWayMode, bool IsInstr, bool CacheBypassHack>
2290static NO_INLINE MDFN_FASTCALL T C_MemReadRT(uint32 A)
2291{
2292 return CPU[which].MemReadRT<T, region, CacheEnabled, TwoWayMode, IsInstr, CacheBypassHack>(A);
2293}
2294
2295template<unsigned which, typename T, unsigned region, bool CacheEnabled>
2296static NO_INLINE MDFN_FASTCALL void C_MemWriteRT(uint32 A, T V)
2297{
2298 CPU[which].MemWriteRT<T, region, CacheEnabled>(A, V);
2299}
2300
2301
2302INLINE void SH7095::SetCCR(uint8 V)
2303{
2304 if(CCR != V)
2305  SS_DBG(SS_DBG_SH2_CACHE, "[%s] CCR changed: 0x%02x->0x%02x%s\n", cpu_name, CCR, V, (V & CCR_CP) ? " (CACHE PURGE!)" : "");
2306
2307 if(V & CCR_CP)
2308 {
2309  for(unsigned entry = 0; entry < 64; entry++)
2310  {
2311   Cache[entry].LRU = 0;
2312   for(unsigned way = 0; way < 4; way++)
2313    Cache[entry].Tag[way] |= 1U << 31;	// Set invalid bit to 1.
2314  }
2315  V &= ~CCR_CP;
2316 }
2317 CCR = V;
2318
2319 #define MAHL(bs,w,cbh)										\
2320		 if(CCR & CCR_CE)								\
2321		 {										\
2322		  if(CCR & CCR_TW)								\
2323		  {										\
2324		   MRFP##bs[0] = C_MemReadRT <w, uint##bs, 0x0, true, true, false, cbh>;	\
2325		   MRFPI[0]    = C_MemReadRT <w, uint32,   0x0, true, true, true, cbh>;		\
2326		  }										\
2327		  else										\
2328		  {										\
2329		   MRFP##bs[0] = C_MemReadRT <w, uint##bs, 0x0, true, false, false, cbh>;	\
2330		   MRFPI[0]    = C_MemReadRT <w, uint32,   0x0, true, false, true, cbh>;	\
2331		  }										\
2332		  MWFP##bs[0] = C_MemWriteRT<w, uint##bs, 0x0, true>;				\
2333		 }										\
2334		 else										\
2335		 {										\
2336		  MRFP##bs[0] =  C_MemReadRT <w, uint##bs, 0x0, false, false, false, cbh>;	\
2337		  MRFPI[0]    =  C_MemReadRT <w, uint32,   0x0, false, false, true, cbh>;	\
2338		  MWFP##bs[0] =  C_MemWriteRT<w, uint##bs, 0x0, false>;				\
2339		 }
2340 if(this == &CPU[0])
2341 {
2342  if(CBH_Setting)
2343  {
2344   MAHL( 8, 0, true)
2345   MAHL(16, 0, true)
2346   MAHL(32, 0, true)
2347  }
2348  else
2349  {
2350   MAHL( 8, 0, false)
2351   MAHL(16, 0, false)
2352   MAHL(32, 0, false)
2353  }
2354 }
2355 else
2356 {
2357  if(CBH_Setting)
2358  {
2359   MAHL( 8, 1, true)
2360   MAHL(16, 1, true)
2361   MAHL(32, 1, true)
2362  }
2363  else
2364  {
2365   MAHL( 8, 1, false)
2366   MAHL(16, 1, false)
2367   MAHL(32, 1, false)
2368  }
2369 }
2370 #undef MAHL
2371}
2372
2373
2374
2375
2376/*
2377
2378
2379*/
2380void NO_INLINE SH7095::Reset(bool power_on_reset, bool from_internal_wdt)
2381{
2382 VBR = 0;
2383 SR |= 0xF << 4;
2384 SetCCR(0);
2385 //
2386 if(power_on_reset)
2387 {
2388  BSC.BCR1 = (BSC.BCR1 & 0x8000) | 0x03F0;
2389  BSC.BCR2 = 0xFC;
2390  BSC.WCR = 0xAAFF;
2391  BSC.MCR = 0x0000;
2392
2393  BSC.RTCSR = 0x00;
2394  BSC.RTCSRM = 0x00;
2395  BSC.RTCNT = 0x00;
2396  BSC.RTCOR = 0x00;
2397 }
2398 //
2399 for(unsigned ch = 0; ch < 2; ch++)
2400 {
2401  DMACH[ch].CHCR = 0x00;
2402  DMACH[ch].CHCRM = 0x00;
2403  DMACH[ch].DRCR = 0x00;
2404 }
2405 DMAOR = 0x00;
2406 DMA_RecalcRunning();
2407 RecalcPendingIntPEX();
2408 //
2409 INTC_Reset();
2410 //
2411 DVCR = 0;
2412 RecalcPendingIntPEX();
2413 //
2414 FRT_Reset();
2415 WDT_Reset(from_internal_wdt);
2416 //
2417 SCI_Reset();
2418 //
2419 SBYCR = 0;
2420 Standby = false;
2421 //
2422 //
2423 //
2424 EPending = 0;
2425 SetPEX(power_on_reset ? PEX_POWERON : PEX_RESET);
2426 Pipe_ID = EPending;
2427}
2428
2429void NO_INLINE SH7095::INTC_Reset(void)
2430{
2431 IPRA = 0;
2432 IPRB = 0;
2433 VCRA = 0;
2434 VCRB = 0;
2435 VCRC = 0;
2436 VCRD = 0;
2437 VCRWDT = 0;
2438 ICR = 0;
2439
2440 RecalcPendingIntPEX();
2441}
2442
2443void SH7095::SetNMI(bool level)
2444{
2445 //printf("NMI: %d, %d %d\n", NMILevel, level, (bool)(ICR & 0x100));
2446 if(NMILevel != level && level == (bool)(ICR & 0x100))
2447 {
2448#ifdef HAVE_DEBUG
2449  SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] NMI - Standby=%u\n", cpu_name, Standby);
2450#endif
2451
2452  SetPEX(PEX_NMI);
2453
2454  if(Standby)
2455  {
2456   WDT.WTCSR |= 0x08;
2457   FRT_WDT_Recalc_NET();
2458  }
2459  else
2460  {
2461   DMAOR |= 0x02;	// TODO: NMIF; set always, or only when DMA was active?
2462   DMA_RecalcRunning();
2463  }
2464 }
2465 NMILevel = level;
2466}
2467
2468void SH7095::SetMD5(bool level)
2469{
2470 BSC.BCR1 = (BSC.BCR1 & 0x7FFF) | (level << 15);
2471}
2472
2473void SH7095::SetIRL(unsigned level)
2474{
2475 assert(level < 16);
2476
2477 IRL = level;
2478 RecalcPendingIntPEX();
2479}
2480
2481void SH7095::ForceInternalEventUpdates(void)
2482{
2483 FRT_WDT_Update();
2484 FRT_WDT_Recalc_NET();
2485}
2486
2487//
2488// Default priority(for same ipr value), highest to lowest:
2489//  NMI
2490//  User break
2491//  IRL15
2492//  [...]
2493//  IRL1
2494//  DIVU
2495//  DMAC0
2496//  DMAC1
2497//  WDT
2498//  REF
2499//  SCI-ERI
2500//  SCI-RXI
2501//  SCI-TXI
2502//  SCI-TEI
2503//  FRT-ICI
2504//  FRT-OCI
2505//  FRT-OVI
2506//
2507//
2508uint8 INLINE SH7095::GetPendingInt(uint8* vecnum_out)
2509{
2510 unsigned ipr;
2511 unsigned vecnum;
2512 unsigned tmp_ipr;
2513
2514 ipr = IRL;
2515 vecnum = (IRL >> 1) + VECNUM_INT_BASE;
2516
2517 if(vecnum_out && (ICR & 0x1) && IRL > 0) // External vec fetch has side effects, make sure to only do it if vecnum_out is non-NULL and ICR & 0x1, and if this is the interrupt being serviced.
2518  vecnum = ~0U;
2519
2520 //
2521 //
2522 //
2523
2524 if((DVCR & 0x3) == 0x3 && (tmp_ipr = ((IPRA >> 12) & 0xF)) > ipr)
2525 {
2526  ipr = tmp_ipr;
2527  vecnum = (VCRDIV & 0x7F);
2528 }
2529
2530 for(unsigned ch = 0; ch < 2; ch++)
2531 {
2532  if((DMACH[ch].CHCR & 0x6) == 0x6 && (tmp_ipr = ((IPRA >> 8) & 0xF)) > ipr)
2533  {
2534   ipr = tmp_ipr;
2535   vecnum = (DMACH[ch].VCR & 0x7F);
2536  }
2537 }
2538
2539 if((WDT.WTCSR & 0x80) && (tmp_ipr = ((IPRA >> 4) & 0xF)) > ipr)
2540 {
2541  ipr = tmp_ipr;
2542  vecnum = (VCRWDT >> 8) & 0x7F;
2543 }
2544
2545 //
2546 //
2547 //
2548#if 0
2549 {
2550  const uint32 sci_ip_tmp = (SCI.SSR & SCI.SCR & 0xC4) | (SCI.SSR & 0x38);
2551
2552  if(sci_ip_tmp && (tmp_ipr = ((IPRB >> 12) & 0xF)) > ipr)
2553  {
2554   ipr = tmp_ipr;
2555
2556   if(sci_ip_tmp & 0x38) // ERI(receive error; ORER, PER, FER)
2557    vecnum = (VCRA >> 8) & 0x7F;
2558   else if(sci_ip_tmp & 0x40)// RXI(receive data full; RDRF)
2559    vecnum = (VCRA >> 0) & 0x7F;
2560   else if(sci_ip_tmp & 0x80)// TXI(transmit data empty; TDRE)
2561    vecnum = (VCRB >> 8) & 0x7F;
2562   else if(sci_ip_tmp & 0x04)// TEI(transmit end; TEND)
2563    vecnum = (VCRB >> 0) & 0x7F;
2564  }
2565 }
2566#endif
2567 //
2568 //
2569 //
2570 const uint32 frt_ip_tmp = (FRT.FTCSR & FRT.TIER & 0x8E);
2571 if(frt_ip_tmp && (tmp_ipr = ((IPRB >> 8) & 0xF)) > ipr)
2572 {
2573  ipr = tmp_ipr;
2574
2575  if(frt_ip_tmp & 0x80)	// ICI
2576   vecnum = (VCRC >> 8) & 0x7F;
2577  else if(frt_ip_tmp & 0x0C)	// OCIA+OCIB
2578   vecnum = (VCRC >> 0) & 0x7F;
2579  else 			// OVI
2580   vecnum = (VCRD >> 8) & 0x7F;
2581 }
2582
2583 if(vecnum_out)
2584 {
2585  if(vecnum == ~0U)
2586   vecnum = ExIVecFetch();
2587
2588  *vecnum_out = vecnum;
2589 }
2590
2591 return ipr;
2592}
2593
2594//
2595// Call after changes to:
2596//	IRL
2597//	SR
2598//
2599//	IPRA
2600//	IPRB
2601//
2602//	DMACH[*].CHCR
2603//
2604//	DVCR
2605//
2606//	FRT.FTCSR
2607//	FRT.TIER
2608//
2609void NO_INLINE SH7095::RecalcPendingIntPEX(void)
2610{
2611 if(GetPendingInt(NULL) > ((SR >> 4) & 0xF))
2612  SetPEX(PEX_INT);
2613 else
2614  ClearPEX(PEX_INT);
2615}
2616
2617static const uint8 InstrDecodeTab[65536] =
2618{
2619 #include "sh7095_idecodetab.inc"
2620};
2621
2622template<bool EmulateICache, bool DebugMode>
2623INLINE void SH7095::FetchIF(bool ForceIBufferFill)
2624{
2625 if(DebugMode)
2626  PC_IF = PC;
2627
2628 if(EmulateICache)
2629 {
2630  if(ForceIBufferFill)
2631  {
2632   IBuffer = MRFPI[PC >> 29](PC &~ 2);
2633   Pipe_IF = (uint16)(IBuffer >> (((PC & 2) ^ 2) << 3));
2634  }
2635  else
2636  {
2637   Pipe_IF = (uint16)IBuffer;
2638   if(!(PC & 0x2))
2639   {
2640    IBuffer = MRFPI[PC >> 29](PC);
2641    Pipe_IF = IBuffer >> 16;
2642   }
2643  }
2644 }
2645 else
2646 {
2647  if(timestamp < (MA_until - (ForceIBufferFill ? 0 : ((int32)(PC & 0x2) << 28))))
2648   timestamp = MA_until;
2649
2650  if(MDFN_UNLIKELY((int32)PC < 0))	// Mr. Boooones
2651  {
2652   Pipe_IF = MRFP16[PC >> 29](PC);
2653   timestamp++;
2654   return;
2655  }
2656
2657  Pipe_IF = *(uint16*)(SH7095_FastMap[PC >> SH7095_EXT_MAP_GRAN_BITS] + PC);
2658 }
2659 timestamp++;
2660}
2661
2662//
2663// TODO: Stop reading from memory when an exception is pending?
2664//
2665template<bool EmulateICache, bool DebugMode, bool DelaySlot, bool IntPreventNext, bool SkipFetchIF>
2666INLINE void SH7095::DoIDIF_Real(void)
2667{
2668 if(DelaySlot)
2669 {
2670  //
2671  // Redecode the opcode from the 16-bit instruction to makes sure exceptions won't be taken in the delay slot(due
2672  // to op field being forced to 0xFF in the previous call to DoIDIF()), and forces usage of the second half of the opcode
2673  // table so we can generate illegal slot instruction exceptions as appropriate.
2674  //
2675  // Oh, and this effectively discards the previously-fetched instruction in Pipe_IF.  Poor, poor instruction.
2676  //
2677  Pipe_ID = (uint16)Pipe_ID;
2678  Pipe_ID |= (InstrDecodeTab[Pipe_ID] | 0x80) << 24;
2679 }
2680 else
2681 {
2682  uint32 op = InstrDecodeTab[Pipe_IF];
2683  uint32 epo = EPending;
2684
2685  if(IntPreventNext)
2686  {
2687   epo &= ~(1U << (PEX_INT + EPENDING_PEXBITS_SHIFT));
2688   if(!(epo & (0xFF << EPENDING_PEXBITS_SHIFT)))
2689    epo = 0;
2690  }
2691
2692  if(DebugMode)
2693   PC_ID = PC_IF;
2694
2695  Pipe_ID = Pipe_IF | (op << 24) | epo;
2696 }
2697
2698 if(!SkipFetchIF)
2699  FetchIF<EmulateICache, DebugMode>(false);
2700}
2701
2702template<unsigned which, bool EmulateICache, bool DebugMode, bool DelaySlot, bool IntPreventNext, bool SkipFetchIF>
2703static NO_INLINE void DoIDIF(void)
2704{
2705 CPU[which].DoIDIF_Real<EmulateICache, DebugMode, DelaySlot, IntPreventNext, SkipFetchIF>();
2706}
2707
2708template<unsigned which, bool EmulateICache, int DebugMode, bool delayed>
2709INLINE void SH7095::Branch(uint32 target)
2710{
2711#if 0
2712 if(DebugMode > 0)
2713  DBG_AddBranchTrace(which, target, -1);
2714#endif
2715
2716 PC = target;
2717
2718 //
2719 // Not totally correct, but simplifies things...probably :p
2720 //
2721 if(delayed)
2722 {
2723  if(MDFN_UNLIKELY(PC & 1))
2724  {
2725   DoIDIF<which, EmulateICache, (bool)DebugMode, true, true, true>();
2726   SetPEX(PEX_CPUADDR);	// Pending for the instruction after the delay slot instruction.
2727  }
2728  else
2729  {
2730   if(EmulateICache)
2731   {
2732    if(PC & 0x2)
2733     IBuffer = MRFPI[PC >> 29](PC &~ 2);
2734   }
2735
2736   DoIDIF<which, EmulateICache, (bool)DebugMode, true, false, false>();
2737  }
2738 }
2739 else
2740 {
2741  if(MDFN_UNLIKELY(PC & 1))
2742  {
2743   SetPEX(PEX_CPUADDR);
2744   DoIDIF<which, EmulateICache, (bool)DebugMode, false, false, true>();
2745  }
2746  else
2747  {
2748   if(EmulateICache)
2749   {
2750    if(PC & 0x2)
2751     IBuffer = MRFPI[PC >> 29](PC &~ 2);
2752   }
2753
2754   DoIDIF<which, EmulateICache, (bool)DebugMode, false, false, false>();
2755   PC += 2;
2756   DoIDIF<which, EmulateICache, (bool)DebugMode, false, false, false>();
2757  }
2758 }
2759}
2760
2761// Remember to use BEGIN_OP_DLYIDIF instead of BEGIN_OP
2762template<unsigned which, bool EmulateICache, int DebugMode>
2763INLINE void SH7095::UCDelayBranch(uint32 target)
2764{
2765#if 0
2766 if(DebugMode > 0)
2767  DBG_AddBranchTrace(which, target, -1);
2768#endif
2769
2770 PC = target;
2771
2772 if(DebugMode)
2773  PC_ID = PC_IF;
2774
2775 Pipe_ID = Pipe_IF | ((InstrDecodeTab[Pipe_IF] | 0x80) << 24);
2776
2777 timestamp++;
2778
2779 if(MDFN_UNLIKELY(PC & 1))
2780 {
2781  DoIDIF<which, EmulateICache, (bool)DebugMode, true, true, true>();
2782  SetPEX(PEX_CPUADDR);	// Pending for the instruction after the delay slot instruction.
2783 }
2784 else
2785 {
2786  FetchIF<EmulateICache, DebugMode>(true);
2787 }
2788}
2789
2790template<unsigned which, bool EmulateICache, int DebugMode>
2791INLINE void SH7095::UCRelDelayBranch(uint32 disp)
2792{
2793 UCDelayBranch<which, EmulateICache, DebugMode>(PC + disp);
2794}
2795
2796
2797template<unsigned which, bool EmulateICache, int DebugMode, bool delayed>
2798INLINE void SH7095::CondRelBranch(bool cond, uint32 disp)
2799{
2800 if(cond)
2801  Branch<which, EmulateICache, DebugMode, delayed>(PC + disp);
2802}
2803
2804template<bool DebugMode>
2805uint32 NO_INLINE SH7095::Exception(const unsigned exnum, const unsigned vecnum)
2806{
2807 uint32 new_PC;
2808
2809 timestamp += 2;
2810
2811 if(exnum == EXCEPTION_RESET || exnum == EXCEPTION_POWERON)
2812 {
2813  new_PC = MemRead<uint32>((vecnum + 0) << 2);
2814  R[15] = MemRead<uint32>((vecnum + 1) << 2);
2815 }
2816 else
2817 {
2818  // Save SR to stack
2819  // Save PC to stack
2820  // Read exception vector table
2821  R[15] -= 4;
2822  MemWrite<uint32>(R[15], SR);
2823  timestamp++;
2824  R[15] -= 4;
2825  MemWrite<uint32>(R[15], PC);
2826  timestamp++;
2827  timestamp++;
2828  new_PC = MemRead<uint32>(VBR + (vecnum << 2));
2829  timestamp++;
2830 }
2831
2832#if 0
2833 if(DebugMode)
2834  DBG_AddBranchTrace(this - CPU, new_PC, exnum, vecnum);
2835#endif
2836
2837 //SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Exception %u, vecnum=%u, vbr=%08x, saved PC=0x%08x --- New PC=0x%08x, New R15=0x%08x\n", cpu_name, exnum, vecnum, VBR, PC, new_PC, R[15]);
2838
2839 return new_PC;
2840}
2841
2842
2843/*
2844 PC == 0
2845 instr = [?]
2846 ID = [?]
2847 IF = [0]
2848
2849 PC == 2
2850 instr = [?]
2851 ID = [0]
2852 IF = [2]
2853
2854 PC == 4
2855 instr = [0]
2856 ID = [2]
2857 IF = [4]
2858
2859*/
2860
2861template<unsigned which, bool EmulateICache, bool DebugMode>
2862INLINE void SH7095::Step(void)
2863{
2864 //
2865 // Ideally, we would place SPEPRecover: after the FRT event check, but doing
2866 // so causes gcc(multiple versions) to produce inconceivably awful code under certain conditions
2867 // (such as disabling all the SS_DBG stuff at compile-time) because it thinks it's an important loop
2868 // or something?(even with all our branch hinting!)
2869 //
2870 SPEPRecover:;
2871
2872 if(MDFN_UNLIKELY(timestamp >= FRT_WDT_NextTS))
2873 {
2874  FRT_WDT_Update();
2875  FRT_WDT_Recalc_NET();
2876 }
2877
2878 const uint32 instr = (uint16)Pipe_ID;
2879 const unsigned instr_nyb1 = (instr >> 4) & 0xF;
2880 const unsigned instr_nyb2 = (instr >> 8) & 0xF;
2881// asm volatile("":: "a"(instr_nyb1), "d"(instr_nyb2));
2882 switch(Pipe_ID >> 24)
2883 {
2884 #include "sh7095_opdefs.inc"
2885
2886 #define PART_OP_NORMIDIF DoIDIF<which, EmulateICache, DebugMode, false, false, false>();
2887
2888 #define BEGIN_OP(x) 	     OP_##x { PART_OP_NORMIDIF
2889 #define BEGIN_OP_DLYIDIF(x) OP_##x {
2890
2891 // "Interrupt-disabled" instruction(blocks interrupt from being taken for next instruction).
2892 // Use with BEGIN_OP_DLYIDIF()
2893 #define PART_OP_INTDIS DoIDIF<which, EmulateICache, DebugMode, false, true, false>();
2894
2895 #define END_OP } break;
2896
2897#if 0
2898 #define WB_EX_CHECK(r) { if(timestamp < WB_until[(r)]) timestamp = WB_until[(r)]; }
2899
2900 #define WB_WRITE(r, v) { R[(r)] = (v); WB_until[(r)] = MA_until + 1; }
2901#else
2902 #define WB_EX_CHECK(r) { }
2903 #define WB_WRITE(r, v) { R[(r)] = (v); }
2904#endif
2905 //
2906 //
2907 //
2908 //
2909 // MOV #imm,Rn
2910 //
2911 BEGIN_OP(MOV_IMM_REG)
2912	const unsigned n = instr_nyb2;
2913	const uint32 imm = (int8)instr;
2914
2915	WB_EX_CHECK(n)
2916
2917	R[n] = imm;
2918 END_OP
2919
2920
2921 //
2922 // MOV.W @(disp,PC),Rn
2923 //
2924 BEGIN_OP(MOV_W_PCREL_REG)
2925	const unsigned n = instr_nyb2;
2926	const unsigned d = (instr >> 0) & 0xff;
2927	const uint32 ea = PC + (d << 1);
2928
2929	WB_WRITE(n, (int16)MemRead<uint16>(ea));
2930 END_OP
2931
2932
2933 //
2934 // MOV.L @(disp,PC),Rn
2935 //
2936 BEGIN_OP(MOV_L_PCREL_REG)
2937	const unsigned n = instr_nyb2;
2938	const unsigned d = (instr >> 0) & 0xff;
2939	const uint32 ea = (PC &~ 0x3) + (d << 2);
2940
2941	WB_WRITE(n, MemRead<uint32>(ea));
2942 END_OP
2943
2944
2945 //
2946 // MOV Rm,Rn
2947 //
2948 BEGIN_OP(MOV_REG_REG)
2949	const unsigned n = instr_nyb2;
2950	const unsigned m = instr_nyb1;
2951
2952	WB_EX_CHECK(n)
2953	WB_EX_CHECK(m)
2954
2955	R[n] = R[m];
2956 END_OP
2957
2958
2959 //
2960 // MOV.B Rm,@Rn
2961 //
2962 BEGIN_OP(MOV_B_REG_REGINDIR)
2963	const unsigned n = instr_nyb2;
2964	const unsigned m = instr_nyb1;
2965	const uint32 val = R[m];
2966	const uint32 ea = R[n];
2967
2968	MemWrite<uint8>(ea, val);
2969 END_OP
2970
2971
2972 //
2973 // MOV.W Rm,@Rn
2974 //
2975 BEGIN_OP(MOV_W_REG_REGINDIR)
2976	const unsigned n = instr_nyb2;
2977	const unsigned m = instr_nyb1;
2978	const uint32 val = R[m];
2979	const uint32 ea = R[n];
2980
2981	MemWrite<uint16>(ea, val);
2982 END_OP
2983
2984
2985 //
2986 // MOV.L Rm,@Rn
2987 //
2988 BEGIN_OP(MOV_L_REG_REGINDIR)
2989	const unsigned n = instr_nyb2;
2990	const unsigned m = instr_nyb1;
2991	const uint32 val = R[m];
2992	const uint32 ea = R[n];
2993
2994	MemWrite<uint32>(ea, val);
2995 END_OP
2996
2997
2998 //
2999 // MOV.B @Rm,Rn
3000 //
3001 BEGIN_OP(MOV_B_REGINDIR_REG)
3002	const unsigned n = instr_nyb2;
3003	const unsigned m = instr_nyb1;
3004	const uint32 ea = R[m];
3005
3006	WB_WRITE(n, (int8)MemRead<uint8>(ea));
3007 END_OP
3008
3009
3010 //
3011 // MOV.W @Rm,Rn
3012 //
3013 BEGIN_OP(MOV_W_REGINDIR_REG)
3014	const unsigned n = instr_nyb2;
3015	const unsigned m = instr_nyb1;
3016	const uint32 ea = R[m];
3017
3018	WB_WRITE(n, (int16)MemRead<uint16>(ea));
3019 END_OP
3020
3021
3022 //
3023 // MOV.L @Rm,Rn
3024 //
3025 BEGIN_OP(MOV_L_REGINDIR_REG)
3026	const unsigned n = instr_nyb2;
3027	const unsigned m = instr_nyb1;
3028	const uint32 ea = R[m];
3029
3030	WB_WRITE(n, MemRead<uint32>(ea));
3031 END_OP
3032
3033
3034 //
3035 // MOV.B Rm,@-Rn
3036 //
3037 BEGIN_OP(MOV_B_REG_REGINDIRPD)
3038	const unsigned n = instr_nyb2;
3039	const unsigned m = instr_nyb1;
3040	const uint32 val = R[m];
3041	uint32 ea;
3042
3043	R[n] -= 1;
3044	ea = R[n];
3045
3046	MemWrite<uint8>(ea, val);
3047 END_OP
3048
3049
3050 //
3051 // MOV.W Rm,@-Rn
3052 //
3053 BEGIN_OP(MOV_W_REG_REGINDIRPD)
3054	const unsigned n = instr_nyb2;
3055	const unsigned m = instr_nyb1;
3056	const uint32 val = R[m];
3057	uint32 ea;
3058
3059	R[n] -= 2;
3060	ea = R[n];
3061
3062	MemWrite<uint16>(ea, val);
3063 END_OP
3064
3065
3066 //
3067 // MOV.L Rm,@-Rn
3068 //
3069 BEGIN_OP(MOV_L_REG_REGINDIRPD)
3070	const unsigned n = instr_nyb2;
3071	const unsigned m = instr_nyb1;
3072	const uint32 val = R[m];
3073	uint32 ea;
3074
3075	R[n] -= 4;
3076	ea = R[n];
3077
3078	MemWrite<uint32>(ea, val);
3079 END_OP
3080
3081
3082 //
3083 // MOV.B @Rm+,Rn
3084 //
3085 BEGIN_OP(MOV_B_REGINDIRPI_REG)
3086	const unsigned n = instr_nyb2;
3087	const unsigned m = instr_nyb1;
3088	uint32 ea;
3089
3090	ea = R[m];
3091	R[m] += 1;
3092
3093	WB_WRITE(n, (int8)MemRead<uint8>(ea));
3094 END_OP
3095
3096
3097 //
3098 // MOV.W @Rm+,Rn
3099 //
3100 BEGIN_OP(MOV_W_REGINDIRPI_REG)
3101	const unsigned n = instr_nyb2;
3102	const unsigned m = instr_nyb1;
3103	uint32 ea;
3104
3105	ea = R[m];
3106	R[m] += 2;
3107
3108	WB_WRITE(n, (int16)MemRead<uint16>(ea));
3109 END_OP
3110
3111
3112 //
3113 // MOV.L @Rm+,Rn
3114 //
3115 BEGIN_OP(MOV_L_REGINDIRPI_REG)
3116	const unsigned n = instr_nyb2;
3117	const unsigned m = instr_nyb1;
3118	uint32 ea;
3119
3120	ea = R[m];
3121	R[m] += 4;
3122
3123	WB_WRITE(n, MemRead<uint32>(ea));
3124 END_OP
3125
3126
3127 //
3128 // MOV.B R0,@(disp,Rn)
3129 //
3130 BEGIN_OP(MOV_B_REG0_REGINDIRDISP)
3131	const unsigned n = instr_nyb1;
3132	const unsigned d = (instr >> 0) & 0xf;
3133	const uint32 ea = R[n] + (d << 0);
3134
3135	MemWrite<uint8>(ea, R[0]);
3136 END_OP
3137
3138
3139 //
3140 // MOV.W R0,@(disp,Rn)
3141 //
3142 BEGIN_OP(MOV_W_REG0_REGINDIRDISP)
3143	const unsigned n = instr_nyb1;
3144	const unsigned d = (instr >> 0) & 0xf;
3145	const uint32 ea = R[n] + (d << 1);
3146
3147	MemWrite<uint16>(ea, R[0]);
3148 END_OP
3149
3150
3151 //
3152 // MOV.L Rm,@(disp,Rn)
3153 //
3154 BEGIN_OP(MOV_L_REG_REGINDIRDISP)
3155	const unsigned n = instr_nyb2;
3156	const unsigned m = instr_nyb1;
3157	const unsigned d = (instr >> 0) & 0xf;
3158	const uint32 ea = R[n] + (d << 2);
3159
3160	MemWrite<uint32>(ea, R[m]);
3161 END_OP
3162
3163
3164 //
3165 // MOV.B @(disp,Rm),R0
3166 //
3167 BEGIN_OP(MOV_B_REGINDIRDISP_REG0)
3168	const unsigned m = instr_nyb1;
3169	const unsigned d = (instr >> 0) & 0xf;
3170	const uint32 ea = R[m] + (d << 0);
3171
3172	WB_WRITE(0, (int8)MemRead<uint8>(ea));
3173 END_OP
3174
3175
3176 //
3177 // MOV.W @(disp,Rm),R0
3178 //
3179 BEGIN_OP(MOV_W_REGINDIRDISP_REG0)
3180	const unsigned m = instr_nyb1;
3181	const unsigned d = (instr >> 0) & 0xf;
3182	const uint32 ea = R[m] + (d << 1);
3183
3184	WB_WRITE(0, (int16)MemRead<uint16>(ea));
3185 END_OP
3186
3187
3188 //
3189 // MOV.L @(disp,Rm),Rn
3190 //
3191 BEGIN_OP(MOV_L_REGINDIRDISP_REG)
3192	const unsigned n = instr_nyb2;
3193	const unsigned m = instr_nyb1;
3194	const unsigned d = (instr >> 0) & 0xf;
3195	const uint32 ea = R[m] + (d << 2);
3196
3197	WB_WRITE(n, MemRead<uint32>(ea));
3198 END_OP
3199
3200
3201 //
3202 // MOV.B Rm,@(R0,Rn)
3203 //
3204 BEGIN_OP(MOV_B_REG_IDXREGINDIR)
3205	const unsigned n = instr_nyb2;
3206	const unsigned m = instr_nyb1;
3207	const uint32 ea = R[0] + R[n];
3208
3209	MemWrite<uint8>(ea, R[m]);
3210 END_OP
3211
3212
3213 //
3214 // MOV.W Rm,@(R0,Rn)
3215 //
3216 BEGIN_OP(MOV_W_REG_IDXREGINDIR)
3217	const unsigned n = instr_nyb2;
3218	const unsigned m = instr_nyb1;
3219	const uint32 ea = R[0] + R[n];
3220
3221	MemWrite<uint16>(ea, R[m]);
3222 END_OP
3223
3224
3225 //
3226 // MOV.L Rm,@(R0,Rn)
3227 //
3228 BEGIN_OP(MOV_L_REG_IDXREGINDIR)
3229	const unsigned n = instr_nyb2;
3230	const unsigned m = instr_nyb1;
3231	const uint32 ea = R[0] + R[n];
3232
3233	MemWrite<uint32>(ea, R[m]);
3234 END_OP
3235
3236
3237 //
3238 // MOV.B @(R0,Rm),Rn
3239 //
3240 BEGIN_OP(MOV_B_IDXREGINDIR_REG)
3241	const unsigned n = instr_nyb2;
3242	const unsigned m = instr_nyb1;
3243	const uint32 ea = R[0] + R[m];
3244
3245	WB_WRITE(n, (int8)MemRead<uint8>(ea));
3246 END_OP
3247
3248
3249 //
3250 // MOV.W @(R0,Rm),Rn
3251 //
3252 BEGIN_OP(MOV_W_IDXREGINDIR_REG)
3253	const unsigned n = instr_nyb2;
3254	const unsigned m = instr_nyb1;
3255	const uint32 ea = R[0] + R[m];
3256
3257	WB_WRITE(n, (int16)MemRead<uint16>(ea));
3258 END_OP
3259
3260
3261 //
3262 // MOV.L @(R0,Rm),Rn
3263 //
3264 BEGIN_OP(MOV_L_IDXREGINDIR_REG)
3265	const unsigned n = instr_nyb2;
3266	const unsigned m = instr_nyb1;
3267	const uint32 ea = R[0] + R[m];
3268
3269	WB_WRITE(n, MemRead<uint32>(ea));
3270 END_OP
3271
3272
3273 //
3274 // MOV.B R0,@(disp,GBR)
3275 //
3276 BEGIN_OP(MOV_B_REG0_GBRINDIRDISP)
3277	const unsigned d = (instr >> 0) & 0xff;
3278	const uint32 ea = GBR + (d << 0);
3279
3280	MemWrite<uint8>(ea, R[0]);
3281 END_OP
3282
3283
3284 //
3285 // MOV.W R0,@(disp,GBR)
3286 //
3287 BEGIN_OP(MOV_W_REG0_GBRINDIRDISP)
3288	const unsigned d = (instr >> 0) & 0xff;
3289	const uint32 ea = GBR + (d << 1);
3290
3291	MemWrite<uint16>(ea, R[0]);
3292 END_OP
3293
3294
3295 //
3296 // MOV.L R0,@(disp,GBR)
3297 //
3298 BEGIN_OP(MOV_L_REG0_GBRINDIRDISP)
3299	const unsigned d = (instr >> 0) & 0xff;
3300	const uint32 ea = GBR + (d << 2);
3301
3302	MemWrite<uint32>(ea, R[0]);
3303 END_OP
3304
3305
3306 //
3307 // MOV.B @(disp,GBR),R0
3308 //
3309 BEGIN_OP(MOV_B_GBRINDIRDISP_REG0)
3310	const unsigned d = (instr >> 0) & 0xff;
3311	const uint32 ea = GBR + (d << 0);
3312
3313	WB_WRITE(0, (int8)MemRead<uint8>(ea));
3314 END_OP
3315
3316
3317 //
3318 // MOV.W @(disp,GBR),R0
3319 //
3320 BEGIN_OP(MOV_W_GBRINDIRDISP_REG0)
3321	const unsigned d = (instr >> 0) & 0xff;
3322	const uint32 ea = GBR + (d << 1);
3323
3324	WB_WRITE(0, (int16)MemRead<uint16>(ea));
3325 END_OP
3326
3327
3328 //
3329 // MOV.L @(disp,GBR),R0
3330 //
3331 BEGIN_OP(MOV_L_GBRINDIRDISP_REG0)
3332	const unsigned d = (instr >> 0) & 0xff;
3333	const uint32 ea = GBR + (d << 2);
3334
3335	WB_WRITE(0, MemRead<uint32>(ea));
3336 END_OP
3337
3338
3339 //
3340 // MOVA @(disp,PC),R0
3341 //
3342 BEGIN_OP(MOVA_PCREL_REG0)
3343	const unsigned d = (instr >> 0) & 0xff;
3344	const uint32 ea = (PC &~ 0x3) + (d << 2);
3345
3346	WB_EX_CHECK(0)
3347
3348	R[0] = ea;
3349 END_OP
3350
3351
3352 //
3353 // MOVT Rn
3354 //
3355 BEGIN_OP(MOVT_REG)
3356	const unsigned n = instr_nyb2;
3357
3358	WB_EX_CHECK(n)
3359
3360	R[n] = GetT();
3361 END_OP
3362
3363
3364 //
3365 // SWAP.B Rm,Rn
3366 //
3367 BEGIN_OP(SWAP_B_REG_REG)
3368	const unsigned n = instr_nyb2;
3369	const unsigned m = instr_nyb1;
3370
3371	WB_EX_CHECK(n)
3372	WB_EX_CHECK(m)
3373
3374	R[n] = (R[m] & 0xFFFF0000) | ((R[m] << 8) & 0xFF00) | ((R[m] >> 8) & 0x00FF);
3375 END_OP
3376
3377
3378 //
3379 // SWAP.W Rm,Rn
3380 //
3381 BEGIN_OP(SWAP_W_REG_REG)
3382	const unsigned n = instr_nyb2;
3383	const unsigned m = instr_nyb1;
3384
3385	WB_EX_CHECK(n)
3386	WB_EX_CHECK(m)
3387
3388	R[n] = (R[m] << 16) | (R[m] >> 16);
3389 END_OP
3390
3391
3392 //
3393 // XTRCT Rm,Rn
3394 //
3395 BEGIN_OP(XTRCT_REG_REG)
3396	const unsigned n = instr_nyb2;
3397	const unsigned m = instr_nyb1;
3398
3399	WB_EX_CHECK(n)
3400	WB_EX_CHECK(m)
3401
3402	R[n] = (R[n] >> 16) | (R[m] << 16);
3403 END_OP
3404
3405
3406 //
3407 // ADD Rm,Rn
3408 //
3409 BEGIN_OP(ADD_REG_REG)
3410	const unsigned n = instr_nyb2;
3411	const unsigned m = instr_nyb1;
3412
3413	WB_EX_CHECK(n)
3414	WB_EX_CHECK(m)
3415
3416	R[n] = R[n] + R[m];
3417 END_OP
3418
3419
3420 //
3421 // ADD #imm,Rn
3422 //
3423 BEGIN_OP(ADD_IMM_REG)
3424	const unsigned n = instr_nyb2;
3425	const uint32 imm = (int8)instr;
3426
3427	WB_EX_CHECK(n)
3428
3429	R[n] = R[n] + imm;
3430 END_OP
3431
3432
3433 //
3434 // ADDC Rm,Rn
3435 //
3436 BEGIN_OP(ADDC_REG_REG)
3437	const unsigned n = instr_nyb2;
3438	const unsigned m = instr_nyb1;
3439	const uint64 result = (uint64)R[n] + R[m] + GetT();
3440
3441	WB_EX_CHECK(n)
3442	WB_EX_CHECK(m)
3443
3444	R[n] = result;
3445	SetT((result >> 32) & 1);
3446 END_OP
3447
3448
3449 //
3450 // ADDV Rm,Rn
3451 //
3452 BEGIN_OP(ADDV_REG_REG)
3453	const unsigned n = instr_nyb2;
3454	const unsigned m = instr_nyb1;
3455	const uint32 result = R[n] + R[m];
3456
3457	WB_EX_CHECK(n)
3458	WB_EX_CHECK(m)
3459
3460	SetT(((~(R[n] ^ R[m])) & (R[n] ^ result)) >> 31);
3461	R[n] = result;
3462 END_OP
3463
3464
3465 //
3466 // CMP/EQ #imm,R0
3467 //
3468 BEGIN_OP(CMP_EQ_IMM_REG0)
3469	const uint32 imm = (int8)instr;
3470
3471	WB_EX_CHECK(0)
3472
3473	SetT(imm == R[0]);
3474 END_OP
3475
3476
3477 //
3478 // CMP/EQ Rm,Rn
3479 //
3480 BEGIN_OP(CMP_EQ_REG_REG)
3481	const unsigned n = instr_nyb2;
3482	const unsigned m = instr_nyb1;
3483
3484	WB_EX_CHECK(n)
3485	WB_EX_CHECK(m)
3486
3487	SetT(R[n] == R[m]);
3488 END_OP
3489
3490
3491 //
3492 // CMP/HS Rm,Rn
3493 //
3494 BEGIN_OP(CMP_HS_REG_REG)
3495	const unsigned n = instr_nyb2;
3496	const unsigned m = instr_nyb1;
3497
3498	WB_EX_CHECK(n)
3499	WB_EX_CHECK(m)
3500
3501	SetT(R[n] >= R[m]);
3502 END_OP
3503
3504
3505 //
3506 // CMP/GE Rm,Rn
3507 //
3508 BEGIN_OP(CMP_GE_REG_REG)
3509	const unsigned n = instr_nyb2;
3510	const unsigned m = instr_nyb1;
3511
3512	WB_EX_CHECK(n)
3513	WB_EX_CHECK(m)
3514
3515	SetT((int32)R[n] >= (int32)R[m]);
3516 END_OP
3517
3518
3519 //
3520 // CMP/HI Rm,Rn
3521 //
3522 BEGIN_OP(CMP_HI_REG_REG)
3523	const unsigned n = instr_nyb2;
3524	const unsigned m = instr_nyb1;
3525
3526	WB_EX_CHECK(n)
3527	WB_EX_CHECK(m)
3528
3529	SetT(R[n] > R[m]);
3530 END_OP
3531
3532
3533 //
3534 // CMP/GT Rm,Rn
3535 //
3536 BEGIN_OP(CMP_GT_REG_REG)
3537	const unsigned n = instr_nyb2;
3538	const unsigned m = instr_nyb1;
3539
3540	WB_EX_CHECK(n)
3541	WB_EX_CHECK(m)
3542
3543	SetT((int32)R[n] > (int32)R[m]);
3544 END_OP
3545
3546
3547 //
3548 // CMP/PZ Rn
3549 //
3550 BEGIN_OP(CMP_PZ_REG)
3551	const unsigned n = instr_nyb2;
3552
3553	WB_EX_CHECK(n)
3554
3555	SetT((int32)R[n] >= 0);
3556 END_OP
3557
3558
3559 //
3560 // CMP/PL Rn
3561 //
3562 BEGIN_OP(CMP_PL_REG)
3563	const unsigned n = instr_nyb2;
3564
3565	WB_EX_CHECK(n)
3566
3567	SetT((int32)R[n] > 0);
3568 END_OP
3569
3570
3571 //
3572 // CMP/STR Rm,Rn
3573 //
3574 BEGIN_OP(CMP_STR_REG_REG)
3575	const unsigned n = instr_nyb2;
3576	const unsigned m = instr_nyb1;
3577	const uint32 tmp = R[n] ^ R[m];
3578	unsigned new_T = 0;
3579
3580	WB_EX_CHECK(n)
3581	WB_EX_CHECK(m)
3582
3583	if(!(tmp & 0x000000FF)) new_T = 1;
3584	if(!(tmp & 0x0000FF00)) new_T = 1;
3585	if(!(tmp & 0x00FF0000)) new_T = 1;
3586	if(!(tmp & 0xFF000000)) new_T = 1;
3587
3588	SetT(new_T);
3589 END_OP
3590
3591
3592 //
3593 // DIV1 Rm,Rn
3594 //
3595 BEGIN_OP(DIV1_REG_REG)
3596	const unsigned n = instr_nyb2;
3597	const unsigned m = instr_nyb1;
3598	uint32 tmp;
3599	bool new_Q;
3600
3601	WB_EX_CHECK(n)
3602	WB_EX_CHECK(m)
3603
3604	new_Q = R[n] >> 31;
3605	R[n] <<= 1;
3606	R[n] |= GetT();
3607
3608	tmp = R[n];
3609	new_Q ^= GetM();
3610
3611	if(!(GetQ() ^ GetM()))
3612	{
3613	 R[n] -= R[m];
3614	 new_Q ^= (R[n] > tmp);
3615	}
3616	else
3617	{
3618	 R[n] += R[m];
3619	 new_Q ^= (R[n] < tmp);
3620	}
3621
3622	SetQ(new_Q);
3623	SetT(new_Q == GetM());
3624 END_OP
3625
3626
3627 //
3628 // DIV0S Rm,Rn
3629 //
3630 BEGIN_OP(DIV0S_REG_REG)
3631	const unsigned n = instr_nyb2;
3632	const unsigned m = instr_nyb1;
3633	const unsigned new_Q = R[n] >> 31;
3634	const unsigned new_M = R[m] >> 31;
3635
3636	WB_EX_CHECK(n)
3637	WB_EX_CHECK(m)
3638
3639	SetQ(new_Q);
3640	SetM(new_M);
3641	SetT(new_Q != new_M);
3642 END_OP
3643
3644
3645 //
3646 // DIV0U
3647 //
3648 BEGIN_OP(DIV0U)
3649	SetQ(false);
3650	SetM(false);
3651	SetT(false);
3652 END_OP
3653
3654
3655 //
3656 // DT
3657 //
3658 BEGIN_OP(DT)
3659	const unsigned n = instr_nyb2;
3660
3661	WB_EX_CHECK(n)
3662
3663	R[n]--;
3664	SetT(!R[n]);
3665 END_OP
3666
3667
3668 //
3669 // EXTS.B Rm,Rn
3670 //
3671 BEGIN_OP(EXTS_B_REG_REG)
3672	const unsigned n = instr_nyb2;
3673	const unsigned m = instr_nyb1;
3674
3675	WB_EX_CHECK(n)
3676	WB_EX_CHECK(m)
3677
3678	R[n] = (int8)R[m];
3679 END_OP
3680
3681
3682 //
3683 // EXTS.W Rm,Rn
3684 //
3685 BEGIN_OP(EXTS_W_REG_REG)
3686	const unsigned n = instr_nyb2;
3687	const unsigned m = instr_nyb1;
3688
3689	WB_EX_CHECK(n)
3690	WB_EX_CHECK(m)
3691
3692	R[n] = (int16)R[m];
3693 END_OP
3694
3695
3696 //
3697 // EXTU.B Rm,Rn
3698 //
3699 BEGIN_OP(EXTU_B_REG_REG)
3700	const unsigned n = instr_nyb2;
3701	const unsigned m = instr_nyb1;
3702
3703	WB_EX_CHECK(n)
3704	WB_EX_CHECK(m)
3705
3706	R[n] = (uint8)R[m];
3707 END_OP
3708
3709
3710 //
3711 // EXTU.W Rm,Rn
3712 //
3713 BEGIN_OP(EXTU_W_REG_REG)
3714	const unsigned n = instr_nyb2;
3715	const unsigned m = instr_nyb1;
3716
3717	WB_EX_CHECK(n)
3718	WB_EX_CHECK(m)
3719
3720	R[n] = (uint16)R[m];
3721 END_OP
3722
3723
3724 //
3725 // MAC.L @Rm+,@Rn+
3726 //
3727 //  Pipeline: page 188(not implemented right here)
3728 BEGIN_OP(MAC_L)
3729	const unsigned n = instr_nyb2;
3730	const unsigned m = instr_nyb1;
3731	uint64 a, b, sum;
3732	int32 m0, m1;
3733
3734	// Order confirmed.
3735	m0 = (int32)MemRead<uint32>(R[m]);
3736	R[m] += 4;
3737        m1 = (int32)MemRead<uint32>(R[n]);
3738	R[n] += 4;
3739
3740	a = GetMAC64();
3741	b = (int64)m0 * m1;
3742	sum = a + b;
3743
3744	if(GetS() && sum > 0x00007FFFFFFFFFFFULL && sum < 0xFFFF800000000000ULL)
3745	{
3746	 if((int32)(m0 ^ m1) < 0)
3747	  sum = 0xFFFF800000000000ULL;
3748	 else
3749	  sum = 0x00007FFFFFFFFFFFULL;
3750	}
3751
3752	SetMAC64(sum);
3753
3754	timestamp++;
3755 END_OP
3756
3757
3758 //
3759 // MAC.W @Rm+,@Rn+
3760 //
3761 //  Pipeline: page 180(not implemented right here)
3762 BEGIN_OP(MAC_W)
3763	const unsigned n = instr_nyb2;
3764	const unsigned m = instr_nyb1;
3765	int16 m0, m1;
3766
3767	// Order confirmed.
3768	m0 = (int16)MemRead<uint16>(R[m]);
3769	R[m] += 2;
3770        m1 = (int16)MemRead<uint16>(R[n]);
3771	R[n] += 2;
3772
3773	if(GetS())
3774	{
3775	 int32 b = (int32)m0 * m1;
3776	 uint64 sum = (int64)(int32)MACL + b;
3777
3778	 if(sum > 0x000000007FFFFFFFULL && sum < 0xFFFFFFFF80000000ULL)
3779	 {
3780	  MACH |= 1;
3781
3782	  if(b < 0)
3783	   sum = 0x80000000ULL;
3784	  else
3785	   sum = 0x7FFFFFFFULL;
3786	 }
3787
3788	 MACL = sum;
3789	}
3790	else
3791	 SetMAC64(GetMAC64() + (int64)m0 * m1);
3792
3793	timestamp++;
3794 END_OP
3795
3796
3797 //
3798 // DMULS.L Rm,Rn
3799 //
3800 //  Pipeline: page 215 (not implemented here totally correctly)
3801 BEGIN_OP_DLYIDIF(DMULS_L_REG_REG)
3802	const unsigned n = instr_nyb2;
3803	const unsigned m = instr_nyb1;
3804	const uint64 result = (int64)(int32)R[n] * (int32)R[m];
3805
3806	timestamp++;
3807
3808	MA_until = std::max<sscpu_timestamp_t>(std::max<sscpu_timestamp_t>(MA_until, MM_until), timestamp + 1);
3809	MM_until = MA_until + 4;
3810	PART_OP_NORMIDIF
3811
3812	MACL = result >> 0;
3813	MACH = result >> 32;
3814 END_OP
3815
3816
3817 //
3818 // DMULU.L Rm,Rn
3819 //
3820 //  Pipeline: page 215 (not implemented here totally correctly)
3821 BEGIN_OP_DLYIDIF(DMULU_L_REG_REG)
3822	const unsigned n = instr_nyb2;
3823	const unsigned m = instr_nyb1;
3824	const uint64 result = (uint64)R[n] * R[m];
3825
3826	timestamp++;
3827
3828	MA_until = std::max<sscpu_timestamp_t>(std::max<sscpu_timestamp_t>(MA_until, MM_until), timestamp + 1);
3829	MM_until = MA_until + 4;
3830	PART_OP_NORMIDIF
3831
3832	MACL = result >> 0;
3833	MACH = result >> 32;
3834 END_OP
3835
3836
3837 //
3838 // MUL.L Rm,Rn
3839 //
3840 //  Pipeline: page 215 (not implemented here totally correctly)
3841 BEGIN_OP_DLYIDIF(MUL_L_REG_REG)
3842	const unsigned n = instr_nyb2;
3843	const unsigned m = instr_nyb1;
3844
3845	timestamp++;
3846
3847	MA_until = std::max<sscpu_timestamp_t>(std::max<sscpu_timestamp_t>(MA_until, MM_until), timestamp + 1);
3848	MM_until = MA_until + 4;
3849	PART_OP_NORMIDIF
3850
3851	MACL = R[n] * R[m];
3852 END_OP
3853
3854
3855 //
3856 // MULS.W Rm,Rn
3857 //
3858 //  Pipeline: page 207
3859 BEGIN_OP(MULS_W_REG_REG)
3860	const unsigned n = instr_nyb2;
3861	const unsigned m = instr_nyb1;
3862
3863	MA_until = std::max<sscpu_timestamp_t>(std::max<sscpu_timestamp_t>(MA_until, MM_until), timestamp + 1);
3864	MM_until = MA_until + 2;
3865
3866	MACL = (int16)R[n] * (int16)R[m];
3867 END_OP
3868
3869
3870 //
3871 // MULU.W Rm,Rn
3872 //
3873 //  Pipeline: page 207
3874 BEGIN_OP(MULU_W_REG_REG)
3875	const unsigned n = instr_nyb2;
3876	const unsigned m = instr_nyb1;
3877
3878	MA_until = std::max<sscpu_timestamp_t>(std::max<sscpu_timestamp_t>(MA_until, MM_until), timestamp + 1);
3879	MM_until = MA_until + 2;
3880
3881	MACL = (uint32)(uint16)R[n] * (uint32)(uint16)R[m];
3882 END_OP
3883
3884
3885 //
3886 // NEG Rm,Rn
3887 //
3888 BEGIN_OP(NEG_REG_REG)
3889	const unsigned n = instr_nyb2;
3890	const unsigned m = instr_nyb1;
3891
3892	WB_EX_CHECK(n)
3893	WB_EX_CHECK(m)
3894
3895	R[n] = -R[m];
3896 END_OP
3897
3898
3899 //
3900 // NEGC Rm,Rn
3901 //
3902 BEGIN_OP(NEGC_REG_REG)
3903	const unsigned n = instr_nyb2;
3904	const unsigned m = instr_nyb1;
3905	const uint64 result = (uint64)0 - R[m] - GetT();
3906
3907	WB_EX_CHECK(n)
3908	WB_EX_CHECK(m)
3909
3910	R[n] = result;
3911	SetT((result >> 32) & 1);
3912 END_OP
3913
3914
3915 //
3916 // SUB Rm,Rn
3917 //
3918 BEGIN_OP(SUB_REG_REG)
3919	const unsigned n = instr_nyb2;
3920	const unsigned m = instr_nyb1;
3921
3922	WB_EX_CHECK(n)
3923	WB_EX_CHECK(m)
3924
3925	R[n] = R[n] - R[m];
3926 END_OP
3927
3928
3929 //
3930 // SUBC Rm,Rn
3931 //
3932 BEGIN_OP(SUBC_REG_REG)
3933	const unsigned n = instr_nyb2;
3934	const unsigned m = instr_nyb1;
3935	const uint64 result = (uint64)R[n] - R[m] - GetT();
3936
3937	WB_EX_CHECK(n)
3938	WB_EX_CHECK(m)
3939
3940	R[n] = result;
3941	SetT((result >> 32) & 1);
3942 END_OP
3943
3944
3945 //
3946 // SUBV Rm,Rn
3947 //
3948 BEGIN_OP(SUBV_REG_REG)
3949	const unsigned n = instr_nyb2;
3950	const unsigned m = instr_nyb1;
3951	const uint32 result = R[n] - R[m];
3952
3953	WB_EX_CHECK(n)
3954	WB_EX_CHECK(m)
3955
3956	SetT((((R[n] ^ R[m])) & (R[n] ^ result)) >> 31);
3957	R[n] = result;
3958 END_OP
3959
3960
3961 //
3962 // AND Rm,Rn
3963 //
3964 BEGIN_OP(AND_REG_REG)
3965	const unsigned n = instr_nyb2;
3966	const unsigned m = instr_nyb1;
3967
3968	WB_EX_CHECK(n)
3969	WB_EX_CHECK(m)
3970
3971	R[n] = R[n] & R[m];
3972 END_OP
3973
3974
3975 //
3976 // AND #imm,R0
3977 //
3978 BEGIN_OP(AND_IMM_REG0)
3979	const unsigned imm = (uint8)instr;
3980
3981	WB_EX_CHECK(0)
3982
3983	R[0] = R[0] & imm;
3984 END_OP
3985
3986
3987 //
3988 // AND.B #imm,@(R0,GBR)
3989 //
3990 BEGIN_OP(AND_B_IMM_IDXGBRINDIR)
3991	const unsigned imm = (uint8)instr;
3992	const uint32 ea = R[0] + GBR;
3993	uint32 tmp;
3994
3995	tmp = MemRead<uint8>(ea);
3996	timestamp++;
3997	tmp &= imm;
3998	MemWrite<uint8>(ea, tmp);
3999	timestamp++;
4000 END_OP
4001
4002
4003 //
4004 // NOT Rm,Rn
4005 //
4006 BEGIN_OP(NOT_REG_REG)
4007	const unsigned n = instr_nyb2;
4008	const unsigned m = instr_nyb1;
4009
4010	WB_EX_CHECK(n)
4011	WB_EX_CHECK(m)
4012
4013	R[n] = ~R[m];
4014 END_OP
4015
4016
4017 //
4018 // OR Rm,Rn
4019 //
4020 BEGIN_OP(OR_REG_REG)
4021	const unsigned n = instr_nyb2;
4022	const unsigned m = instr_nyb1;
4023
4024	WB_EX_CHECK(n)
4025	WB_EX_CHECK(m)
4026
4027	R[n] |= R[m];
4028 END_OP
4029
4030
4031 //
4032 // OR #imm,R0
4033 //
4034 BEGIN_OP(OR_IMM_REG0)
4035	const unsigned imm = (uint8)instr;
4036
4037	WB_EX_CHECK(0)
4038
4039	R[0] |= imm;
4040 END_OP
4041
4042
4043 //
4044 // OR.B #imm,@(R0,GBR)
4045 //
4046 BEGIN_OP(OR_B_IMM_IDXGBRINDIR)
4047	const unsigned imm = (uint8)instr;
4048	const uint32 ea = R[0] + GBR;
4049	uint32 tmp;
4050
4051	tmp = MemRead<uint8>(ea);
4052	timestamp++;
4053	tmp |= imm;
4054	MemWrite<uint8>(ea, tmp);
4055	timestamp++;
4056 END_OP
4057
4058
4059 //
4060 // TAS.B @Rn
4061 //
4062 BEGIN_OP(TAS_B_REGINDIR)
4063	const unsigned n = instr_nyb2;
4064	const uint32 ea = R[n];
4065	uint8 tmp;
4066
4067	SH7095_BusLock++;
4068	tmp = ExtBusRead<uint8, false>(ea);	// FIXME: Address error on invalid address(>= 0x40000000 ?).
4069	timestamp = SH7095_mem_timestamp;
4070
4071	SetT(!tmp);
4072
4073	tmp |= 0x80;
4074
4075	MemWrite<uint8>(ea, tmp);
4076	SH7095_BusLock--;
4077
4078	timestamp += 3;
4079 END_OP
4080
4081
4082 //
4083 // TST Rm,Rn
4084 //
4085 BEGIN_OP(TST_REG_REG)
4086	const unsigned n = instr_nyb2;
4087	const unsigned m = instr_nyb1;
4088
4089	WB_EX_CHECK(n)
4090	WB_EX_CHECK(m)
4091
4092	SetT(!(R[n] & R[m]));
4093 END_OP
4094
4095
4096 //
4097 // TST #imm,R0
4098 //
4099 BEGIN_OP(TST_IMM_REG0)
4100	const unsigned imm = (uint8)instr;
4101
4102	WB_EX_CHECK(0)
4103
4104	SetT(!(R[0] & imm));
4105 END_OP
4106
4107
4108 //
4109 // TST.B #imm,@(R0,GBR)
4110 //
4111 BEGIN_OP(TST_B_IMM_IDXGBRINDIR)
4112	const unsigned imm = (uint8)instr;
4113	const uint32 ea = R[0] + GBR;
4114	uint32 tmp;
4115
4116	tmp = MemRead<uint8>(ea);
4117	timestamp++;
4118	SetT(!(tmp & imm));
4119	timestamp++;
4120 END_OP
4121
4122
4123 //
4124 // XOR Rm,Rn
4125 //
4126 BEGIN_OP(XOR_REG_REG)
4127	const unsigned n = instr_nyb2;
4128	const unsigned m = instr_nyb1;
4129
4130	WB_EX_CHECK(n)
4131	WB_EX_CHECK(m)
4132
4133	R[n] = R[n] ^ R[m];
4134 END_OP
4135
4136
4137 //
4138 // XOR #imm,R0
4139 //
4140 BEGIN_OP(XOR_IMM_REG0)
4141	const unsigned imm = (uint8)instr;
4142
4143	WB_EX_CHECK(0)
4144
4145	R[0] = R[0] ^ imm;
4146 END_OP
4147
4148
4149 //
4150 // XOR.B #imm,@(R0,GBR)
4151 //
4152 BEGIN_OP(XOR_B_IMM_IDXGBRINDIR)
4153	const unsigned imm = (uint8)instr;
4154	const uint32 ea = R[0] + GBR;
4155	uint32 tmp;
4156
4157	tmp = MemRead<uint8>(ea);
4158	timestamp++;
4159	tmp ^= imm;
4160	MemWrite<uint8>(ea, tmp);
4161	timestamp++;
4162 END_OP
4163
4164
4165 //
4166 // ROTL Rn
4167 //
4168 BEGIN_OP(ROTL_REG)
4169	const unsigned n = instr_nyb2;
4170	const unsigned rotbit = R[n] >> 31;
4171
4172	WB_EX_CHECK(n)
4173
4174	R[n] = (R[n] << 1) | rotbit;
4175	SetT(rotbit);
4176 END_OP
4177
4178
4179 //
4180 // ROTR Rn
4181 //
4182 BEGIN_OP(ROTR_REG)
4183	const unsigned n = instr_nyb2;
4184	const unsigned rotbit = R[n] & 1;
4185
4186	WB_EX_CHECK(n)
4187
4188	R[n] = (R[n] >> 1) | (rotbit << 31);
4189	SetT(rotbit);
4190 END_OP
4191
4192
4193 //
4194 // ROTCL Rn
4195 //
4196 BEGIN_OP(ROTCL_REG)
4197	const unsigned n = instr_nyb2;
4198	const unsigned rotbit = R[n] >> 31;
4199
4200	WB_EX_CHECK(n)
4201
4202	R[n] = (R[n] << 1) | GetT();
4203	SetT(rotbit);
4204 END_OP
4205
4206
4207 //
4208 // ROTCR Rn
4209 //
4210 BEGIN_OP(ROTCR_REG)
4211	const unsigned n = instr_nyb2;
4212	const unsigned rotbit = R[n] & 1;
4213
4214	WB_EX_CHECK(n)
4215
4216	R[n] = (R[n] >> 1) | (GetT() << 31);
4217	SetT(rotbit);
4218 END_OP
4219
4220
4221 //
4222 // SHAR Rn
4223 //
4224 BEGIN_OP(SHAR_REG)
4225	const unsigned n = instr_nyb2;
4226	const unsigned shbit = R[n] & 1;
4227
4228	WB_EX_CHECK(n)
4229
4230	R[n] = (int32)R[n] >> 1;
4231	SetT(shbit);
4232 END_OP
4233
4234
4235 //
4236 // SHLL Rn
4237 //
4238 BEGIN_OP(SHLL_REG)
4239	const unsigned n = instr_nyb2;
4240	const unsigned shbit = R[n] >> 31;
4241
4242	WB_EX_CHECK(n)
4243
4244	R[n] <<= 1;
4245	SetT(shbit);
4246 END_OP
4247
4248
4249 //
4250 // SHLR Rn
4251 //
4252 BEGIN_OP(SHLR_REG)
4253	const unsigned n = instr_nyb2;
4254	const unsigned shbit = R[n] & 1;
4255
4256	WB_EX_CHECK(n)
4257
4258	R[n] >>= 1;
4259	SetT(shbit);
4260 END_OP
4261
4262
4263 //
4264 // SHLL2 Rn
4265 //
4266 BEGIN_OP(SHLL2_REG)
4267	const unsigned n = instr_nyb2;
4268
4269	WB_EX_CHECK(n)
4270
4271	R[n] <<= 2;
4272 END_OP
4273
4274
4275 //
4276 // SHLR2 Rn
4277 //
4278 BEGIN_OP(SHLR2_REG)
4279	const unsigned n = instr_nyb2;
4280
4281	WB_EX_CHECK(n)
4282
4283	R[n] >>= 2;
4284 END_OP
4285
4286
4287 //
4288 // SHLL8 Rn
4289 //
4290 BEGIN_OP(SHLL8_REG)
4291	const unsigned n = instr_nyb2;
4292
4293	WB_EX_CHECK(n)
4294
4295	R[n] <<= 8;
4296 END_OP
4297
4298
4299 //
4300 // SHLR8 Rn
4301 //
4302 BEGIN_OP(SHLR8_REG)
4303	const unsigned n = instr_nyb2;
4304
4305	WB_EX_CHECK(n)
4306
4307	R[n] >>= 8;
4308 END_OP
4309
4310
4311 //
4312 // SHLL16 Rn
4313 //
4314 BEGIN_OP(SHLL16_REG)
4315	const unsigned n = instr_nyb2;
4316
4317	WB_EX_CHECK(n)
4318
4319	R[n] <<= 16;
4320 END_OP
4321
4322
4323 //
4324 // SHLR16 Rn
4325 //
4326 BEGIN_OP(SHLR16_REG)
4327	const unsigned n = instr_nyb2;
4328
4329	WB_EX_CHECK(n)
4330
4331	R[n] >>= 16;
4332 END_OP
4333
4334
4335 //
4336 // BF
4337 //
4338 BEGIN_OP(BF)
4339	CondRelBranch<which, EmulateICache, DebugMode, false>(!GetT(), (uint32)(int8)instr << 1);
4340 END_OP
4341
4342
4343 //
4344 // BF/S
4345 //
4346 BEGIN_OP(BF_S)
4347	CondRelBranch<which, EmulateICache, DebugMode, true>(!GetT(), (uint32)(int8)instr << 1);
4348 END_OP
4349
4350
4351 //
4352 // BT
4353 //
4354 BEGIN_OP(BT)
4355	CondRelBranch<which, EmulateICache, DebugMode, false>(GetT(), (uint32)(int8)instr << 1);
4356 END_OP
4357
4358
4359 //
4360 // BT/S
4361 //
4362 BEGIN_OP(BT_S)
4363	CondRelBranch<which, EmulateICache, DebugMode, true>(GetT(), (uint32)(int8)instr << 1);
4364 END_OP
4365
4366
4367 //
4368 // BRA
4369 //
4370 BEGIN_OP_DLYIDIF(BRA)
4371	UCRelDelayBranch<which, EmulateICache, DebugMode>((uint32)sign_x_to_s32(12, instr) << 1);
4372 END_OP
4373
4374
4375 //
4376 // BRAF Rm
4377 //
4378 BEGIN_OP_DLYIDIF(BRAF_REG)
4379	const unsigned m = instr_nyb2;
4380
4381	UCRelDelayBranch<which, EmulateICache, DebugMode>(R[m]);
4382 END_OP
4383
4384
4385 //
4386 // BSR
4387 //
4388 BEGIN_OP_DLYIDIF(BSR)
4389	PR = PC;
4390
4391	UCRelDelayBranch<which, EmulateICache, DebugMode>((uint32)sign_x_to_s32(12, instr) << 1);
4392 END_OP
4393
4394
4395 //
4396 // BSRF Rm
4397 //
4398 BEGIN_OP_DLYIDIF(BSRF_REG)
4399	const unsigned m = instr_nyb2;
4400
4401	PR = PC;
4402
4403	UCRelDelayBranch<which, EmulateICache, DebugMode>(R[m]);
4404 END_OP
4405
4406
4407 //
4408 // JMP @Rm
4409 //
4410 BEGIN_OP_DLYIDIF(JMP_REGINDIR)
4411	const unsigned m = instr_nyb2;
4412
4413	UCDelayBranch<which, EmulateICache, DebugMode>(R[m]);
4414 END_OP
4415
4416
4417 //
4418 // JSR @Rm
4419 //
4420 BEGIN_OP_DLYIDIF(JSR_REGINDIR)
4421	const unsigned m = instr_nyb2;
4422
4423	PR = PC;
4424
4425	UCDelayBranch<which, EmulateICache, DebugMode>(R[m]);
4426 END_OP
4427
4428
4429 //
4430 // RTS
4431 //
4432 BEGIN_OP_DLYIDIF(RTS)
4433	UCDelayBranch<which, EmulateICache, DebugMode>(PR);
4434 END_OP
4435
4436
4437 //
4438 // CLRT
4439 //
4440 BEGIN_OP(CLRT)
4441	SetT(false);
4442 END_OP
4443
4444
4445 //
4446 // CLRMAC
4447 //
4448 BEGIN_OP(CLRMAC)
4449	MACH = 0;
4450	MACL = 0;
4451 END_OP
4452
4453
4454 //
4455 // LDC
4456 //
4457 BEGIN_OP_DLYIDIF(LDC)
4458	const unsigned m = instr_nyb2;
4459	const unsigned cri = (instr >> 4) & 0x3;
4460
4461	CtrlRegs[cri] = R[m];
4462	if(cri == 0)
4463	{
4464	 SR &= 0x3F3;
4465	 RecalcPendingIntPEX();
4466	}
4467	PART_OP_INTDIS
4468 END_OP
4469
4470 //
4471 // LDC.L
4472 //
4473 // Pipeline: page 233
4474 //
4475 BEGIN_OP_DLYIDIF(LDC_L)
4476	const unsigned m = instr_nyb2;
4477	const unsigned cri = (instr >> 4) & 0x3;
4478	uint32 ea;
4479
4480	ea = R[m];
4481	R[m] += 4;
4482
4483	timestamp++;
4484	CtrlRegs[cri] = MemRead<uint32>(ea);
4485	if(cri == 0)
4486	{
4487	 SR &= 0x3F3;
4488	 RecalcPendingIntPEX();
4489	}
4490
4491	timestamp++;
4492	PART_OP_INTDIS
4493 END_OP
4494
4495
4496 //
4497 // LDS
4498 //
4499 BEGIN_OP_DLYIDIF(LDS)
4500	const unsigned m = instr_nyb2;
4501	const unsigned sri = (instr >> 4) & 0x3;
4502
4503	SysRegs[sri] = R[m];
4504	PART_OP_INTDIS
4505 END_OP
4506
4507
4508 //
4509 // LDS.L
4510 //
4511 BEGIN_OP_DLYIDIF(LDS_L)	// Pipeline same as ordinary load instruction
4512	const unsigned m = instr_nyb2;
4513	const unsigned sri = (instr >> 4) & 0x3;
4514	uint32 ea;
4515
4516	ea = R[m];
4517	R[m] += 4;
4518
4519	PART_OP_INTDIS
4520
4521	SysRegs[sri] = MemRead<uint32>(ea);
4522	//printf(" LDS.L: (0x%08x)->0x%08x\n", ea, SysRegs[sri]);
4523 END_OP
4524
4525
4526 //
4527 // NOP
4528 //
4529 BEGIN_OP(NOP)
4530 END_OP
4531
4532
4533 //
4534 // RTE
4535 //
4536 // Pipeline: page 241
4537 //
4538 BEGIN_OP(RTE)
4539	uint32 new_PC;
4540
4541	new_PC = MemRead<uint32>(R[15]);
4542	R[15] += 4;
4543
4544	SR = MemRead<uint32>(R[15]);
4545	RecalcPendingIntPEX();
4546	R[15] += 4;
4547
4548	timestamp++;
4549
4550	Branch<which, EmulateICache, DebugMode, true>(new_PC);
4551 END_OP
4552
4553
4554 //
4555 // SETT
4556 //
4557 BEGIN_OP(SETT)
4558	SetT(true);
4559 END_OP
4560
4561
4562 //
4563 // SLEEP
4564 //
4565 BEGIN_OP_DLYIDIF(SLEEP)
4566	//
4567	// Standby mode time yay?
4568	//
4569	if(MDFN_UNLIKELY(SBYCR & 0x80))
4570	{
4571#ifdef HAVE_DEBUG
4572	 SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Entering standby mode.\n", cpu_name);
4573#endif
4574
4575	 for(unsigned ch = 0; ch < 2; ch++)
4576	 {
4577	  DMACH[ch].CHCR = 0x00;
4578	  DMACH[ch].CHCRM = 0x00;
4579	 }
4580	 DMAOR = 0x00;
4581	 DMA_RecalcRunning();
4582	 RecalcPendingIntPEX();
4583	 //
4584	 //
4585	 FRT_Reset();
4586	 //
4587	 //
4588	 WDT_StandbyReset();
4589	 //
4590	 //
4591	 SCI_Reset();
4592	 //
4593	 //
4594
4595	 timestamp++;
4596	 Pipe_ID = (Pipe_ID & 0x00FFFFFF) | (0x7E << 24);
4597
4598	 Standby = true;
4599
4600	 return;
4601	}
4602
4603	if(MDFN_LIKELY(!EPending))
4604	{
4605	 timestamp += 3;
4606	 return;
4607	}
4608	else
4609	{
4610	 DoIDIF<which, EmulateICache, DebugMode, false, false, false>();
4611	}
4612 END_OP
4613
4614 BEGIN_OP_DLYIDIF(PSEUDO_STANDBY)
4615	if(MDFN_LIKELY(Standby))
4616	{
4617	 timestamp += 7;
4618	 return;
4619	}
4620	else
4621	{
4622#ifdef HAVE_DEBUG
4623	 SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Exiting standby mode.\n", cpu_name);
4624#endif
4625
4626	 FRT_Reset();	// Reset again(for the counter) because we didn't stop clocking it.
4627
4628	 DoIDIF<which, EmulateICache, DebugMode, false, false, false>();
4629	}
4630 END_OP
4631
4632 //
4633 // STC
4634 //
4635 BEGIN_OP_DLYIDIF(STC)
4636	const unsigned n = instr_nyb2;
4637	const unsigned cri = (instr >> 4) & 0x3;
4638
4639	R[n] = CtrlRegs[cri];
4640	PART_OP_INTDIS
4641 END_OP
4642
4643
4644 //
4645 // STC.L
4646 //
4647 // pipeline: page 234
4648 BEGIN_OP_DLYIDIF(STC_L)
4649	const unsigned n = instr_nyb2;
4650	const unsigned cri = (instr >> 4) & 0x3;
4651	uint32 ea;
4652
4653	R[n] -= 4;
4654	ea = R[n];
4655
4656	MemWrite<uint32>(ea, CtrlRegs[cri]);
4657	timestamp++;
4658	PART_OP_INTDIS
4659 END_OP
4660
4661
4662 //
4663 // STS
4664 //
4665 BEGIN_OP_DLYIDIF(STS)
4666	const unsigned n = instr_nyb2;
4667	const unsigned sri = (instr >> 4) & 0x3;
4668
4669	R[n] = SysRegs[sri];
4670	PART_OP_INTDIS
4671 END_OP
4672
4673
4674 //
4675 // STS.L
4676 //
4677 BEGIN_OP_DLYIDIF(STS_L)	// Pipeline same as ordinary store instruction
4678	const unsigned n = instr_nyb2;
4679	const unsigned sri = (instr >> 4) & 0x3;
4680	uint32 ea;
4681
4682	R[n] -= 4;
4683	ea = R[n];
4684
4685	//printf(" STS.L: 0x%08x->(0x%08x)\n", SysRegs[sri], ea);
4686
4687	MemWrite<uint32>(ea, SysRegs[sri]);
4688
4689	PART_OP_INTDIS
4690 END_OP
4691
4692
4693 //
4694 // TRAPA #imm
4695 //
4696 // Saved PC is the address of the instruction after the TRAPA instruction
4697 //
4698 BEGIN_OP_DLYIDIF(TRAPA)
4699	const unsigned imm = (uint8)instr;
4700
4701	PC -= 2;
4702	Branch<which, EmulateICache, -DebugMode, false>(Exception<DebugMode>(EXCEPTION_TRAP, imm));
4703 END_OP
4704
4705
4706 /*
4707 **
4708 **
4709 */
4710 //
4711 // Illegal Instruction
4712 //
4713 // Saved PC is the address of the illegal instruction.
4714 //
4715 BEGIN_OP_DLYIDIF(ILLEGAL)
4716	PC -= 4;
4717	Branch<which, EmulateICache, -DebugMode, false>(Exception<DebugMode>(EXCEPTION_ILLINSTR, VECNUM_ILLINSTR));
4718 END_OP
4719
4720 //
4721 // Illegal Slot Instruction
4722 //
4723 // Saved PC is the effective target address of the jump.
4724 //
4725 BEGIN_OP_DLYIDIF(SLOT_ILLEGAL)
4726	PC -= 2;
4727	Branch<which, EmulateICache, -DebugMode, false>(Exception<DebugMode>(EXCEPTION_ILLSLOT, VECNUM_ILLSLOT));
4728 END_OP
4729
4730 //
4731 // Pending exception(address error/interrupt)
4732 //
4733 BEGIN_OP_DLYIDIF(PSEUDO_EPENDING)
4734	uint32 new_PC = 0;
4735
4736	//
4737	// Priority here(listed highest to lowest):
4738	//  External halt
4739	//   Power
4740	//    Reset
4741	//     Pseudo DMA burst(hacky abusey thing to stall the CPU, should be above everything but reset/power and ext halt otherwise kaboom!).
4742	//      CPU address error
4743	//       DMA address error
4744	//        NMI
4745	//         Interrupt (final else, may be called quasi-spuriously)
4746	//
4747	#define TPP(x) (Pipe_ID & (1U << ((x) + EPENDING_PEXBITS_SHIFT)))
4748	//
4749	// Test against Pipe_ID, reset bits in EPending(if appropriate).
4750	//
4751	if(MDFN_UNLIKELY(TPP(PEX_PSEUDO_EXTHALT)))
4752	{
4753	 //SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Ext halt begin: Pipe_ID=0x%08x PC=0x%08x\n", cpu_name, Pipe_ID, PC);
4754	 Pipe_ID = (Pipe_ID & 0x00FFFFFF) | (0xFE << 24);
4755	 return;
4756	}
4757	else if(MDFN_UNLIKELY(TPP(PEX_POWERON) || TPP(PEX_RESET)))
4758	{
4759         if(TPP(PEX_POWERON))
4760	 {
4761	  EPending = 0;
4762	  new_PC = Exception<DebugMode>(EXCEPTION_POWERON, VECNUM_POWERON);
4763	 }
4764	 else
4765	 {
4766	  EPending = 0;
4767	  new_PC = Exception<DebugMode>(EXCEPTION_RESET, VECNUM_RESET);
4768	 }
4769	}
4770	else if(MDFN_UNLIKELY(TPP(PEX_PSEUDO_DMABURST)))
4771	{
4772	 //SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Burst begin: Pipe_ID=0x%08x PC=0x%08x\n", cpu_name, Pipe_ID, PC);
4773	 Pipe_ID = (Pipe_ID & 0x00FFFFFF) | (0xFE << 24);
4774	 return;
4775	}
4776	else if(MDFN_UNLIKELY(TPP(PEX_CPUADDR)))
4777	{
4778	 PC -= 4;
4779	 ClearPEX(PEX_CPUADDR);
4780	 new_PC = Exception<DebugMode>(EXCEPTION_CPUADDR, VECNUM_CPUADDR);
4781	 ClearPEX(PEX_CPUADDR);	// Infinite recursive address errors are not good(stack wraparound could clobber backup memory).
4782	}
4783	else if(MDFN_UNLIKELY(TPP(PEX_DMAADDR)))
4784	{
4785	 PC -= 4;
4786	 ClearPEX(PEX_DMAADDR);
4787	 new_PC = Exception<DebugMode>(EXCEPTION_DMAADDR, VECNUM_DMAADDR);
4788	}
4789	else if(TPP(PEX_NMI))
4790	{
4791	 PC -= 4;
4792	 ClearPEX(PEX_NMI);
4793	 new_PC = Exception<DebugMode>(EXCEPTION_NMI, VECNUM_NMI);
4794	 //
4795	 //
4796	 //
4797	 SR |= 0xF << 4;
4798	 RecalcPendingIntPEX();
4799	}
4800	else	// Int
4801	{
4802	 uint8 ipr;
4803
4804	 ipr = GetPendingInt(NULL);
4805
4806	 if(MDFN_LIKELY(ipr > ((SR >> 4) & 0xF)))
4807	 {
4808	  uint8 vecnum;
4809
4810	  // Note: GetPendingInt() may call ExIVecFetch(), which may call SetIRL with a new value, so be
4811	  // careful to use the "old" value here.
4812	  GetPendingInt(&vecnum);
4813
4814	  PC -= 4;
4815	  new_PC = Exception<DebugMode>(EXCEPTION_INT, vecnum);
4816	  //
4817	  //
4818	  //
4819	  SR &= ~(0xF << 4);
4820	  SR |= ipr << 4;
4821	  RecalcPendingIntPEX();
4822	 }
4823	 else
4824	 {
4825	  //
4826	  // Can happen like so(note for future testing):
4827	  //
4828	  // (WDT interval timer IRQ pending here)
4829	  //
4830	  // WTCSR_R;
4831	  // asm volatile(
4832	  //	"ldc %0,SR\n\t"
4833	  //	"mov.w %2, @%1\n\t"
4834	  //	:
4835	  //	:"r"(0), "r"(0xFFFFFE88), "r"(0xA500 | 0x00)
4836	  // 	: "memory");
4837	  //
4838#ifdef HAVE_DEBUG
4839	  SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Spurious EPENDING. IPR=0x%02x SR=0x%04x EPending=0x%08x Pipe_ID=0x%08x PC=0x%08x\n", cpu_name, ipr, SR, EPending, Pipe_ID, PC);
4840#endif
4841
4842	  Pipe_ID = (uint16)Pipe_ID;
4843	  Pipe_ID |= InstrDecodeTab[Pipe_ID] << 24;
4844	  goto SPEPRecover;
4845	 }
4846	}
4847	//
4848	//
4849	//
4850	Branch<which, EmulateICache, -DebugMode, false>(new_PC);
4851 END_OP
4852
4853 BEGIN_OP_DLYIDIF(PSEUDO_DMABURST)
4854	if(MDFN_LIKELY(DMA_InBurst() || ExtHalt))
4855	{
4856	 timestamp += 7;
4857	 return;
4858	}
4859	else
4860	{
4861	 ClearPEX(PEX_PSEUDO_DMABURST);
4862	 ClearPEX(PEX_PSEUDO_EXTHALT);
4863
4864	 //
4865	 // Recover Pipe_ID opcode field; only use Pipe_ID for this, not EPending, otherwise
4866	 // we may accidentally allow an interrupt to occur immediately after an interrupt-disabled instruction.
4867	 //
4868	 Pipe_ID &= 0x00FFFFFF;
4869	 Pipe_ID &= ~(1U << (PEX_PSEUDO_DMABURST + EPENDING_PEXBITS_SHIFT));
4870	 Pipe_ID &= ~(1U << (PEX_PSEUDO_EXTHALT + EPENDING_PEXBITS_SHIFT));
4871	 Pipe_ID |= InstrDecodeTab[(uint16)Pipe_ID] << 24;
4872	 if(Pipe_ID & (0xFF << EPENDING_PEXBITS_SHIFT))
4873	  Pipe_ID |= EPENDING_OP_OR;
4874
4875	 //SS_DBG(SS_DBG_WARNING | SS_DBG_SH2, "[%s] Burst/External halt end: Pipe_ID=0x%08x PC=0x%08x\n", cpu_name, Pipe_ID, PC);
4876	 return;
4877	}
4878 END_OP
4879
4880
4881 #undef BEGIN_OP
4882 #undef BEGIN_OP_DLYIDIF
4883 #undef END_OP
4884 }
4885
4886 PC += 2;
4887}
4888
4889
4890void SH7095::StateAction(StateMem* sm, const unsigned load, const bool data_only, const char* sname)
4891{
4892 SFORMAT StateRegs[] =
4893 {
4894  SFVAR(R),
4895  SFVAR(PC),
4896  SFVAR(CtrlRegs),
4897
4898  SFVAR(timestamp),
4899  SFVAR(MA_until),
4900  SFVAR(MM_until),
4901  SFVAR(write_finish_timestamp),
4902#if 0
4903 sscpu_timestamp_t WB_until[16];
4904#endif
4905  SFVAR(SysRegs),
4906
4907  SFVAR(EPending),
4908  SFVAR(Pipe_ID),
4909  SFVAR(Pipe_IF),
4910
4911  SFVAR(IBuffer),
4912
4913  SFPTR32(Cache->Tag, 4, 64, sizeof(*Cache), Cache),
4914  SFVAR(Cache->LRU, 64, sizeof(*Cache), Cache),
4915  SFPTR32((uint32*)Cache->Data, 16, 64, sizeof(*Cache), Cache),	// Cast because it's stored as native-endian 32-bit.
4916
4917  SFVAR(CCR),
4918
4919  SFVAR(NMILevel),
4920  SFVAR(IRL),
4921
4922  SFVAR(IPRA),
4923  SFVAR(IPRB),
4924  SFVAR(VCRWDT),
4925  SFVAR(VCRA),
4926  SFVAR(VCRB),
4927  SFVAR(VCRC),
4928  SFVAR(VCRD),
4929  SFVAR(ICR),
4930
4931 //
4932 //
4933 //
4934  SFVAR(BSC.BCR1),
4935  SFVAR(BSC.BCR2),
4936  SFVAR(BSC.WCR),
4937  SFVAR(BSC.MCR),
4938  SFVAR(BSC.RTCSR),
4939  SFVAR(BSC.RTCSRM),
4940  SFVAR(BSC.RTCNT),
4941  SFVAR(BSC.RTCOR),
4942
4943  SFVAR(SBYCR),
4944  SFVAR(Standby),
4945
4946  SFVAR(FRT.lastts),
4947  SFVAR(FRT.FTI),
4948  SFVAR(FRT.FTCI),
4949  SFVAR(FRT.FRC),
4950  SFVAR(FRT.OCR),
4951  SFVAR(FRT.FICR),
4952  SFVAR(FRT.TIER),
4953  SFVAR(FRT.FTCSR),
4954  SFVAR(FRT.FTCSRM),
4955  SFVAR(FRT.TCR),
4956  SFVAR(FRT.TOCR),
4957  SFVAR(FRT.RW_Temp),
4958
4959  SFVAR(FRT_WDT_ClockDivider),
4960
4961  SFVAR(FRT_WDT_NextTS),
4962
4963  SFVAR(WDT.WTCSR),
4964  SFVAR(WDT.WTCSRM),
4965  SFVAR(WDT.WTCNT),
4966  SFVAR(WDT.RSTCSR),
4967  SFVAR(WDT.RSTCSRM),
4968
4969  SFVAR(dma_lastts),
4970
4971  SFVAR(DMA_ClockCounter),
4972  SFVAR(DMA_SGCounter),
4973  SFVAR(DMA_RoundRobinRockinBoppin),
4974
4975  SFVAR(DMA_PenaltyKludgeAmount),
4976  SFVAR(DMA_PenaltyKludgeAccum),
4977
4978  SFVAR(DMACH->SAR, 2, sizeof(*DMACH), DMACH),
4979  SFVAR(DMACH->DAR, 2, sizeof(*DMACH), DMACH),
4980  SFVAR(DMACH->TCR, 2, sizeof(*DMACH), DMACH),
4981  SFVAR(DMACH->CHCR, 2, sizeof(*DMACH), DMACH),
4982  SFVAR(DMACH->CHCRM, 2, sizeof(*DMACH), DMACH),
4983  SFVAR(DMACH->VCR, 2, sizeof(*DMACH), DMACH),
4984  SFVAR(DMACH->DRCR, 2, sizeof(*DMACH), DMACH),
4985
4986  SFVAR(DMAOR),
4987  SFVAR(DMAORM),
4988
4989  SFVAR(divide_finish_timestamp),
4990  SFVAR(DVSR),
4991  SFVAR(DVDNT),
4992  SFVAR(DVDNTH),
4993  SFVAR(DVDNTL),
4994  SFVAR(DVDNTH_Shadow),
4995  SFVAR(DVDNTL_Shadow),
4996  SFVAR(VCRDIV),
4997  SFVAR(DVCR),
4998
4999  SFVAR(SCI.SMR),
5000  SFVAR(SCI.BRR),
5001  SFVAR(SCI.SCR),
5002  SFVAR(SCI.TDR),
5003  SFVAR(SCI.SSR),
5004  SFVAR(SCI.SSRM),
5005  SFVAR(SCI.RDR),
5006
5007  SFVAR(SCI.RSR),
5008  SFVAR(SCI.TSR),
5009
5010  SFVAR(ExtHalt),
5011
5012  SFVAR(PC_IF),
5013  SFVAR(PC_ID),
5014
5015  SFEND
5016 };
5017
5018 MDFNSS_StateAction(sm, load, data_only, StateRegs, sname, false);
5019
5020 if(load)
5021 {
5022  SetCCR(CCR);
5023 }
5024}
5025
5026//
5027//
5028//
5029//
5030//
5031//
5032//
5033//
5034
5035INLINE uint32 SH7095::GetRegister(const unsigned id, char* const special, const uint32 special_len)
5036{
5037 uint32 ret = 0xDEADBEEF;
5038
5039 switch(id)
5040 {
5041  case GSREG_PC_ID:
5042	ret = PC_ID;
5043	break;
5044
5045  case GSREG_PC_IF:
5046	ret = PC_IF;
5047	break;
5048
5049  case GSREG_PID:
5050	ret = Pipe_ID;
5051	break;
5052
5053  case GSREG_PIF:
5054	ret = Pipe_IF;
5055	break;
5056
5057  case GSREG_EP:
5058	ret = EPending;
5059	break;
5060
5061  case GSREG_RPC:
5062	ret = PC;
5063	break;
5064
5065  case GSREG_R0: case GSREG_R1: case GSREG_R2: case GSREG_R3: case GSREG_R4: case GSREG_R5: case GSREG_R6: case GSREG_R7:
5066  case GSREG_R8: case GSREG_R9: case GSREG_R10: case GSREG_R11: case GSREG_R12: case GSREG_R13: case GSREG_R14: case GSREG_R15:
5067	ret = R[id - GSREG_R0];
5068	break;
5069
5070  case GSREG_SR:
5071	ret = SR;
5072	break;
5073
5074  case GSREG_GBR:
5075	ret = GBR;
5076	break;
5077
5078  case GSREG_VBR:
5079	ret = VBR;
5080	break;
5081
5082  case GSREG_MACH:
5083	ret = MACH;
5084	break;
5085
5086  case GSREG_MACL:
5087	ret = MACL;
5088	break;
5089
5090  case GSREG_PR:
5091	ret = PR;
5092	break;
5093
5094  //
5095  //
5096  //
5097  case GSREG_NMIL:
5098	ret = NMILevel;
5099	break;
5100
5101  case GSREG_IRL:
5102	ret = IRL;
5103	break;
5104
5105  case GSREG_IPRA:
5106	ret = IPRA;
5107	break;
5108
5109  case GSREG_IPRB:
5110	ret = IPRB;
5111	break;
5112
5113  case GSREG_VCRWDT:
5114	ret = VCRWDT;
5115	break;
5116
5117  case GSREG_VCRA:
5118	ret = VCRA;
5119	break;
5120
5121  case GSREG_VCRB:
5122	ret = VCRB;
5123	break;
5124
5125  case GSREG_VCRC:
5126	ret = VCRC;
5127	if(special)
5128	{
5129	 snprintf(special, special_len, "FIC: 0x%02x, FOC: 0x%02x", (ret >> 8) & 0x7F, ret & 0x7F);
5130	}
5131	break;
5132
5133  case GSREG_VCRD:
5134	ret = VCRD;
5135	break;
5136
5137  case GSREG_ICR:
5138	ret = ICR;
5139	break;
5140  //
5141  //
5142  //
5143  case GSREG_DVSR:
5144	ret = DVSR;
5145	break;
5146
5147  case GSREG_DVDNT:
5148	ret = DVDNT;
5149	break;
5150
5151  case GSREG_DVDNTH:
5152	ret = DVDNTH;
5153	break;
5154
5155  case GSREG_DVDNTL:
5156	ret = DVDNTL;
5157	break;
5158
5159  case GSREG_DVDNTHS:
5160	ret = DVDNTH_Shadow;
5161	break;
5162
5163  case GSREG_DVDNTLS:
5164	ret = DVDNTL_Shadow;
5165	break;
5166
5167  case GSREG_VCRDIV:
5168	ret = VCRDIV;
5169	break;
5170
5171  case GSREG_DVCR:
5172	ret = DVCR;
5173	break;
5174  //
5175  //
5176  //
5177  case GSREG_WTCSR:
5178	ret = WDT.WTCSR;
5179	break;
5180
5181  case GSREG_WTCSRM:
5182	ret = WDT.WTCSRM;
5183	break;
5184
5185  case GSREG_WTCNT:
5186	ret = WDT.WTCNT;
5187	break;
5188
5189  case GSREG_RSTCSR:
5190	ret = WDT.RSTCSR;
5191	break;
5192
5193  case GSREG_RSTCSRM:
5194	ret = WDT.RSTCSRM;
5195	break;
5196  //
5197  //
5198  //
5199  case GSREG_DMAOR:
5200	ret = DMAOR;
5201	break;
5202
5203  case GSREG_DMAORM:
5204	ret = DMAORM;
5205	break;
5206
5207  case GSREG_DMA0_SAR:
5208  case GSREG_DMA1_SAR:
5209	ret = DMACH[id == GSREG_DMA1_SAR].SAR;
5210	break;
5211
5212  case GSREG_DMA0_DAR:
5213  case GSREG_DMA1_DAR:
5214	ret = DMACH[id == GSREG_DMA1_DAR].DAR;
5215	break;
5216
5217  case GSREG_DMA0_TCR:
5218  case GSREG_DMA1_TCR:
5219	ret = DMACH[id == GSREG_DMA1_TCR].TCR;
5220	break;
5221
5222  case GSREG_DMA0_CHCR:
5223  case GSREG_DMA1_CHCR:
5224	ret = DMACH[id == GSREG_DMA1_CHCR].CHCR;
5225	break;
5226
5227  case GSREG_DMA0_CHCRM:
5228  case GSREG_DMA1_CHCRM:
5229	ret = DMACH[id == GSREG_DMA1_CHCRM].CHCRM;
5230	break;
5231
5232  case GSREG_DMA0_VCR:
5233  case GSREG_DMA1_VCR:
5234	ret = DMACH[id == GSREG_DMA1_VCR].VCR;
5235	break;
5236
5237  case GSREG_DMA0_DRCR:
5238  case GSREG_DMA1_DRCR:
5239	ret = DMACH[id == GSREG_DMA1_DRCR].DRCR;
5240	break;
5241  //
5242  //
5243  //
5244  case GSREG_FRC:
5245	ret = FRT.FRC;
5246	break;
5247
5248  case GSREG_OCR0:
5249	ret = FRT.OCR[0];
5250	break;
5251
5252  case GSREG_OCR1:
5253	ret = FRT.OCR[1];
5254	break;
5255
5256  case GSREG_FICR:
5257	ret = FRT.FICR;
5258	break;
5259
5260  case GSREG_TIER:
5261	ret = FRT.TIER;
5262	break;
5263
5264  case GSREG_FTCSR:
5265	ret = FRT.FTCSR;
5266	break;
5267
5268  case GSREG_FTCSRM:
5269	ret = FRT.FTCSRM;
5270	break;
5271
5272  case GSREG_TCR:
5273	ret = FRT.TCR;
5274	break;
5275
5276  case GSREG_TOCR:
5277	ret = FRT.TOCR;
5278	break;
5279
5280  case GSREG_RWT:
5281	ret = FRT.RW_Temp;
5282	break;
5283 }
5284
5285 return ret;
5286}
5287
5288void SH7095::SetRegister(const unsigned id, const uint32 value)
5289{
5290 switch(id)
5291 {
5292  //case GSREG_PC: break;
5293
5294  case GSREG_PID:
5295	Pipe_ID = value;
5296	break;
5297
5298  case GSREG_PIF:
5299	Pipe_IF = value;
5300	break;
5301
5302  //case GSREG_EP:
5303  //	EPending = value;
5304  //	break;
5305
5306  case GSREG_RPC:
5307	PC = value;
5308	break;
5309
5310  case GSREG_R0: case GSREG_R1: case GSREG_R2: case GSREG_R3: case GSREG_R4: case GSREG_R5: case GSREG_R6: case GSREG_R7:
5311  case GSREG_R8: case GSREG_R9: case GSREG_R10: case GSREG_R11: case GSREG_R12: case GSREG_R13: case GSREG_R14: case GSREG_R15:
5312	R[id - GSREG_R0] = value;
5313	break;
5314
5315  case GSREG_SR:
5316	SR = value & 0x3F3;
5317	RecalcPendingIntPEX();
5318	break;
5319
5320  case GSREG_GBR:
5321	GBR = value;
5322	break;
5323
5324  case GSREG_VBR:
5325	VBR = value;
5326	break;
5327
5328  case GSREG_MACH:
5329	MACH = value;
5330	break;
5331
5332  case GSREG_MACL:
5333	MACL = value;
5334	break;
5335
5336  case GSREG_PR:
5337	PR = value;
5338	break;
5339
5340  //
5341  //
5342  //
5343  case GSREG_FTCSR:
5344	FRT.FTCSR = value & 0x8F;
5345	RecalcPendingIntPEX();
5346	FRT_CheckOCR();
5347	break;
5348
5349  case GSREG_FTCSRM:
5350	FRT.FTCSRM = value & 0x8F;
5351	break;
5352 }
5353}
5354
5355//
5356//
5357//
5358//
5359//
5360//
5361//
5362
5363//
5364//
5365//
5366//
5367INLINE void SH7095::CheckRWBreakpoints(void (*MRead)(unsigned len, uint32 addr), void (*MWrite)(unsigned len, uint32 addr)) const
5368{
5369 uint32 lpid = Pipe_ID;
5370 //
5371 //
5372 //
5373 //SPEPRecover:;
5374 const uint32 instr = (uint16)lpid;
5375 const unsigned instr_nyb1 = (instr >> 4) & 0xF;
5376 const unsigned instr_nyb2 = (instr >> 8) & 0xF;
5377
5378 switch(lpid >> 24)
5379 {
5380 #include "sh7095_opdefs.inc"
5381 #define BEGIN_BP_OP(x) OP_##x {
5382 #define END_BP_OP } break;
5383
5384 //
5385 // MOV.W @(disp,PC),Rn
5386 //
5387 BEGIN_BP_OP(MOV_W_PCREL_REG)
5388	const unsigned d = (instr >> 0) & 0xff;
5389	const uint32 ea = PC + (d << 1);
5390
5391	MRead(2, ea);
5392 END_BP_OP
5393
5394
5395 //
5396 // MOV.L @(disp,PC),Rn
5397 //
5398 BEGIN_BP_OP(MOV_L_PCREL_REG)
5399	const unsigned d = (instr >> 0) & 0xff;
5400	const uint32 ea = (PC &~ 0x3) + (d << 2);
5401
5402	MRead(4, ea);
5403 END_BP_OP
5404
5405
5406 //
5407 // MOV.B Rm,@Rn
5408 //
5409 BEGIN_BP_OP(MOV_B_REG_REGINDIR)
5410	const unsigned n = instr_nyb2;
5411	const uint32 ea = R[n];
5412
5413	MWrite(1, ea);
5414 END_BP_OP
5415
5416
5417 //
5418 // MOV.W Rm,@Rn
5419 //
5420 BEGIN_BP_OP(MOV_W_REG_REGINDIR)
5421	const unsigned n = instr_nyb2;
5422	const uint32 ea = R[n];
5423
5424	MWrite(2, ea);
5425 END_BP_OP
5426
5427
5428 //
5429 // MOV.L Rm,@Rn
5430 //
5431 BEGIN_BP_OP(MOV_L_REG_REGINDIR)
5432	const unsigned n = instr_nyb2;
5433	const uint32 ea = R[n];
5434
5435	MWrite(4, ea);
5436 END_BP_OP
5437
5438
5439 //
5440 // MOV.B @Rm,Rn
5441 //
5442 BEGIN_BP_OP(MOV_B_REGINDIR_REG)
5443	const unsigned m = instr_nyb1;
5444	const uint32 ea = R[m];
5445
5446	MRead(1, ea);
5447 END_BP_OP
5448
5449
5450 //
5451 // MOV.W @Rm,Rn
5452 //
5453 BEGIN_BP_OP(MOV_W_REGINDIR_REG)
5454	const unsigned m = instr_nyb1;
5455	const uint32 ea = R[m];
5456
5457	MRead(2, ea);
5458 END_BP_OP
5459
5460
5461 //
5462 // MOV.L @Rm,Rn
5463 //
5464 BEGIN_BP_OP(MOV_L_REGINDIR_REG)
5465	const unsigned m = instr_nyb1;
5466	const uint32 ea = R[m];
5467
5468	MRead(4, ea);
5469 END_BP_OP
5470
5471
5472 //
5473 // MOV.B Rm,@-Rn
5474 //
5475 BEGIN_BP_OP(MOV_B_REG_REGINDIRPD)
5476	const unsigned n = instr_nyb2;
5477	const uint32 ea = R[n] - 1;
5478
5479	MWrite(1, ea);
5480 END_BP_OP
5481
5482
5483 //
5484 // MOV.W Rm,@-Rn
5485 //
5486 BEGIN_BP_OP(MOV_W_REG_REGINDIRPD)
5487	const unsigned n = instr_nyb2;
5488	const uint32 ea = R[n] - 2;
5489
5490	MWrite(2, ea);
5491 END_BP_OP
5492
5493
5494 //
5495 // MOV.L Rm,@-Rn
5496 //
5497 BEGIN_BP_OP(MOV_L_REG_REGINDIRPD)
5498	const unsigned n = instr_nyb2;
5499	const uint32 ea = R[n] - 4;
5500
5501	MWrite(4, ea);
5502 END_BP_OP
5503
5504
5505 //
5506 // MOV.B @Rm+,Rn
5507 //
5508 BEGIN_BP_OP(MOV_B_REGINDIRPI_REG)
5509	const unsigned m = instr_nyb1;
5510	const uint32 ea = R[m];
5511
5512	MRead(1, ea);
5513 END_BP_OP
5514
5515
5516 //
5517 // MOV.W @Rm+,Rn
5518 //
5519 BEGIN_BP_OP(MOV_W_REGINDIRPI_REG)
5520	const unsigned m = instr_nyb1;
5521	const uint32 ea = R[m];
5522
5523	MRead(2, ea);
5524 END_BP_OP
5525
5526
5527 //
5528 // MOV.L @Rm+,Rn
5529 //
5530 BEGIN_BP_OP(MOV_L_REGINDIRPI_REG)
5531	const unsigned m = instr_nyb1;
5532	const uint32 ea = R[m];
5533
5534	MRead(4, ea);
5535 END_BP_OP
5536
5537
5538 //
5539 // MOV.B R0,@(disp,Rn)
5540 //
5541 BEGIN_BP_OP(MOV_B_REG0_REGINDIRDISP)
5542	const unsigned n = instr_nyb1;
5543	const unsigned d = (instr >> 0) & 0xf;
5544	const uint32 ea = R[n] + (d << 0);
5545
5546	MWrite(1, ea);
5547 END_BP_OP
5548
5549
5550 //
5551 // MOV.W R0,@(disp,Rn)
5552 //
5553 BEGIN_BP_OP(MOV_W_REG0_REGINDIRDISP)
5554	const unsigned n = instr_nyb1;
5555	const unsigned d = (instr >> 0) & 0xf;
5556	const uint32 ea = R[n] + (d << 1);
5557
5558	MWrite(2, ea);
5559 END_BP_OP
5560
5561
5562 //
5563 // MOV.L Rm,@(disp,Rn)
5564 //
5565 BEGIN_BP_OP(MOV_L_REG_REGINDIRDISP)
5566	const unsigned n = instr_nyb2;
5567	const unsigned d = (instr >> 0) & 0xf;
5568	const uint32 ea = R[n] + (d << 2);
5569
5570	MWrite(4, ea);
5571 END_BP_OP
5572
5573
5574 //
5575 // MOV.B @(disp,Rm),R0
5576 //
5577 BEGIN_BP_OP(MOV_B_REGINDIRDISP_REG0)
5578	const unsigned m = instr_nyb1;
5579	const unsigned d = (instr >> 0) & 0xf;
5580	const uint32 ea = R[m] + (d << 0);
5581
5582	MRead(1, ea);
5583 END_BP_OP
5584
5585
5586 //
5587 // MOV.W @(disp,Rm),R0
5588 //
5589 BEGIN_BP_OP(MOV_W_REGINDIRDISP_REG0)
5590	const unsigned m = instr_nyb1;
5591	const unsigned d = (instr >> 0) & 0xf;
5592	const uint32 ea = R[m] + (d << 1);
5593
5594	MRead(2, ea);
5595 END_BP_OP
5596
5597
5598 //
5599 // MOV.L @(disp,Rm),Rn
5600 //
5601 BEGIN_BP_OP(MOV_L_REGINDIRDISP_REG)
5602	const unsigned m = instr_nyb1;
5603	const unsigned d = (instr >> 0) & 0xf;
5604	const uint32 ea = R[m] + (d << 2);
5605
5606	MRead(4, ea);
5607 END_BP_OP
5608
5609
5610 //
5611 // MOV.B Rm,@(R0,Rn)
5612 //
5613 BEGIN_BP_OP(MOV_B_REG_IDXREGINDIR)
5614	const unsigned n = instr_nyb2;
5615	const uint32 ea = R[0] + R[n];
5616
5617	MWrite(1, ea);
5618 END_BP_OP
5619
5620
5621 //
5622 // MOV.W Rm,@(R0,Rn)
5623 //
5624 BEGIN_BP_OP(MOV_W_REG_IDXREGINDIR)
5625	const unsigned n = instr_nyb2;
5626	const uint32 ea = R[0] + R[n];
5627
5628	MWrite(2, ea);
5629 END_BP_OP
5630
5631
5632 //
5633 // MOV.L Rm,@(R0,Rn)
5634 //
5635 BEGIN_BP_OP(MOV_L_REG_IDXREGINDIR)
5636	const unsigned n = instr_nyb2;
5637	const uint32 ea = R[0] + R[n];
5638
5639	MWrite(4, ea);
5640 END_BP_OP
5641
5642
5643 //
5644 // MOV.B @(R0,Rm),Rn
5645 //
5646 BEGIN_BP_OP(MOV_B_IDXREGINDIR_REG)
5647	const unsigned m = instr_nyb1;
5648	const uint32 ea = R[0] + R[m];
5649
5650	MRead(1, ea);
5651 END_BP_OP
5652
5653
5654 //
5655 // MOV.W @(R0,Rm),Rn
5656 //
5657 BEGIN_BP_OP(MOV_W_IDXREGINDIR_REG)
5658	const unsigned m = instr_nyb1;
5659	const uint32 ea = R[0] + R[m];
5660
5661	MRead(2, ea);
5662 END_BP_OP
5663
5664
5665 //
5666 // MOV.L @(R0,Rm),Rn
5667 //
5668 BEGIN_BP_OP(MOV_L_IDXREGINDIR_REG)
5669	const unsigned m = instr_nyb1;
5670	const uint32 ea = R[0] + R[m];
5671
5672	MRead(4, ea);
5673 END_BP_OP
5674
5675
5676 //
5677 // MOV.B R0,@(disp,GBR)
5678 //
5679 BEGIN_BP_OP(MOV_B_REG0_GBRINDIRDISP)
5680	const unsigned d = (instr >> 0) & 0xff;
5681	const uint32 ea = GBR + (d << 0);
5682
5683	MWrite(1, ea);
5684 END_BP_OP
5685
5686
5687 //
5688 // MOV.W R0,@(disp,GBR)
5689 //
5690 BEGIN_BP_OP(MOV_W_REG0_GBRINDIRDISP)
5691	const unsigned d = (instr >> 0) & 0xff;
5692	const uint32 ea = GBR + (d << 1);
5693
5694	MWrite(2, ea);
5695 END_BP_OP
5696
5697
5698 //
5699 // MOV.L R0,@(disp,GBR)
5700 //
5701 BEGIN_BP_OP(MOV_L_REG0_GBRINDIRDISP)
5702	const unsigned d = (instr >> 0) & 0xff;
5703	const uint32 ea = GBR + (d << 2);
5704
5705	MWrite(4, ea);
5706 END_BP_OP
5707
5708
5709 //
5710 // MOV.B @(disp,GBR),R0
5711 //
5712 BEGIN_BP_OP(MOV_B_GBRINDIRDISP_REG0)
5713	const unsigned d = (instr >> 0) & 0xff;
5714	const uint32 ea = GBR + (d << 0);
5715
5716	MRead(1, ea);
5717 END_BP_OP
5718
5719
5720 //
5721 // MOV.W @(disp,GBR),R0
5722 //
5723 BEGIN_BP_OP(MOV_W_GBRINDIRDISP_REG0)
5724	const unsigned d = (instr >> 0) & 0xff;
5725	const uint32 ea = GBR + (d << 1);
5726
5727	MRead(2, ea);
5728 END_BP_OP
5729
5730
5731 //
5732 // MOV.L @(disp,GBR),R0
5733 //
5734 BEGIN_BP_OP(MOV_L_GBRINDIRDISP_REG0)
5735	const unsigned d = (instr >> 0) & 0xff;
5736	const uint32 ea = GBR + (d << 2);
5737
5738	MRead(4, ea);
5739 END_BP_OP
5740
5741
5742 //
5743 // MAC.L @Rm+,@Rn+
5744 //
5745 BEGIN_BP_OP(MAC_L)
5746	const unsigned n = instr_nyb2;
5747	const unsigned m = instr_nyb1;
5748
5749	MRead(4, R[m]);
5750        MRead(4, R[n] + ((m == n) << 2));
5751 END_BP_OP
5752
5753
5754 //
5755 // MAC.W @Rm+,@Rn+
5756 //
5757 BEGIN_BP_OP(MAC_W)
5758	const unsigned n = instr_nyb2;
5759	const unsigned m = instr_nyb1;
5760
5761	MRead(2, R[m]);
5762        MRead(2, R[n] + ((m == n) << 1));
5763 END_BP_OP
5764
5765
5766 //
5767 // AND.B #imm,@(R0,GBR)
5768 //
5769 BEGIN_BP_OP(AND_B_IMM_IDXGBRINDIR)
5770	const uint32 ea = R[0] + GBR;
5771
5772	MRead(1, ea);
5773	MWrite(1, ea);
5774 END_BP_OP
5775
5776 //
5777 // OR.B #imm,@(R0,GBR)
5778 //
5779 BEGIN_BP_OP(OR_B_IMM_IDXGBRINDIR)
5780	const uint32 ea = R[0] + GBR;
5781
5782	MRead(1, ea);
5783	MWrite(1, ea);
5784 END_BP_OP
5785
5786
5787 //
5788 // TAS.B @Rn
5789 //
5790 BEGIN_BP_OP(TAS_B_REGINDIR)
5791	const unsigned n = instr_nyb2;
5792	const uint32 ea = R[n];
5793
5794	MRead(1, ea);
5795	MWrite(1, ea);
5796 END_BP_OP
5797
5798
5799 //
5800 // TST.B #imm,@(R0,GBR)
5801 //
5802 BEGIN_BP_OP(TST_B_IMM_IDXGBRINDIR)
5803	const uint32 ea = R[0] + GBR;
5804
5805	MRead(1, ea);
5806 END_BP_OP
5807
5808
5809 //
5810 // XOR.B #imm,@(R0,GBR)
5811 //
5812 BEGIN_BP_OP(XOR_B_IMM_IDXGBRINDIR)
5813	const uint32 ea = R[0] + GBR;
5814
5815	MRead(1, ea);
5816	MWrite(1, ea);
5817 END_BP_OP
5818
5819
5820 //
5821 // LDC.L
5822 //
5823 BEGIN_BP_OP(LDC_L)
5824	const unsigned m = instr_nyb2;
5825	const uint32 ea = R[m];
5826
5827	MRead(4, ea);
5828 END_BP_OP
5829
5830
5831 //
5832 // LDS.L
5833 //
5834 BEGIN_BP_OP(LDS_L)
5835	const unsigned m = instr_nyb2;
5836	const uint32 ea = R[m];
5837
5838	MRead(4, ea);
5839 END_BP_OP
5840
5841
5842 //
5843 // RTE
5844 //
5845 BEGIN_BP_OP(RTE)
5846	MRead(4, R[15]);
5847	MRead(4, 4 + R[15]);
5848 END_BP_OP
5849
5850 //
5851 // STC.L
5852 //
5853 BEGIN_BP_OP(STC_L)
5854	const unsigned n = instr_nyb2;
5855	const uint32 ea = R[n] - 4;
5856
5857	MWrite(4, ea);
5858 END_BP_OP
5859
5860 //
5861 // STS.L
5862 //
5863 BEGIN_BP_OP(STS_L)	// Pipeline same as ordinary store instruction
5864	const unsigned n = instr_nyb2;
5865	const uint32 ea = R[n] - 4;
5866
5867	MWrite(4, ea);
5868 END_BP_OP
5869
5870
5871#if 0
5872 //
5873 // TRAPA #imm
5874 //
5875 // Saved PC is the address of the instruction after the TRAPA instruction
5876 //
5877 BEGIN_BP_OP_DLYIDIF(TRAPA)
5878	const unsigned imm = (uint8)instr;
5879
5880	BP_EXCEPT(EXCEPTION_TRAP, imm);
5881 END_BP_OP
5882
5883
5884 //
5885 // Illegal Instruction
5886 //
5887 BEGIN_BP_OP_DLYIDIF(ILLEGAL)
5888	BP_EXCEPT(EXCEPTION_ILLINSTR, VECNUM_ILLINSTR);
5889 END_BP_OP
5890
5891 //
5892 // Illegal Slot Instruction
5893 //
5894 BEGIN_BP_OP_DLYIDIF(SLOT_ILLEGAL)
5895	BP_EXCEPT(EXCEPTION_ILLSLOT, VECNUM_ILLSLOT);
5896 END_BP_OP
5897
5898 //
5899 // Pending exception(address error/interrupt)
5900 //
5901 BEGIN_BP_OP_DLYIDIF(PSEUDO_EPENDING)
5902	#define TPP(x) (Pipe_ID & (1U << ((x) + EPENDING_PEXBITS_SHIFT)))
5903
5904	if(MDFN_UNLIKELY(TPP(PEX_PSEUDO_EXTHALT)))
5905	 return;
5906	else if(MDFN_UNLIKELY(TPP(PEX_POWERON) || TPP(PEX_RESET)))
5907	{
5908         if(TPP(PEX_POWERON))
5909	  BP_EXCEPT(EXCEPTION_POWERON, VECNUM_POWERON);
5910	 else
5911	  BP_EXCEPT(EXCEPTION_RESET, VECNUM_RESET);
5912	}
5913	else if(MDFN_UNLIKELY(TPP(PEX_PSEUDO_DMABURST)))
5914	 return;
5915	else if(MDFN_UNLIKELY(TPP(PEX_CPUADDR)))
5916	 BP_EXCEPT(EXCEPTION_CPUADDR, VECNUM_CPUADDR);
5917	else if(MDFN_UNLIKELY(TPP(PEX_DMAADDR)))
5918	 BP_EXCEPT(EXCEPTION_DMAADDR, VECNUM_DMAADDR);
5919	else if(TPP(PEX_NMI))
5920	 BP_EXCEPT(EXCEPTION_NMI, VECNUM_NMI);
5921	else	// Int
5922	{
5923	 uint8 ipr = GetPendingInt(NULL);
5924
5925	 if(MDFN_LIKELY(ipr > ((SR >> 4) & 0xF)))
5926	 {
5927	  uint8 vecnum;
5928
5929	  // Note: GetPendingInt() may call ExIVecFetch(), which may call SetIRL with a new value, so be
5930	  // careful to use the "old" value here.
5931	  GetPendingInt(&vecnum);
5932	  BP_EXCEPT(EXCEPTION_INT, vecnum);
5933	 }
5934	 else
5935	 {
5936	  lpid = (uint16)lpid;
5937	  lpid |= InstrDecodeTab[lpid] << 24;
5938	  goto SPEPRecover;
5939	 }
5940	}
5941END_BP_OP
5942#endif
5943
5944 #undef BEGIN_BP_OP
5945 #undef END_BP_OP
5946 }
5947}
5948