gt:           _state.Y = load(read(readAbsoluteZeropageAddressPC()));
context: package de.heiden.jem.models.c64.components.cpu;
  
  import de.heiden.c64dt.bytes.HexUtil;
  import de.heiden.jem.components.bus.BusDevice;
  import de.heiden.jem.components.clock.ClockedComponent;
  import de.heiden.jem.components.clock.Tick;
  import de.heiden.jem.components.ports.*;
  import de.heiden.jem.models.c64.components.memory.Patchable;
  import org.serialthreads.Interruptible;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  import java.util.HashMap;
  import java.util.Map;
  
  /**
   * CPU.
   */
  public class CPU6510 implements ClockedComponent {
    /**
     * Logger.
     */
    private final Logger logger = LoggerFactory.getLogger(getClass());
  
    /**
     * Enable debug features.
     */
    protected static final boolean DEBUG = false;
  
    /**
     * State.
     */
    protected final CPU6510State _state;
  
    /**
     * Tick.
     */
    protected Tick _tick;
  
    /**
     * Bus.
     */
    protected BusDevice _bus;
  
    /**
     * Port at address $0000/$0001 controlled by this cpu.
     */
    private final InputOutputPortImpl _portOut;
  
    /**
     * Input for port at address $0000/$0001 driven by surrounding hardware.
     */
    private final OutputPortImpl _portIn;
  
    /**
     * Port for interrupt.
     */
    private final InputPort _irq;
    private boolean _irqState = false;
  
    /**
     * Port for nmi.
     */
    private final InputPort _nmi;
    private boolean _nmiState = false;
  
    /**
     * Address -> Patch.
     */
    private final Map<Integer, Patch> patches = new HashMap<>();
  
    /**
     * Constructor.
     */
    public CPU6510() {
      _state = new CPU6510State();
  
      // TODO mh: connect to emulated hardware
      _portIn = new OutputPortImpl();
      _portIn.setOutputMask(0xFF);
      _portIn.setOutputData(0xDF);
      _portOut = new InputOutputPortImpl();
      _portOut.connect(_portIn);
  
  
      _irq = new InputPortImpl();
      _irq.addInputPortListener((value, mask) -> {
        // irq is low active
        boolean irq = (value & 0x01) == 0;
        if (irq && !_irqState) {
          _state.triggerIRQ();
        } else if (!irq) {
          // normally irq will be reset when it is about to be executed,
          // but if the irq is not being handled due to the I flag,
          // then it will be reset when the interrupt request is cleared
          _state.resetIRQ();
        }
        _irqState = irq;
      });
  
      _nmi = new InputPortImpl();
      _nmi.addInputPortListener((value, mask) -> {
        // nmi is low active
        boolean nmi = (value & 0x01) == 0;
        if (nmi && !_nmiState) {
          _state.NMI = true;
        } else if (!nmi) {
          _state.NMI = false;
        }
        _nmiState = nmi;
      });
  
      logger.debug("start cpu");
    }
  
    @Override
    public void setTick(Tick tick) {
      _tick = tick;
    }
  
    /**
     * Connect to bus.
     *
     * @param bus cpu bus
     * @require bus != null
     */
    public void connect(BusDevice bus) {
      assert bus != null : "bus != null";
  
      _bus = bus;
    }
  
    /**
     * Add a patch.
     *
     * @param patch Patch
     */
    public void add(Patch patch) {
      assert patch != null : "patch != null";
  
      patches.put(patch.getAddress(), patch);
      writePort(0xFF, 0x0001); // standard memory layout
      patch.replaced = _bus.read(patch.getAddress());
      ((Patchable) _bus).patch(0x02, patch.getAddress()); // add breakpoint
    }
  
    /**
     * Reset CPU.
     * <p/>
     * TODO should be protected?
     */
    @Interruptible
    public void reset() {
      logger.debug("reset");
  
      // wait for first tick
      _tick.waitForTick();
  
      // TODO init something else?
      _state.S = 0xFF;
      _state.setP(0x00); // TODO correct?
      _state.PC = readAbsoluteAddress(0xFFFC);
    }
  
    @Override
    public String getName() {
      return getClass().getSimpleName();
    }
  
    /**
     * CPU port.
     */
    public InputOutputPort getPort() {
      return _portOut;
    }
  
    /**
     * IRQ input signal.
     */
    public InputPort getIRQ() {
      return _irq;
    }
  
    /**
     * NMI input signal.
     */
    public InputPort getNMI() {
      return _nmi;
    }
  
    @Override
    @Interruptible
    public final void run() {
      reset();
  
      final CPU6510State state = _state;
      //noinspection InfiniteLoopStatement
      while (true) {
        if (state.NMI) {
          nmi();
  
        } else if (state.interrupt) {
          irq();
  
        } else {
          execute();
        }
      }
    }
  
    /**
     * Execute NMI.
     */
    @Interruptible
    private void nmi() {
      _state.NMI = false;
      interrupt(0xFFFA);
    }
  
    /**
     * Execute IRQ.
     */
    @Interruptible
    private void irq() {
      CPU6510State state = _state;
      state.resetIRQ();
      state.B = false;
      interrupt(0xFFFE);
    }
  
    @Interruptible
    protected void execute() {
  //      int b = readBytePC();
  //      Opcode opcode = OPCODES[b];
  //      opcode.execute();
      OPCODES[readBytePC()].execute();
    }
  
    // <editor-fold desc="Opcodes">
  
    @SuppressWarnings({"Convert2Lambda", "Anonymous2MethodRef", "SpellCheckingInspection"})
    private final Opcode[] OPCODES =
      {
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $00: BRK (7)
          {
            readBytePC();
            pushWord(_state.PC);
            _state.B = true;
            pushByte(_state.getP());
            _state.I = true;
            _state.PC = readAbsoluteAddress(0xFFFE);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $01: ORA ($XX,X) (6) // izx
          {
            or(read(readZeropageIndirectXAddressPC()));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $02: *KIL (*) // TODO imm?
          {
            // Use opcode $02 as escape
            Patch patch = patches.get(_state.PC - 1);
            if (patch != null) {
              int opcode = patch.execute(_state, _bus);
              if (opcode != Patch.DO_NOT_EXECUTE) {
                OPCODES[opcode].execute();
              }
            } else {
              // no patch -> standard behaviour: crash
              crash();
            }
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $03: *SLO ($XX,X) (8) // izx
          {
            slo(readZeropageIndirectXAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $04: *NOP $XX (3) // zp
          {
            read(readAbsoluteZeropageAddressPC());
            nop();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $05: ORA $XX (3) // zp
          {
            or(read(readAbsoluteZeropageAddressPC()));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $06: ASL $XX (5) // zp
          {
            int addr = readAbsoluteZeropageAddressPC();
            write(shiftLeft(read(addr)), addr);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $07: *SLO $XX (5) // zp
          {
            slo(readAbsoluteZeropageAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $08: PHP (3) // no
          {
            idleRead();
            pushByte(_state.getP());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $09: ORA #$XX (2)
          {
            or(readImmediatePC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $0A: ASL (2) // no
          {
            _state.A = shiftLeft(_state.A);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $0B: *ANC #$XX (2)
          {
            anc(readImmediatePC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $0C: *NOP $XXXX (4) // abs
          {
            read(readAbsoluteAddressPC());
            nop();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $0D: ORA $XXXX (4)
          {
            or(read(readAbsoluteAddressPC()));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $0E: ASL $XXXX (6)
          {
            int addr = readAbsoluteAddressPC();
            write(shiftLeft(read(addr)), addr);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $0F: *SLO $XXXX (6)
          {
            slo(readAbsoluteAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $10: BPL $XXXX (2/3) // rel
          {
            branchIf(!_state.N);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $11: ORA ($XX),Y (5) // izy
          {
            or(read(readZeropageIndirectYAddressPC()));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $12: *KIL (*) // TODO imm?
          {
            crash();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $13: *SLO ($XX),Y (8) // izy
          {
            // TODO 1 tick
            slo(readZeropageIndirectYAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $14: *NOP $XX,X (4) // zpx
          {
            read(readAbsoluteZeropageAddressPC(_state.X));
            nop();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $15: ORA $XX,X (4) // zpx
          {
            or(read(readAbsoluteZeropageAddressPC(_state.X)));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $16: ASL $XX,X (6) // zpx
          {
            int addr = readAbsoluteZeropageAddressPC(_state.X);
            write(shiftLeft(read(addr)), addr);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $17: *SLO $XX,X (6) // zpx
          {
            slo(readAbsoluteZeropageAddressPC(_state.X));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $18: CLC (2) // no
          {
            idleRead(); // during operation
            _state.C = false;
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $19: ORA $XXXX,Y (4)
          {
            or(read(readAbsoluteAddressPC(_state.Y)));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $1A: *NOP (2) // no
          {
            readImpliedPC();
            nop();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $1B: *SLO $XXXX,Y (7)
          {
            // TODO 1 tick
            slo(readAbsoluteAddressPC(_state.Y));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $1C: *NOP $XXXX,X (5) // abx
          {
            read(readAbsoluteAddressPC(_state.X));
            nop();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $1D: ORA $XXXX,X (4)
          {
            or(read(readAbsoluteAddressPC(_state.X)));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $1E: ASL $XXXX,X (7)
          {
            // TODO 1 tick
            int addr = readAbsoluteAddressPC(_state.X);
            write(shiftLeft(read(addr)), addr);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $1F: *SLO $XXXX,X (7)
          {
            // TODO 1 tick
            slo(readAbsoluteAddressPC(_state.X));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $20: JSR $XXXX (6) (TODO rework: see AAY64)
          {
            int addr = readAbsoluteAddressPC();
            int returnAddr = (_state.PC - 1) & 0xFFFF;
            _tick.waitForTick(); // internal operation
            pushWord(returnAddr);
            _state.PC = addr;
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $21: AND ($XX,X) (6) // izx
          {
            and(read(readZeropageIndirectXAddressPC()));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $22: *KIL (*) // TODO imm?
          {
            crash();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $23: *RLA ($XX,X) (8) // izx
          {
            rla(readZeropageIndirectXAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $24: BIT $XX (4) // zp
          {
            bit(read(readAbsoluteZeropageAddressPC()));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $25: AND $XX (3) // zp
          {
            and(read(readAbsoluteZeropageAddressPC()));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $26: ROL $XX (5) // zp
          {
            int addr = readAbsoluteZeropageAddressPC();
            write(rotateLeft(read(addr)), addr);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $27: *RLA $XX (5) // zp
          {
            rla(readAbsoluteZeropageAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $28: PLP (4) // no
          {
            _state.setP(popByte());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $29: AND #$XX (2)
          {
            and(readImmediatePC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $2A: ROL (2) // no
          {
            _state.A = rotateLeft(_state.A);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $2B: *ANC #$XX (2)
          {
            anc(readImmediatePC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $2C: BIT $XXXX (4)
          {
            bit(read(readAbsoluteAddressPC()));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $2D: AND $XXXX (4)
          {
            and(read(readAbsoluteAddressPC()));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $2E: ROL $XXXX (6)
          {
            int addr = readAbsoluteAddressPC();
            write(rotateLeft(read(addr)), addr);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $2F: *RLA $XXXX (6)
          {
            rla(readAbsoluteAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $30: BMI $XXXX (2/3) // rel
          {
            branchIf(_state.N);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $31: AND ($XX),Y (5) // izy
          {
            and(read(readZeropageIndirectYAddressPC()));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $32: *KIL (*) // TODO imm?
          {
            crash();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $33: *RLA ($XX),Y (8) // izy
          {
            // TODO 1 tick
            rla(readZeropageIndirectYAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $34: *NOP $XX,X (4) // zpx
          {
            read(readAbsoluteZeropageAddressPC(_state.X));
            nop();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $35: AND $XX,X (4) // zpx
          {
            and(read(readAbsoluteZeropageAddressPC(_state.X)));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $36: ROL $XX,X (6) // zpx
          {
            int addr = readAbsoluteZeropageAddressPC(_state.X);
            write(rotateLeft(read(addr)), addr);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $37: *RLA $XX,X (6) // zpx
          {
            rla(readAbsoluteZeropageAddressPC(_state.X));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $38: SEC (2) // no
          {
            idleRead(); // during operation
            _state.C = true;
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $39: AND $XXXX,Y (4)
          {
            and(read(readAbsoluteAddressPC(_state.Y)));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $3A: *NOP (2) // no
          {
            readImpliedPC();
            nop();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $3B: *RLA $XXXX,Y (7)
          {
            // TODO 1 tick
            rla(readAbsoluteAddressPC(_state.Y));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $3C: *NOP $XXXX,X (5) // abx
          {
            read(readAbsoluteAddressPC(_state.X));
            nop();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $3D: AND $XXXX,X (4) // abx
          {
            and(read(readAbsoluteAddressPC(_state.X)));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $3E: ROL $XXXX,X (7)
          {
            // TODO 1 tick
            int addr = readAbsoluteAddressPC(_state.X);
            write(rotateLeft(read(addr)), addr);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $3F: *RLA $XXXX,X (7)
          {
            // TODO 1 tick
            rla(readAbsoluteAddressPC(_state.X));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $40: RTI (6)
          {
            // TODO 2 ticks
            _state.setP(popByte());
            _state.PC = popWord();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $41: EOR ($XX,X) (6) // izx
          {
            xor(read(readZeropageIndirectXAddressPC()));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $42: *KIL (*) // TODO imm?
          {
            crash();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $43: *LSE ($XX,X) // izx
          {
            lse(readZeropageIndirectXAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $44: *NOP $XX (3) // zp
          {
            read(readAbsoluteZeropageAddressPC());
            nop();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $45: EOR $XX (3) // zp
          {
            xor(read(readAbsoluteZeropageAddressPC()));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $46: LSR $XX (5) // zp
          {
            int addr = readAbsoluteZeropageAddressPC();
            write(shiftRight(read(addr)), addr);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $47: *LSE $XX // zp
          {
            lse(readAbsoluteZeropageAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $48: PHA (3) // no
          {
            idleRead();
            pushByte(_state.A);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $49: EOR #$XX (2)
          {
            xor(readImmediatePC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $4A: LSR (2) // no
          {
            _state.A = shiftRight(_state.A);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $4B: ALR #$XX (2)
          {
            alr(readImmediatePC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $4C: JMP $XXXX (3) (AAY64)
          {
            _state.PC = readAbsoluteAddressPC();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $4D: EOR $XXXX (4)
          {
            xor(read(readAbsoluteAddressPC()));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $4E: LSR $XXXX (6)
          {
            int addr = readAbsoluteAddressPC();
            write(shiftRight(read(addr)), addr);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $4F: *LSE $XXXX
          {
            lse(readAbsoluteAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $50: BVC $XXXX (2/3) // rel
          {
            branchIf(!_state.V);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $51: EOR ($XX),Y (5) // izy
          {
            xor(read(readZeropageIndirectYAddressPC()));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $52: *KIL (*) // TODO imm?
          {
            crash();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $53: *LSE ($XX),Y // izy
          {
            lse(readZeropageIndirectYAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $54: *NOP $XX,X (4) // zpx
          {
            read(readAbsoluteZeropageAddressPC(_state.X));
            nop();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $55: EOR $XX,X (4) // zpx
          {
            xor(read(readAbsoluteZeropageAddressPC(_state.X)));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $56: LSR $XX,X (6) // zpx
          {
            int addr = readAbsoluteZeropageAddressPC(_state.X);
            write(shiftRight(read(addr)), addr);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $57: *LSE $XX,X // zpx
          {
            lse(readAbsoluteZeropageAddressPC(_state.X));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $58: CLI (2) // no
          {
            idleRead(); // during operation
            _state.cli();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $59: EOR $XXXX,Y (4)
          {
            xor(read(readAbsoluteAddressPC(_state.Y)));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $5A: *NOP (2) // no
          {
            readImpliedPC();
            nop();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $5B: *LSE $XXXX,Y
          {
            lse(readAbsoluteAddressPC(_state.Y));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $5C: *NOP $XXXX,X (5) // abx
          {
            read(readAbsoluteAddressPC(_state.X));
            nop();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $5D: EOR $XXXX,X (4)
          {
            xor(read(readAbsoluteAddressPC(_state.X)));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $5E: LSR $XXXX,X (7)
          {
            // TODO 1 tick
            int addr = readAbsoluteAddressPC(_state.X);
            write(shiftRight(read(addr)), addr);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $5F: *LSE $XXXX,X
          {
            lse(readAbsoluteAddressPC(_state.X));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $60: RTS (6)
          {
            rts();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $61: ADC ($XX,X) (6) // izx
          {
            add(read(readZeropageIndirectXAddressPC()));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $62: *KIL (*) // TODO imm?
          {
            crash();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $63: *RRA ($XX,X) // izx
          {
            rra(readZeropageIndirectXAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $64: *NOP $XX (3) // zp
          {
            read(readAbsoluteZeropageAddressPC());
            nop();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $65: ADC $XX (3) // zp
          {
            add(read(readAbsoluteZeropageAddressPC()));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $66: ROR $XX (5) // zp
          {
            int addr = readAbsoluteZeropageAddressPC();
            write(rotateRight(read(addr)), addr);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $67: *RRA $XX // zp
          {
            rra(readAbsoluteZeropageAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $68: PLA (4) // no
          {
            int a = popByte();
            _state.setZeroNegativeP(a);
            _state.A = a;
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $69: ADC #$XX (2)
          {
            add(readImmediatePC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $6A: ROR (2) // no
          {
            _state.A = rotateRight(_state.A);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $6B: *ARR #$XX (2)
          {
            arr(readImmediatePC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $6C: JMP ($XXXX) (5)
          {
            _state.PC = readIndirectAddress();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $6D: ADC $XXXX (4)
          {
            add(read(readAbsoluteAddressPC()));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $6E: ROR $XXXX (6)
          {
            int addr = readAbsoluteAddressPC();
            write(rotateRight(read(addr)), addr);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $6F: *RRA $XXXX
          {
            rra(readAbsoluteAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $70: BVS $XXXX (2/3) // rel
          {
            branchIf(_state.V);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $71: ADC ($XX),Y (4) // izy
          {
            add(read(readZeropageIndirectYAddressPC()));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $72: *KIL (*) // TODO imm?
          {
            crash();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $73: *RRA ($XX),Y // izy
          {
            rra(readZeropageIndirectYAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $74: *NOP $XX,X (4) // zpx
          {
            read(readAbsoluteZeropageAddressPC(_state.X));
            nop();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $75: ADC $XX,X (4) // zpx
          {
            add(read(readAbsoluteZeropageAddressPC(_state.X)));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $76: ROR $XX,X (6) // zpx
          {
            int addr = readAbsoluteZeropageAddressPC(_state.X);
            write(rotateRight(read(addr)), addr);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $77: *RRA $XX,X // zpx
          {
            rra(readAbsoluteZeropageAddressPC(_state.X));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $78: SEI (2) // no
          {
            idleRead(); // during operation
            _state.sei();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $79: ADC $XXXX,Y (5)
          {
            add(read(readAbsoluteAddressPC(_state.Y)));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $7A: *NOP (2) // no
          {
            readImpliedPC();
            nop();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $7B: *RRA $XXXX,Y
          {
            rra(readAbsoluteAddressPC(_state.Y));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $7C: *NOP $XXXX,X (5) // abx
          {
            read(readAbsoluteAddressPC(_state.X));
            nop();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $7D: ADC $XXXX,X (4)
          {
            add(read(readAbsoluteAddressPC(_state.X)));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $7E: ROR $XXXX,X (7)
          {
            // TODO 1 ticks
            int addr = readAbsoluteAddressPC(_state.X);
            write(rotateRight(read(addr)), addr);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $7F: *RRA $XXXX,X
          {
            rra(readAbsoluteAddressPC(_state.X));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $80: *NOP #$XX (2) // imm
          {
            readImmediatePC();
            nop();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $81: STA ($XX,X) (6) // izx
          {
            write(_state.A, readZeropageIndirectXAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $82: *NOP #$XX (2) // imm
          {
            readImmediatePC();
            nop();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $83: *AXS ($XX,X) // izx
          {
            axs(readZeropageIndirectXAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $84: STY $XX (3) // zp
          {
            write(_state.Y, readAbsoluteZeropageAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $85: STA $XX (3) // zp
          {
            write(_state.A, readAbsoluteZeropageAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $86: STX $XX (3) // zp
          {
            write(_state.X, readAbsoluteZeropageAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $87: *AXS $XX // zp
          {
            axs(readAbsoluteZeropageAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $88: DEY (2) // no
          {
            _state.Y = decrement(_state.Y);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $89: *NOP (2) // imm
          {
            readImmediatePC();
            nop();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $8A: TXA (2) // no
          {
            idleRead();
            _state.A = load(_state.X);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $8B: *XAA #$XX (?)
          {
            xaa(readImmediatePC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $8C: STY $XXXX (4)
          {
            write(_state.Y, readAbsoluteAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $8D: STA $XXXX (4)
          {
            write(_state.A, readAbsoluteAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $8E: STX $XXXX (4)
          {
            write(_state.X, readAbsoluteAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $8F: *AXS $XXXX
          {
            axs(readAbsoluteAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $90: BCC $XXXX (2/3) // rel
          {
            branchIf(!_state.C);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $91: STA ($XX),Y (6) // izy
          {
            write(_state.A, readZeropageIndirectYAddressPC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $92: *KIL (*) // TODO imm?
          {
            crash();
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $93: *AHX ($XX),Y
          {
            int addr = readZeropageIndirectYAddressPC();
            ahx(read(addr), addr);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $94: STY $XX,X (4) // zpx
          {
            write(_state.Y, readAbsoluteZeropageAddressPC(_state.X));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $95: STA $XX,X (4) // zpx
          {
            write(_state.A, readAbsoluteZeropageAddressPC(_state.X));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $96: STX $XX,Y (4) // zpy
          {
            write(_state.X, readAbsoluteZeropageAddressPC(_state.Y));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $97: *AXS $XX,Y // zpy
          {
            axs(readAbsoluteZeropageAddressPC(_state.Y));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $98: TYA (2) // no
          {
            idleRead();
            _state.A = load(_state.Y);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $99: STA $XXXX,Y (5)
          {
            // TODO 1 tick
            write(_state.A, readAbsoluteAddressPC(_state.Y));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $9A: TXS (2) // no
          {
            idleRead(); // during operation
            _state.S = _state.X; // no update of P !!!
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $9B: *TAS $XXXX,Y
          {
            tas(readAbsoluteAddressPC(_state.Y));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $9C: *SHY $XXXX,X
          {
            int addr = readAbsoluteAddressPC(_state.X);
            shy(read(addr), addr);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $9D: STA $XXXX,X (5)
          {
            write(_state.A, readAbsoluteAddressPC(_state.X));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $9E: *SHX $XXXX,Y
          {
            int addr = readAbsoluteAddressPC(_state.Y);
            shx(read(addr), addr);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $9F: *AHX $XXXX,Y
          {
            int addr = readAbsoluteAddressPC(_state.Y);
            ahx(read(addr), addr);
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $A0: LDY #$XX (2) // imm
          {
            _state.Y = load(readImmediatePC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $A1: LDA ($XX,X) (6) // izx
          {
            _state.A = load(read(readZeropageIndirectXAddressPC()));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $A2: LDX #$XX (2) // imm
          {
            _state.X = load(readImmediatePC());
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $A3: *LAX ($XX,X) // izx
          {
            lax(read(readZeropageIndirectXAddressPC()));
          }
        },
  
        new Opcode() {
          @Override
          @Interruptible
          public final void execute() // $A4: LDY $XX (3) // zp
          {
  