opcodes.cpp (30105B)
1/* 2 * Gearboy - Nintendo Game Boy Emulator 3 * Copyright (C) 2012 Ignacio Sanchez 4 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * any later version. 9 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see http://www.gnu.org/licenses/ 17 * 18 */ 19 20#include "Processor.h" 21#include "Memory.h" 22#include "opcode_timing.h" 23 24void Processor::OPCode0x00() 25{ 26 // NOP 27} 28 29void Processor::OPCode0x01() 30{ 31 // LD BC,nn 32 OPCodes_LD(BC.GetLowRegister(), PC.GetValue()); 33 PC.Increment(); 34 OPCodes_LD(BC.GetHighRegister(), PC.GetValue()); 35 PC.Increment(); 36} 37 38void Processor::OPCode0x02() 39{ 40 // LD (BC),A 41 OPCodes_LD(BC.GetValue(), AF.GetHigh()); 42} 43 44void Processor::OPCode0x03() 45{ 46 // INC BC 47 BC.Increment(); 48} 49 50void Processor::OPCode0x04() 51{ 52 // INC B 53 OPCodes_INC(BC.GetHighRegister()); 54} 55 56void Processor::OPCode0x05() 57{ 58 // DEC B 59 OPCodes_DEC(BC.GetHighRegister()); 60} 61 62void Processor::OPCode0x06() 63{ 64 // LD B,n 65 OPCodes_LD(BC.GetHighRegister(), PC.GetValue()); 66 PC.Increment(); 67} 68 69void Processor::OPCode0x07() 70{ 71 // RLCA 72 OPCodes_RLC(AF.GetHighRegister(), true); 73} 74 75void Processor::OPCode0x08() 76{ 77 // LD (nn),SP 78 u8 l = m_pMemory->Read(PC.GetValue()); 79 PC.Increment(); 80 u8 h = m_pMemory->Read(PC.GetValue()); 81 PC.Increment(); 82 u16 address = ((h << 8) + l); 83 m_pMemory->Write(address, SP.GetLow()); 84 m_pMemory->Write(address + 1, SP.GetHigh()); 85} 86 87void Processor::OPCode0x09() 88{ 89 // ADD HL,BC 90 OPCodes_ADD_HL(BC.GetValue()); 91} 92 93void Processor::OPCode0x0A() 94{ 95 // LD A,(BC) 96 OPCodes_LD(AF.GetHighRegister(), BC.GetValue()); 97} 98 99void Processor::OPCode0x0B() 100{ 101 // DEC BC 102 BC.Decrement(); 103} 104 105void Processor::OPCode0x0C() 106{ 107 // INC C 108 OPCodes_INC(BC.GetLowRegister()); 109} 110 111void Processor::OPCode0x0D() 112{ 113 // DEC C 114 OPCodes_DEC(BC.GetLowRegister()); 115} 116 117void Processor::OPCode0x0E() 118{ 119 // LD C,n 120 OPCodes_LD(BC.GetLowRegister(), PC.GetValue()); 121 PC.Increment(); 122} 123 124void Processor::OPCode0x0F() 125{ 126 // RRCA 127 OPCodes_RRC(AF.GetHighRegister(), true); 128} 129 130void Processor::OPCode0x10() 131{ 132 // STOP 133 PC.Increment(); 134 135 if (m_bCGB) 136 { 137 u8 current_key1 = m_pMemory->Retrieve(0xFF4D); 138 139 if (IsSetBit(current_key1, 0)) 140 { 141 m_bCGBSpeed = !m_bCGBSpeed; 142 143 if (m_bCGBSpeed) 144 { 145 m_iSpeedMultiplier = 1; 146 m_pMemory->Load(0xFF4D, 0x80); 147 } 148 else 149 { 150 m_iSpeedMultiplier = 0; 151 m_pMemory->Load(0xFF4D, 0x00); 152 } 153 } 154 } 155} 156 157void Processor::OPCode0x11() 158{ 159 // LD DE,nn 160 OPCodes_LD(DE.GetLowRegister(), PC.GetValue()); 161 PC.Increment(); 162 OPCodes_LD(DE.GetHighRegister(), PC.GetValue()); 163 PC.Increment(); 164} 165 166void Processor::OPCode0x12() 167{ 168 // LD (DE),A 169 OPCodes_LD(DE.GetValue(), AF.GetHigh()); 170} 171 172void Processor::OPCode0x13() 173{ 174 // INC DE 175 DE.Increment(); 176} 177 178void Processor::OPCode0x14() 179{ 180 // INC D 181 OPCodes_INC(DE.GetHighRegister()); 182} 183 184void Processor::OPCode0x15() 185{ 186 // DEC D 187 OPCodes_DEC(DE.GetHighRegister()); 188} 189 190void Processor::OPCode0x16() 191{ 192 // LD D,n 193 OPCodes_LD(DE.GetHighRegister(), PC.GetValue()); 194 PC.Increment(); 195} 196 197void Processor::OPCode0x17() 198{ 199 // RLA 200 OPCodes_RL(AF.GetHighRegister(), true); 201} 202 203void Processor::OPCode0x18() 204{ 205 // JR n 206 PC.SetValue(PC.GetValue() + 1 + (static_cast<s8> (m_pMemory->Read(PC.GetValue())))); 207} 208 209void Processor::OPCode0x19() 210{ 211 // ADD HL,DE 212 OPCodes_ADD_HL(DE.GetValue()); 213} 214 215void Processor::OPCode0x1A() 216{ 217 // LD A,(DE) 218 OPCodes_LD(AF.GetHighRegister(), DE.GetValue()); 219} 220 221void Processor::OPCode0x1B() 222{ 223 // DEC DE 224 DE.Decrement(); 225} 226 227void Processor::OPCode0x1C() 228{ 229 // INC E 230 OPCodes_INC(DE.GetLowRegister()); 231} 232 233void Processor::OPCode0x1D() 234{ 235 // DEC E 236 OPCodes_DEC(DE.GetLowRegister()); 237} 238 239void Processor::OPCode0x1E() 240{ 241 // LD E,n 242 OPCodes_LD(DE.GetLowRegister(), PC.GetValue()); 243 PC.Increment(); 244} 245 246void Processor::OPCode0x1F() 247{ 248 // RRA 249 OPCodes_RR(AF.GetHighRegister(), true); 250} 251 252void Processor::OPCode0x20() 253{ 254 // JR NZ,n 255 if (!IsSetFlag(FLAG_ZERO)) 256 { 257 PC.SetValue(PC.GetValue() + 1 + (static_cast<s8> (m_pMemory->Read(PC.GetValue())))); 258 m_bBranchTaken = true; 259 } 260 else 261 { 262 PC.Increment(); 263 } 264} 265 266void Processor::OPCode0x21() 267{ 268 // LD HL,nn 269 OPCodes_LD(HL.GetLowRegister(), PC.GetValue()); 270 PC.Increment(); 271 OPCodes_LD(HL.GetHighRegister(), PC.GetValue()); 272 PC.Increment(); 273} 274 275void Processor::OPCode0x22() 276{ 277 // LD (HLI),A 278 OPCodes_LD(HL.GetValue(), AF.GetHigh()); 279 HL.Increment(); 280} 281 282void Processor::OPCode0x23() 283{ 284 // INC HL 285 HL.Increment(); 286} 287 288void Processor::OPCode0x24() 289{ 290 // INC H 291 OPCodes_INC(HL.GetHighRegister()); 292} 293 294void Processor::OPCode0x25() 295{ 296 // DEC H 297 OPCodes_DEC(HL.GetHighRegister()); 298} 299 300void Processor::OPCode0x26() 301{ 302 // LD H,n 303 OPCodes_LD(HL.GetHighRegister(), PC.GetValue()); 304 PC.Increment(); 305} 306 307void Processor::OPCode0x27() 308{ 309 // DAA 310 int a = AF.GetHigh(); 311 312 if (!IsSetFlag(FLAG_SUB)) 313 { 314 if (IsSetFlag(FLAG_HALF) || ((a & 0xF) > 9)) 315 a += 0x06; 316 317 if (IsSetFlag(FLAG_CARRY) || (a > 0x9F)) 318 a += 0x60; 319 } 320 else 321 { 322 if (IsSetFlag(FLAG_HALF)) 323 a = (a - 6) & 0xFF; 324 325 if (IsSetFlag(FLAG_CARRY)) 326 a -= 0x60; 327 } 328 329 UntoggleFlag(FLAG_HALF); 330 UntoggleFlag(FLAG_ZERO); 331 332 if ((a & 0x100) == 0x100) 333 ToggleFlag(FLAG_CARRY); 334 335 a &= 0xFF; 336 337 ToggleZeroFlagFromResult(a); 338 339 AF.SetHigh(a); 340} 341 342void Processor::OPCode0x28() 343{ 344 // JR Z,n 345 if (IsSetFlag(FLAG_ZERO)) 346 { 347 PC.SetValue(PC.GetValue() + 1 + (static_cast<s8> (m_pMemory->Read(PC.GetValue())))); 348 m_bBranchTaken = true; 349 } 350 else 351 { 352 PC.Increment(); 353 } 354} 355 356void Processor::OPCode0x29() 357{ 358 // ADD HL,HL 359 OPCodes_ADD_HL(HL.GetValue()); 360} 361 362void Processor::OPCode0x2A() 363{ 364 // LD A,(HLI) 365 OPCodes_LD(AF.GetHighRegister(), HL.GetValue()); 366 HL.Increment(); 367} 368 369void Processor::OPCode0x2B() 370{ 371 // DEC HL 372 HL.Decrement(); 373} 374 375void Processor::OPCode0x2C() 376{ 377 // INC L 378 OPCodes_INC(HL.GetLowRegister()); 379} 380 381void Processor::OPCode0x2D() 382{ 383 // DEC L 384 OPCodes_DEC(HL.GetLowRegister()); 385} 386 387void Processor::OPCode0x2E() 388{ 389 // LD L,n 390 OPCodes_LD(HL.GetLowRegister(), PC.GetValue()); 391 PC.Increment(); 392 393} 394 395void Processor::OPCode0x2F() 396{ 397 // CPL 398 AF.SetHigh(~AF.GetHigh()); 399 ToggleFlag(FLAG_HALF); 400 ToggleFlag(FLAG_SUB); 401} 402 403void Processor::OPCode0x30() 404{ 405 // JR NC,n 406 if (!IsSetFlag(FLAG_CARRY)) 407 { 408 PC.SetValue(PC.GetValue() + 1 + (static_cast<s8> (m_pMemory->Read(PC.GetValue())))); 409 m_bBranchTaken = true; 410 } 411 else 412 { 413 PC.Increment(); 414 } 415} 416 417void Processor::OPCode0x31() 418{ 419 // LD SP,nn 420 SP.SetLow(m_pMemory->Read(PC.GetValue())); 421 PC.Increment(); 422 SP.SetHigh(m_pMemory->Read(PC.GetValue())); 423 PC.Increment(); 424} 425 426void Processor::OPCode0x32() 427{ 428 // LD (HLD), A 429 OPCodes_LD(HL.GetValue(), AF.GetHigh()); 430 HL.Decrement(); 431} 432 433void Processor::OPCode0x33() 434{ 435 // INC SP 436 SP.Increment(); 437} 438 439void Processor::OPCode0x34() 440{ 441 // INC (HL) 442 OPCodes_INC_HL(); 443} 444 445void Processor::OPCode0x35() 446{ 447 // DEC (HL) 448 OPCodes_DEC_HL(); 449} 450 451void Processor::OPCode0x36() 452{ 453 // LD (HL),n 454 m_pMemory->Write(HL.GetValue(), m_pMemory->Read(PC.GetValue())); 455 PC.Increment(); 456} 457 458void Processor::OPCode0x37() 459{ 460 // SCF 461 ToggleFlag(FLAG_CARRY); 462 UntoggleFlag(FLAG_HALF); 463 UntoggleFlag(FLAG_SUB); 464} 465 466void Processor::OPCode0x38() 467{ 468 // JR C,n 469 if (IsSetFlag(FLAG_CARRY)) 470 { 471 PC.SetValue(PC.GetValue() + 1 + (static_cast<s8> (m_pMemory->Read(PC.GetValue())))); 472 m_bBranchTaken = true; 473 } 474 else 475 { 476 PC.Increment(); 477 } 478} 479 480void Processor::OPCode0x39() 481{ 482 // ADD HL,SP 483 OPCodes_ADD_HL(SP.GetValue()); 484} 485 486void Processor::OPCode0x3A() 487{ 488 // LD A,(HLD) 489 OPCodes_LD(AF.GetHighRegister(), HL.GetValue()); 490 HL.Decrement(); 491} 492 493void Processor::OPCode0x3B() 494{ 495 // DEC SP 496 SP.Decrement(); 497} 498 499void Processor::OPCode0x3C() 500{ 501 // INC A 502 OPCodes_INC(AF.GetHighRegister()); 503} 504 505void Processor::OPCode0x3D() 506{ 507 // DEC A 508 OPCodes_DEC(AF.GetHighRegister()); 509 510} 511 512void Processor::OPCode0x3E() 513{ 514 // LD A,n 515 OPCodes_LD(AF.GetHighRegister(), PC.GetValue()); 516 PC.Increment(); 517} 518 519void Processor::OPCode0x3F() 520{ 521 // CCF 522 FlipFlag(FLAG_CARRY); 523 UntoggleFlag(FLAG_HALF); 524 UntoggleFlag(FLAG_SUB); 525} 526 527void Processor::OPCode0x40() 528{ 529 // LD B,B 530 OPCodes_LD(BC.GetHighRegister(), BC.GetHigh()); 531} 532 533void Processor::OPCode0x41() 534{ 535 // LD B,C 536 OPCodes_LD(BC.GetHighRegister(), BC.GetLow()); 537} 538 539void Processor::OPCode0x42() 540{ 541 // LD B,D 542 OPCodes_LD(BC.GetHighRegister(), DE.GetHigh()); 543} 544 545void Processor::OPCode0x43() 546{ 547 // LD B,E 548 OPCodes_LD(BC.GetHighRegister(), DE.GetLow()); 549} 550 551void Processor::OPCode0x44() 552{ 553 // LD B,H 554 OPCodes_LD(BC.GetHighRegister(), HL.GetHigh()); 555} 556 557void Processor::OPCode0x45() 558{ 559 // LD B,L 560 OPCodes_LD(BC.GetHighRegister(), HL.GetLow()); 561} 562 563void Processor::OPCode0x46() 564{ 565 // LD B,(HL) 566 OPCodes_LD(BC.GetHighRegister(), HL.GetValue()); 567} 568 569void Processor::OPCode0x47() 570{ 571 // LD B,A 572 OPCodes_LD(BC.GetHighRegister(), AF.GetHigh()); 573} 574 575void Processor::OPCode0x48() 576{ 577 // LD C,B 578 OPCodes_LD(BC.GetLowRegister(), BC.GetHigh()); 579} 580 581void Processor::OPCode0x49() 582{ 583 // LD C,C 584 OPCodes_LD(BC.GetLowRegister(), BC.GetLow()); 585} 586 587void Processor::OPCode0x4A() 588{ 589 // LD C,D 590 OPCodes_LD(BC.GetLowRegister(), DE.GetHigh()); 591} 592 593void Processor::OPCode0x4B() 594{ 595 // LD C,E 596 OPCodes_LD(BC.GetLowRegister(), DE.GetLow()); 597} 598 599void Processor::OPCode0x4C() 600{ 601 // LD C,H 602 OPCodes_LD(BC.GetLowRegister(), HL.GetHigh()); 603} 604 605void Processor::OPCode0x4D() 606{ 607 // LD C,L 608 OPCodes_LD(BC.GetLowRegister(), HL.GetLow()); 609} 610 611void Processor::OPCode0x4E() 612{ 613 // LD C,(HL) 614 OPCodes_LD(BC.GetLowRegister(), HL.GetValue()); 615} 616 617void Processor::OPCode0x4F() 618{ 619 // LD C,A 620 OPCodes_LD(BC.GetLowRegister(), AF.GetHigh()); 621} 622 623void Processor::OPCode0x50() 624{ 625 // LD D,B 626 OPCodes_LD(DE.GetHighRegister(), BC.GetHigh()); 627} 628 629void Processor::OPCode0x51() 630{ 631 // LD D,C 632 OPCodes_LD(DE.GetHighRegister(), BC.GetLow()); 633} 634 635void Processor::OPCode0x52() 636{ 637 // LD D,D 638 OPCodes_LD(DE.GetHighRegister(), DE.GetHigh()); 639} 640 641void Processor::OPCode0x53() 642{ 643 // LD D,E 644 OPCodes_LD(DE.GetHighRegister(), DE.GetLow()); 645} 646 647void Processor::OPCode0x54() 648{ 649 // LD D,H 650 OPCodes_LD(DE.GetHighRegister(), HL.GetHigh()); 651} 652 653void Processor::OPCode0x55() 654{ 655 // LD D,L 656 OPCodes_LD(DE.GetHighRegister(), HL.GetLow()); 657} 658 659void Processor::OPCode0x56() 660{ 661 // LD D,(HL) 662 OPCodes_LD(DE.GetHighRegister(), HL.GetValue()); 663} 664 665void Processor::OPCode0x57() 666{ 667 // LD D,A 668 OPCodes_LD(DE.GetHighRegister(), AF.GetHigh()); 669} 670 671void Processor::OPCode0x58() 672{ 673 // LD E,B 674 OPCodes_LD(DE.GetLowRegister(), BC.GetHigh()); 675} 676 677void Processor::OPCode0x59() 678{ 679 // LD E,C 680 OPCodes_LD(DE.GetLowRegister(), BC.GetLow()); 681} 682 683void Processor::OPCode0x5A() 684{ 685 // LD E,D 686 OPCodes_LD(DE.GetLowRegister(), DE.GetHigh()); 687} 688 689void Processor::OPCode0x5B() 690{ 691 // LD E,E 692 OPCodes_LD(DE.GetLowRegister(), DE.GetLow()); 693} 694 695void Processor::OPCode0x5C() 696{ 697 // LD E,H 698 OPCodes_LD(DE.GetLowRegister(), HL.GetHigh()); 699} 700 701void Processor::OPCode0x5D() 702{ 703 // LD E,L 704 OPCodes_LD(DE.GetLowRegister(), HL.GetLow()); 705} 706 707void Processor::OPCode0x5E() 708{ 709 // LD E,(HL) 710 OPCodes_LD(DE.GetLowRegister(), HL.GetValue()); 711} 712 713void Processor::OPCode0x5F() 714{ 715 // LD E,A 716 OPCodes_LD(DE.GetLowRegister(), AF.GetHigh()); 717} 718 719void Processor::OPCode0x60() 720{ 721 // LD H,B 722 OPCodes_LD(HL.GetHighRegister(), BC.GetHigh()); 723} 724 725void Processor::OPCode0x61() 726{ 727 // LD H,C 728 OPCodes_LD(HL.GetHighRegister(), BC.GetLow()); 729} 730 731void Processor::OPCode0x62() 732{ 733 // LD H,D 734 OPCodes_LD(HL.GetHighRegister(), DE.GetHigh()); 735} 736 737void Processor::OPCode0x63() 738{ 739 // LD H,E 740 OPCodes_LD(HL.GetHighRegister(), DE.GetLow()); 741} 742 743void Processor::OPCode0x64() 744{ 745 // LD H,H 746 OPCodes_LD(HL.GetHighRegister(), HL.GetHigh()); 747} 748 749void Processor::OPCode0x65() 750{ 751 // LD H,L 752 OPCodes_LD(HL.GetHighRegister(), HL.GetLow()); 753} 754 755void Processor::OPCode0x66() 756{ 757 // LD H,(HL) 758 OPCodes_LD(HL.GetHighRegister(), HL.GetValue()); 759} 760 761void Processor::OPCode0x67() 762{ 763 // LD H,A 764 OPCodes_LD(HL.GetHighRegister(), AF.GetHigh()); 765} 766 767void Processor::OPCode0x68() 768{ 769 // LD L,B 770 OPCodes_LD(HL.GetLowRegister(), BC.GetHigh()); 771} 772 773void Processor::OPCode0x69() 774{ 775 // LD L,C 776 OPCodes_LD(HL.GetLowRegister(), BC.GetLow()); 777} 778 779void Processor::OPCode0x6A() 780{ 781 // LD L,D 782 OPCodes_LD(HL.GetLowRegister(), DE.GetHigh()); 783} 784 785void Processor::OPCode0x6B() 786{ 787 // LD L,E 788 OPCodes_LD(HL.GetLowRegister(), DE.GetLow()); 789} 790 791void Processor::OPCode0x6C() 792{ 793 // LD L,H 794 OPCodes_LD(HL.GetLowRegister(), HL.GetHigh()); 795} 796 797void Processor::OPCode0x6D() 798{ 799 // LD L,L 800 OPCodes_LD(HL.GetLowRegister(), HL.GetLow()); 801} 802 803void Processor::OPCode0x6E() 804{ 805 // LD L,(HL) 806 OPCodes_LD(HL.GetLowRegister(), HL.GetValue()); 807} 808 809void Processor::OPCode0x6F() 810{ 811 // LD L,A 812 OPCodes_LD(HL.GetLowRegister(), AF.GetHigh()); 813} 814 815void Processor::OPCode0x70() 816{ 817 // LD (HL),B 818 OPCodes_LD(HL.GetValue(), BC.GetHigh()); 819} 820 821void Processor::OPCode0x71() 822{ 823 // LD (HL),C 824 OPCodes_LD(HL.GetValue(), BC.GetLow()); 825} 826 827void Processor::OPCode0x72() 828{ 829 // LD (HL),D 830 OPCodes_LD(HL.GetValue(), DE.GetHigh()); 831} 832 833void Processor::OPCode0x73() 834{ 835 // LD (HL),E 836 OPCodes_LD(HL.GetValue(), DE.GetLow()); 837} 838 839void Processor::OPCode0x74() 840{ 841 // LD (HL),H 842 OPCodes_LD(HL.GetValue(), HL.GetHigh()); 843} 844 845void Processor::OPCode0x75() 846{ 847 // LD (HL),L 848 OPCodes_LD(HL.GetValue(), HL.GetLow()); 849} 850 851void Processor::OPCode0x76() 852{ 853 // HALT 854 if (m_iIMECycles > 0) 855 { 856 // If EI is pending interrupts are triggered before Halt 857 m_iIMECycles = 0; 858 m_bIME = true; 859 PC.Decrement(); 860 } 861 else 862 { 863 u8 if_reg = m_pMemory->Retrieve(0xFF0F); 864 u8 ie_reg = m_pMemory->Retrieve(0xFFFF); 865 866 m_bHalt = true; 867 868 if (!m_bCGB && !m_bIME && (if_reg & ie_reg & 0x1F)) 869 { 870 m_bSkipPCBug = true; 871 } 872 } 873} 874 875void Processor::OPCode0x77() 876{ 877 // LD (HL),A 878 OPCodes_LD(HL.GetValue(), AF.GetHigh()); 879} 880 881void Processor::OPCode0x78() 882{ 883 // LD A,B 884 OPCodes_LD(AF.GetHighRegister(), BC.GetHigh()); 885} 886 887void Processor::OPCode0x79() 888{ 889 // LD A,C 890 OPCodes_LD(AF.GetHighRegister(), BC.GetLow()); 891} 892 893void Processor::OPCode0x7A() 894{ 895 // LD A,D 896 OPCodes_LD(AF.GetHighRegister(), DE.GetHigh()); 897} 898 899void Processor::OPCode0x7B() 900{ 901 // LD A,E 902 OPCodes_LD(AF.GetHighRegister(), DE.GetLow()); 903 904} 905 906void Processor::OPCode0x7C() 907{ 908 // LD A,H 909 OPCodes_LD(AF.GetHighRegister(), HL.GetHigh()); 910} 911 912void Processor::OPCode0x7D() 913{ 914 // LD A,L 915 OPCodes_LD(AF.GetHighRegister(), HL.GetLow()); 916} 917 918void Processor::OPCode0x7E() 919{ 920 // LD A,(HL) 921 OPCodes_LD(AF.GetHighRegister(), HL.GetValue()); 922} 923 924void Processor::OPCode0x7F() 925{ 926 // LD A,A 927 OPCodes_LD(AF.GetHighRegister(), AF.GetHigh()); 928} 929 930void Processor::OPCode0x80() 931{ 932 // ADD A,B 933 OPCodes_ADD(BC.GetHigh()); 934} 935 936void Processor::OPCode0x81() 937{ 938 // ADD A,C 939 OPCodes_ADD(BC.GetLow()); 940} 941 942void Processor::OPCode0x82() 943{ 944 // ADD A,D 945 OPCodes_ADD(DE.GetHigh()); 946} 947 948void Processor::OPCode0x83() 949{ 950 // ADD A,E 951 OPCodes_ADD(DE.GetLow()); 952} 953 954void Processor::OPCode0x84() 955{ 956 // ADD A,H 957 OPCodes_ADD(HL.GetHigh()); 958} 959 960void Processor::OPCode0x85() 961{ 962 // ADD A,L 963 OPCodes_ADD(HL.GetLow()); 964} 965 966void Processor::OPCode0x86() 967{ 968 // ADD A,(HL) 969 OPCodes_ADD(m_pMemory->Read(HL.GetValue())); 970} 971 972void Processor::OPCode0x87() 973{ 974 // ADD A,A 975 OPCodes_ADD(AF.GetHigh()); 976} 977 978void Processor::OPCode0x88() 979{ 980 // ADC A,B 981 OPCodes_ADC(BC.GetHigh()); 982} 983 984void Processor::OPCode0x89() 985{ 986 // ADC A,C 987 OPCodes_ADC(BC.GetLow()); 988} 989 990void Processor::OPCode0x8A() 991{ 992 // ADC A,D 993 OPCodes_ADC(DE.GetHigh()); 994} 995 996void Processor::OPCode0x8B() 997{ 998 // ADC A,E 999 OPCodes_ADC(DE.GetLow()); 1000} 1001 1002void Processor::OPCode0x8C() 1003{ 1004 // ADC A,H 1005 OPCodes_ADC(HL.GetHigh()); 1006} 1007 1008void Processor::OPCode0x8D() 1009{ 1010 // ADC A,L 1011 OPCodes_ADC(HL.GetLow()); 1012} 1013 1014void Processor::OPCode0x8E() 1015{ 1016 // ADC A,(HL) 1017 OPCodes_ADC(m_pMemory->Read(HL.GetValue())); 1018} 1019 1020void Processor::OPCode0x8F() 1021{ 1022 // ADC A,A 1023 OPCodes_ADC(AF.GetHigh()); 1024} 1025 1026void Processor::OPCode0x90() 1027{ 1028 // SUB B 1029 OPCodes_SUB(BC.GetHigh()); 1030} 1031 1032void Processor::OPCode0x91() 1033{ 1034 // SUB C 1035 OPCodes_SUB(BC.GetLow()); 1036} 1037 1038void Processor::OPCode0x92() 1039{ 1040 // SUB D 1041 OPCodes_SUB(DE.GetHigh()); 1042} 1043 1044void Processor::OPCode0x93() 1045{ 1046 // SUB E 1047 OPCodes_SUB(DE.GetLow()); 1048} 1049 1050void Processor::OPCode0x94() 1051{ 1052 // SUB H 1053 OPCodes_SUB(HL.GetHigh()); 1054} 1055 1056void Processor::OPCode0x95() 1057{ 1058 // SUB L 1059 OPCodes_SUB(HL.GetLow()); 1060} 1061 1062void Processor::OPCode0x96() 1063{ 1064 // SUB (HL) 1065 OPCodes_SUB(m_pMemory->Read(HL.GetValue())); 1066} 1067 1068void Processor::OPCode0x97() 1069{ 1070 // SUB A 1071 OPCodes_SUB(AF.GetHigh()); 1072} 1073 1074void Processor::OPCode0x98() 1075{ 1076 // SBC B 1077 OPCodes_SBC(BC.GetHigh()); 1078} 1079 1080void Processor::OPCode0x99() 1081{ 1082 // SBC C 1083 OPCodes_SBC(BC.GetLow()); 1084} 1085 1086void Processor::OPCode0x9A() 1087{ 1088 // SBC D 1089 OPCodes_SBC(DE.GetHigh()); 1090} 1091 1092void Processor::OPCode0x9B() 1093{ 1094 // SBC E 1095 OPCodes_SBC(DE.GetLow()); 1096} 1097 1098void Processor::OPCode0x9C() 1099{ 1100 // SBC H 1101 OPCodes_SBC(HL.GetHigh()); 1102} 1103 1104void Processor::OPCode0x9D() 1105{ 1106 // SBC L 1107 OPCodes_SBC(HL.GetLow()); 1108} 1109 1110void Processor::OPCode0x9E() 1111{ 1112 // SBC (HL) 1113 OPCodes_SBC(m_pMemory->Read(HL.GetValue())); 1114} 1115 1116void Processor::OPCode0x9F() 1117{ 1118 // SBC A 1119 OPCodes_SBC(AF.GetHigh()); 1120} 1121 1122void Processor::OPCode0xA0() 1123{ 1124 // AND B 1125 OPCodes_AND(BC.GetHigh()); 1126} 1127 1128void Processor::OPCode0xA1() 1129{ 1130 // AND C 1131 OPCodes_AND(BC.GetLow()); 1132} 1133 1134void Processor::OPCode0xA2() 1135{ 1136 // AND D 1137 OPCodes_AND(DE.GetHigh()); 1138} 1139 1140void Processor::OPCode0xA3() 1141{ 1142 // AND E 1143 OPCodes_AND(DE.GetLow()); 1144} 1145 1146void Processor::OPCode0xA4() 1147{ 1148 // AND H 1149 OPCodes_AND(HL.GetHigh()); 1150} 1151 1152void Processor::OPCode0xA5() 1153{ 1154 // AND L 1155 OPCodes_AND(HL.GetLow()); 1156} 1157 1158void Processor::OPCode0xA6() 1159{ 1160 // AND (HL) 1161 OPCodes_AND(m_pMemory->Read(HL.GetValue())); 1162} 1163 1164void Processor::OPCode0xA7() 1165{ 1166 // AND A 1167 OPCodes_AND(AF.GetHigh()); 1168} 1169 1170void Processor::OPCode0xA8() 1171{ 1172 // XOR B 1173 OPCodes_XOR(BC.GetHigh()); 1174} 1175 1176void Processor::OPCode0xA9() 1177{ 1178 // XOR C 1179 OPCodes_XOR(BC.GetLow()); 1180} 1181 1182void Processor::OPCode0xAA() 1183{ 1184 // XOR D 1185 OPCodes_XOR(DE.GetHigh()); 1186} 1187 1188void Processor::OPCode0xAB() 1189{ 1190 // XOR E 1191 OPCodes_XOR(DE.GetLow()); 1192} 1193 1194void Processor::OPCode0xAC() 1195{ 1196 // XOR H 1197 OPCodes_XOR(HL.GetHigh()); 1198} 1199 1200void Processor::OPCode0xAD() 1201{ 1202 // XOR L 1203 OPCodes_XOR(HL.GetLow()); 1204} 1205 1206void Processor::OPCode0xAE() 1207{ 1208 // XOR (HL) 1209 OPCodes_XOR(m_pMemory->Read(HL.GetValue())); 1210} 1211 1212void Processor::OPCode0xAF() 1213{ 1214 // XOR A 1215 OPCodes_XOR(AF.GetHigh()); 1216} 1217 1218void Processor::OPCode0xB0() 1219{ 1220 // OR B 1221 OPCodes_OR(BC.GetHigh()); 1222} 1223 1224void Processor::OPCode0xB1() 1225{ 1226 // OR C 1227 OPCodes_OR(BC.GetLow()); 1228} 1229 1230void Processor::OPCode0xB2() 1231{ 1232 // OR D 1233 OPCodes_OR(DE.GetHigh()); 1234} 1235 1236void Processor::OPCode0xB3() 1237{ 1238 // OR E 1239 OPCodes_OR(DE.GetLow()); 1240 1241} 1242 1243void Processor::OPCode0xB4() 1244{ 1245 // OR H 1246 OPCodes_OR(HL.GetHigh()); 1247} 1248 1249void Processor::OPCode0xB5() 1250{ 1251 // OR L 1252 OPCodes_OR(HL.GetLow()); 1253} 1254 1255void Processor::OPCode0xB6() 1256{ 1257 // OR (HL) 1258 OPCodes_OR(m_pMemory->Read(HL.GetValue())); 1259} 1260 1261void Processor::OPCode0xB7() 1262{ 1263 // OR A 1264 OPCodes_OR(AF.GetHigh()); 1265} 1266 1267void Processor::OPCode0xB8() 1268{ 1269 // CP B 1270 OPCodes_CP(BC.GetHigh()); 1271} 1272 1273void Processor::OPCode0xB9() 1274{ 1275 // CP C 1276 OPCodes_CP(BC.GetLow()); 1277} 1278 1279void Processor::OPCode0xBA() 1280{ 1281 // CP D 1282 OPCodes_CP(DE.GetHigh()); 1283} 1284 1285void Processor::OPCode0xBB() 1286{ 1287 // CP E 1288 OPCodes_CP(DE.GetLow()); 1289} 1290 1291void Processor::OPCode0xBC() 1292{ 1293 // CP H 1294 OPCodes_CP(HL.GetHigh()); 1295} 1296 1297void Processor::OPCode0xBD() 1298{ 1299 // CP L 1300 OPCodes_CP(HL.GetLow()); 1301} 1302 1303void Processor::OPCode0xBE() 1304{ 1305 // CP (HL) 1306 OPCodes_CP(m_pMemory->Read(HL.GetValue())); 1307} 1308 1309void Processor::OPCode0xBF() 1310{ 1311 // CP A 1312 OPCodes_CP(AF.GetHigh()); 1313} 1314 1315void Processor::OPCode0xC0() 1316{ 1317 // RET NZ 1318 if (!IsSetFlag(FLAG_ZERO)) 1319 { 1320 StackPop(&PC); 1321 m_bBranchTaken = true; 1322 } 1323} 1324 1325void Processor::OPCode0xC1() 1326{ 1327 // POP BC 1328 StackPop(&BC); 1329} 1330 1331void Processor::OPCode0xC2() 1332{ 1333 // JP NZ,nn 1334 if (!IsSetFlag(FLAG_ZERO)) 1335 { 1336 u8 l = m_pMemory->Read(PC.GetValue()); 1337 PC.Increment(); 1338 u8 h = m_pMemory->Read(PC.GetValue()); 1339 PC.SetHigh(h); 1340 PC.SetLow(l); 1341 m_bBranchTaken = true; 1342 } 1343 else 1344 { 1345 PC.Increment(); 1346 PC.Increment(); 1347 } 1348} 1349 1350void Processor::OPCode0xC3() 1351{ 1352 // JP nn 1353 u8 l = m_pMemory->Read(PC.GetValue()); 1354 PC.Increment(); 1355 u8 h = m_pMemory->Read(PC.GetValue()); 1356 PC.SetHigh(h); 1357 PC.SetLow(l); 1358} 1359 1360void Processor::OPCode0xC4() 1361{ 1362 // CALL NZ,nn 1363 if (!IsSetFlag(FLAG_ZERO)) 1364 { 1365 u8 l = m_pMemory->Read(PC.GetValue()); 1366 PC.Increment(); 1367 u8 h = m_pMemory->Read(PC.GetValue()); 1368 PC.Increment(); 1369 StackPush(&PC); 1370 PC.SetHigh(h); 1371 PC.SetLow(l); 1372 m_bBranchTaken = true; 1373 } 1374 else 1375 { 1376 PC.Increment(); 1377 PC.Increment(); 1378 } 1379} 1380 1381void Processor::OPCode0xC5() 1382{ 1383 // PUSH BC 1384 StackPush(&BC); 1385} 1386 1387void Processor::OPCode0xC6() 1388{ 1389 // ADD A,n 1390 OPCodes_ADD(m_pMemory->Read(PC.GetValue())); 1391 PC.Increment(); 1392} 1393 1394void Processor::OPCode0xC7() 1395{ 1396 // RST 00H 1397 StackPush(&PC); 1398 PC.SetValue(0x0000); 1399} 1400 1401void Processor::OPCode0xC8() 1402{ 1403 // RET Z 1404 if (IsSetFlag(FLAG_ZERO)) 1405 { 1406 StackPop(&PC); 1407 m_bBranchTaken = true; 1408 } 1409} 1410 1411void Processor::OPCode0xC9() 1412{ 1413 // RET 1414 StackPop(&PC); 1415} 1416 1417void Processor::OPCode0xCA() 1418{ 1419 // JP Z,nn 1420 if (IsSetFlag(FLAG_ZERO)) 1421 { 1422 u8 l = m_pMemory->Read(PC.GetValue()); 1423 PC.Increment(); 1424 u8 h = m_pMemory->Read(PC.GetValue()); 1425 PC.SetHigh(h); 1426 PC.SetLow(l); 1427 m_bBranchTaken = true; 1428 } 1429 else 1430 { 1431 PC.Increment(); 1432 PC.Increment(); 1433 } 1434} 1435 1436void Processor::OPCode0xCB() 1437{ 1438 // CB prefixed instruction 1439} 1440 1441void Processor::OPCode0xCC() 1442{ 1443 // CALL Z,nn 1444 if (IsSetFlag(FLAG_ZERO)) 1445 { 1446 u8 l = m_pMemory->Read(PC.GetValue()); 1447 PC.Increment(); 1448 u8 h = m_pMemory->Read(PC.GetValue()); 1449 PC.Increment(); 1450 StackPush(&PC); 1451 PC.SetHigh(h); 1452 PC.SetLow(l); 1453 m_bBranchTaken = true; 1454 } 1455 else 1456 { 1457 PC.Increment(); 1458 PC.Increment(); 1459 } 1460} 1461 1462void Processor::OPCode0xCD() 1463{ 1464 // CALL nn 1465 u8 l = m_pMemory->Read(PC.GetValue()); 1466 PC.Increment(); 1467 u8 h = m_pMemory->Read(PC.GetValue()); 1468 PC.Increment(); 1469 StackPush(&PC); 1470 PC.SetHigh(h); 1471 PC.SetLow(l); 1472} 1473 1474void Processor::OPCode0xCE() 1475{ 1476 // ADC A,n 1477 OPCodes_ADC(m_pMemory->Read(PC.GetValue())); 1478 PC.Increment(); 1479} 1480 1481void Processor::OPCode0xCF() 1482{ 1483 // RST 08H 1484 StackPush(&PC); 1485 PC.SetValue(0x0008); 1486} 1487 1488void Processor::OPCode0xD0() 1489{ 1490 // RET NC 1491 if (!IsSetFlag(FLAG_CARRY)) 1492 { 1493 StackPop(&PC); 1494 m_bBranchTaken = true; 1495 } 1496} 1497 1498void Processor::OPCode0xD1() 1499{ 1500 // POP DE 1501 StackPop(&DE); 1502} 1503 1504void Processor::OPCode0xD2() 1505{ 1506 // JP NC,nn 1507 if (!IsSetFlag(FLAG_CARRY)) 1508 { 1509 u8 l = m_pMemory->Read(PC.GetValue()); 1510 PC.Increment(); 1511 u8 h = m_pMemory->Read(PC.GetValue()); 1512 PC.SetHigh(h); 1513 PC.SetLow(l); 1514 m_bBranchTaken = true; 1515 } 1516 else 1517 { 1518 PC.Increment(); 1519 PC.Increment(); 1520 } 1521} 1522 1523void Processor::OPCode0xD3() 1524{ 1525 InvalidOPCode(); 1526} 1527 1528void Processor::OPCode0xD4() 1529{ 1530 // CALL NC,nn 1531 if (!IsSetFlag(FLAG_CARRY)) 1532 { 1533 u8 l = m_pMemory->Read(PC.GetValue()); 1534 PC.Increment(); 1535 u8 h = m_pMemory->Read(PC.GetValue()); 1536 PC.Increment(); 1537 StackPush(&PC); 1538 PC.SetHigh(h); 1539 PC.SetLow(l); 1540 m_bBranchTaken = true; 1541 } 1542 else 1543 { 1544 PC.Increment(); 1545 PC.Increment(); 1546 } 1547} 1548 1549void Processor::OPCode0xD5() 1550{ 1551 // PUSH DE 1552 StackPush(&DE); 1553} 1554 1555void Processor::OPCode0xD6() 1556{ 1557 // SUB n 1558 OPCodes_SUB(m_pMemory->Read(PC.GetValue())); 1559 PC.Increment(); 1560} 1561 1562void Processor::OPCode0xD7() 1563{ 1564 // RST 10H 1565 StackPush(&PC); 1566 PC.SetValue(0x0010); 1567} 1568 1569void Processor::OPCode0xD8() 1570{ 1571 // RET C 1572 if (IsSetFlag(FLAG_CARRY)) 1573 { 1574 StackPop(&PC); 1575 m_bBranchTaken = true; 1576 } 1577} 1578 1579void Processor::OPCode0xD9() 1580{ 1581 // RETI 1582 StackPop(&PC); 1583 m_bIME = true; 1584} 1585 1586void Processor::OPCode0xDA() 1587{ 1588 // JP C,nn 1589 if (IsSetFlag(FLAG_CARRY)) 1590 { 1591 u8 l = m_pMemory->Read(PC.GetValue()); 1592 PC.Increment(); 1593 u8 h = m_pMemory->Read(PC.GetValue()); 1594 PC.SetHigh(h); 1595 PC.SetLow(l); 1596 m_bBranchTaken = true; 1597 } 1598 else 1599 { 1600 PC.Increment(); 1601 PC.Increment(); 1602 } 1603} 1604 1605void Processor::OPCode0xDB() 1606{ 1607 InvalidOPCode(); 1608} 1609 1610void Processor::OPCode0xDC() 1611{ 1612 // CALL C,nn 1613 if (IsSetFlag(FLAG_CARRY)) 1614 { 1615 u8 l = m_pMemory->Read(PC.GetValue()); 1616 PC.Increment(); 1617 u8 h = m_pMemory->Read(PC.GetValue()); 1618 PC.Increment(); 1619 StackPush(&PC); 1620 PC.SetHigh(h); 1621 PC.SetLow(l); 1622 m_bBranchTaken = true; 1623 } 1624 else 1625 { 1626 PC.Increment(); 1627 PC.Increment(); 1628 } 1629} 1630 1631void Processor::OPCode0xDD() 1632{ 1633 InvalidOPCode(); 1634} 1635 1636void Processor::OPCode0xDE() 1637{ 1638 // SBC n 1639 OPCodes_SBC(m_pMemory->Read(PC.GetValue())); 1640 PC.Increment(); 1641} 1642 1643void Processor::OPCode0xDF() 1644{ 1645 // RST 18H 1646 StackPush(&PC); 1647 PC.SetValue(0x0018); 1648} 1649 1650void Processor::OPCode0xE0() 1651{ 1652 // LD (0xFF00+n),A 1653 OPCodes_LD(static_cast<u16> (0xFF00 + m_pMemory->Read(PC.GetValue())), AF.GetHigh()); 1654 PC.Increment(); 1655} 1656 1657void Processor::OPCode0xE1() 1658{ 1659 // POP HL 1660 StackPop(&HL); 1661} 1662 1663void Processor::OPCode0xE2() 1664{ 1665 // LD (0xFF00+C),A 1666 OPCodes_LD(static_cast<u16> (0xFF00 + BC.GetLow()), AF.GetHigh()); 1667} 1668 1669void Processor::OPCode0xE3() 1670{ 1671 InvalidOPCode(); 1672} 1673 1674void Processor::OPCode0xE4() 1675{ 1676 InvalidOPCode(); 1677} 1678 1679void Processor::OPCode0xE5() 1680{ 1681 // PUSH HL 1682 StackPush(&HL); 1683} 1684 1685void Processor::OPCode0xE6() 1686{ 1687 // AND n 1688 OPCodes_AND(m_pMemory->Read(PC.GetValue())); 1689 PC.Increment(); 1690} 1691 1692void Processor::OPCode0xE7() 1693{ 1694 // RST 20H 1695 StackPush(&PC); 1696 PC.SetValue(0x0020); 1697} 1698 1699void Processor::OPCode0xE8() 1700{ 1701 // ADD SP,n 1702 OPCodes_ADD_SP(static_cast<u8> (m_pMemory->Read(PC.GetValue()))); 1703 PC.Increment(); 1704} 1705 1706void Processor::OPCode0xE9() 1707{ 1708 // JP (HL) 1709 PC.SetValue(HL.GetValue()); 1710} 1711 1712void Processor::OPCode0xEA() 1713{ 1714 // LD (nn),A 1715 SixteenBitRegister tmp; 1716 tmp.SetLow(m_pMemory->Read(PC.GetValue())); 1717 PC.Increment(); 1718 tmp.SetHigh(m_pMemory->Read(PC.GetValue())); 1719 PC.Increment(); 1720 OPCodes_LD(tmp.GetValue(), AF.GetHigh()); 1721} 1722 1723void Processor::OPCode0xEB() 1724{ 1725 InvalidOPCode(); 1726} 1727 1728void Processor::OPCode0xEC() 1729{ 1730 InvalidOPCode(); 1731} 1732 1733void Processor::OPCode0xED() 1734{ 1735 InvalidOPCode(); 1736} 1737 1738void Processor::OPCode0xEE() 1739{ 1740 // XOR n 1741 OPCodes_XOR(m_pMemory->Read(PC.GetValue())); 1742 PC.Increment(); 1743} 1744 1745void Processor::OPCode0xEF() 1746{ 1747 // RST 28H 1748 StackPush(&PC); 1749 PC.SetValue(0x28); 1750} 1751 1752void Processor::OPCode0xF0() 1753{ 1754 // LD A,(0xFF00+n) 1755 OPCodes_LD(AF.GetHighRegister(), 1756 static_cast<u16> (0xFF00 + m_pMemory->Read(PC.GetValue()))); 1757 PC.Increment(); 1758} 1759 1760void Processor::OPCode0xF1() 1761{ 1762 // POP AF 1763 StackPop(&AF); 1764 AF.SetLow(AF.GetLow() & 0xF0); 1765} 1766 1767void Processor::OPCode0xF2() 1768{ 1769 // LD A,(C) 1770 OPCodes_LD(AF.GetHighRegister(), static_cast<u16> (0xFF00 + BC.GetLow())); 1771} 1772 1773void Processor::OPCode0xF3() 1774{ 1775 // DI 1776 m_bIME = false; 1777 m_iIMECycles = 0; 1778} 1779 1780void Processor::OPCode0xF4() 1781{ 1782 InvalidOPCode(); 1783} 1784 1785void Processor::OPCode0xF5() 1786{ 1787 // PUSH AF 1788 StackPush(&AF); 1789} 1790 1791void Processor::OPCode0xF6() 1792{ 1793 // OR n 1794 OPCodes_OR(m_pMemory->Read(PC.GetValue())); 1795 PC.Increment(); 1796} 1797 1798void Processor::OPCode0xF7() 1799{ 1800 // RST 30H 1801 StackPush(&PC); 1802 PC.SetValue(0x0030); 1803} 1804 1805void Processor::OPCode0xF8() 1806{ 1807 // LD HL,SP+n 1808 s8 n = m_pMemory->Read(PC.GetValue()); 1809 u16 result = SP.GetValue() + n; 1810 ClearAllFlags(); 1811 if (((SP.GetValue() ^ n ^ result) & 0x100) == 0x100) 1812 ToggleFlag(FLAG_CARRY); 1813 if (((SP.GetValue() ^ n ^ result) & 0x10) == 0x10) 1814 ToggleFlag(FLAG_HALF); 1815 HL.SetValue(result); 1816 PC.Increment(); 1817} 1818 1819void Processor::OPCode0xF9() 1820{ 1821 // LD SP,HL 1822 SP.SetValue(HL.GetValue()); 1823} 1824 1825void Processor::OPCode0xFA() 1826{ 1827 // LD A,(nn) 1828 SixteenBitRegister tmp; 1829 tmp.SetLow(m_pMemory->Read(PC.GetValue())); 1830 PC.Increment(); 1831 tmp.SetHigh(m_pMemory->Read(PC.GetValue())); 1832 PC.Increment(); 1833 OPCodes_LD(AF.GetHighRegister(), tmp.GetValue()); 1834} 1835 1836void Processor::OPCode0xFB() 1837{ 1838 // EI 1839 int ei_cycles = kOPCodeMachineCycles[0xFB] * AdjustedCycles(4); 1840 m_iIMECycles = ei_cycles + 1; 1841} 1842 1843void Processor::OPCode0xFC() 1844{ 1845 InvalidOPCode(); 1846} 1847 1848void Processor::OPCode0xFD() 1849{ 1850 InvalidOPCode(); 1851} 1852 1853void Processor::OPCode0xFE() 1854{ 1855 // CP n 1856 OPCodes_CP(m_pMemory->Read(PC.GetValue())); 1857 PC.Increment(); 1858} 1859 1860void Processor::OPCode0xFF() 1861{ 1862 // RST 38H 1863 StackPush(&PC); 1864 PC.SetValue(0x0038); 1865}