From 2c62a32264218a84c47adaed0a14bdea073c1905 Mon Sep 17 00:00:00 2001 From: Raimon Zamora Date: Sat, 1 Feb 2025 11:19:52 +0100 Subject: [PATCH] =?UTF-8?q?-=20M=C3=A9s=20de=20la=20meitat=20de=20opcodes?= =?UTF-8?q?=20implementats?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 6502.cpp | 567 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 560 insertions(+), 7 deletions(-) diff --git a/6502.cpp b/6502.cpp index e89610a..69a263a 100644 --- a/6502.cpp +++ b/6502.cpp @@ -34,7 +34,7 @@ namespace cpu6502 #define aZeroPage 2 #define aZeroPageX 3 #define aZeroPageY 4 - #define aRelative 5 + #define aRelative 5 // Is really needed? #define aIndirect 6 #define aIndirectX 7 #define aIndirectY 8 @@ -42,6 +42,11 @@ namespace cpu6502 #define aAbsoluteX 10 #define aAbsoluteY 11 + #define FLAG_IS_RESET true + #define FLAG_IS_SET false + + uint8_t i_reg_value = 0; + uint8_t regs[7]; uint8_t *_rA = ®s[0]; @@ -63,7 +68,7 @@ namespace cpu6502 uint8_t READ_MEM_8(const uint16_t addr, const bool code=false) { if (debug::isbreak(addr, 2)) debug::stop(); - t+=1; //[TODO] + //t+=1; //[TODO] const uint8_t tag = mem::getTag(addr); if ( !(tag&MEMTAG_IGNORE) ) { @@ -110,7 +115,7 @@ namespace cpu6502 const uint8_t WRITE_MEM_8(const uint16_t addr, const uint8_t value) { - t+=1; // [TODO] + //t+=1; // [TODO] mem::writeMem(addr, value); if (debug::isbreak(addr, 4)) debug::stop(); @@ -148,24 +153,302 @@ namespace cpu6502 } + void notImplemented() + { + + } + + uint16_t addr_mode_address = 0; + bool page_crossed = false; + uint8_t loadValue(uint8_t addr_mode) + { + page_crossed = false; + switch (addr_mode) + { + case aAccumulator: + t+=2; + return rA; + + case aImmediate: + t+=2; + return READ_MEM_8(); + + case aZeroPage: + t+=3; + addr_mode_address = READ_MEM_8(); + return READ_MEM_8(addr_mode_address); + + case aZeroPageX: + t+=4; + addr_mode_address = (READ_MEM_8()+rX)&0xff; + return READ_MEM_8(addr_mode_address); + + case aZeroPageY: + t+=4; + addr_mode_address = (READ_MEM_8()+rY)&0xff; + return READ_MEM_8(addr_mode_address); + + case aIndirectX: + t+=6; + addr_mode_address = READ_MEM_16((READ_MEM_8()+rX)&0xff); + return READ_MEM_8(addr_mode_address); + + case aIndirectY: + t+=5; + addr_mode_address = READ_MEM_16(READ_MEM_8()); + if ( (addr_mode_address&0xff) + rY > 0xff ) { t++; page_crossed=true; } + addr_mode_address = (addr_mode_address+rY)&0xffff; + return READ_MEM_8(addr_mode_address); + + case aAbsolute: + t+=4; + addr_mode_address = READ_MEM_16(); + return READ_MEM_8(addr_mode_address); + + case aAbsoluteX: + t+=4; + addr_mode_address = READ_MEM_16(); + if ( (addr_mode_address&0xff) + rX > 0xff ) { t++; page_crossed=true; } + addr_mode_address = (addr_mode_address+rX) & 0xffff; + return READ_MEM_8(addr_mode_address); + + case aAbsoluteY: + t+=4; + addr_mode_address = READ_MEM_16(); + if ( (addr_mode_address&0xff) + rY > 0xff ) { t++; page_crossed=true; } + addr_mode_address = (addr_mode_address+rY) & 0xffff; + return READ_MEM_8(addr_mode_address); + + } + } + + void storeValue(uint8_t value, uint8_t addr_mode) + { + switch (addr_mode) + { + case aAccumulator: + rA = value; + break; + + case aZeroPage: + case aZeroPageX: + case aZeroPageY: + t+=2; + WRITE_MEM_8(addr_mode_address, value); + break; + + case aIndirectX: + WRITE_MEM_8(addr_mode_address, value); + break; + + case aAbsolute: + t+=2; + WRITE_MEM_8(addr_mode_address, value); + break; + + case aAbsoluteX: + t+=page_crossed?2:3; + WRITE_MEM_8(addr_mode_address, value); + break; + } + } + + void PHP() + { + t+= 3; + WRITE_MEM_8(0x0100+rS, rP|f1|fB); rS--; + } + + void PHA() + { + t+= 3; + WRITE_MEM_8(0x0100+rS, rA); rS--; + } + + void PLP() + { + t+=4; + rS++; + rP = READ_MEM_8(0x0100+rS) & ~(f1|fB); + } + + void PLA() + { + t+=4; + rS++; + rA = READ_MEM_8(0x0100+rS); + rP = ( rP & ~fN ) | ( rA & fN ); + rP = ( rA ? rP & ~fZ : rP | fZ ); + } + void BRK() { - rPC++; + READ_MEM_8(); WRITE_MEM_16(0x0100+rS, rPC); rS-=2; - WRITE_MEM_8(0x0100+rS, rP|f1|fB); rS--; + PHP(); // t+=3 rP |= fI; rPC = READ_MEM_16(0xfffe); - t++; + t+=4; + } + + void RTI() + { + PLP(); i_reg_value = rP&fI; // effect of changing fI is not delayed + rS+=2; + rPC = READ_MEM_16(0x0100+rS); + t+=2; + } + + void ADC(uint8_t addr_mode) + { + uint8_t value = loadValue(addr_mode); + uint16_t result = rA + value + fC; + rA = result & 0xff; + rP = ( rP & ~fC ) | ( (result>>8) & fC ); + rP = ( rP & ~fN ) | ( rA & fN ); + rP = ( rA ? rP & ~fZ : rP | fZ ); + rP = ( (result ^ rA) & (result ^ value) & 0x80 ) ? rP | fV : rP & ~fV; } void ORA(uint8_t addr_mode) { - + uint8_t value = loadValue(addr_mode); + rA |= value; + rP = ( rP & ~fN ) | ( rA & fN ); + rP = ( rA ? rP & ~fZ : rP | fZ ); } + void AND(uint8_t addr_mode) + { + uint8_t value = loadValue(addr_mode); + rA &= value; + rP = ( rP & ~fN ) | ( rA & fN ); + rP = ( rA ? rP & ~fZ : rP | fZ ); + } + + void EOR(uint8_t addr_mode) + { + uint8_t value = loadValue(addr_mode); + rA = rA ^ value; + rP = ( rP & ~fN ) | ( rA & fN ); + rP = ( rA ? rP & ~fZ : rP | fZ ); + } + + void BIT(uint8_t addr_mode) + { + uint8_t value = loadValue(addr_mode); + uint8_t result = rA & value; + rP = ( rP & ~(fN|fV) ) | ( rA & (fN|fV) ); + rP = ( rA ? rP & ~fZ : rP | fZ ); + } + + void ASL(uint8_t addr_mode) + { + uint8_t value = loadValue(addr_mode); + rP = ( rP & ~fC ) | ( (value & 0x80)>>7 ); + value = value << 1; + rP = ( rP & ~fN ) | ( value & fN ); + rP = ( value ? rP & ~fZ : rP | fZ ); + storeValue(value, addr_mode); + } + + void LSR(uint8_t addr_mode) + { + uint8_t value = loadValue(addr_mode); + rP = ( rP & ~fC ) | ( (value & fC) ); + value = value >> 1; + rP = ( rP & ~fN ) | ( value & fN ); + rP = ( value ? rP & ~fZ : rP | fZ ); + storeValue(value, addr_mode); + } + + void ROL(uint8_t addr_mode) + { + uint8_t value = loadValue(addr_mode); + uint8_t old_fC = rP & fC; + rP = ( rP & ~fC ) | ( (value & 0x80)>>7 ); + value = (value << 1) | old_fC; + rP = ( rP & ~fN ) | ( value & fN ); + rP = ( value ? rP & ~fZ : rP | fZ ); + storeValue(value, addr_mode); + } + + void ROR(uint8_t addr_mode) + { + uint8_t value = loadValue(addr_mode); + uint8_t old_fC = (rP & fC) << 7; + rP = ( rP & ~fC ) | ( (value & fC) ); + value = (value >> 1) | old_fC; + rP = ( rP & ~fN ) | ( value & fN ); + rP = ( value ? rP & ~fZ : rP | fZ ); + storeValue(value, addr_mode); + } + + void JMP(uint8_t addr_mode) + { + t+=3; + addr_mode_address = READ_MEM_16(); + if (addr_mode == aIndirect) { + t+=5; + const uint8_t L = READ_MEM_8(addr_mode_address); + const uint8_t H = READ_MEM_8( (addr_mode_address&0xff00) | ((addr_mode_address+1)&0x00ff) ); + addr_mode_address = (H << 8) + L; + } + rPC = addr_mode_address; + } + + void BRANCH(uint8_t flag, bool negate) + { + t+=3; + int8_t offset = (int8_t)READ_MEM_8(); + bool condition = (rP & flag); + if (negate) condition = !condition; + if (condition) { + t++; + if ( (rPC&0xff) + offset > 0xff ) t++; + rPC = (rPC + offset) & 0xffff; + } + } + void BPL() { BRANCH(fN, FLAG_IS_RESET); } + void BMI() { BRANCH(fN, FLAG_IS_SET); } + void BNE() { BRANCH(fZ, FLAG_IS_RESET); } + void BEQ() { BRANCH(fZ, FLAG_IS_SET); } + void BCC() { BRANCH(fC, FLAG_IS_RESET); } + void BCS() { BRANCH(fC, FLAG_IS_SET); } + void BVC() { BRANCH(fV, FLAG_IS_RESET); } + void BVS() { BRANCH(fV, FLAG_IS_SET); } + + void JSR(uint8_t addr_mode) + { + uint8_t value = loadValue(addr_mode); + t+=2; + WRITE_MEM_16(0x0100+rS, rPC-1); rS-=2; + rPC = value; + } + + void RTS() + { + rS+=2; + rPC = READ_MEM_16(0x0100+rS); + rPC++; + t+=6; + } + + void SET_FLAG(uint8_t flag) { t+=2; rP = rP | flag; } + void SEC() { SET_FLAG(fC); } + void SED() { SET_FLAG(fD); } + void SEI() { SET_FLAG(fI); } + + void CLEAR_FLAG(uint8_t flag) { t+=2; rP = rP & ~flag; } + void CLC() { CLEAR_FLAG(fC); } + void CLD() { CLEAR_FLAG(fD); } + void CLI() { CLEAR_FLAG(fI); } + void CLV() { CLEAR_FLAG(fV); } + uint32_t step() { t = 0; + i_reg_value = rP & fI; uint16_t current_opcode_address = rPC; const uint8_t opcode = READ_M1(); @@ -179,9 +462,279 @@ namespace cpu6502 { case 0x00: BRK(); break; case 0x01: ORA(aIndirectX); break; + case 0x02: notImplemented(); break; + case 0x03: notImplemented(); break; + case 0x04: notImplemented(); break; + case 0x05: ORA(aZeroPage); break; + case 0x06: ASL(aZeroPage); break; + case 0x07: notImplemented(); break; + case 0x08: PHP(); break; + case 0x09: ORA(aImmediate); break; + case 0x0a: ASL(aAccumulator); break; + case 0x0b: notImplemented(); break; + case 0x0c: notImplemented(); break; + case 0x0d: ORA(aAbsolute); break; + case 0x0e: ASL(aAbsolute); break; + case 0x0f: notImplemented(); break; + + case 0x10: BPL(); break; + case 0x11: ORA(aIndirectY); break; + case 0x12: notImplemented(); break; + case 0x13: notImplemented(); break; + case 0x14: notImplemented(); break; + case 0x15: ORA(aZeroPageX); break; + case 0x16: ASL(aZeroPageX); break; + case 0x17: notImplemented(); break; + case 0x18: CLC(); break; + case 0x19: ORA(aAbsoluteY); break; + case 0x1a: notImplemented(); break; + case 0x1b: notImplemented(); break; + case 0x1c: notImplemented(); break; + case 0x1d: ORA(aAbsoluteX); break; + case 0x1e: ASL(aAbsoluteX); break; + case 0x1f: notImplemented(); break; + + case 0x20: JSR(aAbsolute); break; + case 0x21: AND(aIndirectX); break; + case 0x22: notImplemented(); break; + case 0x23: notImplemented(); break; + case 0x24: BIT(aZeroPage); break; + case 0x25: AND(aZeroPage); break; + case 0x26: ROL(aZeroPage); break; + case 0x27: notImplemented(); break; + case 0x28: PLP(); break; + case 0x29: AND(aImmediate); break; + case 0x2a: ROL(aAccumulator); break; + case 0x2b: notImplemented(); break; + case 0x2c: BIT(aAbsolute); break; + case 0x2d: AND(aAbsolute); break; + case 0x2e: ROL(aAbsolute); break; + case 0x2f: notImplemented(); break; + + case 0x30: BMI(); break; + case 0x31: AND(aIndirectY); break; + case 0x32: notImplemented(); break; + case 0x33: notImplemented(); break; + case 0x34: notImplemented(); break; + case 0x35: AND(aZeroPageX); break; + case 0x36: ROL(aZeroPageX); break; + case 0x37: notImplemented(); break; + case 0x38: SEC(); break; + case 0x39: AND(aAbsoluteY); break; + case 0x3a: notImplemented(); break; + case 0x3b: notImplemented(); break; + case 0x3c: notImplemented(); break; + case 0x3d: AND(aAbsoluteX); break; + case 0x3e: ROL(aAbsoluteX); break; + case 0x3f: notImplemented(); break; + + case 0x40: RTI(); break; + case 0x41: EOR(aIndirectX); break; + case 0x42: notImplemented(); break; + case 0x43: notImplemented(); break; + case 0x44: notImplemented(); break; + case 0x45: EOR(aZeroPage); break; + case 0x46: LSR(aZeroPage); break; + case 0x47: notImplemented(); break; + case 0x48: PHA(); break; + case 0x49: EOR(aImmediate); break; + case 0x4a: LSR(aAccumulator); break; + case 0x4b: notImplemented(); break; + case 0x4c: JMP(aAbsolute); break; + case 0x4d: EOR(aAbsolute); break; + case 0x4e: LSR(aAbsolute); break; + case 0x4f: notImplemented(); break; + + case 0x50: BVC(); break; + case 0x51: EOR(aIndirectY); break; + case 0x52: notImplemented(); break; + case 0x53: notImplemented(); break; + case 0x54: notImplemented(); break; + case 0x55: EOR(aZeroPageX); break; + case 0x56: LSR(aZeroPageX); break; + case 0x57: notImplemented(); break; + case 0x58: CLI(); break; + case 0x59: EOR(aAbsoluteY); break; + case 0x5a: notImplemented(); break; + case 0x5b: notImplemented(); break; + case 0x5c: notImplemented(); break; + case 0x5d: EOR(aAbsoluteX); break; + case 0x5e: LSR(aAbsoluteX); break; + case 0x5f: notImplemented(); break; + + case 0x60: RTS(); break; + case 0x61: ADC(aIndirectX); break; + case 0x62: notImplemented(); break; + case 0x63: notImplemented(); break; + case 0x64: notImplemented(); break; + case 0x65: ADC(aZeroPage); break; + case 0x66: ROR(aZeroPage); break; + case 0x67: notImplemented(); break; + case 0x68: PLA(); break; + case 0x69: ADC(aImmediate); break; + case 0x6a: ROR(aAccumulator); break; + case 0x6b: notImplemented(); break; + case 0x6c: JMP(aIndirect); break; + case 0x6d: ADC(aAbsolute); break; + case 0x6e: ROR(aAbsolute); break; + case 0x6f: notImplemented(); break; + + case 0x70: BVS(); break; + case 0x71: ADC(aIndirectY); break; + case 0x72: notImplemented(); break; + case 0x73: notImplemented(); break; + case 0x74: notImplemented(); break; + case 0x75: ADC(aZeroPageX); break; + case 0x76: ROR(aZeroPageX); break; + case 0x77: notImplemented(); break; + case 0x78: SEI(); break; + case 0x79: ADC(aAbsoluteY); break; + case 0x7a: notImplemented(); break; + case 0x7b: notImplemented(); break; + case 0x7c: notImplemented(); break; + case 0x7d: ADC(aAbsoluteX); break; + case 0x7e: ROR(aAbsoluteX); break; + case 0x7f: notImplemented(); break; + + case 0x80: notImplemented(); break; + case 0x81: break; + case 0x82: break; + case 0x83: notImplemented(); break; + case 0x84: notImplemented(); break; + case 0x85: break; + case 0x86: break; + case 0x87: notImplemented(); break; + case 0x88: break; + case 0x89: notImplemented(); break; + case 0x8a: break; + case 0x8b: notImplemented(); break; + case 0x8c: break; + case 0x8d: break; + case 0x8e: break; + case 0x8f: notImplemented(); break; + + case 0x90: break; + case 0x91: break; + case 0x92: notImplemented(); break; + case 0x93: notImplemented(); break; + case 0x94: break; + case 0x95: break; + case 0x96: break; + case 0x97: notImplemented(); break; + case 0x98: break; + case 0x99: break; + case 0x9a: break; + case 0x9b: notImplemented(); break; + case 0x9c: notImplemented(); break; + case 0x9d: break; + case 0x9e: notImplemented(); break; + case 0x9f: notImplemented(); break; + + case 0xa0: break; + case 0xa1: break; + case 0xa2: break; + case 0xa3: notImplemented(); break; + case 0xa4: break; + case 0xa5: break; + case 0xa6: break; + case 0xa7: notImplemented(); break; + case 0xa8: break; + case 0xa9: break; + case 0xaa: break; + case 0xab: notImplemented(); break; + case 0xac: break; + case 0xad: break; + case 0xae: break; + case 0xaf: notImplemented(); break; + + case 0xb0: break; + case 0xb1: break; + case 0xb2: notImplemented(); break; + case 0xb3: notImplemented(); break; + case 0xb4: break; + case 0xb5: break; + case 0xb6: break; + case 0xb7: notImplemented(); break; + case 0xb8: break; + case 0xb9: break; + case 0xba: break; + case 0xbb: notImplemented(); break; + case 0xbc: break; + case 0xbd: break; + case 0xbe: break; + case 0xbf: notImplemented(); break; + + case 0xc0: break; + case 0xc1: break; + case 0xc2: notImplemented(); break; + case 0xc3: notImplemented(); break; + case 0xc4: break; + case 0xc5: break; + case 0xc6: break; + case 0xc7: notImplemented(); break; + case 0xc8: break; + case 0xc9: break; + case 0xca: break; + case 0xcb: notImplemented(); break; + case 0xcc: break; + case 0xcd: break; + case 0xce: break; + case 0xcf: notImplemented(); break; + + case 0xd0: break; + case 0xd1: break; + case 0xd2: notImplemented(); break; + case 0xd3: notImplemented(); break; + case 0xd4: notImplemented(); break; + case 0xd5: break; + case 0xd6: break; + case 0xd7: notImplemented(); break; + case 0xd8: break; + case 0xd9: break; + case 0xda: notImplemented(); break; + case 0xdb: notImplemented(); break; + case 0xdc: notImplemented(); break; + case 0xdd: break; + case 0xde: break; + case 0xdf: notImplemented(); break; + + case 0xe0: break; + case 0xe1: break; + case 0xe2: notImplemented(); break; + case 0xe3: notImplemented(); break; + case 0xe4: break; + case 0xe5: break; + case 0xe6: break; + case 0xe7: notImplemented(); break; + case 0xe8: break; + case 0xe9: break; + case 0xea: break; + case 0xeb: notImplemented(); break; + case 0xec: break; + case 0xed: break; + case 0xee: break; + case 0xef: notImplemented(); break; + + case 0xf0: break; + case 0xf1: break; + case 0xf2: notImplemented(); break; + case 0xf3: notImplemented(); break; + case 0xf4: notImplemented(); break; + case 0xf5: break; + case 0xf6: break; + case 0xf7: notImplemented(); break; + case 0xf8: break; + case 0xf9: break; + case 0xfa: notImplemented(); break; + case 0xfb: notImplemented(); break; + case 0xfc: notImplemented(); break; + case 0xfd: break; + case 0xfe: break; + case 0xff: notImplemented(); break; }; // [TODO] Gestionar interrupcions + //if (!i_reg_value) gestionar interrupcions //debug::setcursor(rPC); //debug::history::store();