// Copyright 2011-2012 Paulo Augusto Peccin. See licence.txt distributed with this file.
package org.javatari.general.m6502.instructions;
import org.javatari.general.m6502.Instruction;
import org.javatari.general.m6502.M6502;
import org.javatari.general.m6502.OperandType;
public final class ADC extends Instruction {
public ADC(M6502 cpu, int type) {
super(cpu);
this.type = type;
}
@Override
public int fetch() {
if (type == OperandType.IMM) { ea = cpu.fetchImmediateAddress(); return 2; }
if (type == OperandType.Z_PAGE) { ea = cpu.fetchZeroPageAddress(); return 3; }
if (type == OperandType.Z_PAGE_X) { ea = cpu.fetchZeroPageXAddress(); return 4; }
if (type == OperandType.ABS) { ea = cpu.fetchAbsoluteAddress(); return 4; }
if (type == OperandType.ABS_X) { ea = cpu.fetchAbsoluteXAddress(); return 4 + (cpu.pageCrossed?1:0); }
if (type == OperandType.ABS_Y) { ea = cpu.fetchAbsoluteYAddress(); return 4 + (cpu.pageCrossed?1:0); }
if (type == OperandType.IND_X) { ea = cpu.fetchIndirectXAddress(); return 6; }
if (type == OperandType.IND_Y) { ea = cpu.fetchIndirectYAddress(); return 5 + (cpu.pageCrossed?1:0); }
throw new IllegalStateException("ADC Invalid Operand Type: " + type);
}
@Override
public void execute() {
int b = cpu.bus.readByte(ea);
int uB = M6502.toUnsignedByte(b);
int oldA = cpu.A;
int uOldA = M6502.toUnsignedByte(oldA);
int aux = oldA + b + (cpu.CARRY?1:0);
int uAux = uOldA + uB + (cpu.CARRY?1:0);
// ZERO flag is affected always as in Binary mode
byte newA = (byte) M6502.toUnsignedByte(uAux); // Could be aux
cpu.ZERO = newA == 0;
// But the others flags and the ACC are computed differently in Decimal Mode
if (!cpu.DECIMAL_MODE) {
cpu.NEGATIVE = newA < 0;
cpu.OVERFLOW = aux > 127 || aux < -128;
cpu.CARRY = uAux > 0xff;
cpu.A = newA;
return;
}
// Decimal Mode computations
uAux = (uOldA & 0x0f) + (uB & 0x0f) + (cpu.CARRY?1:0);
if (uAux >= 0x0A) uAux = ((uAux + 0x06) & 0x0f) + 0x10;
aux = (byte)(uOldA & 0xf0) + (byte)(uB & 0xf0) + (byte)uAux; // Holy shit, that was the *unsigned* operation
cpu.NEGATIVE = (aux & 0x80) > 0;
cpu.OVERFLOW = (aux > 127) | (aux < -128);
uAux = (uOldA & 0xf0) + (uB & 0xf0) + uAux;
if (uAux >= 0xA0) uAux += 0x60;
cpu.CARRY = uAux > 0xff;
cpu.A = (byte) M6502.toUnsignedByte(uAux);
}
private final int type;
private int ea;
public static final long serialVersionUID = 1L;
}