diff --git a/A2Mac/Base.lproj/Main.storyboard b/A2Mac/Base.lproj/Main.storyboard index 6d444b5..e636126 100644 --- a/A2Mac/Base.lproj/Main.storyboard +++ b/A2Mac/Base.lproj/Main.storyboard @@ -921,13 +921,13 @@ - + - + diff --git a/A2Mac/ViewController.swift b/A2Mac/ViewController.swift index 70588f9..58c132c 100644 --- a/A2Mac/ViewController.swift +++ b/A2Mac/ViewController.swift @@ -98,7 +98,7 @@ class ViewController: NSViewController { static var charConvTbl = charConvTblFlashOn - static var romFileName = "Apple2e.rom"; + static var romFileName = "Apple2e_Enhanced.rom"; static let textLineOfs : [Int] = [ 0x000, 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, 0x028, 0x0A8, 0x128, 0x1A8, diff --git a/src/cpu/6502.c b/src/cpu/6502.c index 3e845dd..1d13d07 100644 --- a/src/cpu/6502.c +++ b/src/cpu/6502.c @@ -5,6 +5,13 @@ // Created by Tamas Rudnai on 7/14/19. // Copyright © 2019 GameAlloy. All rights reserved. // +// 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 @@ -407,7 +414,7 @@ INLINE int m6502_Step() { case 0x01: ORA( src_X_ind() ); return 6; // ORA X,ind case 0x02: KIL(); return 0; // KIL - Hangs the CPU // t jams case 0x03: SLO( addr_zp_X() ); return 8; // SLO* zpg,X (undocumented) - case 0x04: NOP2( src_zp() ); return 3; // NOP* zpg (undocumented) + case 0x04: NOP(); src_zp(); return 3; // NOP* zpg (undocumented) case 0x05: ORA( src_zp() ); return 3; // ORA zpg case 0x06: ASL( addr_zp() ); return 5; // ASL zpg case 0x07: SLO( addr_zp() ); return 5; // SLO* zpg (undocumented) @@ -415,7 +422,7 @@ INLINE int m6502_Step() { case 0x09: ORA( imm() ); return 2; // ORA imm case 0x0A: ASLA(); return 2; // ASL A case 0x0B: ANC( imm() ); return 2; // ANC** imm (undocumented) - case 0x0C: NOP2( src_abs() ); return 4; // NOP* (undocumented) + case 0x0C: NOP(); src_abs(); return 4; // NOP* (undocumented) case 0x0D: ORA( src_abs() ); return 4; // ORA abs case 0x0E: ASL( addr_abs() ); return 6; // ASL abs case 0x0F: SLO( addr_abs() ); return 6; // SLO* (undocumented) @@ -423,7 +430,7 @@ INLINE int m6502_Step() { case 0x11: ORA( src_ind_Y() ); return 5; // ORA ind,Y case 0x12: KIL(); return 0; // KIL - Hangs the CPU // t jams case 0x13: SLO( addr_zp_Y() ); return 8; // SLO* zpg,Y (undocumented) - case 0x14: NOP2( addr_zp_X() ); return 4; // NOP* zpg,X (undocumented) + case 0x14: NOP(); addr_zp_X(); return 4; // NOP* zpg,X (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( addr_zp_X() ); return 6; // SLO* zpg,X (undocumented) @@ -431,7 +438,7 @@ INLINE int m6502_Step() { case 0x19: ORA( src_abs_Y() ); return 4; // ORA abs,Y case 0x1A: NOP(); return 2; // NOP* (undocumented) case 0x1B: SLO( addr_abs_Y() ); return 7; // SLO* abs,Y (undocumented) - case 0x1C: NOP2( src_abs_X() ); return 4; // NOP* (undocumented) + case 0x1C: NOP(); src_abs_X(); return 4; // 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( addr_abs_X() ); return 7; // SLO* abs,X (undocumented) @@ -455,7 +462,7 @@ INLINE int m6502_Step() { case 0x31: AND( src_ind_Y() ); return 5; // AND ind,Y case 0x32: KIL(); return 0; // KIL - Hangs the CPU case 0x33: RLA( addr_ind_Y() ); return 8; // RLA* izy 8 (undocumented) - case 0x34: NOP2( src_zp_X() ); return 4; // NOP* zpx 4 (undocumented) + case 0x34: NOP(); src_zp_X(); return 4; // NOP* zpx 4 (undocumented) 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( addr_zp_X() ); return 6; // RLA* zpx 6 (undocumented) @@ -463,7 +470,7 @@ INLINE int m6502_Step() { case 0x39: AND( src_abs_Y() ); return 4; // AND abs,Y case 0x3A: NOP(); return 2; // NOP* 2 (undocumented) case 0x3B: RLA( addr_abs_Y() ); return 7; // RLA* aby 7 (undocumented) - case 0x3C: NOP2( src_abs_X() ); return 4; // NOP* abx 4 (undocumented) + case 0x3C: NOP(); src_abs_X(); return 4; // NOP* abx 4 (undocumented) 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( addr_abs_X() ); return 7; // RLA* abx 7 (undocumented) @@ -487,7 +494,7 @@ INLINE int m6502_Step() { case 0x51: EOR( src_ind_Y() ); return 5; // EOR ind,Y case 0x52: KIL(); return 0; // KIL - Hangs the CPU case 0x53: SRE( addr_ind_Y() ); return 8; // SRE* izy 8 (undocumented) - case 0x54: NOP2( src_zp_X() ); return 4; // NOP* zpx 4 (undocumented) + case 0x54: NOP(); src_zp_X(); return 4; // NOP* zpx 4 (undocumented) 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( addr_ind_X() ); return 6; // SRE* zpx 6 (undocumented) @@ -495,170 +502,170 @@ INLINE int m6502_Step() { case 0x59: EOR( src_abs_Y() ); return 4; // EOR abs,Y case 0x5A: NOP(); return 2; // NOP* 2 (undocumented) case 0x5B: SRE( addr_abs_Y() ); return 7; // SRE* aby 7 (undocumented) - case 0x5C: NOP2( src_abs_X() ); return 4; // NOP* abx 4 (undocumented) + case 0x5C: NOP(); src_abs_X(); return 4; // NOP* abx 4 (undocumented) 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( addr_abs_X() ); return 7; // SRE* abx 7 (undocumented) case 0x60: RTS(); return 6; // RTS case 0x61: ADC( src_X_ind() ); return 6; // ADC X,ind case 0x62: KIL(); return 0; // KIL - Hangs the CPU -// case 0x63: RRA izx 8 + case 0x63: RRA( addr_ind_X() ); return 8; // RRA* izx 8 (undocumented) case 0x64: NOP(); return 3; // NOP* zp 3 (undocumented) case 0x65: ADC( src_zp() ); return 3; // ADC zpg case 0x66: ROR( addr_zp() ); return 5; // ROR zpg -// case 0x67: RRA zp 5 + case 0x67: RRA( addr_zp() ); return 5; // RRA* zp 5 (undocumented) 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 0x6B: ARC( imm() ); return 2; // ARR/ARC* imm 2 (undocumented) 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 0x6F: RRA( abs_addr() ); return 6; // RRA* abs 6 (undocumented) 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 0x72: KIL(); return 0; // KIL - Hangs the CPU + case 0x73: RRA( addr_ind_Y() ); return 8; // RRA* izy 8 (undocumented) + case 0x74: NOP(); src_zp_X(); return 4; // NOP* zpx 4 (undocumented) 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 0x77: RRA( addr_zp_X() ); return 6; // RRA* zpx 6 (undocumented) case 0x78: SEI(); return 2; // SEI case 0x79: ADC( src_abs_Y() ); return 4; // ADC abs,Y -// case 0x7A: -// case 0x7B: -// case 0x7C: + case 0x7A: NOP(); return 2; // NOP* 2 (undocumented) + case 0x7B: RRA( addr_abs_Y() ); return 7; // RRA* aby 7 (undocumented) + case 0x7C: NOP(); src_abs_X(); return 4; // NOP* abx 4 (undocumented) 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 0x7F: RRA( addr_abs_X() ); return 7; // RRA* abx 7 (undocumented) + case 0x80: NOP(); imm(); return 2; // NOP* imm 2 (undocumented) case 0x81: STA( addr_ind_X() ) ; return 6; // STA X,ind -// case 0x82: -// case 0x83: + case 0x82: NOP(); imm(); return 2; // NOP* imm 2 (undocumented) + case 0x83: SAX( addr_ind_X() ); return 6; // SAX* izx 6 (undocumented) 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 0x87: SAX( addr_zp() ); return 3; // SAX* izx 6 (undocumented) case 0x88: DEY(); return 2; // DEY -// case 0x89: NOP(); imm(); return 4; // NOP imm + case 0x89: NOP(); imm(); return 2; // NOP* imm (undocumented) case 0x8A: TXA(); return 2; // TXA -// case 0x8B: + case 0x8B: XAA( imm() ); return 2; // XAA* imm 2 (undocumented, highly unstable!) 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 0x8F: SAX( addr_abs() ); return 4; // SAX* abs 4 (undocumented) 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 0x92: KIL(); return 0; // KIL* (undocumented) + case 0x93: SHA( addr_ind_Y() ); return 6; // SHA* izy 6 (undocumented, unstable) 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 0x97: SAX( addr_zp_Y() ); return 4; // SAX* izy 4 (undocumented) 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 0x9B: SAS( addr_abs_Y() ); return 5; // SAS* aby 5 (undocumented, unstable) + case 0x9C: SHY( addr_abs_X() ); return 5; // SHY* abx 5 (undocumented, unstable) case 0x9D: STA( addr_abs_X() ); return 5; // STA abs,X -// case 0x9E: -// case 0x9F: + case 0x9E: SHX( addr_abs_Y() ); return 5; // SHX* aby 5 (undocumented, unstable) + case 0x9F: SAX( addr_abs_Y() ); return 5; // SAX* aby 5 (undocumented, unstable) 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 0xA3: LAX( src_X_ind() ); return 6; // LAX* izx 6 (undocumented) 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 0xA7: LAX( src_zp() ); return 3; // LAX* zpg 3 (undocumented) case 0xA8: TAY(); return 2; // TAY case 0xA9: LDA( imm() ); return 2; // LDA imm case 0xAA: TAX(); return 2; // TAX -// case 0xAB: + case 0xAB: LAX( imm() ); return 2; // LAX* imm 2 (undocumented, highly unstable) 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 0xAF: LAX( src_abs() ); return 4; // LAX* abs 4 (undocumented) 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 0xB2: KIL(); return 0; // KIL - Hangs the CPU // t jams + case 0xB3: LAX( src_ind_Y() ); return 5; // LAX* izy 5 (undocumented) 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 0xB7: LAX( src_zp_Y() ); return 4; // LAX* zpy 4 (undocumented) 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 0xBB: LAS( src_abs_Y() ); return 4; // LAX* aby 4 (undocumented) 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 0xBF: LAX( src_abs_Y() ); return 4; // LAX* aby 4 (undocumented) case 0xC0: CPY( imm() ); return 2; // CPY imm case 0xC1: CMP( src_X_ind() ) ; return 6; // LDA X,ind -// case 0xC2: -// case 0xC3: + case 0xC2: NOP(); imm(); return 2; // NOP* imm 2 (undocumented) + case 0xC3: DCP( addr_ind_X() ); return 8; // DCP* izx 8 (undocumented) 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 0xC7: DCP( addr_zp() ); return 5; // DCP* zpg 5 (undocumented) case 0xC8: INY(); return 2; // INY case 0xC9: CMP( imm() ); return 2; // CMP imm case 0xCA: DEX(); return 2; // DEX -// case 0xCB: + case 0xCB: SBX( imm() ); return 2; // SBX* imm 2 (undocumented) 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 0xCF: DCP( addr_abs() ); return 6; // DCP* abs 6 (undocumented) 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 0xD2: KIL(); return 0; // KIL - Hangs the CPU // t jams + case 0xD3: DCP( addr_ind_Y() ); return 8; // DCP* izy 8 (undocumented) + case 0xD4: NOP(); src_zp_X(); return 4; // NOP* zpx 4 (undocumented) 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 0xD7: DCP( addr_zp_X() ); return 6; // DCP* zpx 6 (undocumented) case 0xD8: CLD(); return 2; // CLD case 0xD9: CMP( src_abs_Y() ); return 4; // CMP abs,Y -// case 0xDA: -// case 0xDB: -// case 0xDC: + case 0xDA: NOP(); return 2; // NOP* 2 (undocumented) + case 0xDB: DCP( addr_abs_Y() ); return 7; // DCP* aby 7 (undocumented) + case 0xDC: NOP(); src_abs_X(); return 4; // NOP* abx 4 (undocumented) 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 0xDF: DCP( addr_abs_X() ); return 7; // DCP* abx 7 (undocumented) case 0xE0: CPX( imm() ); return 2; // CPX imm case 0xE1: SBC( src_X_ind() ) ; return 6; // SBC (X,ind) -// case 0xE2: -// case 0xE3: + case 0xE2: NOP(); imm(); return 2; // NOP* imm 2 (undocumented) + case 0xE3: ISB( addr_ind_X() ); return 8; // ISB* izx 8 (undocumented) 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 0xE7: ISB( addr_zp() ); return 5; // ISB* zpg 5 (undocumented) case 0xE8: INX(); return 2; // INX case 0xE9: SBC( imm() ); return 2; // SBC imm case 0xEA: NOP(); return 2; // NOP -// case 0xEB: + case 0xEB: SBC( imm() ); return 2; // SBC* imm 2 (undocumented) 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 0xEF: ISB( addr_abs() ); return 6; // ISB* abs 6 (undocumented) 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 0xF2: KIL(); return 0; // KIL - Hangs the CPU // t jams + case 0xF3: ISB( addr_ind_Y() ); return 8; // ISB* izy 8 (undocumented) + case 0xF4: NOP(); src_zp_X(); return 4; // NOP* zpx 4 (undocumented) 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 0xF7: ISB( addr_zp_X() ); return 6; // ISB* zpx 6 (undocumented) case 0xF8: SED(); return 2; // SED case 0xF9: SBC( src_abs_Y() ); return 4; // SBC abs,Y -// case 0xFA: -// case 0xFB: -// case 0xFC: + case 0xFA: NOP(); return 2; // NOP + case 0xFB: ISB( addr_abs_Y() ); return 7; // ISB* aby 7 (undocumented) + case 0xFC: NOP(); src_abs_X(); return 4; // NOP* abx 4 (undocumented) case 0xFD: SBC( src_abs_X() ); return 4; // SBC abs,X case 0xFE: INC( addr_abs_X() ); return 7; // INC abs,X -// case 0xFF: + case 0xFF: ISB( addr_abs_X() ); return 7; // ISB* abx 7 (undocumented) default: dbgPrintf("%04X: Unimplemented Instruction 0x%02X\n", m6502.PC -1, memread( m6502.PC -1 )); diff --git a/src/cpu/instructions/6502_instr_arithmetic.h b/src/cpu/instructions/6502_instr_arithmetic.h index 2d73cc2..2ad1d9f 100644 --- a/src/cpu/instructions/6502_instr_arithmetic.h +++ b/src/cpu/instructions/6502_instr_arithmetic.h @@ -88,11 +88,7 @@ INLINE void ADC( uint8_t src ) { (indirect,X) SBC (oper,X) E1 2 6 (indirect),Y SBC (oper),Y F1 2 5* **/ -INLINE void SBC( uint8_t src ) { - dbgPrintf("SBC(%02X) ", src); - disPrintf(disassembly.inst, "SBC"); -// ADC( ~src ); - +INLINE void _SBC( uint8_t src ) { uint16_t tmp; if( m6502.D ) { @@ -109,14 +105,19 @@ INLINE void SBC( uint8_t src ) { } } else - { + { tmp = m6502.A - src - !m6502.C; - } + } m6502.C = tmp < 0x100; m6502.V = ( (m6502.A ^ tmp) & 0x80 ) && ( (m6502.A ^ src) & 0x80 ); set_flags_NZ( m6502.A = tmp ); } +INLINE void SBC( uint8_t src ) { + dbgPrintf("SBC(%02X) ", src); + disPrintf(disassembly.inst, "SBC"); + _SBC(src); +} #endif // __6502_INSTR_ARITHMETIC_H__ diff --git a/src/cpu/instructions/6502_instr_compare_test.h b/src/cpu/instructions/6502_instr_compare_test.h index 17a948d..087eaca 100644 --- a/src/cpu/instructions/6502_instr_compare_test.h +++ b/src/cpu/instructions/6502_instr_compare_test.h @@ -48,10 +48,13 @@ INLINE void BIT( uint8_t src ) { (indirect,X) CMP (oper,X) C1 2 6 (indirect),Y CMP (oper),Y D1 2 5* **/ +INLINE void _CMP( uint8_t src ) { + set_flags_NZC( (int16_t)m6502.A - src ); +} INLINE void CMP( uint8_t src ) { dbgPrintf("CMP(%02X) ", src); disPrintf(disassembly.inst, "CMP"); - set_flags_NZC( (int16_t)m6502.A - src ); + _CMP(src); } /** diff --git a/src/cpu/instructions/6502_instr_inc_dec.h b/src/cpu/instructions/6502_instr_inc_dec.h index 2d63e17..a57b302 100644 --- a/src/cpu/instructions/6502_instr_inc_dec.h +++ b/src/cpu/instructions/6502_instr_inc_dec.h @@ -23,11 +23,12 @@ absolute INC oper EE 3 6 absolute,X INC oper,X FE 3 7 **/ -INLINE void INC( uint16_t addr ) { - dbgPrintf("INC %02X -> ", WRLOMEM[addr]); - disPrintf(disassembly.inst, "INC"); +INLINE void _INC( uint16_t addr ) { set_flags_NZ( ++(WRLOMEM[addr]) ); - dbgPrintf("%02X ", WRLOMEM[addr]); +} +INLINE void INC( uint16_t addr ) { + disPrintf(disassembly.inst, "INC"); + _INC(addr); } /** @@ -77,11 +78,12 @@ INLINE void INY() { absolute DEC oper CE 3 3 absolute,X DEC oper,X DE 3 7 **/ -INLINE void DEC( uint16_t addr ) { - dbgPrintf("DEC %02X -> ", WRLOMEM[addr]); - disPrintf(disassembly.inst, "DEC"); +INLINE void _DEC( uint16_t addr ) { set_flags_NZ( --(WRLOMEM[addr]) ); - dbgPrintf("%02X ", WRLOMEM[addr]); +} +INLINE void DEC( uint16_t addr ) { + disPrintf(disassembly.inst, "DEC"); + _DEC(addr); } /** diff --git a/src/cpu/instructions/6502_instr_logic.h b/src/cpu/instructions/6502_instr_logic.h index 2962d70..72fce15 100644 --- a/src/cpu/instructions/6502_instr_logic.h +++ b/src/cpu/instructions/6502_instr_logic.h @@ -27,10 +27,13 @@ (indirect,X) ORA (oper,X) 01 2 6 (indirect),Y ORA (oper),Y 11 2 5* **/ +INLINE void _ORA( uint8_t src ) { + set_flags_NZ( m6502.A |= src ); +} INLINE void ORA( uint8_t src ) { dbgPrintf("ORA(%02X) ", src); disPrintf(disassembly.inst, "ORA"); - set_flags_NZ( m6502.A |= src ); + _ORA(src); } /** @@ -50,10 +53,13 @@ INLINE void ORA( uint8_t src ) { (indirect,X) AND (oper,X) 21 2 6 (indirect),Y AND (oper),Y 31 2 5* **/ +INLINE void _AND( uint8_t src ) { + set_flags_NZ( m6502.A &= src ); +} INLINE void AND( uint8_t src ) { dbgPrintf("AND(%02X) ", src); disPrintf(disassembly.inst, "AND"); - set_flags_NZ( m6502.A &= src ); + _AND(src); } /** diff --git a/src/cpu/instructions/6502_instr_shift_rotate.h b/src/cpu/instructions/6502_instr_shift_rotate.h index 366c46e..5e9316c 100644 --- a/src/cpu/instructions/6502_instr_shift_rotate.h +++ b/src/cpu/instructions/6502_instr_shift_rotate.h @@ -24,11 +24,14 @@ absolute ASL oper 0E 3 6 absolute,X ASL oper,X 1E 3 7 **/ +INLINE void _ASL( uint16_t addr ) { + m6502.C = WRLOMEM[addr] & 0x80; + set_flags_NZ( WRLOMEM[addr] <<= 1 ); +} INLINE void ASL( uint16_t addr ) { dbgPrintf("ASL "); disPrintf(disassembly.inst, "ASL"); - m6502.C = WRLOMEM[addr] & 0x80; - set_flags_NZ( WRLOMEM[addr] <<= 1 ); + _ASL(addr); } INLINE void ASLA() { dbgPrintf("ASL "); @@ -78,14 +81,17 @@ INLINE void LSRA() { absolute ROL oper 2E 3 6 absolute,X ROL oper,X 3E 3 7 **/ -INLINE void ROL( uint16_t addr ) { - dbgPrintf("ROL "); - disPrintf(disassembly.inst, "ROL"); +INLINE void _ROL( uint16_t addr ) { uint8_t C = m6502.C != 0; m6502.C = WRLOMEM[addr] & 0x80; WRLOMEM[addr] <<= 1; set_flags_NZ( WRLOMEM[addr] |= C ); } +INLINE void ROL( uint16_t addr ) { + dbgPrintf("ROL "); + disPrintf(disassembly.inst, "ROL"); + _ROL(addr); +} INLINE void ROLA() { dbgPrintf("ROL "); disPrintf(disassembly.inst, "ROL"); diff --git a/src/cpu/instructions/6502_instr_undoc.h b/src/cpu/instructions/6502_instr_undoc.h index 674a1a3..0afacd6 100644 --- a/src/cpu/instructions/6502_instr_undoc.h +++ b/src/cpu/instructions/6502_instr_undoc.h @@ -25,6 +25,29 @@ INLINE void ANC ( uint8_t src ) { } +/** + ARC - "AND" Memory with Accumulator + THEN Copy Bit 7 of Result into Carry + THEN Rotate Accumulator One Bit Right + (Carry unaffected) + + (M "AND" A) -> A + THEN msb(A) -> C + THEN ROR A +**/ +INLINE void ARC ( uint8_t src ) { + disPrintf(disassembly.inst, "ARC"); + + _AND(src); + m6502.C = m6502.A >> 7; + + // RORA -- Carry not affected + uint8_t C = m6502.C != 0; + m6502.A >>= 1; + set_flags_NZ( m6502.A |= C << 7); +} + + /** ASR - "AND" Memory with Accumulator THEN Shift Accumulator One Bit Right @@ -45,20 +68,52 @@ INLINE void ASR ( uint8_t src ) { /** - NOP No Operation + DCP - Decrement Memory by One + THEN Compare Memory with Accumulator - --- N Z C I D V - - - - - - - - - addressing assembler opc bytes cyles - -------------------------------------------- - implied NOP EA ? ? + (M - 1) -> M + THEN CMP M **/ -INLINE void NOP2( uint8_t src ) { - disPrintf(disassembly.inst, "NOP2"); +INLINE void DCP ( uint16_t addr ) { + disPrintf(disassembly.inst, "DCP"); + _DEC(addr); + _CMP(WRLOMEM[addr]); } +/** + LAS - Stores {adr} & S into A, X and S + **/ +INLINE void LAS ( uint8_t src ) { + disPrintf(disassembly.inst, "LAS"); + set_flags_NZ( m6502.A = m6502.X = m6502.SP = m6502.SP & src ); +} + + +/** + ISB / ISC / INS - Increment Memory by One + THEN Subtract Memory from Accumulator with Borrow + + (M + 1) -> M + THEN (A - M - ~C) -> A + **/ +INLINE void ISB ( uint16_t addr ) { + disPrintf(disassembly.inst, "ISB"); + _INC(addr); + _SBC(WRLOMEM[addr]); +} + + +/** + LAX - Load Index X and Accumulator with Memory + + M -> X,A + **/ +INLINE void LAX ( uint8_t src ) { + disPrintf(disassembly.inst, "LAX"); + set_flags_NZ(m6502.A = m6502.X = src); +} + /** RLA - Rotate Memory One Bit Left @@ -70,15 +125,8 @@ INLINE void NOP2( uint8_t src ) { INLINE void RLA ( uint16_t addr ) { disPrintf(disassembly.inst, "RLA"); - // ROL M - uint8_t C = m6502.C != 0; - m6502.C = WRLOMEM[addr] & 0x80; - WRLOMEM[addr] <<= 1; - WRLOMEM[addr] |= C; - - // AND M - set_flags_NZ( m6502.A &= WRLOMEM[addr] ); - + _ROL(addr); + _AND(WRLOMEM[addr]); } @@ -96,6 +144,92 @@ INLINE void RRA ( uint16_t addr ) { } +/** + SAS - "AND" Accumulator with Index X into Stack Pointer + THEN Store Result "AND" (MSB(Address)+1) in Memory + + (A "AND" X) -> SP + THEN (SP "AND" (MSB(adr)+1)) -> M + **/ + +INLINE void SAS ( uint16_t addr ) { + disPrintf(disassembly.inst, "SAS"); + m6502.SP = m6502.A & m6502.X; + set_flags_NZ( WRLOMEM[addr] = m6502.SP & ((addr >> 8) + 1) ); +} + + +/** + SBX - Store Index X "AND" Accumulator in Memory + + Carry and Decimal flags are ignored but the + Carry flag will be set in substraction. This + is due to the CMP command, which is executed + instead of the real SBC. + + (A & X) - Immediate -> X + + The 'SBX' ($CB) may seem to be very complex operation, even though it + is a combination of the subtraction of accumulator and parameter, as + in the 'CMP' instruction, and the command 'DEX'. As a result, both A + and X are connected to ALU but only the subtraction takes place. Since + the comparison logic was used, the result of subtraction should be + normally ignored, but the 'DEX' now happily stores to X the value of + (A & X) - Immediate. That is why this instruction does not have any + decimal mode, and it does not affect the V flag. Also Carry flag will + be ignored in the subtraction but set according to the result. + + **/ +INLINE void SBX ( uint8_t src ) { + disPrintf(disassembly.inst, "SBX"); + + uint16_t tmp; + + // Decimal flag is ignored + tmp = (m6502.A & m6502.X) - src; + + m6502.C = tmp < 0x100; + m6502.V = ( (m6502.A ^ tmp) & 0x80 ) && ( (m6502.A ^ src) & 0x80 ); + set_flags_NZ( m6502.X = tmp ); +} + + +/** + SHA - Store Index X "AND" Accumulator in Memory + + (X "AND" A "AND" addr.H) -> M + **/ + +INLINE void SHA ( uint16_t addr ) { + disPrintf(disassembly.inst, "SHA"); + set_flags_NZ( WRLOMEM[addr] = m6502.X & m6502.A & ((addr >> 8) + 1) ); +} + + +/** + SHY - Store (MSB(Address)+1) "AND" Index Y in Memory + + ((MSB(adr)+1) "AND" Y) -> M + **/ + +INLINE void SHY ( uint16_t addr ) { + disPrintf(disassembly.inst, "SHY"); + set_flags_NZ( WRLOMEM[addr] = m6502.Y &((addr >> 8) + 1) ); +} + + +/** + SHX - Store (MSB(Address)+1) "AND" Index Y in Memory + + ((MSB(adr)+1) "AND" X) -> M + **/ + +INLINE void SHX ( uint16_t addr ) { + disPrintf(disassembly.inst, "SHX"); + set_flags_NZ( WRLOMEM[addr] = m6502.X &((addr >> 8) + 1) ); +} + + /** SLO - Shift Memory One Bit Left THEN "OR" Memory with Accumulator @@ -109,13 +243,24 @@ INLINE void RRA ( uint16_t addr ) { INLINE void SLO ( uint16_t addr ) { disPrintf(disassembly.inst, "SLO"); - m6502.C = WRLOMEM[addr] & 0x80; - WRLOMEM[addr] <<= 1; // ASL M -> M - m6502.A ^= WRLOMEM[addr]; // EOR M -> A + _ASL(addr); + _ORA( WRLOMEM[addr] ); set_flags_NZ( WRLOMEM[addr] = m6502.A ); // A -> M } +/** + SAX - Store Accumulator "AND" Index X in Memory + + (A "AND" X) -> M + **/ + +INLINE void SAX ( uint16_t addr ) { + disPrintf(disassembly.inst, "SAX"); + set_flags_NZ( WRLOMEM[addr] = m6502.A & m6502.X ); +} + + /** SRE - Shift Memory One Bit Right THEN "OR" Memory with Accumulator @@ -137,6 +282,17 @@ INLINE void SRE ( uint16_t addr ) { } +/** +XAA - "AND" Memory with Index X into Accumulator + + (M "AND" X) -> A +**/ +INLINE void XAA ( uint8_t src ) { + disPrintf(disassembly.inst, "XAA"); + set_flags_NZ( m6502.A = m6502.X & src ); +} + + #endif // __6502_INSTR_UNDOC_H__