v6502
The MOS 6502 Virtual Machine and Toolchain Infrastructure
Instruction Set Reference

Table of Contents

ADC - Add With Carry

Address ModeMnemonicOpcode
Absoluteadc m160x6D 0xLL 0xHH
Absolute + Xadc m16, X0x7D 0xLL 0xHH
Absolute + Yadc m16, Y0x79 0xLL 0xHH
Immediateadc #imm80x69 0xLL
Indirect + Xadc (m16, X)0x61 0xLL 0xHH
Indirect + Yadc (m16), Y0x71 0xLL 0xHH
Zeropageadc *m80x65 0xLL
Zeropage + Xadc *m8, X0x75 0xLL
Implementation
uint8_t a = cpu->ac;
cpu->ac += operand + ((cpu->sr & v6502_cpu_status_carry) ? 1 : 0);
FLAG_OVERFLOW_WITH_COMPARISON(a, operand, cpu->ac);
FLAG_CARRY_WITH_COMPARISON(cpu->ac, operand);
FLAG_NEG_AND_ZERO_WITH_RESULT(cpu->ac);

AND - Bitwise And

Address ModeMnemonicOpcode
Absoluteand m160x2D 0xLL 0xHH
Absolute + Xand m16, X0x3D 0xLL 0xHH
Absolute + Yand m16, Y0x39 0xLL 0xHH
Immediateand #imm80x29 0xLL
Indirect + Xand (m16, X)0x21 0xLL 0xHH
Indirect + Yand (m16), Y0x31 0xLL 0xHH
Zeropageand *m80x25 0xLL
Zeropage + Xand *m8, X0x35 0xLL
Implementation
cpu->ac &= operand;
FLAG_NEG_AND_ZERO_WITH_RESULT(cpu->ac);

ASL - Arithmetic Shift Left

Address ModeMnemonicOpcode
Absoluteasl m160x0E 0xLL 0xHH
Absolute + Xasl m16, X0x1E 0xLL 0xHH
Accumulatorasl A0x0A
Zeropageasl *m80x06 0xLL
Zeropage + Xasl *m8, X0x16 0xLL
Implementation
FLAG_CARRY_WITH_HIGH_BIT(operand);
operand <<= 1;
FLAG_NEG_AND_ZERO_WITH_RESULT(operand);
return operand;

BCC - Branch if Carry Clear

Address ModeMnemonicOpcode
Relativebcc m80x90 0xLL
Implementation
if (!(cpu->sr & v6502_cpu_status_carry)) {
cpu->pc += v6502_signedValueOfByte(low);
}

BCS - Branch if Carry Set

Address ModeMnemonicOpcode
Relativebcs m80xB0 0xLL
Implementation
if (cpu->sr & v6502_cpu_status_carry) {
cpu->pc += v6502_signedValueOfByte(low);
}

BEQ - Branch if Equal (Zero Set)

Address ModeMnemonicOpcode
Relativebeq m80xF0 0xLL
Implementation
if (cpu->sr & v6502_cpu_status_zero) {
cpu->pc += v6502_signedValueOfByte(low);
}

BIT - Bit Test

Address ModeMnemonicOpcode
Absolutebit m160x2C 0xLL 0xHH
Zeropagebit *m80x24 0xLL
Implementation
uint8_t result = cpu->ac & operand;
cpu->sr &= ~(v6502_cpu_status_overflow | v6502_cpu_status_negative);
cpu->sr |= (operand & (v6502_cpu_status_overflow | v6502_cpu_status_negative));
FLAG_ZERO_WITH_RESULT(result);

BMI - Branch if Minus (Negative Set)

Address ModeMnemonicOpcode
Relativebmi m80x30 0xLL
Implementation
if (cpu->sr & v6502_cpu_status_negative) {
cpu->pc += v6502_signedValueOfByte(low);
}

BNE - Branch if Not Equal (Zero Clear)

Address ModeMnemonicOpcode
Relativebne m80xD0 0xLL
Implementation
if (!(cpu->sr & v6502_cpu_status_zero)) {
cpu->pc += v6502_signedValueOfByte(low);
}

BPL - Branch if Plus (Negative Clear)

Address ModeMnemonicOpcode
Relativebpl m80x10 0xLL
Implementation
if (!(cpu->sr & v6502_cpu_status_negative)) {
cpu->pc += v6502_signedValueOfByte(low);
}

BRK - Break

Address ModeMnemonicOpcode
Impliedbrk 0x00
Implementation
cpu->sr |= v6502_cpu_status_break;
cpu->sr |= v6502_cpu_status_interrupt;

BVC - Branch if Overflow Clear

Address ModeMnemonicOpcode
Relativebvc m80x50 0xLL
Implementation
if (!(cpu->sr & v6502_cpu_status_overflow)) {
cpu->pc += v6502_signedValueOfByte(low);
}

BVS - Branch if Overflow Set

Address ModeMnemonicOpcode
Relativebvs m80x70 0xLL
Implementation
if (cpu->sr & v6502_cpu_status_overflow) {
cpu->pc += v6502_signedValueOfByte(low);
}

CLC - Clear Carry Flag

Address ModeMnemonicOpcode
Impliedclc 0x18
Implementation
cpu->sr &= ~v6502_cpu_status_carry;

CLD - Clear Decimal Flag

Address ModeMnemonicOpcode
Impliedcld 0xD8
Implementation
cpu->sr &= ~v6502_cpu_status_decimal;

CLI - Clear Interrupt Flag

Address ModeMnemonicOpcode
Impliedcli 0x58
Implementation
cpu->sr &= ~v6502_cpu_status_interrupt;

CLV - Clear Overflow Flag

Address ModeMnemonicOpcode
Impliedclv 0xB8
Implementation
cpu->sr &= ~v6502_cpu_status_overflow;

CMP - Compare Accumulator

Address ModeMnemonicOpcode
Absolutecmp m160xCD 0xLL 0xHH
Absolute + Xcmp m16, X0xDD 0xLL 0xHH
Absolute + Ycmp m16, Y0xD9 0xLL 0xHH
Immediatecmp #imm80xC9 0xLL
Indirect + Xcmp (m16, X)0xC1 0xLL 0xHH
Indirect + Ycmp (m16), Y0xD1 0xLL 0xHH
Zeropagecmp *m80xC5 0xLL
Zeropage + Xcmp *m8, X0xD5 0xLL
Implementation
uint8_t result = reg - operand;
FLAG_CARRY_WITH_COMPARISON(operand, reg);
FLAG_NEG_AND_ZERO_WITH_RESULT(result);

CPX - Compare X

Address ModeMnemonicOpcode
Absolutecpx m160xEC 0xLL 0xHH
Immediatecpx #imm80xE0 0xLL
Zeropagecpx *m80xE4 0xLL
Implementation
uint8_t result = reg - operand;
FLAG_CARRY_WITH_COMPARISON(operand, reg);
FLAG_NEG_AND_ZERO_WITH_RESULT(result);

CPY - Compare Y

Address ModeMnemonicOpcode
Absolutecpy m160xCC 0xLL 0xHH
Immediatecpy #imm80xC0 0xLL
Zeropagecpy *m80xC4 0xLL
Implementation
uint8_t result = reg - operand;
FLAG_CARRY_WITH_COMPARISON(operand, reg);
FLAG_NEG_AND_ZERO_WITH_RESULT(result);

DEC - Decrement Accumulator

Address ModeMnemonicOpcode
Absolutedec m160xCE 0xLL 0xHH
Absolute + Xdec m16, X0xDE 0xLL 0xHH
Zeropagedec *m80xC6 0xLL
Zeropage + Xdec *m8, X0xD6 0xLL
Implementation
operand--;
FLAG_NEG_AND_ZERO_WITH_RESULT(operand);

DEX - Decrement X

Address ModeMnemonicOpcode
Implieddex 0xCA
Implementation
operand--;
FLAG_NEG_AND_ZERO_WITH_RESULT(operand);

DEY - Decrement Y

Address ModeMnemonicOpcode
Implieddey 0x88
Implementation
operand--;
FLAG_NEG_AND_ZERO_WITH_RESULT(operand);

EOR - Bitwise Exclusive Or

Address ModeMnemonicOpcode
Absoluteeor m160x4D 0xLL 0xHH
Absolute + Xeor m16, X0x5D 0xLL 0xHH
Absolute + Yeor m16, Y0x59 0xLL 0xHH
Immediateeor #imm80x49 0xLL
Indirect + Xeor (m16, X)0x41 0xLL 0xHH
Indirect + Yeor (m16), Y0x51 0xLL 0xHH
Zeropageeor *m80x45 0xLL
Zeropage + Xeor *m8, X0x55 0xLL
Implementation
cpu->ac ^= operand;
FLAG_NEG_AND_ZERO_WITH_RESULT(cpu->ac);

INC - Increment Accumulator

Address ModeMnemonicOpcode
Absoluteinc m160xEE 0xLL 0xHH
Absolute + Xinc m16, X0xFE 0xLL 0xHH
Zeropageinc *m80xE6 0xLL
Zeropage + Xinc *m8, X0xF6 0xLL
Implementation
operand++;
FLAG_NEG_AND_ZERO_WITH_RESULT(operand);

INX - Increment X

Address ModeMnemonicOpcode
Impliedinx 0xE8
Implementation
operand++;
FLAG_NEG_AND_ZERO_WITH_RESULT(operand);

INY - Increment Y

Address ModeMnemonicOpcode
Impliediny 0xC8
Implementation
operand++;
FLAG_NEG_AND_ZERO_WITH_RESULT(operand);

JMP - Unconditional Jump

Address ModeMnemonicOpcode
Absolutejmp m160x4C 0xLL 0xHH
Indirectjmp (m16)0x6C 0xLL 0xHH
Implementation
case v6502_opcode_jmp_abs: {
if (BOTH_BYTES == cpu->pc) {
v6502_execute(cpu, v6502_opcode_wai, 0, 0);
cpu->pc -= 3; // PC shift
return;
}
cpu->pc = BOTH_BYTES;
cpu->pc -= 3; // PC shift
} return;
case v6502_opcode_jmp_ind: {
uint16_t address = BOTH_BYTES;
low = v6502_read(cpu->memory, address, NO);
high = v6502_read(cpu->memory, address + 1, NO);
// Trap was already triggered by indirect memory classification in prior switch
cpu->pc = BOTH_BYTES;
cpu->pc -= 3; // PC shift
} return;

JSR - Call Subroutine

Address ModeMnemonicOpcode
Absolutejsr m160x20 0xLL 0xHH
Implementation
cpu->memory->bytes[v6502_memoryStartStack + cpu->sp--] = cpu->pc; // Low byte first
cpu->memory->bytes[v6502_memoryStartStack + cpu->sp--] = (cpu->pc >> 8); // High byte second
cpu->pc = BOTH_BYTES;
cpu->pc -= 3; // To compensate for post execution shift

LDA - Load Accumulator

Address ModeMnemonicOpcode
Absolutelda m160xAD 0xLL 0xHH
Absolute + Xlda m16, X0xBD 0xLL 0xHH
Absolute + Ylda m16, Y0xB9 0xLL 0xHH
Immediatelda #imm80xA9 0xLL
Indirect + Xlda (m16, X)0xA1 0xLL 0xHH
Indirect + Ylda (m16), Y0xB1 0xLL 0xHH
Zeropagelda *m80xA5 0xLL
Zeropage + Xlda *m8, X0xB5 0xLL
Implementation
cpu->ac = operand;
FLAG_NEG_AND_ZERO_WITH_RESULT(operand);

LDX - Load X

Address ModeMnemonicOpcode
Absoluteldx m160xAE 0xLL 0xHH
Absolute + Yldx m16, Y0xBE 0xLL 0xHH
Immediateldx #imm80xA2 0xLL
Zeropageldx *m80xA6 0xLL
Zeropage + Yldx *m8, Y0xB6 0xLL
Implementation
cpu->x = operand;
FLAG_NEG_AND_ZERO_WITH_RESULT(operand);

LDY - Load Y

Address ModeMnemonicOpcode
Absoluteldy m160xAC 0xLL 0xHH
Absolute + Xldy m16, X0xBC 0xLL 0xHH
Immediateldy #imm80xA0 0xLL
Zeropageldy *m80xA4 0xLL
Zeropage + Xldy *m8, X0xB4 0xLL
Implementation
cpu->y = operand;
FLAG_NEG_AND_ZERO_WITH_RESULT(operand);

LSR - Logical Shift Right

Address ModeMnemonicOpcode
Absolutelsr m160x4E 0xLL 0xHH
Absolute + Xlsr m16, X0x5E 0xLL 0xHH
Accumulatorlsr A0x4A
Zeropagelsr *m80x46 0xLL
Zeropage + Xlsr *m8, X0x56 0xLL
Implementation
FLAG_CARRY_WITH_LOW_BIT(operand);
operand >>= 1;
FLAG_ZERO_WITH_RESULT(operand);
return operand;

NOP - No-op

Address ModeMnemonicOpcode
Impliednop 0xEA
Implementation
/* Do nothing */

ORA - Bitwise Or

Address ModeMnemonicOpcode
Absoluteora m160x0D 0xLL 0xHH
Absolute + Xora m16, X0x1D 0xLL 0xHH
Absolute + Yora m16, Y0x19 0xLL 0xHH
Immediateora #imm80x09 0xLL
Indirect + Xora (m16, X)0x01 0xLL 0xHH
Indirect + Yora (m16), Y0x11 0xLL 0xHH
Zeropageora *m80x05 0xLL
Zeropage + Xora *m8, X0x15 0xLL
Implementation
cpu->ac |= operand;
FLAG_NEG_AND_ZERO_WITH_RESULT(cpu->ac);

PHA - Push Accumulator to Stack

Address ModeMnemonicOpcode
Impliedpha 0x48
Implementation
cpu->memory->bytes[v6502_memoryStartStack + cpu->sp--] = cpu->ac;

PHP - Push Program Counter to Stack

Address ModeMnemonicOpcode
Impliedphp 0x08
Implementation
cpu->memory->bytes[v6502_memoryStartStack + cpu->sp--] = cpu->sr;

PLA - Pull Accumulator from Stack

Address ModeMnemonicOpcode
Impliedpla 0x68
Implementation
cpu->ac = cpu->memory->bytes[v6502_memoryStartStack + ++cpu->sp];
FLAG_NEG_AND_ZERO_WITH_RESULT(cpu->ac);

PLP - Pull Program Counter from Stack

Address ModeMnemonicOpcode
Impliedplp 0x28
Implementation
cpu->sr = cpu->memory->bytes[v6502_memoryStartStack + ++cpu->sp];

ROL - Rotate Left

Address ModeMnemonicOpcode
Absoluterol m160x2E 0xLL 0xHH
Absolute + Xrol m16, X0x3E 0xLL 0xHH
Accumulatorrol A0x2A
Zeropagerol *m80x26 0xLL
Zeropage + Xrol *m8, X0x36 0xLL
Implementation
uint8_t carry = (cpu->sr & v6502_cpu_status_carry);
FLAG_CARRY_WITH_HIGH_BIT(operand);
operand = (operand << 1) | (carry);
FLAG_NEG_AND_ZERO_WITH_RESULT(operand);
return operand;

ROR - Rotate Right

Address ModeMnemonicOpcode
Absoluteror m160x6E 0xLL 0xHH
Absolute + Xror m16, X0x7E 0xLL 0xHH
Accumulatorror A0x6A
Zeropageror *m80x66 0xLL
Zeropage + Xror *m8, X0x76 0xLL
Implementation
uint8_t carry = (cpu->sr & v6502_cpu_status_carry);
FLAG_CARRY_WITH_LOW_BIT(operand);
operand = (operand >> 1) | (carry << 7);
FLAG_NEG_AND_ZERO_WITH_RESULT(operand);
return operand;

RTI - Return from Interrupt

Address ModeMnemonicOpcode
Impliedrti 0x40
Implementation

RTS - Return from Subroutine

Address ModeMnemonicOpcode
Impliedrts 0x60
Implementation
cpu->pc = (cpu->memory->bytes[v6502_memoryStartStack + ++cpu->sp] << 8);
cpu->pc |= cpu->memory->bytes[v6502_memoryStartStack + ++cpu->sp];
cpu->pc += 2; // To compensate for post execution shift ( - 1 rts, + 3 jsr )

SBC - Subtract with Carry

Address ModeMnemonicOpcode
Absolutesbc m160xED 0xLL 0xHH
Absolute + Xsbc m16, X0xFD 0xLL 0xHH
Absolute + Ysbc m16, Y0xF9 0xLL 0xHH
Immediatesbc #imm80xE9 0xLL
Indirect + Xsbc (m16, X)0xE1 0xLL 0xHH
Indirect + Ysbc (m16), Y0xF1 0xLL 0xHH
Zeropagesbc *m80xE5 0xLL
Zeropage + Xsbc *m8, X0xF5 0xLL
Implementation
_executeInPlaceADC(cpu, operand ^ BYTE_MAX);

SEC - Set Carry Flag

Address ModeMnemonicOpcode
Impliedsec 0x38
Implementation
cpu->sr |= v6502_cpu_status_carry;

SED - Set Decimal Flag

Address ModeMnemonicOpcode
Impliedsed 0xF8
Implementation
cpu->sr |= v6502_cpu_status_decimal;

SEI - Set Interrupt Flag

Address ModeMnemonicOpcode
Impliedsei 0x78
Implementation
cpu->sr |= v6502_cpu_status_interrupt;

STA - Store Accumulator

Address ModeMnemonicOpcode
Absolutesta m160x8D 0xLL 0xHH
Absolute + Xsta m16, X0x9D 0xLL 0xHH
Absolute + Ysta m16, Y0x99 0xLL 0xHH
Indirect + Xsta (m16, X)0x81 0xLL 0xHH
Indirect + Ysta (m16), Y0x91 0xLL 0xHH
Zeropagesta *m80x85 0xLL
Zeropage + Xsta *m8, X0x95 0xLL
Implementation
v6502_write(cpu->memory, ref, cpu->ac);

STX - Store X

Address ModeMnemonicOpcode
Absolutestx m160x8E 0xLL 0xHH
Zeropagestx *m80x86 0xLL
Zeropage + Ystx *m8, Y0x96 0xLL
Implementation
v6502_write(cpu->memory, ref, cpu->x);

STY - Store Y

Address ModeMnemonicOpcode
Absolutesty m160x8C 0xLL 0xHH
Zeropagesty *m80x84 0xLL
Zeropage + Xsty *m8, X0x94 0xLL
Implementation
v6502_write(cpu->memory, ref, cpu->y);

TAX - Transfer Accumulator to X

Address ModeMnemonicOpcode
Impliedtax 0xAA
Implementation
cpu->x = cpu->ac;
FLAG_NEG_AND_ZERO_WITH_RESULT(cpu->ac);

TAY - Transfer Accumulator to Y

Address ModeMnemonicOpcode
Impliedtay 0xA8
Implementation
cpu->y = cpu->ac;
FLAG_NEG_AND_ZERO_WITH_RESULT(cpu->ac);

TSX - Transfer Status Flags to X

Address ModeMnemonicOpcode
Impliedtsx 0xBA
Implementation
cpu->x = cpu->sp;
FLAG_NEG_AND_ZERO_WITH_RESULT(cpu->sp);

TXA - Transfer X to Accumulator

Address ModeMnemonicOpcode
Impliedtxa 0x8A
Implementation
cpu->ac = cpu->x;
FLAG_NEG_AND_ZERO_WITH_RESULT(cpu->ac);

TXS - Transfer X to Status Flags

Address ModeMnemonicOpcode
Impliedtxs 0x9A
Implementation
cpu->sp = cpu->x;
FLAG_NEG_AND_ZERO_WITH_RESULT(cpu->sp);

TYA - Transfer Y to Accumulator

Address ModeMnemonicOpcode
Impliedtya 0x98
Implementation
cpu->ac = cpu->y;
FLAG_NEG_AND_ZERO_WITH_RESULT(cpu->ac);