From bca5d074db404070f9a1c9c2de2e3d25b9e83b91 Mon Sep 17 00:00:00 2001 From: tudnai Date: Tue, 28 Jul 2020 17:37:27 -0700 Subject: [PATCH] 65C02 Instructions --- A2Mac.xcodeproj/project.pbxproj | 6 +- src/cpu/6502_C.h | 61 ++ src/cpu/6502_std.h | 6 +- src/cpu/6502_und.h | 6 +- src/cpu/65C02.c | 694 ++++-------------- .../instructions/6502_instr_compare_test.h | 56 ++ src/cpu/instructions/6502_instr_inc_dec.h | 34 + src/cpu/instructions/6502_instr_load_store.h | 19 + src/cpu/instructions/6502_instr_stack.h | 66 ++ src/dev/mem/mmio.h | 7 + 10 files changed, 396 insertions(+), 559 deletions(-) create mode 100644 src/cpu/6502_C.h diff --git a/A2Mac.xcodeproj/project.pbxproj b/A2Mac.xcodeproj/project.pbxproj index b863807..93a6837 100644 --- a/A2Mac.xcodeproj/project.pbxproj +++ b/A2Mac.xcodeproj/project.pbxproj @@ -11,11 +11,11 @@ 320B3FC424AD88B0005EA133 /* power.png in Copy Image Files */ = {isa = PBXBuildFile; fileRef = 320B3FC324AD88B0005EA133 /* power.png */; }; 320B4FC124B182DE00070038 /* Apple Disk II.png in Copy Image Files */ = {isa = PBXBuildFile; fileRef = 320B4FC024B182DD00070038 /* Apple Disk II.png */; }; 320F2A8824CFD74100671B35 /* Steve2Icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 320F2A8724CFD74000671B35 /* Steve2Icon.icns */; }; + 320F2A8D24D0FB9200671B35 /* 6502.c in Sources */ = {isa = PBXBuildFile; fileRef = 32439F7422ECD8AD0077AAE0 /* 6502.c */; }; 3213936624079C30007F5C4A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 32BFFB6022EACC660003B53F /* Main.storyboard */; }; 323D042E248980600086A901 /* Preferences.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 323D042D248980600086A901 /* Preferences.storyboard */; }; 323D043024898AB70086A901 /* PreferencesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 323D042F24898AB70086A901 /* PreferencesViewController.swift */; }; 323D04332489BFD80086A901 /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 323D04312489BFD80086A901 /* PreferencesWindowController.swift */; }; - 323D0437248B6BEA0086A901 /* 6502.c in Sources */ = {isa = PBXBuildFile; fileRef = 32439F7422ECD8AD0077AAE0 /* 6502.c */; }; 323D04442490B3930086A901 /* dotmatrix_effect.png in Copy Image Files */ = {isa = PBXBuildFile; fileRef = 323D04432490B3930086A901 /* dotmatrix_effect.png */; }; 323E2DCF245531E600156805 /* Apple2e_Enhanced.rom in Resources */ = {isa = PBXBuildFile; fileRef = 323E2DCC245531E500156805 /* Apple2e_Enhanced.rom */; }; 323E2DD1245531E600156805 /* Apple2e.rom in Resources */ = {isa = PBXBuildFile; fileRef = 323E2DCD245531E500156805 /* Apple2e.rom */; }; @@ -312,6 +312,7 @@ 320F2A8724CFD74000671B35 /* Steve2Icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = Steve2Icon.icns; sourceTree = ""; }; 320F2A8924CFFBE300671B35 /* 6502_std.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = 6502_std.h; sourceTree = ""; }; 320F2A8A24D0001600671B35 /* 6502_und.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = 6502_und.h; sourceTree = ""; }; + 320F2A8B24D0828600671B35 /* 6502_C.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 6502_C.h; sourceTree = ""; }; 323D042D248980600086A901 /* Preferences.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Preferences.storyboard; sourceTree = ""; }; 323D042F24898AB70086A901 /* PreferencesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesViewController.swift; sourceTree = ""; }; 323D04312489BFD80086A901 /* PreferencesWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesWindowController.swift; sourceTree = ""; }; @@ -679,6 +680,7 @@ 32439F7422ECD8AD0077AAE0 /* 6502.c */, 320F2A8924CFFBE300671B35 /* 6502_std.h */, 320F2A8A24D0001600671B35 /* 6502_und.h */, + 320F2A8B24D0828600671B35 /* 6502_C.h */, 32440B69247CA1CE000F9DA1 /* 65C02.c */, 32440B67247CA1AF000F9DA1 /* 6502_vanilla.c */, ); @@ -1208,13 +1210,13 @@ 32E3126D24AC033A00E61891 /* ToolBarController.swift in Sources */, 323D043024898AB70086A901 /* PreferencesViewController.swift in Sources */, 323D04332489BFD80086A901 /* PreferencesWindowController.swift in Sources */, + 320F2A8D24D0FB9200671B35 /* 6502.c in Sources */, 32E3126924A98B9300E61891 /* dsk2woz.c in Sources */, 325EB63623F8F78300C6B4A4 /* disk.c in Sources */, 325EB62F23F8856F00C6B4A4 /* woz.c in Sources */, 32A9F74A2467B60B004902A1 /* speaker.c in Sources */, 325EB63923F9E48100C6B4A4 /* common.c in Sources */, 32BFFB5D22EACC630003B53F /* ViewController.swift in Sources */, - 323D0437248B6BEA0086A901 /* 6502.c in Sources */, 325EB69323FE6C6200C6B4A4 /* HiRes.swift in Sources */, 32440BA32480D5C0000F9DA1 /* LoRes.swift in Sources */, 32C45306232E3EEF0000EBA1 /* RepeatingTimer.swift in Sources */, diff --git a/src/cpu/6502_C.h b/src/cpu/6502_C.h new file mode 100644 index 0000000..e4c1da0 --- /dev/null +++ b/src/cpu/6502_C.h @@ -0,0 +1,61 @@ +// +// 6502_und.h +// A2Mac +// +// Created by Tamas Rudnai on 7/27/20. +// Copyright © 2020 GameAlloy. All rights reserved. +// + +#ifndef _6502_C_h +#define _6502_C_h + +// 6502 instructions with additional addressing modes + + // ADC AND CMP EOR LDA ORA SBC STA - (zp) addressing mode + case 0x12: ORA( src_zp_0() ); return 5; // ORA (zpg) + case 0x32: AND( src_zp_0() ); return 5; // AND (zpg) + case 0x52: EOR( src_zp_0() ); return 5; // EOR (zpg) + case 0x72: ADC( src_zp_0() ); return 5; // ADC (zpg) + case 0x92: STA( src_zp_0() ); return 5; // STA (zpg) + case 0xB2: LDA( src_zp_0() ); return 5; // LDA (zpg) + case 0xD2: CMP( src_zp_0() ); return 5; // CMP (zpg) + case 0xF2: SBC( src_zp_0() ); return 5; // SBC (zpg) + + // BIT - imm abs,X zp,X addressing modes + case 0x34: BIT( src_zp_X() ); return 4; // BIT zpg,X + case 0x3C: BIT( src_abs_X() ); return 4; // BIT abs,X + case 0x89: BIT( imm() ); return 2; // BIT imm + + // DEC INC - acc addressing mode + case 0x1A: INA(); return 2; // INA imm (INC A) + case 0x3A: DEA(); return 2; // DEA imm (DEC A) + + // JMP - (abs,X) addressing mode + case 0x7C: JMP( addr_abs_X() ); return 6; // JMP abs,X + +// Additional instructions + + // BRA - BRanch Always + case 0x80: JMP( rel_addr() ); return 3; // BRA reladdr + + // PHX PHY PLX PLY - PusH or PulL X or Y register + case 0x5A: PHY(); return 3; // PHY + case 0x7A: PLY(); return 4; // PLY + case 0xDA: PHX(); return 3; // PHX + case 0xFA: PLX(); return 4; // PLX + + // STZ - STore Zero + case 0x64: STZ( addr_zp() ); return 3; // STZ zpg + case 0x74: STZ( addr_zp_X() ); return 4; // STZ zpg,X + case 0x9C: STZ( addr_abs() ); return 4; // STZ abs + case 0x9E: STZ( addr_abs_X() ); return 5; // STZ abs,X + + // TRB - Test and Reset Bits + case 0x04: TSB( addr_zp() ); return 5; // TSB zpg + case 0x0C: TSB( addr_abs() ); return 6; // TSB abs + case 0x14: TRB( addr_zp() ); return 5; // TRB zpg + case 0x1C: TRB( addr_abs() ); return 6; // TRB abs + + + +#endif /* _6502_C_h */ diff --git a/src/cpu/6502_std.h b/src/cpu/6502_std.h index edddc29..c0cd280 100644 --- a/src/cpu/6502_std.h +++ b/src/cpu/6502_std.h @@ -6,8 +6,8 @@ // Copyright © 2020 GameAlloy. All rights reserved. // -#ifndef _502_std_h -#define _502_std_h +#ifndef _6502_std_h +#define _6502_std_h case 0x00: BRK(); return 7; // BRK case 0x01: ORA( src_X_ind() ); return 6; // ORA X,ind @@ -226,4 +226,4 @@ case 0xFE: INC( addr_abs_X() ); return 7; // INC abs,X -#endif /* _502_std_h */ +#endif /* _6502_std_h */ diff --git a/src/cpu/6502_und.h b/src/cpu/6502_und.h index d9186a2..3af46db 100644 --- a/src/cpu/6502_und.h +++ b/src/cpu/6502_und.h @@ -6,8 +6,8 @@ // Copyright © 2020 GameAlloy. All rights reserved. // -#ifndef _502_und_h -#define _502_und_h +#ifndef _6502_und_h +#define _6502_und_h case 0x02: HLT(); return 0; // HLT* - Halts / Hangs / Jams / Kills the CPU (undocumented) case 0x03: SLO( addr_zp_X() ); return 8; // SLO* zpg,X (undocumented) @@ -180,4 +180,4 @@ case 0xFF: ISB( addr_abs_X() ); return 7; // ISB* abx 7 (undocumented) -#endif /* _502_und_h */ +#endif /* _6502_und_h */ diff --git a/src/cpu/65C02.c b/src/cpu/65C02.c index afca17d..b95c4ad 100644 --- a/src/cpu/65C02.c +++ b/src/cpu/65C02.c @@ -20,6 +20,13 @@ // You should have received a copy of the GNU General Public License // along with Steve ][. If not, see . // +// Documentations: +// +// http://nesdev.com/6502_cpu.txt +// http://www.oxyron.de/html/opcodes02.html +// https://macgui.com/kb/article/46 +// https://www.masswerk.at/6502/6502_instruction_set.html +// #define CLK_WAIT @@ -29,7 +36,6 @@ #include #include #include "6502.h" -#include "woz.h" #include "speaker.h" @@ -37,6 +43,10 @@ void ViewController_spk_up_play(void); void ViewController_spk_dn_play(void); +volatile cpuMode_s cpuMode = cpuMode_normal; +volatile cpuState_s cpuState = cpuState_unknown; + + #include "../util/common.h" @@ -49,12 +59,17 @@ void ViewController_spk_dn_play(void); const unsigned long long int iterations = G; unsigned long long int inst_cnt = 0; -//const unsigned int fps = 30; -const unsigned long long default_MHz_6502 = 1.023 * M; // 2 * M; // 4 * M; // 8 * M; // 16 * M; // 128 * M; // 256 * M; // 512 * M; -const unsigned long long startup_MHz_6502 = 32 * M; -unsigned long long MHz_6502 = default_MHz_6502; -unsigned long long clk_6502_per_frm = default_MHz_6502 / fps; -unsigned long long clk_6502_per_frm_set = default_MHz_6502 / fps; +unsigned int video_fps_divider = DEF_VIDEO_DIV; +unsigned int fps = DEFAULT_FPS; + +const double default_MHz_6502 = 1.023; // 2 * M; // 4 * M; // 8 * M; // 16 * M; // 128 * M; // 256 * M; // 512 * M; +const double iigs_MHz_6502 = 2.8; +const double iicplus_MHz_6502 = 4; +const double startup_MHz_6502 = 32; +double MHz_6502 = default_MHz_6502; +unsigned long long clk_6502_per_frm = FRAME_INIT( default_MHz_6502 ); +unsigned long long clk_6502_per_frm_set = FRAME_INIT( default_MHz_6502 ); +unsigned long long clk_6502_per_frm_max_sound = 4 * FRAME_INIT( default_MHz_6502 ); unsigned long long clk_6502_per_frm_max = 0; @@ -81,13 +96,13 @@ m6502_t m6502 = { 0, // res 0, // V 0, // N - + 0, // PC 0, // SP 0, // clktime 0, // clklast - + 0, // trace 0, // step 0, // brk @@ -154,7 +169,7 @@ typedef struct { !!!! `his has to be here!!! This idea is that "INLINE" would work only if it is located in the same source file -- hence the include... -**/ + **/ INLINE flags_t getFlags() { flags_t f = { @@ -167,7 +182,7 @@ INLINE flags_t getFlags() { m6502.V != 0, // Overflow Flag ??? m6502.N != 0, // Negative Flag }; - + return f; } @@ -188,7 +203,7 @@ INLINE void setFlags( uint8_t byte ) { #include "6502_instructions.h" INLINE int m6502_Step() { - + #ifdef DEBUG___ switch ( m6502.PC ) { @@ -203,7 +218,7 @@ INLINE int m6502_Step() { default: break; } - + switch ( m6502.PC ) { case 0xE000: @@ -227,458 +242,18 @@ INLINE int m6502_Step() { } #endif -#ifdef FUNCTIONTEST - switch ( m6502.PC ) { - case 0x400: - dbgPrintf("START...\n"); - break; - - case 0x0438: - dbgPrintf2("*** TEST 1 (%04X)\n", m6502.PC); - break; - - case 0x0581: - dbgPrintf2("*** TEST 2 (%04X)\n", m6502.PC); - break; - - case 0x05C8: - dbgPrintf2("*** TEST 3 (%04X)\n", m6502.PC); - break; - - case 0x05FC: - dbgPrintf2("*** TEST 4 (%04X)\n", m6502.PC); - break; - - case 0x0776: - dbgPrintf2("*** TEST 5 (%04X)\n", m6502.PC); - break; - - case 0x0872: - dbgPrintf2("*** TEST 6 (%04X)\n", m6502.PC); - break; - - case 0x08A6: - dbgPrintf2("*** TEST 7 (%04X)\n", m6502.PC); - break; - - case 0x08F0: - dbgPrintf2("*** TEST 8 (%04X)\n", m6502.PC); - break; - - case 0x0946: - dbgPrintf2("*** TEST 9 (%04X)\n", m6502.PC); - break; - - case 0x0982: - dbgPrintf2("*** TEST 10 (%04X)\n", m6502.PC); - break; - - case 0x09B9: - dbgPrintf2("*** TEST 11 (%04X)\n", m6502.PC); - break; - - case 0x0A11: - dbgPrintf2("*** TEST 12 (%04X)\n", m6502.PC); - break; - - case 0x0AB7: - dbgPrintf2("*** TEST 13 (%04X)\n", m6502.PC); - break; - - case 0x0D7D: - dbgPrintf2("*** TEST 14 (%04X)\n", m6502.PC); - break; - - case 0x0E46: - dbgPrintf2("*** TEST 15 (%04X)\n", m6502.PC); - break; - - case 0x0F01: - dbgPrintf2("*** TEST 16 (%04X)\n", m6502.PC); - break; - - case 0x0F43: - dbgPrintf2("*** TEST 17 (%04X)\n", m6502.PC); - break; - - case 0x0FFA: - dbgPrintf2("*** TEST 18 (%04X)\n", m6502.PC); - break; - - case 0x103A: - dbgPrintf2("*** TEST 19 (%04X)\n", m6502.PC); - break; - - case 0x1330: - dbgPrintf2("*** TEST 20 (%04X)\n", m6502.PC); - break; - - case 0x162A: - dbgPrintf2("*** TEST 21 (%04X)\n", m6502.PC); - break; - - case 0x16DB: - dbgPrintf2("*** TEST 22 (%04X)\n", m6502.PC); - break; - - case 0x17FA: - dbgPrintf2("*** TEST 23 (%04X)\n", m6502.PC); - break; - - case 0x1899: - dbgPrintf2("*** TEST 24 (%04X)\n", m6502.PC); - break; - - case 0x1B63: - dbgPrintf2("*** TEST 25 (%04X)\n", m6502.PC); - break; - - case 0x1CB7: - dbgPrintf2("*** TEST 26 (%04X)\n", m6502.PC); - break; - - case 0x1DC5: - dbgPrintf("*** TEST 27 (%04X)\n", m6502.PC); - break; - - case 0x1ED3: - dbgPrintf2("*** TEST 28 (%04X)\n", m6502.PC); - break; - - case 0x22B7: - dbgPrintf2("*** TEST 29 (%04X)\n", m6502.PC); - break; - - case 0x23FB: - dbgPrintf2("*** TEST 30 (%04X)\n", m6502.PC); - break; - - case 0x257B: - dbgPrintf2("*** TEST 31 (%04X)\n", m6502.PC); - break; - - case 0x271F: - dbgPrintf2("*** TEST 32 (%04X)\n", m6502.PC); - break; - - case 0x289F: - dbgPrintf2("*** TEST 33 (%04X)\n", m6502.PC); - break; - - case 0x2A43: - dbgPrintf2("*** TEST 34 (%04X)\n", m6502.PC); - break; - - case 0x2AED: - dbgPrintf2("*** TEST 35 (%04X)\n", m6502.PC); - break; - - case 0x2BA7: - dbgPrintf2("*** TEST 36 (%04X)\n", m6502.PC); - break; - - case 0x2C55: - dbgPrintf2("*** TEST 37 (%04X)\n", m6502.PC); - break; - - case 0x2D13: - dbgPrintf2("*** TEST 38 (%04X)\n", m6502.PC); - break; - - case 0x3103: - dbgPrintf2("*** TEST 40 (%04X)\n", m6502.PC); - break; - - case 0x32FC: - dbgPrintf2("*** TEST 41 (%04X)\n", m6502.PC); - break; - - case 0x3361: - dbgPrintf2("*** TEST 42 (%04X)\n", m6502.PC); - break; - - case 0x3405: - dbgPrintf2("*** TEST 43 (%04X)\n", m6502.PC); - break; - - case 0x345D: - dbgPrintf2("*** TEST 44 (%04X)\n", m6502.PC); - break; - - case 0x3469: - dbgPrintf2("*** TEST PASSED (%04X)\n", m6502.PC); - break; - - default: - break; - } -#endif - disNewInstruction(); switch ( fetch() ) { - case 0x00: BRK(); return 7; // BRK - case 0x01: ORA( src_X_ind() ); return 6; // ORA X,ind -// case 0x02: // t jams -// case 0x03: // SLO* (undocumented) -// case 0x04: // NOP* (undocumented) - case 0x05: ORA( src_zp() ); return 3; // ORA zpg - case 0x06: ASL( addr_zp() ); return 5; // ASL zpg -// case 0x07: // SLO* (undocumented) - case 0x08: PHP(); return 3; // PHP - case 0x09: ORA( imm() ); return 2; // ORA imm - case 0x0A: ASLA(); return 2; // ASL A -// case 0x0B: // ANC** (undocumented) -// case 0x0C: // NOP* (undocumented) - case 0x0D: ORA( src_abs() ); return 4; // ORA abs - case 0x0E: ASL( addr_abs() ); return 6; // ASL abs -// case 0x0F: // SLO* (undocumented) - case 0x10: BPL( rel_addr() ); return 3; // BPL rel - case 0x11: ORA( src_ind_Y() ); return 5; // ORA ind,Y -// case 0x12: // t jams -// case 0x13: // SLO* (undocumented) -// case 0x14: // NOP* (undocumented) - case 0x15: ORA( src_zp_X() ); return 4; // ORA zpg,X - case 0x16: ASL( addr_zp_X() ); return 6; // ASL zpg,X -// case 0x17: // SLO* (undocumented) - case 0x18: CLC(); return 2; // CLC - case 0x19: ORA( src_abs_Y() ); return 4; // ORA abs,Y -// case 0x1A: // NOP* (undocumented) -// case 0x1B: // SLO* (undocumented) -// case 0x1C: // NOP* (undocumented) - case 0x1D: ORA( src_abs_X() ); return 4; // ORA abs,X - case 0x1E: ASL( addr_abs_X() ); return 7; // ASL abs,X -// case 0x1F: // SLO* (undocumented) - case 0x20: JSR( abs_addr() ); return 6; // JSR abs - case 0x21: AND( src_X_ind() ); return 6; // AND X,ind -// case 0x22: HLT* - Halts / Hangs / Jams / Kills the CPU (undocumented) -// case 0x23: RLA izx 8 - case 0x24: BIT( src_zp() ); return 3; // BIT zpg - case 0x25: AND( src_zp() ); return 3; // AND zpg - case 0x26: ROL( addr_zp() ); return 5; // ROL zpg -// case 0x27: RLA zp 5 - case 0x28: PLP(); return 4; // PLP - case 0x29: AND( imm() ); return 2; // AND imm - case 0x2A: ROLA(); return 2; // ROL A -// case 0x2B: ANC imm 2 - case 0x2C: BIT( src_abs() ); return 4; // BIT abs - case 0x2D: AND( src_abs() ); return 4; // AND abs - case 0x2E: ROL( addr_abs() ); return 6; // ROL abs -// case 0x2F: RLA abs 6 - case 0x30: BMI( rel_addr() ); return 3; // BMI rel - case 0x31: AND( src_ind_Y() ); return 5; // AND ind,Y -// case 0x32: HLT* - Halts / Hangs / Jams / Kills the CPU (undocumented) -// case 0x33: RLA izy 8 -// case 0x34: NOP zpx 4 - case 0x35: AND( src_zp_X() ); return 4; // AND zpg,X - case 0x36: ROL( addr_zp_X() ); return 6; // ROL zpg,X -// case 0x37: RLA zpx 6 - case 0x38: SEC(); return 2; // SEC - case 0x39: AND( src_abs_Y() ); return 4; // AND abs,Y -// case 0x3A: NOP 2 -// case 0x3B: RLA aby 7 -// case 0x3C: NOP abx 4 - case 0x3D: AND( src_abs_X() ); return 4; // AND abs,X - case 0x3E: ROL( addr_abs_X() ); return 7; // ROL abs,X -// case 0x3F: RLA abx 7 - case 0x40: RTI(); return 6; // RTI - case 0x41: EOR( src_X_ind() ); return 6; // EOR X,ind -// case 0x42: HLT* - Halts / Hangs / Jams / Kills the CPU (undocumented) -// case 0x43: SRE izx 8 -// case 0x44: NOP zp 3 - case 0x45: EOR( src_zp() ); return 3; // EOR zpg - case 0x46: LSR( addr_zp() ); return 5; // LSR zpg -// case 0x47: SRE zp 5 - case 0x48: PHA(); return 3; // PHA - case 0x49: EOR( imm() ); return 2; // EOR imm - case 0x4A: LSRA(); return 2; // LSR A -// case 0x4B: ALR imm 2 - case 0x4C: JMP( abs_addr() ); return 3; // JMP abs - case 0x4D: EOR( src_abs() ); return 4; // EOR abs - case 0x4E: LSR( addr_abs() ); return 6; // LSR abs -// case 0x4F: SRE abs 6 - case 0x50: BVC( rel_addr() ); return 3; // BVC rel - case 0x51: EOR( src_ind_Y() ); return 5; // EOR ind,Y -// case 0x52: HLT* - Halts / Hangs / Jams / Kills the CPU (undocumented) -// case 0x53: SRE izy 8 -// case 0x54: NOP zpx 4 - case 0x55: EOR( src_zp_X() ); return 4; // AND zpg,X - case 0x56: LSR( addr_zp_X() ); return 6; // LSR zpg,X -// case 0x57: SRE zpx 6 - case 0x58: CLI(); return 2; // CLI - case 0x59: EOR( src_abs_Y() ); return 4; // EOR abs,Y -// case 0x5A: NOP 2 -// case 0x5B: SRE aby 7 -// case 0x5C: NOP abx 4 - case 0x5D: EOR( src_abs_X() ); return 4; // EOR abs,X - case 0x5E: LSR( addr_abs_X() ); return 7; // LSR abs,X -// case 0x5F: SRE abx 7 - case 0x60: RTS(); return 6; // RTS - case 0x61: ADC( src_X_ind() ); return 6; // ADC X,ind -// case 0x62: HLT* - Halts / Hangs / Jams / Kills the CPU (undocumented) -// case 0x63: RRA izx 8 -// case 0x64: NOP zp 3 - case 0x65: ADC( src_zp() ); return 3; // ADC zpg - case 0x66: ROR( addr_zp() ); return 5; // ROR zpg -// case 0x67: RRA zp 5 - case 0x68: PLA(); break; // PLA - case 0x69: ADC( imm() ); return 2; // ADC imm - case 0x6A: RORA(); return 2; // ROR A -// case 0x6B: ARR imm 2 - case 0x6C: JMP( ind_addr() ); return 5; // JMP ind - case 0x6D: ADC( src_abs() ); return 4; // ADC abs - case 0x6E: ROR( addr_abs() ); return 6; // ROR abs -// case 0x6F: RRA abs 6 - case 0x70: BVS( rel_addr() ); return 3; // BVS rel - case 0x71: ADC( src_ind_Y() ); return 5; // ADC ind,Y -// case 0x72: -// case 0x73: -// case 0x74: - case 0x75: ADC( src_zp_X() ); return 4; // ADC zpg,X - case 0x76: ROR( addr_zp_X() ); return 6; // ROR zpg,X -// case 0x77: - case 0x78: SEI(); return 2; // SEI - case 0x79: ADC( src_abs_Y() ); return 4; // ADC abs,Y -// case 0x7A: -// case 0x7B: -// case 0x7C: - case 0x7D: ADC( src_abs_X() ); return 4; // ADC abs,X - case 0x7E: ROR( addr_abs_X() ); return 7; // ROR abs,X -// case 0x7F: -// case 0x80: - case 0x81: STA( addr_X_ind() ) ; return 6; // STA X,ind -// case 0x82: -// case 0x83: - case 0x84: STY( addr_zp() ); return 3; // STY zpg - case 0x85: STA( addr_zp() ); return 3; // STA zpg - case 0x86: STX( addr_zp() ); return 3; // STX zpg -// case 0x87: - case 0x88: DEY(); return 2; // DEY -// case 0x89: NOP(); imm(); return 4; // NOP imm - case 0x8A: TXA(); return 2; // TXA -// case 0x8B: - case 0x8C: STY( addr_abs() ); return 4; // STY abs - case 0x8D: STA( addr_abs() ); return 4; // STA abs - case 0x8E: STX( addr_abs() ); return 4; // STX abs -// case 0x8F: - case 0x90: BCC( rel_addr() ); return 3; // BCC rel - case 0x91: STA( addr_ind_Y() ); return 6; // STA ind,Y -// case 0x92: -// case 0x93: - case 0x94: STY( addr_zp_X() ); return 4; // STY zpg,X - case 0x95: STA( addr_zp_X() ); return 4; // STA zpg,X - case 0x96: STX( addr_zp_Y() ); return 4; // STX zpg,Y -// case 0x97: - case 0x98: TYA(); return 2; // TYA - case 0x99: STA( addr_abs_Y() ); return 5; // STA abs,Y - case 0x9A: TXS(); return 2; // TXS -// case 0x9B: -// case 0x9C: - case 0x9D: STA( addr_abs_X() ); return 5; // STA abs,X -// case 0x9E: -// case 0x9F: - case 0xA0: LDY( imm() ); return 2; // LDY imm - case 0xA1: LDA( src_X_ind() ) ; return 6; // LDA X,ind - case 0xA2: LDX( imm() ); return 2; // LDX imm -// case 0xA3: - case 0xA4: LDY( src_zp() ); return 3; // LDY zpg - case 0xA5: LDA( src_zp() ); return 3; // LDA zpg - case 0xA6: LDX( src_zp() ); return 3; // LDX zpg -// case 0xA7: - case 0xA8: TAY(); return 2; // TAY - case 0xA9: LDA( imm() ); return 2; // LDA imm - case 0xAA: TAX(); return 2; // TAX -// case 0xAB: - case 0xAC: LDY( src_abs() ); return 4; // LDY abs - case 0xAD: LDA( src_abs() ); return 4; // LDA abs - case 0xAE: LDX( src_abs() ); return 4; // LDX abs -// case 0xAF: - case 0xB0: BCS( rel_addr() ); return 3; // BCS rel - case 0xB1: LDA( src_ind_Y() ); return 5; // LDA ind,Y -// case 0xB2: -// case 0xB3: - case 0xB4: LDY( src_zp_X() ); return 4; // LDY zpg,X - case 0xB5: LDA( src_zp_X() ); return 4; // LDA zpg,X - case 0xB6: LDX( src_zp_Y() ); return 4; // LDX zpg,Y -// case 0xB7: - case 0xB8: CLV(); return 2; // CLV - case 0xB9: LDA( src_abs_Y() ); return 4; // LDA abs,Y - case 0xBA: TSX(); return 2; // TSX -// case 0xBB: - case 0xBC: LDY( src_abs_X() ); return 4; // LDY abs,X - case 0xBD: LDA( src_abs_X() ); return 4; // LDA abs,X - case 0xBE: LDX( src_abs_Y() ); return 4; // LDX abs,Y -// case 0xBF: - case 0xC0: CPY( imm() ); return 2; // CPY imm - case 0xC1: CMP( src_X_ind() ) ; return 6; // LDA X,ind -// case 0xC2: -// case 0xC3: - case 0xC4: CPY( src_zp() ); return 3; // CPY zpg - case 0xC5: CMP( src_zp() ); return 3; // CMP zpg - case 0xC6: DEC( addr_zp() ); return 5; // DEC zpg -// case 0xC7: - case 0xC8: INY(); return 2; // INY - case 0xC9: CMP( imm() ); return 2; // CMP imm - case 0xCA: DEX(); return 2; // DEX -// case 0xCB: - case 0xCC: CPY( src_abs() ); return 4; // CPY abs - case 0xCD: CMP( src_abs() ); return 4; // CMP abs - case 0xCE: DEC( addr_abs() ); return 6; // DEC abs -// case 0xCF: - case 0xD0: BNE( rel_addr() ); return 3; // BNE rel - case 0xD1: CMP( src_ind_Y() ); return 5; // CMP ind,Y -// case 0xD2: -// case 0xD3: -// case 0xD4: - case 0xD5: CMP( src_zp_X() ); return 4; // CMP zpg,X - case 0xD6: DEC( addr_zp_X() ); return 6; // DEC zpg,X -// case 0xD7: - case 0xD8: CLD(); return 2; // CLD - case 0xD9: CMP( src_abs_Y() ); return 4; // CMP abs,Y -// case 0xDA: -// case 0xDB: -// case 0xDC: - case 0xDD: CMP( src_abs_X() ); return 4; // CMP abs,X - case 0xDE: DEC( addr_abs_X() ); return 7; // DEC abs,X -// case 0xDF: - case 0xE0: CPX( imm() ); return 2; // CPX imm - case 0xE1: SBC( src_X_ind() ) ; return 6; // SBC (X,ind) -// case 0xE2: -// case 0xE3: - case 0xE4: CPX( src_zp() ); return 3; // CPX zpg - case 0xE5: SBC( src_zp() ); return 3; // SBC zpg - case 0xE6: INC( addr_zp() ); return 5; // INC zpg -// case 0xE7: - case 0xE8: INX(); return 2; // INX - case 0xE9: SBC( imm() ); return 2; // SBC imm - case 0xEA: NOP(); return 2; // NOP -// case 0xEB: - case 0xEC: CPX( src_abs() ); return 4; // CPX abs - case 0xED: SBC( src_abs() ); return 4; // SBC abs - case 0xEE: INC( addr_abs() ); return 6; // INC abs -// case 0xEF: - case 0xF0: BEQ( rel_addr() ); return 3; // BEQ rel - case 0xF1: SBC( src_ind_Y() ); return 5; // SBC ind,Y -// case 0xF2: -// case 0xF3: -// case 0xF4: - case 0xF5: SBC( src_zp_X() ); return 4; // SBC zpg,X - case 0xF6: INC( addr_zp_X() ); return 6; // INC zpg,X -// case 0xF7: - case 0xF8: SED(); return 2; // SED - case 0xF9: SBC( src_abs_Y() ); return 4; // SBC abs,Y -// case 0xFA: -// case 0xFB: -// case 0xFC: - case 0xFD: SBC( src_abs_X() ); return 4; // SBC abs,X - case 0xFE: INC( addr_abs_X() ); return 7; // INC abs,X -// case 0xFF: - + +#include "6502_std.h" // standard instructions +#include "6502_C.h" // 65"C"02 extended instructions + default: dbgPrintf("%04X: Unimplemented Instruction 0x%02X\n", m6502.PC -1, memread( m6502.PC -1 )); return 2; } -// } // fetch16 + // } // fetch16 return 2; } @@ -717,22 +292,24 @@ void hardReset() { } void softReset() { -// m6502.PC = memread16(SOFTRESET_VECTOR); + // m6502.PC = memread16(SOFTRESET_VECTOR); m6502.PC = memread16( RESET_VECTOR ); m6502.SP = 0xFF; // N V - B D I Z C // 0 0 1 0 0 1 0 1 setFlags(0x25); + + spkr_stopAll(); } void m6502_Run() { // init time -//#ifdef CLK_WAIT -// unsigned long long elpased = (unsigned long long)-1LL; -//#endif - + //#ifdef CLK_WAIT + // unsigned long long elpased = (unsigned long long)-1LL; + //#endif + #ifdef SPEEDTEST for ( inst_cnt = 0; inst_cnt < iterations ; inst_cnt++ ) #elif defined( CLK_WAIT ) @@ -740,44 +317,48 @@ void m6502_Run() { // we will also use this to pause the simulation if not finished by the end of the frame for ( clk_6502_per_frm_max = clk_6502_per_frm; clkfrm < clk_6502_per_frm_max ; clkfrm += m6502_Step() ) #else - // this is for max speed only -- WARNING! It works only if simulation runs in a completely different thread from the Update() - for ( ; ; ) + // this is for max speed only -- WARNING! It works only if simulation runs in a completely different thread from the Update() + for ( ; ; ) #endif - { - + { + + // TODO: clkfrm is already increamented!!! + printDisassembly(outdev); + #ifdef INTERRUPT_CHECK_PER_STEP - if ( m6502.IF ) { - switch (m6502.interrupt) { - case HALT: - // CPU is haletd, nothing to do here... - return; + if ( m6502.IF ) { + switch (m6502.interrupt) { + case HALT: + // CPU is haletd, nothing to do here... + return; + + case IRQ: + interrupt_IRQ(); + break; + + case NMI: + interrupt_NMI(); + break; + + case HARDRESET: + hardReset(); + break; + + case SOFTRESET: + softReset(); + break; + + default: + break; + } - case IRQ: - interrupt_IRQ(); - break; - - case NMI: - interrupt_NMI(); - break; - - case HARDRESET: - hardReset(); - break; - - case SOFTRESET: - softReset(); - break; - - default: - break; - } - - m6502.IF = 0; - } + m6502.IF = 0; + } #endif // INTERRUPT_CHECK_PER_STEP - - } + + } + // TODO: WHat if we dynamically reduce or increace CPU speed? m6502.clktime += clk_6502_per_frm; if( diskAccelerator_count ) { @@ -787,9 +368,11 @@ void m6502_Run() { clk_6502_per_frm = clk_6502_per_frm_set; } } - + // play the entire sound buffer for this frame spkr_update(); + // this will take care of turning off disk motor sound when time is up + spkr_update_disk_sfx(); } void read_rom( const char * bundlePath, const char * filename, uint8_t * rom, const uint16_t addr ) { @@ -799,7 +382,7 @@ void read_rom( const char * bundlePath, const char * filename, uint8_t * rom, co strcpy( fullPath, bundlePath ); strcat( fullPath, "/"); strcat( fullPath, filename ); - + FILE * f = fopen(fullPath, "rb"); if (f == NULL) { perror("Failed to read ROM: "); @@ -809,10 +392,10 @@ void read_rom( const char * bundlePath, const char * filename, uint8_t * rom, co fseek(f, 0L, SEEK_END); uint16_t flen = ftell(f); fseek(f, 0L, SEEK_SET); - + fread( rom + addr, 1, flen, f); fclose(f); - + } @@ -826,7 +409,7 @@ size_t getFileSize ( const char * fullPath ) { fseek(f, 0L, SEEK_END); size_t flen = ftell(f); fseek(f, 0L, SEEK_SET); - + fclose(f); return flen; @@ -839,7 +422,7 @@ void rom_loadFile( const char * bundlePath, const char * filename ) { strcpy( fullPath, bundlePath ); strcat( fullPath, "/"); strcat( fullPath, filename ); - + size_t flen = getFileSize(fullPath); if ( flen == 0 ) { @@ -855,17 +438,33 @@ void rom_loadFile( const char * bundlePath, const char * filename ) { read_rom( bundlePath, filename, Apple2_16K_ROM, 0x1000); memcpy(Apple2_64K_MEM + 0xD000, Apple2_16K_ROM + 0x1000, 12 * KB); } + +} + +void openLog() { +#ifdef DISASSEMBLY + outdev = fopen("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/disassembly_new.log", "w+"); +#endif + // for DEBUG ONLY!!! -- use stdout if could not create log file + // if (outdev == NULL) { + // outdev = stdout; + // } +} + + +void closeLog() { + if ( ( outdev ) && ( outdev != stdout ) && ( outdev != stderr ) ) { + fclose(outdev); + } } void m6502_ColdReset( const char * bundlePath, const char * romFileName ) { inst_cnt = 0; - mhz = (double)MHz_6502 / M; spkr_init(); - unsigned long long saved_frm_set = clk_6502_per_frm_set; clk_6502_per_frm = clk_6502_per_frm_max = clk_6502_per_frm_set = 0; @@ -873,35 +472,22 @@ void m6502_ColdReset( const char * bundlePath, const char * romFileName ) { // wait 100ms to be sure simulation has been halted usleep(100000); - printf("Bundlepath: %s\n", bundlePath); - -// epoch = rdtsc(); -// sleep(1); -// unsigned long long e = rdtsc(); -// tick_per_sec = e - epoch; -// tick_6502_per_sec = tick_per_sec / MHz_6502; - + // printf("Bundlepath: %s\n", bundlePath); + + // epoch = rdtsc(); + // sleep(1); + // unsigned long long e = rdtsc(); + // tick_per_sec = e - epoch; + // tick_6502_per_sec = tick_per_sec / MHz_6502; + resetMemory(); - - outdev = fopen("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/disassembly_new.log", "w+"); - if (outdev == NULL) { - outdev = stdout; - } - - + #ifdef FUNCTIONTEST - FILE * f = fopen("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/6502_functional_test.bin", "rb"); - if (f == NULL) { - perror("Failed: "); - return; - } - - fread( RAM, 1, 65536, f); - fclose(f); + read_rom( bundlePath, "6502_functional_test.bin", Apple2_64K_RAM, 0); + memcpy(Apple2_64K_MEM, Apple2_64K_RAM, 65536); m6502.PC = 0x400; - #else // Apple ][+ ROM @@ -911,7 +497,7 @@ void m6502_ColdReset( const char * bundlePath, const char * romFileName ) { read_rom( bundlePath, "DISK_II_C600.ROM", Apple2_64K_RAM, 0xC600); memcpy(Apple2_64K_MEM + 0xC600, Apple2_64K_RAM + 0xC600, 0x100); -// read_rom( "/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/", "DISK_II_C600.ROM", Apple2_64K_MEM, 0xC600); + // read_rom( "/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/", "DISK_II_C600.ROM", Apple2_64K_MEM, 0xC600); m6502.A = m6502.X = m6502.Y = 0xFF; // reset vector @@ -925,30 +511,30 @@ void m6502_ColdReset( const char * bundlePath, const char * romFileName ) { // memory size //*((uint16_t*)(&RAM[0x73])) = 0xC000; - + m6502.PC = memread16( RESET_VECTOR ); #endif uint8_t counter[] = { - // 1 * COUNTER2 - // 2 - // 3 ORG $1000 - // 4 SCREEN EQU $400 - // 5 HOME EQU $FC58 - // 6 DIGITS EQU $06 - // 7 ZERO EQU $B0 - // 8 CARRY EQU $BA - // 9 RDKEY EQU $FD0C - //10 - + // 1 * COUNTER2 + // 2 + // 3 ORG $1000 + // 4 SCREEN EQU $400 + // 5 HOME EQU $FC58 + // 6 DIGITS EQU $06 + // 7 ZERO EQU $B0 + // 8 CARRY EQU $BA + // 9 RDKEY EQU $FD0C + //10 + // I have placed NOP to keep addresses 0xA0, 0x09, 0xEA, //11 LDY #$09 ; NOP 0x84, 0x06, //12 STY #DIGITS 0xEA, 0xEA, //13 NOP NOP 0xEA, 0xEA, 0xEA, //14 NOP NOP NOP - + 0xA6, 0x06, //15 LDY DIGITS 0xA9, 0xB0, //16 CLEAR LDA #ZERO 0x99, 0x00, 0x04, //17 STA SCREEN,Y @@ -973,7 +559,7 @@ void m6502_ColdReset( const char * bundlePath, const char * romFileName ) { 0x4C, 0x20, 0x10, //33 JMP NEXT 0x60, //34 END RTS - + 0xB9, 0x00, 0x04, //36 INC LDA SCREEN,Y 0xAA, //37 TAX 0xE8, //38 INX @@ -981,7 +567,7 @@ void m6502_ColdReset( const char * bundlePath, const char * romFileName ) { 0x99, 0x00, 0x04, //40 STA SCREEN,Y 0x60, //41 RTS }; - + uint8_t counter_fast[] = { // 1 * COUNTER2 @@ -994,7 +580,7 @@ void m6502_ColdReset( const char * bundlePath, const char * romFileName ) { // 8 CARRY EQU $BA // 9 RDKEY EQU $FD0C //10 - + // I have placed NOP to keep addresses 0xA0, 0x06, // 00 LDY #$09 @@ -1027,11 +613,17 @@ void m6502_ColdReset( const char * bundlePath, const char * romFileName ) { 0x60, // 2E END RTS }; - - + + // set the default speed - clk_6502_per_frm_set = clk_6502_per_frm = default_MHz_6502 / fps; - + clk_6502_per_frm_set = clk_6502_per_frm = FRAME(default_MHz_6502); + + + // Initialize Paddle / Game Controller / Joystick / Mouse Buttons + setIO(0xC061, 0); + setIO(0xC062, 0); + setIO(0xC063, 1 << 7); // inverted (bit 7: not pressed) + } @@ -1042,7 +634,7 @@ void tst6502() { m6502_ColdReset( "", "" ); // clock_t start = clock(); -// epoch = rdtsc(); + // epoch = rdtsc(); m6502_Run(); // clock_t end = clock(); // double execution_time = ((double) (end - start)) / CLOCKS_PER_SEC; @@ -1055,7 +647,7 @@ void tst6502() { double mips = inst_cnt / (execution_time * M); double mhz = m6502.clktime / (execution_time * M); printf("clk:%llu Elpased time: (%llu / %u / %llu), %.3lfs (%.3lf MIPS, %.3lf MHz)\n", iterations *3, tick_per_sec, MHz_6502, tick_6502_per_sec, execution_time, mips, mhz); -// printf(" dd:%llu ee:%llu nn:%llu\n", dd, ee, ee - dd); + // printf(" dd:%llu ee:%llu nn:%llu\n", dd, ee, ee - dd); #endif } diff --git a/src/cpu/instructions/6502_instr_compare_test.h b/src/cpu/instructions/6502_instr_compare_test.h index ee432c8..0aa6c0b 100644 --- a/src/cpu/instructions/6502_instr_compare_test.h +++ b/src/cpu/instructions/6502_instr_compare_test.h @@ -46,6 +46,62 @@ INLINE void BIT( uint8_t src ) { set_flags_Z(m6502.A & src); } +/** + TRB - Test and Reset Bits + + TRB can be one the more confusing instructions for a couple of reasons. + + First, the term reset is used to refer to the clearing of a bit, whereas the term clear had been used consistently before, such as CLC + which stands for CLear Carry. Second, the effect on the Z flag is determined by a different function than the effect on memory. + + TRB has the same effect on the Z flag that a BIT instruction does. Specifically, it is based on whether the result of a bitwise AND of the + accumulator with the contents of the memory location specified in the operand is zero. Also, like BIT, the accumulator is not affected. + + The accumulator determines which bits in the memory location specified in the operand are cleared and which are not affected. + The bits in the accumulator that are ones are cleared (in memory), and the bits that are zeros (in the accumulator) are not affected (in memory). + This is the same as saying that the resulting memory contents are the bitwise AND of the memory contents with the complement of the + accumulator (i.e. the exclusive-or of the accululator with $FF). + + OP LEN CYC MODE FLAGS SYNTAX + -- --- --- ---- ----- ------ + 14 2 5 zp ......Z. TRB $12 + 1C 3 6 abs ......Z. TRB $3456 + + **/ +INLINE void TRB( uint16_t addr ) { + dbgPrintf("TRB(%02X) ", src); + disPrintf(disassembly.inst, "TRB"); + set_flags_Z( WRLOMEM[addr] & m6502.A ); + WRLOMEM[addr] &= ~m6502.A; +} + +/** + TSB - Test and Set Bits + + TSB, like TRB, can be confusing. For one, like TRB, the effect on the Z flag is determined by a different function than the effect on memory. + + TSB, like TRB, has the same effect on the Z flag that a BIT instruction does. Specifically, it is based on whether the result of a bitwise AND + of the accumulator with the contents of the memory location specified in the operand is zero. Also, like BIT (and TRB), the accumulator is not affected. + + The accumulator determines which bits in the memory location specified in the operand are set and which are not affected. The bits in the + accumulator that are ones are set to one (in memory), and the bits that are zeros (in the accumulator) are not affected (in memory). + This is the same as saying that the resulting memory contents are the bitwise OR of the memory contents with the accumulator. + + Flags affected: Z + + OP LEN CYC MODE FLAGS SYNTAX + -- --- --- ---- ----- ------ + 04 2 5 zp ......Z. TSB $12 + 0C 3 6 abs ......Z. TSB $3456 + + **/ +INLINE void TSB( uint16_t addr ) { + dbgPrintf("TSB(%02X) ", src); + disPrintf(disassembly.inst, "TSB"); + set_flags_Z( WRLOMEM[addr] & m6502.A ); + WRLOMEM[addr] |= m6502.A; +} + /** CMP Compare Memory with Accumulator diff --git a/src/cpu/instructions/6502_instr_inc_dec.h b/src/cpu/instructions/6502_instr_inc_dec.h index 9e6f469..d993786 100644 --- a/src/cpu/instructions/6502_instr_inc_dec.h +++ b/src/cpu/instructions/6502_instr_inc_dec.h @@ -80,6 +80,23 @@ INLINE void INY() { dbgPrintf("%02X ", m6502.Y); } +/** + INA Increment Accumulator by One + + A + 1 -> A N Z C I D V + + + - - - - + + addressing assembler opc bytes cyles + -------------------------------------------- + implied INA C8 1 2 + **/ +INLINE void INA() { + dbgPrintf("INA %02X -> ", m6502.A); + disPrintf(disassembly.inst, "INA"); + set_flags_NZ( ++m6502.A ); + dbgPrintf("%02X ", m6502.A); +} + /** DEC Decrement Memory by One @@ -135,5 +152,22 @@ INLINE void DEY() { dbgPrintf("%02X ", m6502.Y); } +/** + DEA Decrement Accumulator by One + + A - 1 -> A N Z C I D V + + + - - - - + +addressing assembler opc bytes cyles +-------------------------------------------- +implied DEC 88 1 2 +**/ +INLINE void DEA() { + dbgPrintf("DEA %02X -> ", m6502.A); + disPrintf(disassembly.inst, "DEA"); + set_flags_NZ( --m6502.A ); + dbgPrintf("%02X ", m6502.A); +} + #endif // __6502_INSTR_INC_DEC_H__ diff --git a/src/cpu/instructions/6502_instr_load_store.h b/src/cpu/instructions/6502_instr_load_store.h index 94fffc7..1eab500 100644 --- a/src/cpu/instructions/6502_instr_load_store.h +++ b/src/cpu/instructions/6502_instr_load_store.h @@ -168,5 +168,24 @@ INLINE void STY( uint16_t addr ) { STR(addr, m6502.Y); } +/** + STZ Store Zero (0) in Memory + + 0 -> M N Z C I D V + - - - - - - + + OP LEN CYC MODE FLAGS SYNTAX + -- --- --- ---- ----- ------ + 64 2 3 zp ........ STZ $12 + 74 2 4 zp,X ........ STZ $12,X + 9C 3 4 abs ........ STZ $3456 + 9E 3 5 abs,X ........ STZ $3456,X +**/ +INLINE void STZ( uint16_t addr ) { + dbgPrintf("STZ "); + disPrintf(disassembly.inst, "STZ"); + STR(addr, 0); +} + #endif // __6502_INSTR_LOAD_STORE_H__ diff --git a/src/cpu/instructions/6502_instr_stack.h b/src/cpu/instructions/6502_instr_stack.h index 5904502..d6a30f2 100644 --- a/src/cpu/instructions/6502_instr_stack.h +++ b/src/cpu/instructions/6502_instr_stack.h @@ -63,6 +63,38 @@ INLINE void PHA() { PUSH( m6502.A ); } +/** + PHX Push index X on Stack + + push X N Z C I D V + - - - - - - + + addressing assembler opc bytes cyles + -------------------------------------------- + implied PHX 48 1 3 + **/ +INLINE void PHX() { + dbgPrintf("PHX %02X ", m6502.X); + disPrintf(disassembly.inst, "PHX"); + PUSH( m6502.X ); +} + +/** + PHY Push index Y on Stack + + push Y N Z C I D V + - - - - - - + + addressing assembler opc bytes cyles + -------------------------------------------- + implied PHY 48 1 3 + **/ +INLINE void PHY() { + dbgPrintf("PHY %02X ", m6502.Y); + disPrintf(disassembly.inst, "PHY"); + PUSH( m6502.Y ); +} + /** PLA Pull Accumulator from Stack @@ -80,6 +112,40 @@ INLINE void PLA() { set_flags_NZ( m6502.A ); } +/** + PLX Pull index X from Stack + + pull X N Z C I D V + + + - - - - + + addressing assembler opc bytes cyles + -------------------------------------------- + implied PLX 68 1 4 + **/ +INLINE void PLX() { + m6502.X = POP(); + dbgPrintf("PLX %02X ", m6502.X); + disPrintf(disassembly.inst, "PLX"); + set_flags_NZ( m6502.X ); +} + +/** + PLY Pull index Y from Stack + + pull Y N Z C I D V + + + - - - - + + addressing assembler opc bytes cyles + -------------------------------------------- + implied PLY 68 1 4 + **/ +INLINE void PLY() { + m6502.Y = POP(); + dbgPrintf("PLY %02X ", m6502.Y); + disPrintf(disassembly.inst, "PLY"); + set_flags_NZ( m6502.Y ); +} + /** PHP Push Processor Status on Stack diff --git a/src/dev/mem/mmio.h b/src/dev/mem/mmio.h index eec40f3..0f7b96f 100644 --- a/src/dev/mem/mmio.h +++ b/src/dev/mem/mmio.h @@ -1396,6 +1396,13 @@ INLINE uint8_t src_zp_Y() { // return WRLOMEM + addr_zp_Y(); //} +/** + (zpg) .... zeropage OPC $LL + operand is zeropage address; + **/ +INLINE uint8_t src_zp_0() { + return memread8_low(addr_zp()); +} #endif // __APPLE2_MMIO_H__