Processor_inline.h (15045B)
1#ifndef PROCESSOR_INLINE_H 2#define PROCESSOR_INLINE_H 3 4#include "definitions.h" 5#include "Memory.h" 6 7inline bool Processor::InterruptIsAboutToRaise() 8{ 9 u8 ie_reg = m_pMemory->Retrieve(0xFFFF); 10 u8 if_reg = m_pMemory->Retrieve(0xFF0F); 11 12 return (if_reg & ie_reg & 0x1F) != 0; 13} 14 15inline Processor::Interrupts Processor::InterruptPending() 16{ 17 u8 ie_reg = m_pMemory->Retrieve(0xFFFF); 18 u8 if_reg = m_pMemory->Retrieve(0xFF0F); 19 u8 ie_if = if_reg & ie_reg; 20 21 if ((ie_if & 0x1F) == 0) 22 { 23 return None_Interrupt; 24 } 25 else if ((ie_if & 0x01) && (m_iInterruptDelayCycles <= 0)) 26 { 27 return VBlank_Interrupt; 28 } 29 else if (ie_if & 0x02) 30 { 31 return LCDSTAT_Interrupt; 32 } 33 else if (ie_if & 0x04) 34 { 35 return Timer_Interrupt; 36 } 37 else if (ie_if & 0x08) 38 { 39 return Serial_Interrupt; 40 } 41 else if (ie_if & 0x10) 42 { 43 return Joypad_Interrupt; 44 } 45 46 return None_Interrupt; 47} 48 49inline void Processor::RequestInterrupt(Interrupts interrupt) 50{ 51 m_pMemory->Load(0xFF0F, m_pMemory->Retrieve(0xFF0F) | interrupt); 52 53 if ((interrupt == VBlank_Interrupt) && !m_bCGBSpeed) 54 { 55 m_iInterruptDelayCycles = 4; 56 } 57} 58 59inline void Processor::ResetTIMACycles() 60{ 61 m_iTIMACycles = 0; 62 m_pMemory->Load(0xFF05, m_pMemory->Retrieve(0xFF06)); 63} 64 65inline void Processor::ResetDIVCycles() 66{ 67 m_iDIVCycles = 0; 68 m_pMemory->Load(0xFF04, 0x00); 69} 70 71inline bool Processor::Halted() const 72{ 73 return m_bHalt; 74} 75 76inline bool Processor::DuringOpCode() const 77{ 78 return m_iAccurateOPCodeState != 0; 79} 80 81inline bool Processor::CGBSpeed() const 82{ 83 return m_bCGBSpeed; 84} 85 86inline void Processor::AddCycles(unsigned int cycles) 87{ 88 m_iCurrentClockCycles += cycles; 89} 90 91inline void Processor::ClearAllFlags() 92{ 93 SetFlag(FLAG_NONE); 94} 95 96inline void Processor::ToggleZeroFlagFromResult(u8 result) 97{ 98 if (result == 0) 99 ToggleFlag(FLAG_ZERO); 100} 101 102inline void Processor::SetFlag(u8 flag) 103{ 104 AF.SetLow(flag); 105} 106 107inline void Processor::FlipFlag(u8 flag) 108{ 109 AF.SetLow(AF.GetLow() ^ flag); 110} 111 112inline void Processor::ToggleFlag(u8 flag) 113{ 114 AF.SetLow(AF.GetLow() | flag); 115} 116 117inline void Processor::UntoggleFlag(u8 flag) 118{ 119 AF.SetLow(AF.GetLow() & (~flag)); 120} 121 122inline bool Processor::IsSetFlag(u8 flag) 123{ 124 return (AF.GetLow() & flag) != 0; 125} 126 127inline void Processor::StackPush(SixteenBitRegister* reg) 128{ 129 SP.Decrement(); 130 m_pMemory->Write(SP.GetValue(), reg->GetHigh()); 131 SP.Decrement(); 132 m_pMemory->Write(SP.GetValue(), reg->GetLow()); 133} 134 135inline void Processor::StackPop(SixteenBitRegister* reg) 136{ 137 reg->SetLow(m_pMemory->Read(SP.GetValue())); 138 SP.Increment(); 139 reg->SetHigh(m_pMemory->Read(SP.GetValue())); 140 SP.Increment(); 141} 142 143inline int Processor::AdjustedCycles(int cycles) 144{ 145 if (!cycles) return cycles; 146 return cycles >> m_iSpeedMultiplier; 147} 148 149inline void Processor::InvalidOPCode() 150{ 151 Log("--> ** INVALID OP Code"); 152} 153 154inline void Processor::OPCodes_LD(u8* reg1, u8 reg2) 155{ 156 *reg1 = reg2; 157} 158 159inline void Processor::OPCodes_LD(u8* reg, u16 address) 160{ 161 *reg = m_pMemory->Read(address); 162} 163 164inline void Processor::OPCodes_LD(u16 address, u8 reg) 165{ 166 m_pMemory->Write(address, reg); 167} 168 169inline void Processor::OPCodes_OR(u8 number) 170{ 171 u8 result = AF.GetHigh() | number; 172 AF.SetHigh(result); 173 ClearAllFlags(); 174 ToggleZeroFlagFromResult(result); 175} 176 177inline void Processor::OPCodes_XOR(u8 number) 178{ 179 u8 result = AF.GetHigh() ^ number; 180 AF.SetHigh(result); 181 ClearAllFlags(); 182 ToggleZeroFlagFromResult(result); 183} 184 185inline void Processor::OPCodes_AND(u8 number) 186{ 187 u8 result = AF.GetHigh() & number; 188 AF.SetHigh(result); 189 SetFlag(FLAG_HALF); 190 ToggleZeroFlagFromResult(result); 191} 192 193inline void Processor::OPCodes_CP(u8 number) 194{ 195 SetFlag(FLAG_SUB); 196 if (AF.GetHigh() < number) 197 { 198 ToggleFlag(FLAG_CARRY); 199 } 200 if (AF.GetHigh() == number) 201 { 202 ToggleFlag(FLAG_ZERO); 203 } 204 if (((AF.GetHigh() - number) & 0xF) > (AF.GetHigh() & 0xF)) 205 { 206 ToggleFlag(FLAG_HALF); 207 } 208} 209 210inline void Processor::OPCodes_INC(u8* reg) 211{ 212 u8 result = *reg + 1; 213 *reg = result; 214 IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags(); 215 ToggleZeroFlagFromResult(result); 216 if ((result & 0x0F) == 0x00) 217 { 218 ToggleFlag(FLAG_HALF); 219 } 220} 221 222inline void Processor::OPCodes_INC_HL() 223{ 224 if (m_iAccurateOPCodeState == 1) 225 { 226 m_iReadCache = m_pMemory->Read(HL.GetValue()) + 1; 227 return; 228 } 229 m_pMemory->Write(HL.GetValue(), m_iReadCache); 230 IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags(); 231 ToggleZeroFlagFromResult(m_iReadCache); 232 if ((m_iReadCache & 0x0F) == 0x00) 233 { 234 ToggleFlag(FLAG_HALF); 235 } 236} 237 238inline void Processor::OPCodes_DEC(u8* reg) 239{ 240 u8 result = *reg - 1; 241 *reg = result; 242 IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags(); 243 ToggleFlag(FLAG_SUB); 244 ToggleZeroFlagFromResult(result); 245 if ((result & 0x0F) == 0x0F) 246 { 247 ToggleFlag(FLAG_HALF); 248 } 249} 250 251inline void Processor::OPCodes_DEC_HL() 252{ 253 if (m_iAccurateOPCodeState == 1) 254 { 255 m_iReadCache = m_pMemory->Read(HL.GetValue()) - 1; 256 return; 257 } 258 m_pMemory->Write(HL.GetValue(), m_iReadCache); 259 IsSetFlag(FLAG_CARRY) ? SetFlag(FLAG_CARRY) : ClearAllFlags(); 260 ToggleFlag(FLAG_SUB); 261 ToggleZeroFlagFromResult(m_iReadCache); 262 if ((m_iReadCache & 0x0F) == 0x0F) 263 { 264 ToggleFlag(FLAG_HALF); 265 } 266} 267 268inline void Processor::OPCodes_ADD(u8 number) 269{ 270 int result = AF.GetHigh() + number; 271 int carrybits = AF.GetHigh() ^ number ^ result; 272 AF.SetHigh(static_cast<u8> (result)); 273 ClearAllFlags(); 274 ToggleZeroFlagFromResult(static_cast<u8> (result)); 275 if ((carrybits & 0x100) != 0) 276 { 277 ToggleFlag(FLAG_CARRY); 278 } 279 if ((carrybits & 0x10) != 0) 280 { 281 ToggleFlag(FLAG_HALF); 282 } 283} 284 285inline void Processor::OPCodes_ADC(u8 number) 286{ 287 int carry = IsSetFlag(FLAG_CARRY) ? 1 : 0; 288 int result = AF.GetHigh() + number + carry; 289 ClearAllFlags(); 290 ToggleZeroFlagFromResult(static_cast<u8> (result)); 291 if (result > 0xFF) 292 { 293 ToggleFlag(FLAG_CARRY); 294 } 295 if (((AF.GetHigh()& 0x0F) + (number & 0x0F) + carry) > 0x0F) 296 { 297 ToggleFlag(FLAG_HALF); 298 } 299 AF.SetHigh(static_cast<u8> (result)); 300} 301 302inline void Processor::OPCodes_SUB(u8 number) 303{ 304 int result = AF.GetHigh() - number; 305 int carrybits = AF.GetHigh() ^ number ^ result; 306 AF.SetHigh(static_cast<u8> (result)); 307 SetFlag(FLAG_SUB); 308 ToggleZeroFlagFromResult(static_cast<u8> (result)); 309 if ((carrybits & 0x100) != 0) 310 { 311 ToggleFlag(FLAG_CARRY); 312 } 313 if ((carrybits & 0x10) != 0) 314 { 315 ToggleFlag(FLAG_HALF); 316 } 317} 318 319inline void Processor::OPCodes_SBC(u8 number) 320{ 321 int carry = IsSetFlag(FLAG_CARRY) ? 1 : 0; 322 int result = AF.GetHigh() - number - carry; 323 SetFlag(FLAG_SUB); 324 ToggleZeroFlagFromResult(static_cast<u8> (result)); 325 if (result < 0) 326 { 327 ToggleFlag(FLAG_CARRY); 328 } 329 if (((AF.GetHigh() & 0x0F) - (number & 0x0F) - carry) < 0) 330 { 331 ToggleFlag(FLAG_HALF); 332 } 333 AF.SetHigh(static_cast<u8> (result)); 334} 335 336inline void Processor::OPCodes_ADD_HL(u16 number) 337{ 338 int result = HL.GetValue() + number; 339 IsSetFlag(FLAG_ZERO) ? SetFlag(FLAG_ZERO) : ClearAllFlags(); 340 if (result & 0x10000) 341 { 342 ToggleFlag(FLAG_CARRY); 343 } 344 if ((HL.GetValue() ^ number ^ (result & 0xFFFF)) & 0x1000) 345 { 346 ToggleFlag(FLAG_HALF); 347 } 348 HL.SetValue(static_cast<u16> (result)); 349} 350 351inline void Processor::OPCodes_ADD_SP(s8 number) 352{ 353 int result = SP.GetValue() + number; 354 ClearAllFlags(); 355 if (((SP.GetValue() ^ number ^ (result & 0xFFFF)) & 0x100) == 0x100) 356 { 357 ToggleFlag(FLAG_CARRY); 358 } 359 if (((SP.GetValue() ^ number ^ (result & 0xFFFF)) & 0x10) == 0x10) 360 { 361 ToggleFlag(FLAG_HALF); 362 } 363 SP.SetValue(static_cast<u16> (result)); 364} 365 366inline void Processor::OPCodes_SWAP_Register(u8* reg) 367{ 368 u8 low_half = *reg & 0x0F; 369 u8 high_half = (*reg >> 4) & 0x0F; 370 *reg = (low_half << 4) + high_half; 371 ClearAllFlags(); 372 ToggleZeroFlagFromResult(*reg); 373} 374 375inline void Processor::OPCodes_SWAP_HL() 376{ 377 if (m_iAccurateOPCodeState == 1) 378 { 379 m_iReadCache = m_pMemory->Read(HL.GetValue()); 380 return; 381 } 382 u8 low_half = m_iReadCache & 0x0F; 383 u8 high_half = (m_iReadCache >> 4) & 0x0F; 384 m_iReadCache = (low_half << 4) + high_half; 385 m_pMemory->Write(HL.GetValue(), m_iReadCache); 386 ClearAllFlags(); 387 ToggleZeroFlagFromResult(m_iReadCache); 388} 389 390inline void Processor::OPCodes_SLA(u8* reg) 391{ 392 (*reg & 0x80) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags(); 393 u8 result = *reg << 1; 394 *reg = result; 395 ToggleZeroFlagFromResult(result); 396} 397 398inline void Processor::OPCodes_SLA_HL() 399{ 400 if (m_iAccurateOPCodeState == 1) 401 { 402 m_iReadCache = m_pMemory->Read(HL.GetValue()); 403 return; 404 } 405 (m_iReadCache & 0x80) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags(); 406 m_iReadCache <<= 1; 407 m_pMemory->Write(HL.GetValue(), m_iReadCache); 408 ToggleZeroFlagFromResult(m_iReadCache); 409} 410 411inline void Processor::OPCodes_SRA(u8* reg) 412{ 413 u8 result = *reg; 414 (result & 0x01) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags(); 415 if ((result & 0x80) != 0) 416 { 417 result >>= 1; 418 result |= 0x80; 419 } 420 else 421 { 422 result >>= 1; 423 } 424 *reg = result; 425 ToggleZeroFlagFromResult(result); 426} 427 428inline void Processor::OPCodes_SRA_HL() 429{ 430 if (m_iAccurateOPCodeState == 1) 431 { 432 m_iReadCache = m_pMemory->Read(HL.GetValue()); 433 return; 434 } 435 (m_iReadCache & 0x01) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags(); 436 if ((m_iReadCache & 0x80) != 0) 437 { 438 m_iReadCache >>= 1; 439 m_iReadCache |= 0x80; 440 } 441 else 442 { 443 m_iReadCache >>= 1; 444 } 445 m_pMemory->Write(HL.GetValue(), m_iReadCache); 446 ToggleZeroFlagFromResult(m_iReadCache); 447} 448 449inline void Processor::OPCodes_SRL(u8* reg) 450{ 451 u8 result = *reg; 452 (result & 0x01) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags(); 453 result >>= 1; 454 *reg = result; 455 ToggleZeroFlagFromResult(result); 456} 457 458inline void Processor::OPCodes_SRL_HL() 459{ 460 if (m_iAccurateOPCodeState == 1) 461 { 462 m_iReadCache = m_pMemory->Read(HL.GetValue()); 463 return; 464 } 465 (m_iReadCache & 0x01) != 0 ? SetFlag(FLAG_CARRY) : ClearAllFlags(); 466 m_iReadCache >>= 1; 467 m_pMemory->Write(HL.GetValue(), m_iReadCache); 468 ToggleZeroFlagFromResult(m_iReadCache); 469} 470 471inline void Processor::OPCodes_RLC(u8* reg, bool isRegisterA) 472{ 473 u8 result = *reg; 474 if ((result & 0x80) != 0) 475 { 476 SetFlag(FLAG_CARRY); 477 result <<= 1; 478 result |= 0x1; 479 } 480 else 481 { 482 ClearAllFlags(); 483 result <<= 1; 484 } 485 *reg = result; 486 if (!isRegisterA) 487 { 488 ToggleZeroFlagFromResult(result); 489 } 490} 491 492inline void Processor::OPCodes_RLC_HL() 493{ 494 if (m_iAccurateOPCodeState == 1) 495 { 496 m_iReadCache = m_pMemory->Read(HL.GetValue()); 497 return; 498 } 499 if ((m_iReadCache & 0x80) != 0) 500 { 501 SetFlag(FLAG_CARRY); 502 m_iReadCache <<= 1; 503 m_iReadCache |= 0x1; 504 } 505 else 506 { 507 ClearAllFlags(); 508 m_iReadCache <<= 1; 509 } 510 m_pMemory->Write(HL.GetValue(), m_iReadCache); 511 ToggleZeroFlagFromResult(m_iReadCache); 512} 513 514inline void Processor::OPCodes_RL(u8* reg, bool isRegisterA) 515{ 516 u8 carry = IsSetFlag(FLAG_CARRY) ? 1 : 0; 517 u8 result = *reg; 518 ((result & 0x80) != 0) ? SetFlag(FLAG_CARRY) : ClearAllFlags(); 519 result <<= 1; 520 result |= carry; 521 *reg = result; 522 if (!isRegisterA) 523 { 524 ToggleZeroFlagFromResult(result); 525 } 526} 527 528inline void Processor::OPCodes_RL_HL() 529{ 530 if (m_iAccurateOPCodeState == 1) 531 { 532 m_iReadCache = m_pMemory->Read(HL.GetValue()); 533 return; 534 } 535 u8 carry = IsSetFlag(FLAG_CARRY) ? 1 : 0; 536 ((m_iReadCache & 0x80) != 0) ? SetFlag(FLAG_CARRY) : ClearAllFlags(); 537 m_iReadCache <<= 1; 538 m_iReadCache |= carry; 539 m_pMemory->Write(HL.GetValue(), m_iReadCache); 540 ToggleZeroFlagFromResult(m_iReadCache); 541} 542 543inline void Processor::OPCodes_RRC(u8* reg, bool isRegisterA) 544{ 545 u8 result = *reg; 546 if ((result & 0x01) != 0) 547 { 548 SetFlag(FLAG_CARRY); 549 result >>= 1; 550 result |= 0x80; 551 } 552 else 553 { 554 ClearAllFlags(); 555 result >>= 1; 556 } 557 *reg = result; 558 if (!isRegisterA) 559 { 560 ToggleZeroFlagFromResult(result); 561 } 562} 563 564inline void Processor::OPCodes_RRC_HL() 565{ 566 if (m_iAccurateOPCodeState == 1) 567 { 568 m_iReadCache = m_pMemory->Read(HL.GetValue()); 569 return; 570 } 571 if ((m_iReadCache & 0x01) != 0) 572 { 573 SetFlag(FLAG_CARRY); 574 m_iReadCache >>= 1; 575 m_iReadCache |= 0x80; 576 } 577 else 578 { 579 ClearAllFlags(); 580 m_iReadCache >>= 1; 581 } 582 m_pMemory->Write(HL.GetValue(), m_iReadCache); 583 ToggleZeroFlagFromResult(m_iReadCache); 584} 585 586inline void Processor::OPCodes_RR(u8* reg, bool isRegisterA) 587{ 588 u8 carry = IsSetFlag(FLAG_CARRY) ? 0x80 : 0x00; 589 u8 result = *reg; 590 ((result & 0x01) != 0) ? SetFlag(FLAG_CARRY) : ClearAllFlags(); 591 result >>= 1; 592 result |= carry; 593 *reg = result; 594 if (!isRegisterA) 595 { 596 ToggleZeroFlagFromResult(result); 597 } 598} 599 600inline void Processor::OPCodes_RR_HL() 601{ 602 if (m_iAccurateOPCodeState == 1) 603 { 604 m_iReadCache = m_pMemory->Read(HL.GetValue()); 605 return; 606 } 607 u8 carry = IsSetFlag(FLAG_CARRY) ? 0x80 : 0x00; 608 ((m_iReadCache & 0x01) != 0) ? SetFlag(FLAG_CARRY) : ClearAllFlags(); 609 m_iReadCache >>= 1; 610 m_iReadCache |= carry; 611 m_pMemory->Write(HL.GetValue(), m_iReadCache); 612 ToggleZeroFlagFromResult(m_iReadCache); 613} 614 615inline void Processor::OPCodes_BIT(u8* reg, int bit) 616{ 617 if (((*reg >> bit) & 0x01) == 0) 618 { 619 ToggleFlag(FLAG_ZERO); 620 } 621 else 622 { 623 UntoggleFlag(FLAG_ZERO); 624 } 625 ToggleFlag(FLAG_HALF); 626 UntoggleFlag(FLAG_SUB); 627} 628 629inline void Processor::OPCodes_BIT_HL(int bit) 630{ 631 if (((m_pMemory->Read(HL.GetValue()) >> bit) & 0x01) == 0) 632 { 633 ToggleFlag(FLAG_ZERO); 634 } 635 else 636 { 637 UntoggleFlag(FLAG_ZERO); 638 } 639 ToggleFlag(FLAG_HALF); 640 UntoggleFlag(FLAG_SUB); 641} 642 643inline void Processor::OPCodes_SET(u8* reg, int bit) 644{ 645 *reg = (*reg | (0x1 << bit)); 646} 647 648inline void Processor::OPCodes_SET_HL(int bit) 649{ 650 if (m_iAccurateOPCodeState == 1) 651 { 652 m_iReadCache = m_pMemory->Read(HL.GetValue()); 653 return; 654 } 655 m_iReadCache |= (0x1 << bit); 656 m_pMemory->Write(HL.GetValue(), m_iReadCache); 657} 658 659inline void Processor::OPCodes_RES(u8* reg, int bit) 660{ 661 *reg = (*reg & (~(0x1 << bit))); 662} 663 664inline void Processor::OPCodes_RES_HL(int bit) 665{ 666 if (m_iAccurateOPCodeState == 1) 667 { 668 m_iReadCache = m_pMemory->Read(HL.GetValue()); 669 return; 670 } 671 m_iReadCache &= ~(0x1 << bit); 672 m_pMemory->Write(HL.GetValue(), m_iReadCache); 673} 674 675#endif /* PROCESSOR_INLINE_H */ 676