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>(¢->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>(¢->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>(¢->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>(¢->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>(¢->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