diff options
Diffstat (limited to 'cpu')
| -rw-r--r-- | cpu/cpu.go | 12 | ||||
| -rw-r--r-- | cpu/opcodes.go | 91 |
2 files changed, 99 insertions, 4 deletions
@@ -13,6 +13,16 @@ type CPU struct { SP uint8 // stack pointer PC uint16 // program counter Status uint8 // status flags + // status flags are NV1B DIZC + // |||| |||| + // |||| |||+- Carry + // |||| ||+-- Zero + // |||| |+--- Interrupt Disable + // |||| +---- Decimal + // |||+------ (no cpu effect, check https://www.nesdev.org/wiki/Status_flags#The_B_flag for a good explanation) + // ||+------- (no cpu effect, always pushed as 1) + // |+-------- Overflow + // +--------- Negative Bus Bus Cycles uint64 @@ -21,7 +31,7 @@ type CPU struct { extraCycles int } -func NewCPU(bus Bus) *CPU { +func NewCPU(bus Bus) *CPU { // creates new cpu with bus return &CPU{Bus: bus} } diff --git a/cpu/opcodes.go b/cpu/opcodes.go index 13f9612..ea6e1b9 100644 --- a/cpu/opcodes.go +++ b/cpu/opcodes.go @@ -28,6 +28,7 @@ func init() { } } + // load accumulator def(0xA9, "LDA", ModeImmediate, 2, false, ldaExec) def(0xA5, "LDA", ModeZeroPage, 3, false, ldaExec) def(0xB5, "LDA", ModeZeroPageX, 4, false, ldaExec) @@ -37,18 +38,21 @@ func init() { def(0xA1, "LDA", ModeIndirectX, 6, false, ldaExec) def(0xB1, "LDA", ModeIndirectY, 5, true, ldaExec) + // load X def(0xA2, "LDX", ModeImmediate, 2, false, ldxExec) def(0xA6, "LDX", ModeZeroPage, 3, false, ldxExec) def(0xB6, "LDX", ModeZeroPageY, 4, false, ldxExec) def(0xAE, "LDX", ModeAbsolute, 4, false, ldxExec) def(0xBE, "LDX", ModeAbsoluteY, 4, true, ldxExec) + // load Y def(0xA0, "LDY", ModeImmediate, 2, false, ldyExec) def(0xA4, "LDY", ModeZeroPage, 3, false, ldyExec) def(0xB4, "LDY", ModeZeroPageX, 4, false, ldyExec) def(0xAC, "LDY", ModeAbsolute, 4, false, ldyExec) def(0xBC, "LDY", ModeAbsoluteX, 4, true, ldyExec) + // store accumulator def(0x85, "STA", ModeZeroPage, 3, false, staExec) def(0x95, "STA", ModeZeroPageX, 4, false, staExec) def(0x8D, "STA", ModeAbsolute, 4, false, staExec) @@ -57,26 +61,48 @@ func init() { def(0x81, "STA", ModeIndirectX, 6, false, staExec) def(0x91, "STA", ModeIndirectY, 6, false, staExec) + // store X def(0x86, "STX", ModeZeroPage, 3, false, stxExec) def(0x96, "STX", ModeZeroPageY, 4, false, stxExec) def(0x8E, "STX", ModeAbsolute, 4, false, stxExec) + // store Y def(0x84, "STY", ModeZeroPage, 3, false, styExec) def(0x94, "STY", ModeZeroPageX, 4, false, styExec) def(0x8C, "STY", ModeAbsolute, 4, false, styExec) + // transfer accumulator to X def(0xAA, "TAX", ModeImplied, 2, false, taxExec) + + // transfer x to accumulator def(0x8A, "TXA", ModeImplied, 2, false, txaExec) + + // transfer accumulator to Y def(0xA8, "TAY", ModeImplied, 2, false, tayExec) + + // transfer y to accumulator def(0x98, "TYA", ModeImplied, 2, false, tyaExec) + + // transfer stack pointer to x def(0xBA, "TSX", ModeImplied, 2, false, tsxExec) + + // transfer x to stack pointer def(0x9A, "TXS", ModeImplied, 2, false, txsExec) + // push accumulator def(0x48, "PHA", ModeImplied, 3, false, phaExec) + + // pull accumulator def(0x68, "PLA", ModeImplied, 4, false, plaExec) + + // originally personal homepage, now PHP: Hypertext Preprocessor + // totally not push processor status (SR) def(0x08, "PHP", ModeImplied, 3, false, phpExec) + + // pull processor status (SR) def(0x28, "PLP", ModeImplied, 4, false, plpExec) + // add with carry def(0x69, "ADC", ModeImmediate, 2, false, adcExec) def(0x65, "ADC", ModeZeroPage, 3, false, adcExec) def(0x75, "ADC", ModeZeroPageX, 4, false, adcExec) @@ -86,7 +112,9 @@ func init() { def(0x61, "ADC", ModeIndirectX, 6, false, adcExec) def(0x71, "ADC", ModeIndirectY, 5, true, adcExec) + // subtract with carry def(0xE9, "SBC", ModeImmediate, 2, false, sbcExec) + def(0xEB, "SBC", ModeImmediate, 2, false, sbcExec) def(0xE5, "SBC", ModeZeroPage, 3, false, sbcExec) def(0xF5, "SBC", ModeZeroPageX, 4, false, sbcExec) def(0xED, "SBC", ModeAbsolute, 4, false, sbcExec) @@ -95,6 +123,7 @@ func init() { def(0xE1, "SBC", ModeIndirectX, 6, false, sbcExec) def(0xF1, "SBC", ModeIndirectY, 5, true, sbcExec) + // and (with accumulator) def(0x29, "AND", ModeImmediate, 2, false, andExec) def(0x25, "AND", ModeZeroPage, 3, false, andExec) def(0x35, "AND", ModeZeroPageX, 4, false, andExec) @@ -104,6 +133,7 @@ func init() { def(0x21, "AND", ModeIndirectX, 6, false, andExec) def(0x31, "AND", ModeIndirectY, 5, true, andExec) + // or with accumulator def(0x09, "ORA", ModeImmediate, 2, false, oraExec) def(0x05, "ORA", ModeZeroPage, 3, false, oraExec) def(0x15, "ORA", ModeZeroPageX, 4, false, oraExec) @@ -113,6 +143,7 @@ func init() { def(0x01, "ORA", ModeIndirectX, 6, false, oraExec) def(0x11, "ORA", ModeIndirectY, 5, true, oraExec) + // exclusive or (with accumulator) def(0x49, "EOR", ModeImmediate, 2, false, eorExec) def(0x45, "EOR", ModeZeroPage, 3, false, eorExec) def(0x55, "EOR", ModeZeroPageX, 4, false, eorExec) @@ -122,48 +153,63 @@ func init() { def(0x41, "EOR", ModeIndirectX, 6, false, eorExec) def(0x51, "EOR", ModeIndirectY, 5, true, eorExec) + // bit test def(0x24, "BIT", ModeZeroPage, 3, false, bitExec) def(0x2C, "BIT", ModeAbsolute, 4, false, bitExec) + // arithmetic shift left def(0x0A, "ASL", ModeAccumulator, 2, false, aslExec) def(0x06, "ASL", ModeZeroPage, 5, false, aslExec) def(0x16, "ASL", ModeZeroPageX, 6, false, aslExec) def(0x0E, "ASL", ModeAbsolute, 6, false, aslExec) def(0x1E, "ASL", ModeAbsoluteX, 7, false, aslExec) + // logical shift right def(0x4A, "LSR", ModeAccumulator, 2, false, lsrExec) def(0x46, "LSR", ModeZeroPage, 5, false, lsrExec) def(0x56, "LSR", ModeZeroPageX, 6, false, lsrExec) def(0x4E, "LSR", ModeAbsolute, 6, false, lsrExec) def(0x5E, "LSR", ModeAbsoluteX, 7, false, lsrExec) + // rotate left def(0x2A, "ROL", ModeAccumulator, 2, false, rolExec) def(0x26, "ROL", ModeZeroPage, 5, false, rolExec) def(0x36, "ROL", ModeZeroPageX, 6, false, rolExec) def(0x2E, "ROL", ModeAbsolute, 6, false, rolExec) def(0x3E, "ROL", ModeAbsoluteX, 7, false, rolExec) + // rotate right def(0x6A, "ROR", ModeAccumulator, 2, false, rorExec) def(0x66, "ROR", ModeZeroPage, 5, false, rorExec) def(0x76, "ROR", ModeZeroPageX, 6, false, rorExec) def(0x6E, "ROR", ModeAbsolute, 6, false, rorExec) def(0x7E, "ROR", ModeAbsoluteX, 7, false, rorExec) + // increment def(0xE6, "INC", ModeZeroPage, 5, false, incExec) def(0xF6, "INC", ModeZeroPageX, 6, false, incExec) def(0xEE, "INC", ModeAbsolute, 6, false, incExec) def(0xFE, "INC", ModeAbsoluteX, 7, false, incExec) + // decrement def(0xC6, "DEC", ModeZeroPage, 5, false, decExec) def(0xD6, "DEC", ModeZeroPageX, 6, false, decExec) def(0xCE, "DEC", ModeAbsolute, 6, false, decExec) def(0xDE, "DEC", ModeAbsoluteX, 7, false, decExec) + // increment x def(0xE8, "INX", ModeImplied, 2, false, inxExec) + + // decrement x def(0xCA, "DEX", ModeImplied, 2, false, dexExec) + + // increment y def(0xC8, "INY", ModeImplied, 2, false, inyExec) + + // decrement y def(0x88, "DEY", ModeImplied, 2, false, deyExec) + // compare (with accumulator) def(0xC9, "CMP", ModeImmediate, 2, false, cmpExec) def(0xC5, "CMP", ModeZeroPage, 3, false, cmpExec) def(0xD5, "CMP", ModeZeroPageX, 4, false, cmpExec) @@ -173,40 +219,79 @@ func init() { def(0xC1, "CMP", ModeIndirectX, 6, false, cmpExec) def(0xD1, "CMP", ModeIndirectY, 5, true, cmpExec) + // compare with X def(0xE0, "CPX", ModeImmediate, 2, false, cpxExec) def(0xE4, "CPX", ModeZeroPage, 3, false, cpxExec) def(0xEC, "CPX", ModeAbsolute, 4, false, cpxExec) + // compare with y def(0xC0, "CPY", ModeImmediate, 2, false, cpyExec) def(0xC4, "CPY", ModeZeroPage, 3, false, cpyExec) def(0xCC, "CPY", ModeAbsolute, 4, false, cpyExec) + // branch on carry clear def(0x90, "BCC", ModeRelative, 2, false, bccExec) + + // branch on carry set def(0xB0, "BCS", ModeRelative, 2, false, bcsExec) + + // branch on not equal (zero clear) def(0xD0, "BNE", ModeRelative, 2, false, bneExec) + + // branch on equal (zero set) def(0xF0, "BEQ", ModeRelative, 2, false, beqExec) + + // branch on plus (negative clear) def(0x10, "BPL", ModeRelative, 2, false, bplExec) + + // branch on minus (negative set) def(0x30, "BMI", ModeRelative, 2, false, bmiExec) + + // branch on overflow clear def(0x50, "BVC", ModeRelative, 2, false, bvcExec) + + // branch on overflow set def(0x70, "BVS", ModeRelative, 2, false, bvsExec) + // jump def(0x4C, "JMP", ModeAbsolute, 3, false, jmpExec) def(0x6C, "JMP", ModeIndirect, 5, false, jmpExec) + + // jump subroutine def(0x20, "JSR", ModeAbsolute, 6, false, jsrExec) + + // return from subroutine def(0x60, "RTS", ModeImplied, 6, false, rtsExec) + + // return from interrupt def(0x40, "RTI", ModeImplied, 6, false, rtiExec) + // clear carry def(0x18, "CLC", ModeImplied, 2, false, clcExec) + + // set carry def(0x38, "SEC", ModeImplied, 2, false, secExec) + + // clear interrupt disable def(0x58, "CLI", ModeImplied, 2, false, cliExec) + + // set interrupt disable def(0x78, "SEI", ModeImplied, 2, false, seiExec) + + // clear decimal def(0xD8, "CLD", ModeImplied, 2, false, cldExec) + + // set decimal def(0xF8, "SED", ModeImplied, 2, false, sedExec) + + // clear overflow def(0xB8, "CLV", ModeImplied, 2, false, clvExec) - def(0xEA, "NOP", ModeImplied, 2, false, nopExec) + // break / interrupt def(0x00, "BRK", ModeImplied, 7, false, brkExec) + // no operation + def(0xEA, "NOP", ModeImplied, 2, false, nopExec) def(0x1A, "NOP", ModeImplied, 2, false, nopExec) def(0x3A, "NOP", ModeImplied, 2, false, nopExec) def(0x5A, "NOP", ModeImplied, 2, false, nopExec) @@ -235,6 +320,7 @@ func init() { def(0xDC, "NOP", ModeAbsoluteX, 4, true, nopExec) def(0xFC, "NOP", ModeAbsoluteX, 4, true, nopExec) + // JAM is sometimes also referred to as HLT or KIL def(0x02, "JAM", ModeImplied, 2, false, jamExec) def(0x12, "JAM", ModeImplied, 2, false, jamExec) def(0x22, "JAM", ModeImplied, 2, false, jamExec) @@ -248,8 +334,7 @@ func init() { def(0xD2, "JAM", ModeImplied, 2, false, jamExec) def(0xF2, "JAM", ModeImplied, 2, false, jamExec) - def(0xEB, "SBC", ModeImmediate, 2, false, sbcExec) - + // illegal / undocumented instructions def(0xA7, "LAX", ModeZeroPage, 3, false, laxExec) def(0xB7, "LAX", ModeZeroPageY, 4, false, laxExec) def(0xAF, "LAX", ModeAbsolute, 4, false, laxExec) |