package cpu func ldaExec(c *CPU, op operand) { c.A = c.operandValue(op); c.setZN(c.A) } func ldxExec(c *CPU, op operand) { c.X = c.operandValue(op); c.setZN(c.X) } func ldyExec(c *CPU, op operand) { c.Y = c.operandValue(op); c.setZN(c.Y) } func staExec(c *CPU, op operand) { c.write(op.addr, c.A) } func stxExec(c *CPU, op operand) { c.write(op.addr, c.X) } func styExec(c *CPU, op operand) { c.write(op.addr, c.Y) } func taxExec(c *CPU, op operand) { c.X = c.A; c.setZN(c.X) } func txaExec(c *CPU, op operand) { c.A = c.X; c.setZN(c.A) } func tayExec(c *CPU, op operand) { c.Y = c.A; c.setZN(c.Y) } func tyaExec(c *CPU, op operand) { c.A = c.Y; c.setZN(c.A) } func tsxExec(c *CPU, op operand) { c.X = c.SP; c.setZN(c.X) } func txsExec(c *CPU, op operand) { c.SP = c.X } // no flags affected func phaExec(c *CPU, op operand) { c.push(c.A) } func plaExec(c *CPU, op operand) { c.A = c.pop(); c.setZN(c.A) } func phpExec(c *CPU, op operand) { c.push(c.Status | FlagB | FlagU) } func plpExec(c *CPU, op operand) { pulled := c.pop() c.Status = (pulled &^ FlagB) | FlagU } func (c *CPU) addWithCarry(v uint8) { var carryIn uint16 if c.flag(FlagC) { carryIn = 1 } sum := uint16(c.A) + uint16(v) + carryIn result := uint8(sum) c.setFlag(FlagC, sum > 0xFF) c.setFlag(FlagV, (c.A^v)&0x80 == 0 && (c.A^result)&0x80 != 0) c.A = result c.setZN(c.A) } func adcExec(c *CPU, op operand) { c.addWithCarry(c.operandValue(op)) } func sbcExec(c *CPU, op operand) { c.addWithCarry(^c.operandValue(op)) } func andExec(c *CPU, op operand) { c.A &= c.operandValue(op); c.setZN(c.A) } func oraExec(c *CPU, op operand) { c.A |= c.operandValue(op); c.setZN(c.A) } func eorExec(c *CPU, op operand) { c.A ^= c.operandValue(op); c.setZN(c.A) } func bitExec(c *CPU, op operand) { v := c.operandValue(op) c.setFlag(FlagZ, c.A&v == 0) c.setFlag(FlagV, v&0x40 != 0) c.setFlag(FlagN, v&0x80 != 0) } func aslExec(c *CPU, op operand) { v := c.operandValue(op) c.setFlag(FlagC, v&0x80 != 0) result := v << 1 c.writeOperand(op, result) c.setZN(result) } func lsrExec(c *CPU, op operand) { v := c.operandValue(op) c.setFlag(FlagC, v&0x01 != 0) result := v >> 1 c.writeOperand(op, result) c.setZN(result) } func rolExec(c *CPU, op operand) { v := c.operandValue(op) var carryIn uint8 if c.flag(FlagC) { carryIn = 1 } c.setFlag(FlagC, v&0x80 != 0) result := v<<1 | carryIn c.writeOperand(op, result) c.setZN(result) } func rorExec(c *CPU, op operand) { v := c.operandValue(op) var carryIn uint8 if c.flag(FlagC) { carryIn = 0x80 } c.setFlag(FlagC, v&0x01 != 0) result := v>>1 | carryIn c.writeOperand(op, result) c.setZN(result) } func incExec(c *CPU, op operand) { v := c.operandValue(op) + 1; c.writeOperand(op, v); c.setZN(v) } func decExec(c *CPU, op operand) { v := c.operandValue(op) - 1; c.writeOperand(op, v); c.setZN(v) } func inxExec(c *CPU, op operand) { c.X++; c.setZN(c.X) } func dexExec(c *CPU, op operand) { c.X--; c.setZN(c.X) } func inyExec(c *CPU, op operand) { c.Y++; c.setZN(c.Y) } func deyExec(c *CPU, op operand) { c.Y--; c.setZN(c.Y) } func (c *CPU) compare(reg, v uint8) { result := reg - v c.setFlag(FlagC, reg >= v) c.setZN(result) } func cmpExec(c *CPU, op operand) { c.compare(c.A, c.operandValue(op)) } func cpxExec(c *CPU, op operand) { c.compare(c.X, c.operandValue(op)) } func cpyExec(c *CPU, op operand) { c.compare(c.Y, c.operandValue(op)) } func (c *CPU) branch(op operand, cond bool) { if !cond { return } c.extraCycles++ if !samePage(c.PC, op.addr) { c.extraCycles++ } c.PC = op.addr } func bccExec(c *CPU, op operand) { c.branch(op, !c.flag(FlagC)) } func bcsExec(c *CPU, op operand) { c.branch(op, c.flag(FlagC)) } func bneExec(c *CPU, op operand) { c.branch(op, !c.flag(FlagZ)) } func beqExec(c *CPU, op operand) { c.branch(op, c.flag(FlagZ)) } func bplExec(c *CPU, op operand) { c.branch(op, !c.flag(FlagN)) } func bmiExec(c *CPU, op operand) { c.branch(op, c.flag(FlagN)) } func bvcExec(c *CPU, op operand) { c.branch(op, !c.flag(FlagV)) } func bvsExec(c *CPU, op operand) { c.branch(op, c.flag(FlagV)) } func jmpExec(c *CPU, op operand) { c.PC = op.addr } func jsrExec(c *CPU, op operand) { c.push16(c.PC - 1) // address of the last byte of the jsr instruction c.PC = op.addr } func rtsExec(c *CPU, op operand) { c.PC = c.pop16() + 1 } func rtiExec(c *CPU, op operand) { pulled := c.pop() c.Status = (pulled &^ FlagB) | FlagU c.PC = c.pop16() } func clcExec(c *CPU, op operand) { c.setFlag(FlagC, false) } func secExec(c *CPU, op operand) { c.setFlag(FlagC, true) } func cliExec(c *CPU, op operand) { c.setFlag(FlagI, false) } func seiExec(c *CPU, op operand) { c.setFlag(FlagI, true) } func cldExec(c *CPU, op operand) { c.setFlag(FlagD, false) } func sedExec(c *CPU, op operand) { c.setFlag(FlagD, true) } func clvExec(c *CPU, op operand) { c.setFlag(FlagV, false) } func nopExec(c *CPU, op operand) {} func brkExec(c *CPU, op operand) { c.PC++ // brk is logically 2 bytes: the byte after the opcode is skipped c.interrupt(vectorIRQ, true) } func laxExec(c *CPU, op operand) { v := c.operandValue(op) c.A, c.X = v, v c.setZN(v) } func saxExec(c *CPU, op operand) { c.write(op.addr, c.A&c.X) } func dcpExec(c *CPU, op operand) { v := c.operandValue(op) - 1 c.writeOperand(op, v) c.compare(c.A, v) } func sloExec(c *CPU, op operand) { v := c.operandValue(op) c.setFlag(FlagC, v&0x80 != 0) result := v << 1 c.writeOperand(op, result) c.A |= result c.setZN(c.A) } func rlaExec(c *CPU, op operand) { v := c.operandValue(op) var carryIn uint8 if c.flag(FlagC) { carryIn = 1 } c.setFlag(FlagC, v&0x80 != 0) result := v<<1 | carryIn c.writeOperand(op, result) c.A &= result c.setZN(c.A) } func sreExec(c *CPU, op operand) { v := c.operandValue(op) c.setFlag(FlagC, v&0x01 != 0) result := v >> 1 c.writeOperand(op, result) c.A ^= result c.setZN(c.A) } func rraExec(c *CPU, op operand) { v := c.operandValue(op) var carryIn uint8 if c.flag(FlagC) { carryIn = 0x80 } c.setFlag(FlagC, v&0x01 != 0) result := v>>1 | carryIn c.writeOperand(op, result) c.addWithCarry(result) } func iscExec(c *CPU, op operand) { v := c.operandValue(op) + 1 c.writeOperand(op, v) c.addWithCarry(^v) } func jamExec(c *CPU, op operand) { c.Jammed = true c.PC-- }