//============================================================================
//
// MM     MM  6666  555555  0000   2222
// MMMM MMMM 66  66 55     00  00 22  22
// MM MMM MM 66     55     00  00     22
// MM  M  MM 66666  55555  00  00  22222  --  "A 6502 Microprocessor Emulator"
// MM     MM 66  66     55 00  00 22
// MM     MM 66  66 55  55 00  00 22
// MM     MM  6666   5555   0000  222222
//
// Copyright (c) 1995-2010 by Bradford W. Mott and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: M6502.ins 1724 2009-05-13 13:55:40Z stephena $
//============================================================================

/** 
  Code and cases to emulate each of the 6502 instructions.

  Recompile with the following:
    'm4 M6502.m4 > M6502.ins'

  @author  Bradford W. Mott
  @version $Id: M6502.m4 1724 2009-05-13 13:55:40Z stephena $
*/

#ifndef NOTSAMEPAGE
  #define NOTSAMEPAGE(_addr1, _addr2) (((_addr1) ^ (_addr2)) & 0xff00)
#endif
























































































































































































































case 0x69:
{
  operand = peek(PC++);
}
{
  if(!D)
  {
    Int32 sum = A + operand + (C ? 1 : 0);
    N = sum & 0x80;
    V = ~(A ^ operand) & (A ^ sum) & 0x80;
    notZ = sum & 0xff;
    C = sum & 0xff00;

    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
    Int32 hi = (A & 0xf0) + (operand & 0xf0);
    notZ = (lo+hi) & 0xff;
    if(lo > 0x09)
    {
      hi += 0x10;
      lo += 0x06;
    }
    N = hi & 0x80;
    V = ~(A ^ operand) & (A ^ hi) & 0x80;
    if(hi > 0x90)
      hi += 0x60;
    C = hi & 0xff00;

    A = (lo & 0x0f) + (hi & 0xf0);
  }
}
break;

case 0x65:
{
  operand = peek(peek(PC++));
}
{
  if(!D)
  {
    Int32 sum = A + operand + (C ? 1 : 0);
    N = sum & 0x80;
    V = ~(A ^ operand) & (A ^ sum) & 0x80;
    notZ = sum & 0xff;
    C = sum & 0xff00;

    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
    Int32 hi = (A & 0xf0) + (operand & 0xf0);
    notZ = (lo+hi) & 0xff;
    if(lo > 0x09)
    {
      hi += 0x10;
      lo += 0x06;
    }
    N = hi & 0x80;
    V = ~(A ^ operand) & (A ^ hi) & 0x80;
    if(hi > 0x90)
      hi += 0x60;
    C = hi & 0xff00;

    A = (lo & 0x0f) + (hi & 0xf0);
  }
}
break;

case 0x75:
{
  uInt8 address = peek(PC++);
  peek(address);
  address += X;
  operand = peek(address); 
}
{
  if(!D)
  {
    Int32 sum = A + operand + (C ? 1 : 0);
    N = sum & 0x80;
    V = ~(A ^ operand) & (A ^ sum) & 0x80;
    notZ = sum & 0xff;
    C = sum & 0xff00;

    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
    Int32 hi = (A & 0xf0) + (operand & 0xf0);
    notZ = (lo+hi) & 0xff;
    if(lo > 0x09)
    {
      hi += 0x10;
      lo += 0x06;
    }
    N = hi & 0x80;
    V = ~(A ^ operand) & (A ^ hi) & 0x80;
    if(hi > 0x90)
      hi += 0x60;
    C = hi & 0xff00;

    A = (lo & 0x0f) + (hi & 0xf0);
  }
}
break;

case 0x6d:
{
  uInt16 address = peek(PC++);
  address |= ((uInt16)peek(PC++) << 8);
  operand = peek(address);
}
{
  if(!D)
  {
    Int32 sum = A + operand + (C ? 1 : 0);
    N = sum & 0x80;
    V = ~(A ^ operand) & (A ^ sum) & 0x80;
    notZ = sum & 0xff;
    C = sum & 0xff00;

    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
    Int32 hi = (A & 0xf0) + (operand & 0xf0);
    notZ = (lo+hi) & 0xff;
    if(lo > 0x09)
    {
      hi += 0x10;
      lo += 0x06;
    }
    N = hi & 0x80;
    V = ~(A ^ operand) & (A ^ hi) & 0x80;
    if(hi > 0x90)
      hi += 0x60;
    C = hi & 0xff00;

    A = (lo & 0x0f) + (hi & 0xf0);
  }
}
break;

case 0x7d:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  operand = peek(high | (uInt8)(low + X));
  if((low + X) > 0xFF)
    operand = peek((high | low) + X);
}
{
  if(!D)
  {
    Int32 sum = A + operand + (C ? 1 : 0);
    N = sum & 0x80;
    V = ~(A ^ operand) & (A ^ sum) & 0x80;
    notZ = sum & 0xff;
    C = sum & 0xff00;

    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
    Int32 hi = (A & 0xf0) + (operand & 0xf0);
    notZ = (lo+hi) & 0xff;
    if(lo > 0x09)
    {
      hi += 0x10;
      lo += 0x06;
    }
    N = hi & 0x80;
    V = ~(A ^ operand) & (A ^ hi) & 0x80;
    if(hi > 0x90)
      hi += 0x60;
    C = hi & 0xff00;

    A = (lo & 0x0f) + (hi & 0xf0);
  }
}
break;

case 0x79:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  operand = peek(high | (uInt8)(low + Y));
  if((low + Y) > 0xFF)
    operand = peek((high | low) + Y);
}
{
  if(!D)
  {
    Int32 sum = A + operand + (C ? 1 : 0);
    N = sum & 0x80;
    V = ~(A ^ operand) & (A ^ sum) & 0x80;
    notZ = sum & 0xff;
    C = sum & 0xff00;

    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
    Int32 hi = (A & 0xf0) + (operand & 0xf0);
    notZ = (lo+hi) & 0xff;
    if(lo > 0x09)
    {
      hi += 0x10;
      lo += 0x06;
    }
    N = hi & 0x80;
    V = ~(A ^ operand) & (A ^ hi) & 0x80;
    if(hi > 0x90)
      hi += 0x60;
    C = hi & 0xff00;

    A = (lo & 0x0f) + (hi & 0xf0);
  }
}
break;

case 0x61:
{
  uInt8 pointer = peek(PC++);
  peek(pointer);
  pointer += X;
  uInt16 address = peek(pointer++);
  address |= ((uInt16)peek(pointer) << 8);
  operand = peek(address);
}
{
  if(!D)
  {
    Int32 sum = A + operand + (C ? 1 : 0);
    N = sum & 0x80;
    V = ~(A ^ operand) & (A ^ sum) & 0x80;
    notZ = sum & 0xff;
    C = sum & 0xff00;

    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
    Int32 hi = (A & 0xf0) + (operand & 0xf0);
    notZ = (lo+hi) & 0xff;
    if(lo > 0x09)
    {
      hi += 0x10;
      lo += 0x06;
    }
    N = hi & 0x80;
    V = ~(A ^ operand) & (A ^ hi) & 0x80;
    if(hi > 0x90)
      hi += 0x60;
    C = hi & 0xff00;

    A = (lo & 0x0f) + (hi & 0xf0);
  }
}
break;

case 0x71:
{
  uInt8 pointer = peek(PC++);
  uInt16 low = peek(pointer++);
  uInt16 high = ((uInt16)peek(pointer) << 8);
  operand = peek(high | (uInt8)(low + Y));
  if((low + Y) > 0xFF)
    operand = peek((high | low) + Y);
}
{
  if(!D)
  {
    Int32 sum = A + operand + (C ? 1 : 0);
    N = sum & 0x80;
    V = ~(A ^ operand) & (A ^ sum) & 0x80;
    notZ = sum & 0xff;
    C = sum & 0xff00;

    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
    Int32 hi = (A & 0xf0) + (operand & 0xf0);
    notZ = (lo+hi) & 0xff;
    if(lo > 0x09)
    {
      hi += 0x10;
      lo += 0x06;
    }
    N = hi & 0x80;
    V = ~(A ^ operand) & (A ^ hi) & 0x80;
    if(hi > 0x90)
      hi += 0x60;
    C = hi & 0xff00;

    A = (lo & 0x0f) + (hi & 0xf0);
  }
}
break;


case 0x4b:
{
  operand = peek(PC++);
}
{
  A &= operand;

  // Set carry flag according to the right-most bit
  C = A & 0x01;

  A = (A >> 1) & 0x7f;

  notZ = A;
  N = A & 0x80;
}
break;


case 0x0b:
case 0x2b:
{
  operand = peek(PC++);
}
{
  A &= operand;
  notZ = A;
  N = A & 0x80;
  C = N;
}
break;


case 0x29:
{
  operand = peek(PC++);
}
{
  A &= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x25:
{
  operand = peek(peek(PC++));
}
{
  A &= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x35:
{
  uInt8 address = peek(PC++);
  peek(address);
  address += X;
  operand = peek(address); 
}
{
  A &= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x2d:
{
  uInt16 address = peek(PC++);
  address |= ((uInt16)peek(PC++) << 8);
  operand = peek(address);
}
{
  A &= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x3d:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  operand = peek(high | (uInt8)(low + X));
  if((low + X) > 0xFF)
    operand = peek((high | low) + X);
}
{
  A &= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x39:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  operand = peek(high | (uInt8)(low + Y));
  if((low + Y) > 0xFF)
    operand = peek((high | low) + Y);
}
{
  A &= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x21:
{
  uInt8 pointer = peek(PC++);
  peek(pointer);
  pointer += X;
  uInt16 address = peek(pointer++);
  address |= ((uInt16)peek(pointer) << 8);
  operand = peek(address);
}
{
  A &= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x31:
{
  uInt8 pointer = peek(PC++);
  uInt16 low = peek(pointer++);
  uInt16 high = ((uInt16)peek(pointer) << 8);
  operand = peek(high | (uInt8)(low + Y));
  if((low + Y) > 0xFF)
    operand = peek((high | low) + Y);
}
{
  A &= operand;
  notZ = A;
  N = A & 0x80;
}
break;


case 0x8b:
{
  operand = peek(PC++);
}
{
  // NOTE: The implementation of this instruction is based on
  // information from the 64doc.txt file.  This instruction is
  // reported to be unstable!
  A = (A | 0xee) & X & operand;
  notZ = A;
  N = A & 0x80;
}
break;


case 0x6b:
{
  operand = peek(PC++);
}
{
  // NOTE: The implementation of this instruction is based on
  // information from the 64doc.txt file.  There are mixed
  // reports on its operation!
  if(!D)
  {
    A &= operand;
    A = ((A >> 1) & 0x7f) | (C ? 0x80 : 0x00);

    C = A & 0x40;
    V = (A & 0x40) ^ ((A & 0x20) << 1);

    notZ = A;
    N = A & 0x80;
  }
  else
  {
    uInt8 value = A & operand;

    A = ((value >> 1) & 0x7f) | (C ? 0x80 : 0x00);
    N = C;
    notZ = A;
    V = (value ^ A) & 0x40;

    if(((value & 0x0f) + (value & 0x01)) > 0x05)
    {
      A = (A & 0xf0) | ((A + 0x06) & 0x0f);
    }
    
    if(((value & 0xf0) + (value & 0x10)) > 0x50) 
    {
      A = (A + 0x60) & 0xff;
      C = 1;
    }
    else
    {
      C = 0;
    }
  }
}
break;


case 0x0a:
{
  peek(PC);
}
{
  // Set carry flag according to the left-most bit in A
  C = A & 0x80;

  A <<= 1;

  notZ = A;
  N = A & 0x80;
}
break;

case 0x06:
{
  operandAddress = peek(PC++);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the left-most bit in value
  C = operand & 0x80;

  operand <<= 1;
  poke(operandAddress, operand);

  notZ = operand;
  N = operand & 0x80;
}
break;

case 0x16:
{
  operandAddress = peek(PC++);
  peek(operandAddress);
  operandAddress = (operandAddress + X) & 0xFF;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the left-most bit in value
  C = operand & 0x80;

  operand <<= 1;
  poke(operandAddress, operand);

  notZ = operand;
  N = operand & 0x80;
}
break;

case 0x0e:
{
  operandAddress = peek(PC++);
  operandAddress |= ((uInt16)peek(PC++) << 8);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the left-most bit in value
  C = operand & 0x80;

  operand <<= 1;
  poke(operandAddress, operand);

  notZ = operand;
  N = operand & 0x80;
}
break;

case 0x1e:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + X));
  operandAddress = (high | low) + X;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the left-most bit in value
  C = operand & 0x80;

  operand <<= 1;
  poke(operandAddress, operand);

  notZ = operand;
  N = operand & 0x80;
}
break;


case 0x90:
{
  operand = peek(PC++);
}
{
  if(!C)
  {
    peek(PC);
    uInt16 address = PC + (Int8)operand;
    if(NOTSAMEPAGE(PC, address))
      peek((PC & 0xFF00) | (address & 0x00FF));
    PC = address;
  }
}
break;


case 0xb0:
{
  operand = peek(PC++);
}
{
  if(C)
  {
    peek(PC);
    uInt16 address = PC + (Int8)operand;
    if(NOTSAMEPAGE(PC, address))
      peek((PC & 0xFF00) | (address & 0x00FF));
    PC = address;
  }
}
break;


case 0xf0:
{
  operand = peek(PC++);
}
{
  if(!notZ)
  {
    peek(PC);
    uInt16 address = PC + (Int8)operand;
    if(NOTSAMEPAGE(PC, address))
      peek((PC & 0xFF00) | (address & 0x00FF));
    PC = address;
  }
}
break;


case 0x24:
{
  operand = peek(peek(PC++));
}
{
  notZ = (A & operand);
  N = operand & 0x80;
  V = operand & 0x40;
}
break;

case 0x2C:
{
  uInt16 address = peek(PC++);
  address |= ((uInt16)peek(PC++) << 8);
  operand = peek(address);
}
{
  notZ = (A & operand);
  N = operand & 0x80;
  V = operand & 0x40;
}
break;


case 0x30:
{
  operand = peek(PC++);
}
{
  if(N)
  {
    peek(PC);
    uInt16 address = PC + (Int8)operand;
    if(NOTSAMEPAGE(PC, address))
      peek((PC & 0xFF00) | (address & 0x00FF));
    PC = address;
  }
}
break;


case 0xD0:
{
  operand = peek(PC++);
}
{
  if(notZ)
  {
    peek(PC);
    uInt16 address = PC + (Int8)operand;
    if(NOTSAMEPAGE(PC, address))
      peek((PC & 0xFF00) | (address & 0x00FF));
    PC = address;
  }
}
break;


case 0x10:
{
  operand = peek(PC++);
}
{
  if(!N)
  {
    peek(PC);
    uInt16 address = PC + (Int8)operand;
    if(NOTSAMEPAGE(PC, address))
      peek((PC & 0xFF00) | (address & 0x00FF));
    PC = address;
  }
}
break;


case 0x00:
{
  peek(PC++);

  B = true;

  poke(0x0100 + SP--, PC >> 8);
  poke(0x0100 + SP--, PC & 0x00ff);
  poke(0x0100 + SP--, PS());

  I = true;

  PC = peek(0xfffe);
  PC |= ((uInt16)peek(0xffff) << 8);
}
break;


case 0x50:
{
  operand = peek(PC++);
}
{
  if(!V)
  {
    peek(PC);
    uInt16 address = PC + (Int8)operand;
    if(NOTSAMEPAGE(PC, address))
      peek((PC & 0xFF00) | (address & 0x00FF));
    PC = address;
  }
}
break;


case 0x70:
{
  operand = peek(PC++);
}
{
  if(V)
  {
    peek(PC);
    uInt16 address = PC + (Int8)operand;
    if(NOTSAMEPAGE(PC, address))
      peek((PC & 0xFF00) | (address & 0x00FF));
    PC = address;
  }
}
break;


case 0x18:
{
  peek(PC);
}
{
  C = false;
}
break;


case 0xd8:
{
  peek(PC);
}
{
  D = false;
}
break;


case 0x58:
{
  peek(PC);
}
{
  I = false;
}
break;


case 0xb8:
{
  peek(PC);
}
{
  V = false;
}
break;


case 0xc9:
{
  operand = peek(PC++);
}
{
  uInt16 value = (uInt16)A - (uInt16)operand;

  notZ = value;
  N = value & 0x0080;
  C = !(value & 0x0100);
}
break;

case 0xc5:
{
  operand = peek(peek(PC++));
}
{
  uInt16 value = (uInt16)A - (uInt16)operand;

  notZ = value;
  N = value & 0x0080;
  C = !(value & 0x0100);
}
break;

case 0xd5:
{
  uInt8 address = peek(PC++);
  peek(address);
  address += X;
  operand = peek(address); 
}
{
  uInt16 value = (uInt16)A - (uInt16)operand;

  notZ = value;
  N = value & 0x0080;
  C = !(value & 0x0100);
}
break;

case 0xcd:
{
  uInt16 address = peek(PC++);
  address |= ((uInt16)peek(PC++) << 8);
  operand = peek(address);
}
{
  uInt16 value = (uInt16)A - (uInt16)operand;

  notZ = value;
  N = value & 0x0080;
  C = !(value & 0x0100);
}
break;

case 0xdd:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  operand = peek(high | (uInt8)(low + X));
  if((low + X) > 0xFF)
    operand = peek((high | low) + X);
}
{
  uInt16 value = (uInt16)A - (uInt16)operand;

  notZ = value;
  N = value & 0x0080;
  C = !(value & 0x0100);
}
break;

case 0xd9:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  operand = peek(high | (uInt8)(low + Y));
  if((low + Y) > 0xFF)
    operand = peek((high | low) + Y);
}
{
  uInt16 value = (uInt16)A - (uInt16)operand;

  notZ = value;
  N = value & 0x0080;
  C = !(value & 0x0100);
}
break;

case 0xc1:
{
  uInt8 pointer = peek(PC++);
  peek(pointer);
  pointer += X;
  uInt16 address = peek(pointer++);
  address |= ((uInt16)peek(pointer) << 8);
  operand = peek(address);
}
{
  uInt16 value = (uInt16)A - (uInt16)operand;

  notZ = value;
  N = value & 0x0080;
  C = !(value & 0x0100);
}
break;

case 0xd1:
{
  uInt8 pointer = peek(PC++);
  uInt16 low = peek(pointer++);
  uInt16 high = ((uInt16)peek(pointer) << 8);
  operand = peek(high | (uInt8)(low + Y));
  if((low + Y) > 0xFF)
    operand = peek((high | low) + Y);
}
{
  uInt16 value = (uInt16)A - (uInt16)operand;

  notZ = value;
  N = value & 0x0080;
  C = !(value & 0x0100);
}
break;


case 0xe0:
{
  operand = peek(PC++);
}
{
  uInt16 value = (uInt16)X - (uInt16)operand;

  notZ = value;
  N = value & 0x0080;
  C = !(value & 0x0100);
}
break;

case 0xe4:
{
  operand = peek(peek(PC++));
}
{
  uInt16 value = (uInt16)X - (uInt16)operand;

  notZ = value;
  N = value & 0x0080;
  C = !(value & 0x0100);
}
break;

case 0xec:
{
  uInt16 address = peek(PC++);
  address |= ((uInt16)peek(PC++) << 8);
  operand = peek(address);
}
{
  uInt16 value = (uInt16)X - (uInt16)operand;

  notZ = value;
  N = value & 0x0080;
  C = !(value & 0x0100);
}
break;


case 0xc0:
{
  operand = peek(PC++);
}
{
  uInt16 value = (uInt16)Y - (uInt16)operand;

  notZ = value;
  N = value & 0x0080;
  C = !(value & 0x0100);
}
break;

case 0xc4:
{
  operand = peek(peek(PC++));
}
{
  uInt16 value = (uInt16)Y - (uInt16)operand;

  notZ = value;
  N = value & 0x0080;
  C = !(value & 0x0100);
}
break;

case 0xcc:
{
  uInt16 address = peek(PC++);
  address |= ((uInt16)peek(PC++) << 8);
  operand = peek(address);
}
{
  uInt16 value = (uInt16)Y - (uInt16)operand;

  notZ = value;
  N = value & 0x0080;
  C = !(value & 0x0100);
}
break;


case 0xcf:
{
  operandAddress = peek(PC++);
  operandAddress |= ((uInt16)peek(PC++) << 8);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = operand - 1;
  poke(operandAddress, value);

  uInt16 value2 = (uInt16)A - (uInt16)value;
  notZ = value2;
  N = value2 & 0x0080;
  C = !(value2 & 0x0100);
}
break;

case 0xdf:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + X));
  operandAddress = (high | low) + X;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = operand - 1;
  poke(operandAddress, value);

  uInt16 value2 = (uInt16)A - (uInt16)value;
  notZ = value2;
  N = value2 & 0x0080;
  C = !(value2 & 0x0100);
}
break;

case 0xdb:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + Y));
  operandAddress = (high | low) + Y;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = operand - 1;
  poke(operandAddress, value);

  uInt16 value2 = (uInt16)A - (uInt16)value;
  notZ = value2;
  N = value2 & 0x0080;
  C = !(value2 & 0x0100);
}
break;

case 0xc7:
{
  operandAddress = peek(PC++);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = operand - 1;
  poke(operandAddress, value);

  uInt16 value2 = (uInt16)A - (uInt16)value;
  notZ = value2;
  N = value2 & 0x0080;
  C = !(value2 & 0x0100);
}
break;

case 0xd7:
{
  operandAddress = peek(PC++);
  peek(operandAddress);
  operandAddress = (operandAddress + X) & 0xFF;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = operand - 1;
  poke(operandAddress, value);

  uInt16 value2 = (uInt16)A - (uInt16)value;
  notZ = value2;
  N = value2 & 0x0080;
  C = !(value2 & 0x0100);
}
break;

case 0xc3:
{
  uInt8 pointer = peek(PC++);
  peek(pointer);
  pointer += X;
  operandAddress = peek(pointer++);
  operandAddress |= ((uInt16)peek(pointer) << 8);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = operand - 1;
  poke(operandAddress, value);

  uInt16 value2 = (uInt16)A - (uInt16)value;
  notZ = value2;
  N = value2 & 0x0080;
  C = !(value2 & 0x0100);
}
break;

case 0xd3:
{
  uInt8 pointer = peek(PC++);
  uInt16 low = peek(pointer++);
  uInt16 high = ((uInt16)peek(pointer) << 8);
  peek(high | (uInt8)(low + Y));
  operandAddress = (high | low) + Y;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = operand - 1;
  poke(operandAddress, value);

  uInt16 value2 = (uInt16)A - (uInt16)value;
  notZ = value2;
  N = value2 & 0x0080;
  C = !(value2 & 0x0100);
}
break;


case 0xc6:
{
  operandAddress = peek(PC++);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = operand - 1;
  poke(operandAddress, value);

  notZ = value;
  N = value & 0x80;
}
break;

case 0xd6:
{
  operandAddress = peek(PC++);
  peek(operandAddress);
  operandAddress = (operandAddress + X) & 0xFF;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = operand - 1;
  poke(operandAddress, value);

  notZ = value;
  N = value & 0x80;
}
break;

case 0xce:
{
  operandAddress = peek(PC++);
  operandAddress |= ((uInt16)peek(PC++) << 8);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = operand - 1;
  poke(operandAddress, value);

  notZ = value;
  N = value & 0x80;
}
break;

case 0xde:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + X));
  operandAddress = (high | low) + X;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = operand - 1;
  poke(operandAddress, value);

  notZ = value;
  N = value & 0x80;
}
break;


case 0xca:
{
  peek(PC);
}
{
  X--;

  notZ = X;
  N = X & 0x80;
}
break;


case 0x88:
{
  peek(PC);
}
{
  Y--;

  notZ = Y;
  N = Y & 0x80;
}
break;


case 0x49:
{
  operand = peek(PC++);
}
{
  A ^= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x45:
{
  operand = peek(peek(PC++));
}
{
  A ^= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x55:
{
  uInt8 address = peek(PC++);
  peek(address);
  address += X;
  operand = peek(address); 
}
{
  A ^= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x4d:
{
  uInt16 address = peek(PC++);
  address |= ((uInt16)peek(PC++) << 8);
  operand = peek(address);
}
{
  A ^= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x5d:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  operand = peek(high | (uInt8)(low + X));
  if((low + X) > 0xFF)
    operand = peek((high | low) + X);
}
{
  A ^= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x59:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  operand = peek(high | (uInt8)(low + Y));
  if((low + Y) > 0xFF)
    operand = peek((high | low) + Y);
}
{
  A ^= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x41:
{
  uInt8 pointer = peek(PC++);
  peek(pointer);
  pointer += X;
  uInt16 address = peek(pointer++);
  address |= ((uInt16)peek(pointer) << 8);
  operand = peek(address);
}
{
  A ^= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x51:
{
  uInt8 pointer = peek(PC++);
  uInt16 low = peek(pointer++);
  uInt16 high = ((uInt16)peek(pointer) << 8);
  operand = peek(high | (uInt8)(low + Y));
  if((low + Y) > 0xFF)
    operand = peek((high | low) + Y);
}
{
  A ^= operand;
  notZ = A;
  N = A & 0x80;
}
break;


case 0xe6:
{
  operandAddress = peek(PC++);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = operand + 1;
  poke(operandAddress, value);

  notZ = value;
  N = value & 0x80;
}
break;

case 0xf6:
{
  operandAddress = peek(PC++);
  peek(operandAddress);
  operandAddress = (operandAddress + X) & 0xFF;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = operand + 1;
  poke(operandAddress, value);

  notZ = value;
  N = value & 0x80;
}
break;

case 0xee:
{
  operandAddress = peek(PC++);
  operandAddress |= ((uInt16)peek(PC++) << 8);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = operand + 1;
  poke(operandAddress, value);

  notZ = value;
  N = value & 0x80;
}
break;

case 0xfe:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + X));
  operandAddress = (high | low) + X;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = operand + 1;
  poke(operandAddress, value);

  notZ = value;
  N = value & 0x80;
}
break;


case 0xe8:
{
  peek(PC);
}
{
  X++;
  notZ = X;
  N = X & 0x80;
}
break;


case 0xc8:
{
  peek(PC);
}
{
  Y++;
  notZ = Y;
  N = Y & 0x80;
}
break;


case 0xef:
{
  operandAddress = peek(PC++);
  operandAddress |= ((uInt16)peek(PC++) << 8);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  operand = operand + 1;
  poke(operandAddress, operand);

  // N, V, Z, C flags are the same in either mode (C calculated at the end)
  Int32 sum = A - operand - (C ? 0 : 1);
  N = sum & 0x80;
  V = (A ^ operand) & (A ^ sum) & 0x80;
  notZ = sum & 0xff;

  if(!D)
  {
    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
    Int32 hi = (A & 0xf0) - (operand & 0xf0);
    if(lo & 0x10)
    {
      lo -= 6;
      hi--;
    }
    if(hi & 0x0100)
      hi -= 0x60;

    A = (lo & 0x0f) | (hi & 0xf0);
  }
  C = (sum & 0xff00) == 0;
}
break;

case 0xff:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + X));
  operandAddress = (high | low) + X;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  operand = operand + 1;
  poke(operandAddress, operand);

  // N, V, Z, C flags are the same in either mode (C calculated at the end)
  Int32 sum = A - operand - (C ? 0 : 1);
  N = sum & 0x80;
  V = (A ^ operand) & (A ^ sum) & 0x80;
  notZ = sum & 0xff;

  if(!D)
  {
    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
    Int32 hi = (A & 0xf0) - (operand & 0xf0);
    if(lo & 0x10)
    {
      lo -= 6;
      hi--;
    }
    if(hi & 0x0100)
      hi -= 0x60;

    A = (lo & 0x0f) | (hi & 0xf0);
  }
  C = (sum & 0xff00) == 0;
}
break;

case 0xfb:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + Y));
  operandAddress = (high | low) + Y;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  operand = operand + 1;
  poke(operandAddress, operand);

  // N, V, Z, C flags are the same in either mode (C calculated at the end)
  Int32 sum = A - operand - (C ? 0 : 1);
  N = sum & 0x80;
  V = (A ^ operand) & (A ^ sum) & 0x80;
  notZ = sum & 0xff;

  if(!D)
  {
    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
    Int32 hi = (A & 0xf0) - (operand & 0xf0);
    if(lo & 0x10)
    {
      lo -= 6;
      hi--;
    }
    if(hi & 0x0100)
      hi -= 0x60;

    A = (lo & 0x0f) | (hi & 0xf0);
  }
  C = (sum & 0xff00) == 0;
}
break;

case 0xe7:
{
  operandAddress = peek(PC++);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  operand = operand + 1;
  poke(operandAddress, operand);

  // N, V, Z, C flags are the same in either mode (C calculated at the end)
  Int32 sum = A - operand - (C ? 0 : 1);
  N = sum & 0x80;
  V = (A ^ operand) & (A ^ sum) & 0x80;
  notZ = sum & 0xff;

  if(!D)
  {
    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
    Int32 hi = (A & 0xf0) - (operand & 0xf0);
    if(lo & 0x10)
    {
      lo -= 6;
      hi--;
    }
    if(hi & 0x0100)
      hi -= 0x60;

    A = (lo & 0x0f) | (hi & 0xf0);
  }
  C = (sum & 0xff00) == 0;
}
break;

case 0xf7:
{
  operandAddress = peek(PC++);
  peek(operandAddress);
  operandAddress = (operandAddress + X) & 0xFF;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  operand = operand + 1;
  poke(operandAddress, operand);

  // N, V, Z, C flags are the same in either mode (C calculated at the end)
  Int32 sum = A - operand - (C ? 0 : 1);
  N = sum & 0x80;
  V = (A ^ operand) & (A ^ sum) & 0x80;
  notZ = sum & 0xff;

  if(!D)
  {
    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
    Int32 hi = (A & 0xf0) - (operand & 0xf0);
    if(lo & 0x10)
    {
      lo -= 6;
      hi--;
    }
    if(hi & 0x0100)
      hi -= 0x60;

    A = (lo & 0x0f) | (hi & 0xf0);
  }
  C = (sum & 0xff00) == 0;
}
break;

case 0xe3:
{
  uInt8 pointer = peek(PC++);
  peek(pointer);
  pointer += X;
  operandAddress = peek(pointer++);
  operandAddress |= ((uInt16)peek(pointer) << 8);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  operand = operand + 1;
  poke(operandAddress, operand);

  // N, V, Z, C flags are the same in either mode (C calculated at the end)
  Int32 sum = A - operand - (C ? 0 : 1);
  N = sum & 0x80;
  V = (A ^ operand) & (A ^ sum) & 0x80;
  notZ = sum & 0xff;

  if(!D)
  {
    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
    Int32 hi = (A & 0xf0) - (operand & 0xf0);
    if(lo & 0x10)
    {
      lo -= 6;
      hi--;
    }
    if(hi & 0x0100)
      hi -= 0x60;

    A = (lo & 0x0f) | (hi & 0xf0);
  }
  C = (sum & 0xff00) == 0;
}
break;

case 0xf3:
{
  uInt8 pointer = peek(PC++);
  uInt16 low = peek(pointer++);
  uInt16 high = ((uInt16)peek(pointer) << 8);
  peek(high | (uInt8)(low + Y));
  operandAddress = (high | low) + Y;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  operand = operand + 1;
  poke(operandAddress, operand);

  // N, V, Z, C flags are the same in either mode (C calculated at the end)
  Int32 sum = A - operand - (C ? 0 : 1);
  N = sum & 0x80;
  V = (A ^ operand) & (A ^ sum) & 0x80;
  notZ = sum & 0xff;

  if(!D)
  {
    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
    Int32 hi = (A & 0xf0) - (operand & 0xf0);
    if(lo & 0x10)
    {
      lo -= 6;
      hi--;
    }
    if(hi & 0x0100)
      hi -= 0x60;

    A = (lo & 0x0f) | (hi & 0xf0);
  }
  C = (sum & 0xff00) == 0;
}
break;


case 0x4c:
{
  operandAddress = peek(PC++);
  operandAddress |= ((uInt16)peek(PC++) << 8);
}
{
  PC = operandAddress;
}
break;

case 0x6c:
{
  uInt16 addr = peek(PC++);
  addr |= ((uInt16)peek(PC++) << 8);

  // Simulate the error in the indirect addressing mode!
  uInt16 high = NOTSAMEPAGE(addr, addr + 1) ? (addr & 0xff00) : (addr + 1);

  operandAddress = peek(addr);
  operandAddress |= ((uInt16)peek(high) << 8);
}
{
  PC = operandAddress;
}
break;


case 0x20:
{
  uInt8 low = peek(PC++);
  peek(0x0100 + SP);

  // It seems that the 650x does not push the address of the next instruction
  // on the stack it actually pushes the address of the next instruction
  // minus one.  This is compensated for in the RTS instruction
  poke(0x0100 + SP--, PC >> 8);
  poke(0x0100 + SP--, PC & 0xff);

  PC = low | ((uInt16)peek(PC++) << 8); 
}
break;


case 0xbb:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  operand = peek(high | (uInt8)(low + Y));
  if((low + Y) > 0xFF)
    operand = peek((high | low) + Y);
}
{
  A = X = SP = SP & operand;
  notZ = A;
  N = A & 0x80;
}
break;


case 0xaf:
{
  uInt16 address = peek(PC++);
  address |= ((uInt16)peek(PC++) << 8);
  operand = peek(address);
}
{
  A = operand;
  X = operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0xbf:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  operand = peek(high | (uInt8)(low + Y));
  if((low + Y) > 0xFF)
    operand = peek((high | low) + Y);
}
{
  A = operand;
  X = operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0xa7:
{
  operand = peek(peek(PC++));
}
{
  A = operand;
  X = operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0xb7:
{
  uInt8 address = peek(PC++);
  peek(address);
  address += Y;
  operand = peek(address); 
}
{
  A = operand;
  X = operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0xa3:
{
  uInt8 pointer = peek(PC++);
  peek(pointer);
  pointer += X;
  uInt16 address = peek(pointer++);
  address |= ((uInt16)peek(pointer) << 8);
  operand = peek(address);
}
{
  A = operand;
  X = operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0xb3:
{
  uInt8 pointer = peek(PC++);
  uInt16 low = peek(pointer++);
  uInt16 high = ((uInt16)peek(pointer) << 8);
  operand = peek(high | (uInt8)(low + Y));
  if((low + Y) > 0xFF)
    operand = peek((high | low) + Y);
}
{
  A = operand;
  X = operand;
  notZ = A;
  N = A & 0x80;
}
break;


case 0xa9:
{
  operand = peek(PC++);
}
{
  A = operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0xa5:
{
  operand = peek(peek(PC++));
}
{
  A = operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0xb5:
{
  uInt8 address = peek(PC++);
  peek(address);
  address += X;
  operand = peek(address); 
}
{
  A = operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0xad:
{
  uInt16 address = peek(PC++);
  address |= ((uInt16)peek(PC++) << 8);
  operand = peek(address);
}
{
  A = operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0xbd:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  operand = peek(high | (uInt8)(low + X));
  if((low + X) > 0xFF)
    operand = peek((high | low) + X);
}
{
  A = operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0xb9:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  operand = peek(high | (uInt8)(low + Y));
  if((low + Y) > 0xFF)
    operand = peek((high | low) + Y);
}
{
  A = operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0xa1:
{
  uInt8 pointer = peek(PC++);
  peek(pointer);
  pointer += X;
  uInt16 address = peek(pointer++);
  address |= ((uInt16)peek(pointer) << 8);
  operand = peek(address);
}
{
  A = operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0xb1:
{
  uInt8 pointer = peek(PC++);
  uInt16 low = peek(pointer++);
  uInt16 high = ((uInt16)peek(pointer) << 8);
  operand = peek(high | (uInt8)(low + Y));
  if((low + Y) > 0xFF)
    operand = peek((high | low) + Y);
}
{
  A = operand;
  notZ = A;
  N = A & 0x80;
}
break;


case 0xa2:
{
  operand = peek(PC++);
}
{
  X = operand;
  notZ = X;
  N = X & 0x80;
}
break;

case 0xa6:
{
  operand = peek(peek(PC++));
}
{
  X = operand;
  notZ = X;
  N = X & 0x80;
}
break;

case 0xb6:
{
  uInt8 address = peek(PC++);
  peek(address);
  address += Y;
  operand = peek(address); 
}
{
  X = operand;
  notZ = X;
  N = X & 0x80;
}
break;

case 0xae:
{
  uInt16 address = peek(PC++);
  address |= ((uInt16)peek(PC++) << 8);
  operand = peek(address);
}
{
  X = operand;
  notZ = X;
  N = X & 0x80;
}
break;

case 0xbe:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  operand = peek(high | (uInt8)(low + Y));
  if((low + Y) > 0xFF)
    operand = peek((high | low) + Y);
}
{
  X = operand;
  notZ = X;
  N = X & 0x80;
}
break;


case 0xa0:
{
  operand = peek(PC++);
}
{
  Y = operand;
  notZ = Y;
  N = Y & 0x80;
}
break;

case 0xa4:
{
  operand = peek(peek(PC++));
}
{
  Y = operand;
  notZ = Y;
  N = Y & 0x80;
}
break;

case 0xb4:
{
  uInt8 address = peek(PC++);
  peek(address);
  address += X;
  operand = peek(address); 
}
{
  Y = operand;
  notZ = Y;
  N = Y & 0x80;
}
break;

case 0xac:
{
  uInt16 address = peek(PC++);
  address |= ((uInt16)peek(PC++) << 8);
  operand = peek(address);
}
{
  Y = operand;
  notZ = Y;
  N = Y & 0x80;
}
break;

case 0xbc:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  operand = peek(high | (uInt8)(low + X));
  if((low + X) > 0xFF)
    operand = peek((high | low) + X);
}
{
  Y = operand;
  notZ = Y;
  N = Y & 0x80;
}
break;


case 0x4a:
{
  peek(PC);
}
{
  // Set carry flag according to the right-most bit
  C = A & 0x01;

  A = (A >> 1) & 0x7f;

  notZ = A;
  N = A & 0x80;
}
break;


case 0x46:
{
  operandAddress = peek(PC++);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the right-most bit in value
  C = operand & 0x01;

  operand = (operand >> 1) & 0x7f;
  poke(operandAddress, operand);

  notZ = operand;
  N = operand & 0x80;
}
break;

case 0x56:
{
  operandAddress = peek(PC++);
  peek(operandAddress);
  operandAddress = (operandAddress + X) & 0xFF;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the right-most bit in value
  C = operand & 0x01;

  operand = (operand >> 1) & 0x7f;
  poke(operandAddress, operand);

  notZ = operand;
  N = operand & 0x80;
}
break;

case 0x4e:
{
  operandAddress = peek(PC++);
  operandAddress |= ((uInt16)peek(PC++) << 8);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the right-most bit in value
  C = operand & 0x01;

  operand = (operand >> 1) & 0x7f;
  poke(operandAddress, operand);

  notZ = operand;
  N = operand & 0x80;
}
break;

case 0x5e:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + X));
  operandAddress = (high | low) + X;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the right-most bit in value
  C = operand & 0x01;

  operand = (operand >> 1) & 0x7f;
  poke(operandAddress, operand);

  notZ = operand;
  N = operand & 0x80;
}
break;


case 0xab:
{
  operand = peek(PC++);
}
{
  // NOTE: The implementation of this instruction is based on
  // information from the 64doc.txt file.  This instruction is
  // reported to be very unstable!
  A = X = (A | 0xee) & operand;
  notZ = A;
  N = A & 0x80;
}
break;


case 0x1a:
case 0x3a:
case 0x5a:
case 0x7a:
case 0xda:
case 0xea:
case 0xfa:
{
  peek(PC);
}
{
}
break;

case 0x80:
case 0x82:
case 0x89:
case 0xc2:
case 0xe2:
{
  operand = peek(PC++);
}
{
}
break;

case 0x04:
case 0x44:
case 0x64:
{
  operand = peek(peek(PC++));
}
{
}
break;

case 0x14:
case 0x34:
case 0x54:
case 0x74:
case 0xd4:
case 0xf4:
{
  uInt8 address = peek(PC++);
  peek(address);
  address += X;
  operand = peek(address); 
}
{
}
break;

case 0x0c:
{
  uInt16 address = peek(PC++);
  address |= ((uInt16)peek(PC++) << 8);
  operand = peek(address);
}
{
}
break;

case 0x1c:
case 0x3c:
case 0x5c:
case 0x7c:
case 0xdc:
case 0xfc:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  operand = peek(high | (uInt8)(low + X));
  if((low + X) > 0xFF)
    operand = peek((high | low) + X);
}
{
}
break;


case 0x09:
{
  operand = peek(PC++);
}
{
  A |= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x05:
{
  operand = peek(peek(PC++));
}
{
  A |= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x15:
{
  uInt8 address = peek(PC++);
  peek(address);
  address += X;
  operand = peek(address); 
}
{
  A |= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x0d:
{
  uInt16 address = peek(PC++);
  address |= ((uInt16)peek(PC++) << 8);
  operand = peek(address);
}
{
  A |= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x1d:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  operand = peek(high | (uInt8)(low + X));
  if((low + X) > 0xFF)
    operand = peek((high | low) + X);
}
{
  A |= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x19:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  operand = peek(high | (uInt8)(low + Y));
  if((low + Y) > 0xFF)
    operand = peek((high | low) + Y);
}
{
  A |= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x01:
{
  uInt8 pointer = peek(PC++);
  peek(pointer);
  pointer += X;
  uInt16 address = peek(pointer++);
  address |= ((uInt16)peek(pointer) << 8);
  operand = peek(address);
}
{
  A |= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x11:
{
  uInt8 pointer = peek(PC++);
  uInt16 low = peek(pointer++);
  uInt16 high = ((uInt16)peek(pointer) << 8);
  operand = peek(high | (uInt8)(low + Y));
  if((low + Y) > 0xFF)
    operand = peek((high | low) + Y);
}
{
  A |= operand;
  notZ = A;
  N = A & 0x80;
}
break;


case 0x48:
{
  peek(PC);
}
{
  poke(0x0100 + SP--, A);
}
break;


case 0x08:
{
  peek(PC);
}
{
  poke(0x0100 + SP--, PS());
}
break;


case 0x68:
{
  peek(PC);
}
{
  peek(0x0100 + SP++);
  A = peek(0x0100 + SP);
  notZ = A;
  N = A & 0x80;
}
break;


case 0x28:
{
  peek(PC);
}
{
  peek(0x0100 + SP++);
  PS(peek(0x0100 + SP));
}
break;


case 0x2f:
{
  operandAddress = peek(PC++);
  operandAddress |= ((uInt16)peek(PC++) << 8);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = (operand << 1) | (C ? 1 : 0);
  poke(operandAddress, value);

  A &= value;
  C = operand & 0x80;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x3f:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + X));
  operandAddress = (high | low) + X;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = (operand << 1) | (C ? 1 : 0);
  poke(operandAddress, value);

  A &= value;
  C = operand & 0x80;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x3b:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + Y));
  operandAddress = (high | low) + Y;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = (operand << 1) | (C ? 1 : 0);
  poke(operandAddress, value);

  A &= value;
  C = operand & 0x80;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x27:
{
  operandAddress = peek(PC++);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = (operand << 1) | (C ? 1 : 0);
  poke(operandAddress, value);

  A &= value;
  C = operand & 0x80;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x37:
{
  operandAddress = peek(PC++);
  peek(operandAddress);
  operandAddress = (operandAddress + X) & 0xFF;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = (operand << 1) | (C ? 1 : 0);
  poke(operandAddress, value);

  A &= value;
  C = operand & 0x80;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x23:
{
  uInt8 pointer = peek(PC++);
  peek(pointer);
  pointer += X;
  operandAddress = peek(pointer++);
  operandAddress |= ((uInt16)peek(pointer) << 8);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = (operand << 1) | (C ? 1 : 0);
  poke(operandAddress, value);

  A &= value;
  C = operand & 0x80;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x33:
{
  uInt8 pointer = peek(PC++);
  uInt16 low = peek(pointer++);
  uInt16 high = ((uInt16)peek(pointer) << 8);
  peek(high | (uInt8)(low + Y));
  operandAddress = (high | low) + Y;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  uInt8 value = (operand << 1) | (C ? 1 : 0);
  poke(operandAddress, value);

  A &= value;
  C = operand & 0x80;
  notZ = A;
  N = A & 0x80;
}
break;


case 0x2a:
{
  peek(PC);
}
{
  bool oldC = C;

  // Set carry flag according to the left-most bit
  C = A & 0x80;

  A = (A << 1) | (oldC ? 1 : 0);

  notZ = A;
  N = A & 0x80;
}
break;


case 0x26:
{
  operandAddress = peek(PC++);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  bool oldC = C;

  // Set carry flag according to the left-most bit in operand
  C = operand & 0x80;

  operand = (operand << 1) | (oldC ? 1 : 0);
  poke(operandAddress, operand);

  notZ = operand;
  N = operand & 0x80;
}
break;

case 0x36:
{
  operandAddress = peek(PC++);
  peek(operandAddress);
  operandAddress = (operandAddress + X) & 0xFF;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  bool oldC = C;

  // Set carry flag according to the left-most bit in operand
  C = operand & 0x80;

  operand = (operand << 1) | (oldC ? 1 : 0);
  poke(operandAddress, operand);

  notZ = operand;
  N = operand & 0x80;
}
break;

case 0x2e:
{
  operandAddress = peek(PC++);
  operandAddress |= ((uInt16)peek(PC++) << 8);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  bool oldC = C;

  // Set carry flag according to the left-most bit in operand
  C = operand & 0x80;

  operand = (operand << 1) | (oldC ? 1 : 0);
  poke(operandAddress, operand);

  notZ = operand;
  N = operand & 0x80;
}
break;

case 0x3e:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + X));
  operandAddress = (high | low) + X;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  bool oldC = C;

  // Set carry flag according to the left-most bit in operand
  C = operand & 0x80;

  operand = (operand << 1) | (oldC ? 1 : 0);
  poke(operandAddress, operand);

  notZ = operand;
  N = operand & 0x80;
}
break;


case 0x6a:
{
  peek(PC);
}
{
  bool oldC = C;

  // Set carry flag according to the right-most bit
  C = A & 0x01;

  A = ((A >> 1) & 0x7f) | (oldC ? 0x80 : 0x00);

  notZ = A;
  N = A & 0x80;
}
break;

case 0x66:
{
  operandAddress = peek(PC++);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  bool oldC = C;

  // Set carry flag according to the right-most bit
  C = operand & 0x01;

  operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00);
  poke(operandAddress, operand);

  notZ = operand;
  N = operand & 0x80;
}
break;

case 0x76:
{
  operandAddress = peek(PC++);
  peek(operandAddress);
  operandAddress = (operandAddress + X) & 0xFF;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  bool oldC = C;

  // Set carry flag according to the right-most bit
  C = operand & 0x01;

  operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00);
  poke(operandAddress, operand);

  notZ = operand;
  N = operand & 0x80;
}
break;

case 0x6e:
{
  operandAddress = peek(PC++);
  operandAddress |= ((uInt16)peek(PC++) << 8);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  bool oldC = C;

  // Set carry flag according to the right-most bit
  C = operand & 0x01;

  operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00);
  poke(operandAddress, operand);

  notZ = operand;
  N = operand & 0x80;
}
break;

case 0x7e:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + X));
  operandAddress = (high | low) + X;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  bool oldC = C;

  // Set carry flag according to the right-most bit
  C = operand & 0x01;

  operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00);
  poke(operandAddress, operand);

  notZ = operand;
  N = operand & 0x80;
}
break;


case 0x6f:
{
  operandAddress = peek(PC++);
  operandAddress |= ((uInt16)peek(PC++) << 8);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  bool oldC = C;

  // Set carry flag according to the right-most bit
  C = operand & 0x01;

  operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00);
  poke(operandAddress, operand);

  if(!D)
  {
    Int32 sum = A + operand + (C ? 1 : 0);
    N = sum & 0x80;
    V = ~(A ^ operand) & (A ^ sum) & 0x80;
    notZ = sum & 0xff;
    C = sum & 0xff00;

    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
    Int32 hi = (A & 0xf0) + (operand & 0xf0);
    notZ = (lo+hi) & 0xff;
    if(lo > 0x09)
    {
      hi += 0x10;
      lo += 0x06;
    }
    N = hi & 0x80;
    V = ~(A ^ operand) & (A ^ hi) & 0x80;
    if(hi > 0x90)
      hi += 0x60;
    C = hi & 0xff00;

    A = (lo & 0x0f) + (hi & 0xf0);
  }
}
break;

case 0x7f:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + X));
  operandAddress = (high | low) + X;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  bool oldC = C;

  // Set carry flag according to the right-most bit
  C = operand & 0x01;

  operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00);
  poke(operandAddress, operand);

  if(!D)
  {
    Int32 sum = A + operand + (C ? 1 : 0);
    N = sum & 0x80;
    V = ~(A ^ operand) & (A ^ sum) & 0x80;
    notZ = sum & 0xff;
    C = sum & 0xff00;

    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
    Int32 hi = (A & 0xf0) + (operand & 0xf0);
    notZ = (lo+hi) & 0xff;
    if(lo > 0x09)
    {
      hi += 0x10;
      lo += 0x06;
    }
    N = hi & 0x80;
    V = ~(A ^ operand) & (A ^ hi) & 0x80;
    if(hi > 0x90)
      hi += 0x60;
    C = hi & 0xff00;

    A = (lo & 0x0f) + (hi & 0xf0);
  }
}
break;

case 0x7b:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + Y));
  operandAddress = (high | low) + Y;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  bool oldC = C;

  // Set carry flag according to the right-most bit
  C = operand & 0x01;

  operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00);
  poke(operandAddress, operand);

  if(!D)
  {
    Int32 sum = A + operand + (C ? 1 : 0);
    N = sum & 0x80;
    V = ~(A ^ operand) & (A ^ sum) & 0x80;
    notZ = sum & 0xff;
    C = sum & 0xff00;

    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
    Int32 hi = (A & 0xf0) + (operand & 0xf0);
    notZ = (lo+hi) & 0xff;
    if(lo > 0x09)
    {
      hi += 0x10;
      lo += 0x06;
    }
    N = hi & 0x80;
    V = ~(A ^ operand) & (A ^ hi) & 0x80;
    if(hi > 0x90)
      hi += 0x60;
    C = hi & 0xff00;

    A = (lo & 0x0f) + (hi & 0xf0);
  }
}
break;

case 0x67:
{
  operandAddress = peek(PC++);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  bool oldC = C;

  // Set carry flag according to the right-most bit
  C = operand & 0x01;

  operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00);
  poke(operandAddress, operand);

  if(!D)
  {
    Int32 sum = A + operand + (C ? 1 : 0);
    N = sum & 0x80;
    V = ~(A ^ operand) & (A ^ sum) & 0x80;
    notZ = sum & 0xff;
    C = sum & 0xff00;

    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
    Int32 hi = (A & 0xf0) + (operand & 0xf0);
    notZ = (lo+hi) & 0xff;
    if(lo > 0x09)
    {
      hi += 0x10;
      lo += 0x06;
    }
    N = hi & 0x80;
    V = ~(A ^ operand) & (A ^ hi) & 0x80;
    if(hi > 0x90)
      hi += 0x60;
    C = hi & 0xff00;

    A = (lo & 0x0f) + (hi & 0xf0);
  }
}
break;

case 0x77:
{
  operandAddress = peek(PC++);
  peek(operandAddress);
  operandAddress = (operandAddress + X) & 0xFF;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  bool oldC = C;

  // Set carry flag according to the right-most bit
  C = operand & 0x01;

  operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00);
  poke(operandAddress, operand);

  if(!D)
  {
    Int32 sum = A + operand + (C ? 1 : 0);
    N = sum & 0x80;
    V = ~(A ^ operand) & (A ^ sum) & 0x80;
    notZ = sum & 0xff;
    C = sum & 0xff00;

    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
    Int32 hi = (A & 0xf0) + (operand & 0xf0);
    notZ = (lo+hi) & 0xff;
    if(lo > 0x09)
    {
      hi += 0x10;
      lo += 0x06;
    }
    N = hi & 0x80;
    V = ~(A ^ operand) & (A ^ hi) & 0x80;
    if(hi > 0x90)
      hi += 0x60;
    C = hi & 0xff00;

    A = (lo & 0x0f) + (hi & 0xf0);
  }
}
break;

case 0x63:
{
  uInt8 pointer = peek(PC++);
  peek(pointer);
  pointer += X;
  operandAddress = peek(pointer++);
  operandAddress |= ((uInt16)peek(pointer) << 8);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  bool oldC = C;

  // Set carry flag according to the right-most bit
  C = operand & 0x01;

  operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00);
  poke(operandAddress, operand);

  if(!D)
  {
    Int32 sum = A + operand + (C ? 1 : 0);
    N = sum & 0x80;
    V = ~(A ^ operand) & (A ^ sum) & 0x80;
    notZ = sum & 0xff;
    C = sum & 0xff00;

    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
    Int32 hi = (A & 0xf0) + (operand & 0xf0);
    notZ = (lo+hi) & 0xff;
    if(lo > 0x09)
    {
      hi += 0x10;
      lo += 0x06;
    }
    N = hi & 0x80;
    V = ~(A ^ operand) & (A ^ hi) & 0x80;
    if(hi > 0x90)
      hi += 0x60;
    C = hi & 0xff00;

    A = (lo & 0x0f) + (hi & 0xf0);
  }
}
break;

case 0x73:
{
  uInt8 pointer = peek(PC++);
  uInt16 low = peek(pointer++);
  uInt16 high = ((uInt16)peek(pointer) << 8);
  peek(high | (uInt8)(low + Y));
  operandAddress = (high | low) + Y;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  bool oldC = C;

  // Set carry flag according to the right-most bit
  C = operand & 0x01;

  operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00);
  poke(operandAddress, operand);

  if(!D)
  {
    Int32 sum = A + operand + (C ? 1 : 0);
    N = sum & 0x80;
    V = ~(A ^ operand) & (A ^ sum) & 0x80;
    notZ = sum & 0xff;
    C = sum & 0xff00;

    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
    Int32 hi = (A & 0xf0) + (operand & 0xf0);
    notZ = (lo+hi) & 0xff;
    if(lo > 0x09)
    {
      hi += 0x10;
      lo += 0x06;
    }
    N = hi & 0x80;
    V = ~(A ^ operand) & (A ^ hi) & 0x80;
    if(hi > 0x90)
      hi += 0x60;
    C = hi & 0xff00;

    A = (lo & 0x0f) + (hi & 0xf0);
  }
}
break;


case 0x40:
{
  peek(PC);
}
{
  peek(0x0100 + SP++);
  PS(peek(0x0100 + SP++));
  PC = peek(0x0100 + SP++);
  PC |= ((uInt16)peek(0x0100 + SP) << 8);
}
break;


case 0x60:
{
  peek(PC);
}
{
  peek(0x0100 + SP++);
  PC = peek(0x0100 + SP++);
  PC |= ((uInt16)peek(0x0100 + SP) << 8);
  peek(PC++);
}
break;


case 0x8f:
{
  operandAddress = peek(PC++);
  operandAddress |= ((uInt16)peek(PC++) << 8);
}
{
  poke(operandAddress, A & X);
}
break;

case 0x87:
{
  operandAddress = peek(PC++);
}
{
  poke(operandAddress, A & X);
}
break;

case 0x97:
{
  operandAddress = peek(PC++);
  peek(operandAddress);
  operandAddress = (operandAddress + Y) & 0xFF;
}
{
  poke(operandAddress, A & X);
}
break;

case 0x83:
{
  uInt8 pointer = peek(PC++);
  peek(pointer);
  pointer += X;
  operandAddress = peek(pointer++);
  operandAddress |= ((uInt16)peek(pointer) << 8);
}
{
  poke(operandAddress, A & X);
}
break;


case 0xe9:
case 0xeb:
{
  operand = peek(PC++);
}
{
  // N, V, Z, C flags are the same in either mode (C calculated at the end)
  Int32 sum = A - operand - (C ? 0 : 1);
  N = sum & 0x80;
  V = (A ^ operand) & (A ^ sum) & 0x80;
  notZ = sum & 0xff;

  if(!D)
  {
    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
    Int32 hi = (A & 0xf0) - (operand & 0xf0);
    if(lo & 0x10)
    {
      lo -= 6;
      hi--;
    }
    if(hi & 0x0100)
      hi -= 0x60;

    A = (lo & 0x0f) | (hi & 0xf0);
  }
  C = (sum & 0xff00) == 0;
}
break;

case 0xe5:
{
  operand = peek(peek(PC++));
}
{
  // N, V, Z, C flags are the same in either mode (C calculated at the end)
  Int32 sum = A - operand - (C ? 0 : 1);
  N = sum & 0x80;
  V = (A ^ operand) & (A ^ sum) & 0x80;
  notZ = sum & 0xff;

  if(!D)
  {
    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
    Int32 hi = (A & 0xf0) - (operand & 0xf0);
    if(lo & 0x10)
    {
      lo -= 6;
      hi--;
    }
    if(hi & 0x0100)
      hi -= 0x60;

    A = (lo & 0x0f) | (hi & 0xf0);
  }
  C = (sum & 0xff00) == 0;
}
break;

case 0xf5:
{
  uInt8 address = peek(PC++);
  peek(address);
  address += X;
  operand = peek(address); 
}
{
  // N, V, Z, C flags are the same in either mode (C calculated at the end)
  Int32 sum = A - operand - (C ? 0 : 1);
  N = sum & 0x80;
  V = (A ^ operand) & (A ^ sum) & 0x80;
  notZ = sum & 0xff;

  if(!D)
  {
    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
    Int32 hi = (A & 0xf0) - (operand & 0xf0);
    if(lo & 0x10)
    {
      lo -= 6;
      hi--;
    }
    if(hi & 0x0100)
      hi -= 0x60;

    A = (lo & 0x0f) | (hi & 0xf0);
  }
  C = (sum & 0xff00) == 0;
}
break;

case 0xed:
{
  uInt16 address = peek(PC++);
  address |= ((uInt16)peek(PC++) << 8);
  operand = peek(address);
}
{
  // N, V, Z, C flags are the same in either mode (C calculated at the end)
  Int32 sum = A - operand - (C ? 0 : 1);
  N = sum & 0x80;
  V = (A ^ operand) & (A ^ sum) & 0x80;
  notZ = sum & 0xff;

  if(!D)
  {
    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
    Int32 hi = (A & 0xf0) - (operand & 0xf0);
    if(lo & 0x10)
    {
      lo -= 6;
      hi--;
    }
    if(hi & 0x0100)
      hi -= 0x60;

    A = (lo & 0x0f) | (hi & 0xf0);
  }
  C = (sum & 0xff00) == 0;
}
break;

case 0xfd:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  operand = peek(high | (uInt8)(low + X));
  if((low + X) > 0xFF)
    operand = peek((high | low) + X);
}
{
  // N, V, Z, C flags are the same in either mode (C calculated at the end)
  Int32 sum = A - operand - (C ? 0 : 1);
  N = sum & 0x80;
  V = (A ^ operand) & (A ^ sum) & 0x80;
  notZ = sum & 0xff;

  if(!D)
  {
    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
    Int32 hi = (A & 0xf0) - (operand & 0xf0);
    if(lo & 0x10)
    {
      lo -= 6;
      hi--;
    }
    if(hi & 0x0100)
      hi -= 0x60;

    A = (lo & 0x0f) | (hi & 0xf0);
  }
  C = (sum & 0xff00) == 0;
}
break;

case 0xf9:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  operand = peek(high | (uInt8)(low + Y));
  if((low + Y) > 0xFF)
    operand = peek((high | low) + Y);
}
{
  // N, V, Z, C flags are the same in either mode (C calculated at the end)
  Int32 sum = A - operand - (C ? 0 : 1);
  N = sum & 0x80;
  V = (A ^ operand) & (A ^ sum) & 0x80;
  notZ = sum & 0xff;

  if(!D)
  {
    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
    Int32 hi = (A & 0xf0) - (operand & 0xf0);
    if(lo & 0x10)
    {
      lo -= 6;
      hi--;
    }
    if(hi & 0x0100)
      hi -= 0x60;

    A = (lo & 0x0f) | (hi & 0xf0);
  }
  C = (sum & 0xff00) == 0;
}
break;

case 0xe1:
{
  uInt8 pointer = peek(PC++);
  peek(pointer);
  pointer += X;
  uInt16 address = peek(pointer++);
  address |= ((uInt16)peek(pointer) << 8);
  operand = peek(address);
}
{
  // N, V, Z, C flags are the same in either mode (C calculated at the end)
  Int32 sum = A - operand - (C ? 0 : 1);
  N = sum & 0x80;
  V = (A ^ operand) & (A ^ sum) & 0x80;
  notZ = sum & 0xff;

  if(!D)
  {
    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
    Int32 hi = (A & 0xf0) - (operand & 0xf0);
    if(lo & 0x10)
    {
      lo -= 6;
      hi--;
    }
    if(hi & 0x0100)
      hi -= 0x60;

    A = (lo & 0x0f) | (hi & 0xf0);
  }
  C = (sum & 0xff00) == 0;
}
break;

case 0xf1:
{
  uInt8 pointer = peek(PC++);
  uInt16 low = peek(pointer++);
  uInt16 high = ((uInt16)peek(pointer) << 8);
  operand = peek(high | (uInt8)(low + Y));
  if((low + Y) > 0xFF)
    operand = peek((high | low) + Y);
}
{
  // N, V, Z, C flags are the same in either mode (C calculated at the end)
  Int32 sum = A - operand - (C ? 0 : 1);
  N = sum & 0x80;
  V = (A ^ operand) & (A ^ sum) & 0x80;
  notZ = sum & 0xff;

  if(!D)
  {
    A = (uInt8) sum;
  }
  else
  {
    Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
    Int32 hi = (A & 0xf0) - (operand & 0xf0);
    if(lo & 0x10)
    {
      lo -= 6;
      hi--;
    }
    if(hi & 0x0100)
      hi -= 0x60;

    A = (lo & 0x0f) | (hi & 0xf0);
  }
  C = (sum & 0xff00) == 0;
}
break;


case 0xcb:
{
  operand = peek(PC++);
}
{
  uInt16 value = (uInt16)(X & A) - (uInt16)operand;
  X = (value & 0xff);

  notZ = X;
  N = X & 0x80;
  C = !(value & 0x0100);
}
break;


case 0x38:
{
  peek(PC);
}
{
  C = true;
}
break;


case 0xf8:
{
  peek(PC);
}
{
  D = true;
}
break;


case 0x78:
{
  peek(PC);
}
{
  I = true;
}
break;


case 0x9f:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + Y));
  operandAddress = (high | low) + Y;
}
{
  // NOTE: There are mixed reports on the actual operation
  // of this instruction!
  poke(operandAddress, A & X & (((operandAddress >> 8) & 0xff) + 1)); 
}
break;

case 0x93:
{
  uInt8 pointer = peek(PC++);
  uInt16 low = peek(pointer++);
  uInt16 high = ((uInt16)peek(pointer) << 8);
  peek(high | (uInt8)(low + Y));
  operandAddress = (high | low) + Y;
}
{
  // NOTE: There are mixed reports on the actual operation
  // of this instruction!
  poke(operandAddress, A & X & (((operandAddress >> 8) & 0xff) + 1)); 
}
break;


case 0x9b:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + Y));
  operandAddress = (high | low) + Y;
}
{
  // NOTE: There are mixed reports on the actual operation
  // of this instruction!
  SP = A & X;
  poke(operandAddress, A & X & (((operandAddress >> 8) & 0xff) + 1)); 
}
break;


case 0x9e:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + Y));
  operandAddress = (high | low) + Y;
}
{
  // NOTE: There are mixed reports on the actual operation
  // of this instruction!
  poke(operandAddress, X & (((operandAddress >> 8) & 0xff) + 1)); 
}
break;


case 0x9c:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + X));
  operandAddress = (high | low) + X;
}
{
  // NOTE: There are mixed reports on the actual operation
  // of this instruction!
  poke(operandAddress, Y & (((operandAddress >> 8) & 0xff) + 1)); 
}
break;


case 0x0f:
{
  operandAddress = peek(PC++);
  operandAddress |= ((uInt16)peek(PC++) << 8);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the left-most bit in value
  C = operand & 0x80;

  operand <<= 1;
  poke(operandAddress, operand);

  A |= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x1f:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + X));
  operandAddress = (high | low) + X;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the left-most bit in value
  C = operand & 0x80;

  operand <<= 1;
  poke(operandAddress, operand);

  A |= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x1b:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + Y));
  operandAddress = (high | low) + Y;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the left-most bit in value
  C = operand & 0x80;

  operand <<= 1;
  poke(operandAddress, operand);

  A |= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x07:
{
  operandAddress = peek(PC++);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the left-most bit in value
  C = operand & 0x80;

  operand <<= 1;
  poke(operandAddress, operand);

  A |= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x17:
{
  operandAddress = peek(PC++);
  peek(operandAddress);
  operandAddress = (operandAddress + X) & 0xFF;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the left-most bit in value
  C = operand & 0x80;

  operand <<= 1;
  poke(operandAddress, operand);

  A |= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x03:
{
  uInt8 pointer = peek(PC++);
  peek(pointer);
  pointer += X;
  operandAddress = peek(pointer++);
  operandAddress |= ((uInt16)peek(pointer) << 8);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the left-most bit in value
  C = operand & 0x80;

  operand <<= 1;
  poke(operandAddress, operand);

  A |= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x13:
{
  uInt8 pointer = peek(PC++);
  uInt16 low = peek(pointer++);
  uInt16 high = ((uInt16)peek(pointer) << 8);
  peek(high | (uInt8)(low + Y));
  operandAddress = (high | low) + Y;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the left-most bit in value
  C = operand & 0x80;

  operand <<= 1;
  poke(operandAddress, operand);

  A |= operand;
  notZ = A;
  N = A & 0x80;
}
break;


case 0x4f:
{
  operandAddress = peek(PC++);
  operandAddress |= ((uInt16)peek(PC++) << 8);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the right-most bit in value
  C = operand & 0x01;

  operand = (operand >> 1) & 0x7f;
  poke(operandAddress, operand);

  A ^= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x5f:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + X));
  operandAddress = (high | low) + X;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the right-most bit in value
  C = operand & 0x01;

  operand = (operand >> 1) & 0x7f;
  poke(operandAddress, operand);

  A ^= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x5b:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + Y));
  operandAddress = (high | low) + Y;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the right-most bit in value
  C = operand & 0x01;

  operand = (operand >> 1) & 0x7f;
  poke(operandAddress, operand);

  A ^= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x47:
{
  operandAddress = peek(PC++);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the right-most bit in value
  C = operand & 0x01;

  operand = (operand >> 1) & 0x7f;
  poke(operandAddress, operand);

  A ^= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x57:
{
  operandAddress = peek(PC++);
  peek(operandAddress);
  operandAddress = (operandAddress + X) & 0xFF;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the right-most bit in value
  C = operand & 0x01;

  operand = (operand >> 1) & 0x7f;
  poke(operandAddress, operand);

  A ^= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x43:
{
  uInt8 pointer = peek(PC++);
  peek(pointer);
  pointer += X;
  operandAddress = peek(pointer++);
  operandAddress |= ((uInt16)peek(pointer) << 8);
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the right-most bit in value
  C = operand & 0x01;

  operand = (operand >> 1) & 0x7f;
  poke(operandAddress, operand);

  A ^= operand;
  notZ = A;
  N = A & 0x80;
}
break;

case 0x53:
{
  uInt8 pointer = peek(PC++);
  uInt16 low = peek(pointer++);
  uInt16 high = ((uInt16)peek(pointer) << 8);
  peek(high | (uInt8)(low + Y));
  operandAddress = (high | low) + Y;
  operand = peek(operandAddress);
  poke(operandAddress, operand);
}
{
  // Set carry flag according to the right-most bit in value
  C = operand & 0x01;

  operand = (operand >> 1) & 0x7f;
  poke(operandAddress, operand);

  A ^= operand;
  notZ = A;
  N = A & 0x80;
}
break;


case 0x85:
{
  operandAddress = peek(PC++);
}
{
  poke(operandAddress, A);
}
break;

case 0x95:
{
  operandAddress = peek(PC++);
  peek(operandAddress);
  operandAddress = (operandAddress + X) & 0xFF;
}
{
  poke(operandAddress, A);
}
break;

case 0x8d:
{
  operandAddress = peek(PC++);
  operandAddress |= ((uInt16)peek(PC++) << 8);
}
{
  poke(operandAddress, A);
}
break;

case 0x9d:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + X));
  operandAddress = (high | low) + X;
}
{
  poke(operandAddress, A);
}
break;

case 0x99:
{
  uInt16 low = peek(PC++);
  uInt16 high = ((uInt16)peek(PC++) << 8);
  peek(high | (uInt8)(low + Y));
  operandAddress = (high | low) + Y;
}
{
  poke(operandAddress, A);
}
break;

case 0x81:
{
  uInt8 pointer = peek(PC++);
  peek(pointer);
  pointer += X;
  operandAddress = peek(pointer++);
  operandAddress |= ((uInt16)peek(pointer) << 8);
}
{
  poke(operandAddress, A);
}
break;

case 0x91:
{
  uInt8 pointer = peek(PC++);
  uInt16 low = peek(pointer++);
  uInt16 high = ((uInt16)peek(pointer) << 8);
  peek(high | (uInt8)(low + Y));
  operandAddress = (high | low) + Y;
}
{
  poke(operandAddress, A);
}
break;


case 0x86:
{
  operandAddress = peek(PC++);
}
{
  poke(operandAddress, X);
}
break;

case 0x96:
{
  operandAddress = peek(PC++);
  peek(operandAddress);
  operandAddress = (operandAddress + Y) & 0xFF;
}
{
  poke(operandAddress, X);
}
break;

case 0x8e:
{
  operandAddress = peek(PC++);
  operandAddress |= ((uInt16)peek(PC++) << 8);
}
{
  poke(operandAddress, X);
}
break;


case 0x84:
{
  operandAddress = peek(PC++);
}
{
  poke(operandAddress, Y);
}
break;

case 0x94:
{
  operandAddress = peek(PC++);
  peek(operandAddress);
  operandAddress = (operandAddress + X) & 0xFF;
}
{
  poke(operandAddress, Y);
}
break;

case 0x8c:
{
  operandAddress = peek(PC++);
  operandAddress |= ((uInt16)peek(PC++) << 8);
}
{
  poke(operandAddress, Y);
}
break;


case 0xaa:
{
  peek(PC);
}
{
  X = A;
  notZ = X;
  N = X & 0x80;
}
break;


case 0xa8:
{
  peek(PC);
}
{
  Y = A;
  notZ = Y;
  N = Y & 0x80;
}
break;


case 0xba:
{
  peek(PC);
}
{
  X = SP;
  notZ = X;
  N = X & 0x80;
}
break;


case 0x8a:
{
  peek(PC);
}
{
  A = X;
  notZ = A;
  N = A & 0x80;
}
break;


case 0x9a:
{
  peek(PC);
}
{
  SP = X;
}
break;


case 0x98:
{
  peek(PC);
}
{
  A = Y;
  notZ = A;
  N = A & 0x80;
}
break;


