// Big Mess o' Wires microcode source // // Each opcode consists of up to 16 phases. The microcode for a phase may depend on // the ALUFLAG input, in which two lines will be provided for that phase: one for // ALUFLAG == 0 and one for ALUFLAG == 1. An ALUFLAG of "*" means the same microcode // should be executed for that phase regardless of ALUFLAG. // HALT // Stops the machine. Backs up the PC and re-executes the HALT instruction. opcode: FF *: T <- X *: X <- PCLO *: PCLO <- X - 1 // back up PC, latch address carry *: X <- PCHI a=0: PCHI <- X a=1: PCHI <- X - 1 *: X <- T; nextop // NOP // Do nothing. Proceed to next instruction. opcode: EA *: nextop // BANK immediate // Sets the bank byte used for subsequent memory references. Interprets // the next byte of the program as the bank byte, and loads it into ARBANK. opcode: EB *: ARBANK <- MEM(PC); PC++ *: nextop // BANK accumulator // Sets the bank byte used for subsequent memory references. Stores the // Accumulator into ARBANK. opcode: FB *: ARBANK <- A; nextop // ADX // Add X to the accumulator, including the current value of the carry flag. // A <- A + X + C opcode: 07 *: T <- X c=0: A <- A + T + 1; latchAllCC; nextop c=1: A <- A + T; latchAllCC; nextop // ADY // Add Y to the accumulator, including the current value of the carry flag. // A <- A + Y + C opcode: 17 *: T <- Y c=0: A <- A + T + 1; latchAllCC; nextop c=1: A <- A + T; latchAllCC; nextop // SBX // Subtract X from the accumulator, including the current value of the carry flag. // A <- A - X - C opcode: 27 *: T <- X c=0: A <- A - T; latchAllCC; nextop c=1: A <- A - T - 1; latchAllCC; nextop // SBY // Subtract Y from the accumulator, including the current value of the carry flag. // A <- A - Y - C opcode: 37 *: T <- Y c=0: A <- A - T; latchAllCC; nextop c=1: A <- A - T - 1; latchAllCC; nextop // JMP absolute // Interpret the next two bytes of the program as the lo,hi bytes of the destination // address. opcode: 4C *: T <- MEM(PC); PC++ *: PCHI <- MEM(PC) *: PCLO <- T *: nextop // JMP indirect // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory // that contains the destination address. opcode: 6C *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: PCLO <- MEM(AR); AR++ *: PCHI <- MEM(AR) *: nextop // LDA immediate // Load the Accumulator with the next byte of the program. opcode: A9 *: A <- MEM(PC); PC++ *: T <- A; latchNZ; nextop // LDA absolute // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory; // and load a byte from that location into the Accumulator. opcode: AD *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: A <- MEM(AR) *: T <- A; latchNZ; nextop // LDA zero page absolute opcode: A5 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: A <- MEM(AR) *: T <- A; latchNZ; nextop // LDA absolute,X // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory; // and load a byte from the location obtained by adding X to that address into the Accumulator. opcode: BD *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: A <- MEM(AR) *: T <- A; latchNZ; nextop // LDA zero page,X opcode: B5 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: ARLO <- X + ARLO // no carry into ARHI *: A <- MEM(AR) *: T <- A; latchNZ; nextop // LDA absolute,Y // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory; // and load a byte from the location obtained by adding Y to that address into the Accumulator. opcode: B9 *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- X // can't assign from Y directly to an address register. *: X <- Y *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: A <- MEM(AR) *: X <- T *: T <- A; latchNZ; nextop // LDA stack relative // LDA 4,S // Interpret the next byte of the program as a positive offset from the stack pointer, // and load a byte into the Accumulator from the location in memory obtained by adding the offset // to the stack pointer. opcode: A3 *: T <- X *: X <- MEM(PC); PC++ *: ARLO <- X + SPLO a=0: ARHI <- 0 + SPHI + 1 a=1: ARHI <- 0 + SPHI *: X <- ARBANK // preserve ARBANK *: ARBANK <- SPBANK *: A <- MEM(AR) *: ARBANK <- X *: X <- T *: T <- A; latchNZ; nextop // LDA stack relative indirect, X // LDA (4,S),X // Interpret the next byte of the program as a positive offset from the stack pointer, // interpert the two bytes beginning at that stack-relative location as the lo, hi bytes of a second // location in memory, and load the Accumulator with the bytes at the location obtained by adding X // to that second address. //opcode: B3 // *: T <- X // *: X <- MEM(PC); PC++ // *: ARLO <- X + SPLO //a=0: ARHI <- 0 + SPHI + 1 //a=1: ARHI <- 0 + SPHI // *: MEM(SP) <- ARBANK // preserve ARBANK using top of stack // *: ARBANK <- SPBANK // this doesn't work!!! // *: X <- T // *: T <- MEM(AR); AR++ // *: ARHI <- MEM(AR) // *: ARLO <- X + T //a=0: ARHI <- 0 + ARHI + 1 //a=1: ARHI <- 0 + ARHI // nop // *: A <- MEM(AR) // *: ARBANK <- MEM(SP) // *: T <- A; latchNZ; nextop // LDA indirect,X // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory; // interpret the two bytes beginning at that memory location as the lo, hi bytes of a second // location in memory, and load the Accumulator with the byte at the location obtained by adding X // to that second address. opcode: B2 *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- MEM(AR); AR++ *: ARHI <- MEM(AR) *: ARLO <- X + T a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: A <- MEM(AR) *: T <- A; latchNZ; nextop // LDA indirect,Y // Interpret the next byte of the program as the location in zero page memory; // interpret the two bytes beginning at that memory location as the lo, hi bytes of a second // location in memory, and load the Accumulator with the byte at the location obtained by adding Y // to that second address. opcode: B1 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: T <- MEM(AR); AR++ *: ARHI <- MEM(AR) *: ARLO <- T // can't assign from Y directly to an address register. *: T <- X *: X <- Y // can't assign from Y directly to an address register. *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: A <- MEM(AR) *: X <- T *: T <- A; latchNZ; nextop // LDA X,indirect // Interpret the next byte of the program as the zero page location of a pointer to a location in memory; // Add X to the pointer, interpret the two bytes beginning at the new pointer location as the lo, hi bytes of a second // location in memory, and load the Accumulator with the byte at that location. opcode: A1 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: ARLO <- X + ARLO // no carry into ARHI *: T <- MEM(AR); AR++ *: ARHI <- MEM(AR) *: ARLO <- T *: A <- MEM(AR) *: T <- A; latchNZ; nextop // LDX immediate // Load X with the next byte of the program. opcode: A2 *: X <- MEM(PC); PC++ *: T <- X; latchNZ; nextop // LDX absolute // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory; // and load a byte from that location into X. opcode: AE *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: X <- MEM(AR) *: T <- X; latchNZ; nextop // LDX absolute,Y // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory; // and store X at the location obtained by adding Y to that address. opcode: BE *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- X // can't assign from Y directly to an address register. *: X <- Y *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: X <- MEM(AR) *: T <- X; latchNZ; nextop // LDX zero page absolute opcode: A6 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: X <- MEM(AR) *: T <- X; latchNZ; nextop // LDY immediate // Load Y with the next byte of the program. opcode: A0 *: Y <- MEM(PC); PC++ *: T <- Y; latchNZ; nextop // LDY absolute // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory; // and load a byte from that location into Y. opcode: AC *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: Y <- MEM(AR) *: T <- Y; latchNZ; nextop // LDY zero page absolute opcode: A4 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: Y <- MEM(AR) *: T <- Y; latchNZ; nextop // LDY absolute,X // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory; // and store Y at the location obtained by adding X to that address. opcode: BC *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: Y <- MEM(AR) *: T <- Y; latchNZ; nextop // LDY zero page,X // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory; // and store Y at the location obtained by adding X to that address. opcode: B4 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: ARLO <- X + ARLO // no carry into ARHI *: Y <- MEM(AR) *: T <- Y; latchNZ; nextop // LDY indirect,X // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory; // interpret the two bytes beginning at that memory location as the lo, hi bytes of a second // location in memory, and load Y with the byte at the location obtained by adding X // to that second address. opcode: CB *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- MEM(AR); AR++ *: ARHI <- MEM(AR) *: ARLO <- X + T a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: Y <- MEM(AR) *: T <- Y; latchNZ; nextop // TAX // Transfer Accumulator to X, latch CCs opcode: AA *: X <- A; latchNZ; nextop // TXA // Transfer X to Accumulator, latch CCs opcode: 8A *: A <- X; latchNZ; nextop // TAY // Transfer Accumulator to Y, latch CCs opcode: A8 *: Y <- A; latchNZ; nextop // TYA // Transfer Y to Accumulator, latch CCs opcode: 98 *: A <- Y; latchNZ; nextop // TXY // Transfer X to Y, latch CCs opcode: 9B *: Y <- X; latchNZ; nextop // TYX // Transfer Y to X, latch CCs opcode: BB *: X <- Y; latchNZ; nextop // PHA // Push Accumulator onto the stack opcode: 48 *: MEM(SP) <- A; SP-- *: nextop // PLA // Pull Accumulator from the stack opcode: 68 *: SP++ *: A <- MEM(SP) *: T <- A; latchNZ; nextop // PHX // Push X onto the stack opcode: DA *: MEM(SP) <- X; SP-- *: nextop // PLX // Pull X from the stack opcode: FA *: SP++ *: X <- MEM(SP) *: nextop // PHY // Push Y onto the stack opcode: 5A *: MEM(SP) <- Y; SP-- *: nextop // PLY // Pull Y from the stack opcode: 7A *: SP++ *: Y <- MEM(SP) *: nextop // CLR absolute // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory; // and store zero at that location. opcode: 9C *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: MEM(AR) <- 0 *: nextop // CLR absolute,X // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory; // and store zero at the location obtained by adding X to that address. opcode: 9E *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: MEM(AR) <- 0 *: nextop // STA absolute // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory; // and store the Accumulator at that location. opcode: 8D *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: MEM(AR) <- A *: nextop // STA zero page absolute opcode: 85 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: MEM(AR) <- A *: nextop // STA absolute,X // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory; // and store the Accumulator at the location obtained by adding X to that address. opcode: 9D *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: MEM(AR) <- A *: nextop // STA zero page,X opcode: 95 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: ARLO <- X + ARLO // no carry into ARHI *: MEM(AR) <- A *: nextop // STA absolute,Y // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory; // and store the Accumulator at the location obtained by adding Y to that address. opcode: 99 *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- X // can't assign from Y directly to an address register. *: X <- Y *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: MEM(AR) <- A *: X <- T; nextop // STA stack relative // Interpret the next byte of the program as a positive offset from the stack pointer, // and store the Accumulator at the location in memory obtained by adding the offset // to the stack pointer. opcode: 83 *: T <- X *: X <- MEM(PC); PC++ *: ARLO <- X + SPLO a=0: ARHI <- 0 + SPHI + 1 a=1: ARHI <- 0 + SPHI *: X <- ARBANK // preserve ARBANK *: ARBANK <- SPBANK *: MEM(AR) <- A *: ARBANK <- X *: X <- T; nextop // STA stack relative indirect, X // Interpret the next byte of the program as a positive offset from the stack pointer, // interpert the two bytes beginning at that stack-relative location as the lo, hi bytes of a second // location in memory, and store the Accumulator at the location in obtained by adding X // to that second address. //opcode: 93 // *: T <- X // *: X <- MEM(PC); PC++ // *: ARLO <- X + SPLO //a=0: ARHI <- 0 + SPHI + 1 //a=1: ARHI <- 0 + SPHI // *: MEM(SP) <- ARBANK // preserve ARBANK using top of stack // *: ARBANK <- SPBANK // this doesn't work!!! // *: X <- T // *: T <- MEM(AR); AR++ // *: ARHI <- MEM(AR) // *: ARLO <- X + T //a=0: ARHI <- 0 + ARHI + 1 //a=1: ARHI <- 0 + ARHI // *: MEM(AR) <- A // *: ARBANK <- MEM(SP) // *: nextop // STA indirect,X // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory; // interpret the two bytes beginning at that memory location as the lo, hi bytes of a second // location in memory, and store the Accumulator at the location obtained by adding X // to that second address. opcode: 92 *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- MEM(AR); AR++ *: ARHI <- MEM(AR) *: ARLO <- X + T a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: MEM(AR) <- A *: nextop // STA indirect,Y // Interpret the next byte of the program as the location in zero page memory; // interpret the two bytes beginning at that memory location as the lo, hi bytes of a second // location in memory, and store the Accumulator at the location obtained by adding Y // to that second address. opcode: 91 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: T <- MEM(AR); AR++ *: ARHI <- MEM(AR) *: ARLO <- T // can't assign from Y directly to an address register. *: T <- X // can't assign from Y directly to an address register. *: X <- Y *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: MEM(AR) <- A *: X <- T; nextop // STA X,indirect // Interpret the next byte of the program as the zero page location of a pointer to a location in memory; // Add X to the pointer, interpret the two bytes beginning at the new pointer location as the lo, hi bytes of a second // location in memory, and store the Accumulator at that location. opcode: 81 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: ARLO <- X + ARLO // no carry into ARHI *: T <- MEM(AR); AR++ *: ARHI <- MEM(AR) *: ARLO <- T *: MEM(AR) <- A *: nextop // STX absolute // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory; // and store X at that location. opcode: 8E *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: MEM(AR) <- X *: nextop // STX zero page absolute opcode: 86 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: MEM(AR) <- X *: nextop // STY absolute // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory; // and store Y at that location. opcode: 8C *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: MEM(AR) <- Y *: nextop // STY zero page absolute opcode: 84 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: MEM(AR) <- Y *: nextop // STY zero page,X // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory; // and store Y at the location obtained by adding X to that address. opcode: 94 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: ARLO <- X + ARLO // no carry to ARHI *: MEM(AR) <- Y *: nextop // STY indirect,X // Interpret the next two bytes of the program as the lo,hi bytes of a location in memory; // interpret the two bytes beginning at that memory location as the lo, hi bytes of a second // location in memory, and store Y at the location obtained by adding X // to that second address. opcode: DB *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- MEM(AR); AR++ *: ARHI <- MEM(AR) *: ARLO <- X + T a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: MEM(AR) <- Y *: nextop // JSR // Push return address onto the stack; then interpret the next two bytes of the program // as the lo;hi bytes of the destination address, and jump to the destination. // Note this actually pushes return address - 2 onto the stack. RTS must compensate. opcode: 20 //*: T <- PCHI //*: MEM(SP) <- T; SP-- //*: T <- PCLO //*: MEM(SP) <- T; SP-- //*: T <- MEM(PC); PC++ //*: PCHI <- MEM(PC) //*: PCLO <- T //*: nextop *: ARLO <- MEM(PC); PC++ // save low byte of destination in ARLO *: T <- PCHI // save return address -1 on stack *: MEM(SP) <- T; SP-- *: T <- PCLO *: MEM(SP) <- T; SP-- *: PCHI <- MEM(PC) // jump to destination *: PCLO <- ARLO *: nextop // RTS // Return from subroutine, using the return address on the stack opcode: 60 *: SP++ *: PCLO <- MEM(SP); SP++ *: PCHI <- MEM(SP) *: PC++ //*: PC++ *: nextop // INX // Increment X by one, latch CC's. opcode: E8 *: X <- X + 1; latchNZ; nextop // DEX // Decrement X by one, latch CC's. opcode: CA *: X <- X - 1; latchNZ; nextop // INY // Increment Y by one, latch CC's. opcode: C8 *: Y <- Y + 1; latchNZ; nextop // DEY // Decrement Y by one, latch CC's. opcode: 88 *: Y <- Y - 1; latchNZ; nextop // DEC // Decrement contents of accumulator opcode: 3A *: A <- A - 1; latchNZ; nextop // DEC // Decrement contents of absolute memory address opcode: CE *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- X *: X <- MEM(AR) *: MEM(AR) <- X - 1; latchNZ *: X <- T; nextop // DEC zero page opcode: C6 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: T <- X *: X <- MEM(AR) *: MEM(AR) <- X - 1; latchNZ *: X <- T; nextop // DEC // Decrement contents of absolute memory address, X-indexed opcode: DE *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: T <- X *: X <- MEM(AR) *: MEM(AR) <- X - 1; latchNZ *: X <- T; nextop // INC // Increment contents of accumulator opcode: 1A *: A <- A + 1; latchNZ; nextop // INC // Increment contents of absolute memory address opcode: EE *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- MEM(AR) *: MEM(AR) <- 0 + T + 1; latchNZ *: nextop // INC zero page opcode: E6 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: T <- MEM(AR) *: MEM(AR) <- 0 + T + 1; latchNZ *: nextop // INC // Increment contents of absolute memory address, X-indexed opcode: FE *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: T <- MEM(AR) *: MEM(AR) <- 0 + T + 1; latchNZ *: nextop // INC zero page, X-indexed // Increment contents of absolute memory address, X-indexed opcode: F6 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: ARLO <- X + ARLO // no carry into ARHI *: T <- MEM(AR) *: MEM(AR) <- 0 + T + 1; latchNZ *: nextop // BRA // Relative branch. Interpret the // next byte of the program as a signed offset from the next instruction's PC, and jump to that // address. opcode: 80 *: T <- X *: X <- MEM(PC); PC++ *: PCLO <- X + PCLO // add delta to low byte of PC a=0: PCHI <- X7 + PCHI + 1 // carry flag == 0 means there was a carry a=1: PCHI <- X7 + PCHI *: X <- T; nextop // BEQ // Branch if result is zero. If Z bit of the condition codes is 0, then interpret the // next byte of the program as a signed offset from the next instruction's PC, and jump to that // address. opcode: F0 z=0: T <- X // brach taken z=1: pc++ // branch not taken z=0: X <- MEM(PC); PC++ z=1: nextop *: PCLO <- X + PCLO // add delta to low byte of PC a=0: PCHI <- X7 + PCHI + 1 // carry flag == 0 means there was a carry a=1: PCHI <- X7 + PCHI *: X <- T; nextop // BNE // Branch if result is non-zero. If Z bit of the condition codes is 1, then interpret the // next byte of the program as a signed offset from the next instruction's PC, and jump to that // address. opcode: D0 z=1: T <- X // brach taken z=0: pc++ // branch not taken z=1: X <- MEM(PC); PC++ z=0: nextop *: PCLO <- X + PCLO // add delta to low byte of PC a=0: PCHI <- X7 + PCHI + 1 // carry flag == 0 means there was a carry a=1: PCHI <- X7 + PCHI *: X <- T; nextop // BCS // Branch if carry set. If C bit of the condition codes is 0, then interpret the // next byte of the program as a signed offset from the next instruction's PC, and jump to that // address. opcode: B0 c=0: T <- X // brach taken c=1: pc++ // branch not taken c=0: X <- MEM(PC); PC++ c=1: nextop *: PCLO <- X + PCLO // add delta to low byte of PC a=0: PCHI <- X7 + PCHI + 1 // carry flag == 0 means there was a carry a=1: PCHI <- X7 + PCHI *: X <- T; nextop // BCC // Branch if carry clear. If C bit of the condition codes is 1, then interpret the // next byte of the program as a signed offset from the next instruction's PC, and jump to that // address. opcode: 90 c=1: T <- X // brach taken c=0: pc++ // branch not taken c=1: X <- MEM(PC); PC++ c=0: nextop *: PCLO <- X + PCLO // add delta to low byte of PC a=0: PCHI <- X7 + PCHI + 1 // carry flag == 0 means there was a carry a=1: PCHI <- X7 + PCHI *: X <- T; nextop // BVS // Branch if overflow set. If V bit of the condition codes is 1, then interpret the // next byte of the program as a signed offset from the next instruction's PC, and jump to that // address. opcode: 70 v=0: T <- X // brach taken v=1: pc++ // branch not taken v=0: X <- MEM(PC); PC++ v=1: nextop *: PCLO <- X + PCLO // add delta to low byte of PC a=0: PCHI <- X7 + PCHI + 1 // carry flag == 0 means there was a carry a=1: PCHI <- X7 + PCHI *: X <- T; nextop // BVC // Branch if overflow clear. If V bit of the condition codes is 0, then interpret the // next byte of the program as a signed offset from the next instruction's PC, and jump to that // address. opcode: 50 v=0: pc++ // branch not taken v=1: T <- X // brach taken v=0: nextop v=1: X <- MEM(PC); PC++ *: PCLO <- X + PCLO // add delta to low byte of PC a=0: PCHI <- X7 + PCHI + 1 // carry flag == 0 means there was a carry a=1: PCHI <- X7 + PCHI *: X <- T; nextop // BMI // Branch if minus. If N bit of the condition codes is 1, then interpret the // next byte of the program as a signed offset from the next instruction's PC, and jump to that // address. opcode: 30 n=0: pc++ // branch not taken n=1: T <- X // brach taken n=0: nextop n=1: X <- MEM(PC); PC++ *: PCLO <- X + PCLO // add delta to low byte of PC a=0: PCHI <- X7 + PCHI + 1 // carry flag == 0 means there was a carry a=1: PCHI <- X7 + PCHI *: X <- T; nextop // BPL // Branch if plus (really, not minus). If N bit of the condition codes is 0, then interpret the // next byte of the program as a signed offset from the next instruction's PC, and jump to that // address. opcode: 10 n=1: pc++ // branch not taken n=0: T <- X // brach taken n=1: nextop n=0: X <- MEM(PC); PC++ *: PCLO <- X + PCLO // add delta to low byte of PC a=0: PCHI <- X7 + PCHI + 1 // carry flag == 0 means there was a carry a=1: PCHI <- X7 + PCHI *: X <- T; nextop // ASL Accumulator // Arithmetic shift left Accumulator one bit. Shifted-out high bit goes to carry flag, inverted. // C <- [76543210] <- 0 // Maybe this should shift the pre-existing carry bit into the low end, to facilitate multi-byte shifts? opcode: 0A *: A <- A + A; latchNZC; nextop // ASL // Arithmetic shift left contents of an absolute memory address one bit. Shifted-out high bit goes to carry flag, inverted. // C <- [76543210] <- 0 // Maybe this should shift the pre-existing carry bit into the low end, to facilitate multi-byte shifts? opcode: 0E *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- A *: A <- MEM(AR) *: MEM(AR) <- A + A; latchNZC *: A <- T; nextop // ASL zero page // Arithmetic shift left contents of an absolute memory address one bit. Shifted-out high bit goes to carry flag, inverted. // C <- [76543210] <- 0 // Maybe this should shift the pre-existing carry bit into the low end, to facilitate multi-byte shifts? opcode: 06 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: T <- A *: A <- MEM(AR) *: MEM(AR) <- A + A; latchNZC *: A <- T; nextop // ASL // Arithmetic shift left contents of an absolute memory address, X-indexed, one bit. Shifted-out high bit goes to carry flag, inverted. // C <- [76543210] <- 0 // Maybe this should shift the pre-existing carry bit into the low end, to facilitate multi-byte shifts? opcode: 1E *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: T <- A *: A <- MEM(AR) *: MEM(AR) <- A + A; latchNZC *: A <- T; nextop // ASL zero page, X-indexed // Arithmetic shift left contents of an absolute memory address, X-indexed, one bit. Shifted-out high bit goes to carry flag, inverted. // C <- [76543210] <- 0 // Maybe this should shift the pre-existing carry bit into the low end, to facilitate multi-byte shifts? opcode: 16 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: ARLO <- X + ARLO // no carry into ARHI *: T <- A *: A <- MEM(AR) *: MEM(AR) <- A + A; latchNZC *: A <- T; nextop // LSR Accumulator // Logical shift right Accumulator one bit. Shifted-out low bit goes to carry flag, inverted. // 0 -> [76543210] -> C // This is pretty slow. If there's space in ROM, maybe just implement this as a 256-entry lookup. // Maybe this should shift the pre-existing carry bit into the high end, to facilitate multi-byte shifts? opcode: 4A *: A <- A + A; latchNZC // A BCDEFGH0 c=0: A <- A + A + 1; latchNZC // B CDEFGH0A c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // C DEFGH0AB c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // D EFGH0ABC c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // E FGH0ABCD c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // F GH0ABCDE c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // G H0ABCDEF c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC; nextop // H 0ABCDEFG c=1: A <- A + A; latchNZC; nextop // LSR // Logical shift right contents of an absolute memory address one bit. Shifted-out low bit goes to carry flag, inverted. // 0 -> [76543210] -> C // This is pretty slow. If there's space in ROM, maybe just implement this as a 256-entry lookup. // Maybe this should shift the pre-existing carry bit into the high end, to facilitate multi-byte shifts? opcode: 4E *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- A *: A <- MEM(AR) *: A <- A + A; latchNZC // A BCDEFGH0 c=0: A <- A + A + 1; latchNZC // B CDEFGH0A c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // C DEFGH0AB c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // D EFGH0ABC c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // E FGH0ABCD c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // F GH0ABCDE c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // G H0ABCDEF c=1: A <- A + A; latchNZC c=0: MEM(AR) <- A + A + 1; latchNZC // H 0ABCDEFG c=1: MEM(AR) <- A + A; latchNZC *: A <- T; nextop // LSR zero page // Logical shift right contents of an absolute memory address one bit. Shifted-out low bit goes to carry flag, inverted. // 0 -> [76543210] -> C // This is pretty slow. If there's space in ROM, maybe just implement this as a 256-entry lookup. // Maybe this should shift the pre-existing carry bit into the high end, to facilitate multi-byte shifts? opcode: 46 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: T <- A *: A <- MEM(AR) *: A <- A + A; latchNZC // A BCDEFGH0 c=0: A <- A + A + 1; latchNZC // B CDEFGH0A c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // C DEFGH0AB c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // D EFGH0ABC c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // E FGH0ABCD c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // F GH0ABCDE c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // G H0ABCDEF c=1: A <- A + A; latchNZC c=0: MEM(AR) <- A + A + 1; latchNZC // H 0ABCDEFG c=1: MEM(AR) <- A + A; latchNZC *: A <- T; nextop // LSR // Logical shift right contents of an absolute memory address, X-indexed, one bit. Shifted-out low bit goes to carry flag, inverted. // 0 -> [76543210] -> C // This is pretty slow. If there's space in ROM, maybe just implement this as a 256-entry lookup. // Maybe this should shift the pre-existing carry bit into the high end, to facilitate multi-byte shifts? opcode: 5E *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: T <- A *: A <- MEM(AR) *: A <- A + A; latchNZC // A BCDEFGH0 c=0: A <- A + A + 1; latchNZC // B CDEFGH0A c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // C DEFGH0AB c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // D EFGH0ABC c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // E FGH0ABCD c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // F GH0ABCDE c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // G H0ABCDEF c=1: A <- A + A; latchNZC c=0: MEM(AR) <- A + A + 1; latchNZC // H 0ABCDEFG c=1: MEM(AR) <- A + A; latchNZC *: A <- T; nextop // LSR zero page, X-indexed // Logical shift right contents of an absolute memory address, X-indexed, one bit. Shifted-out low bit goes to carry flag, inverted. // 0 -> [76543210] -> C // This is pretty slow. If there's space in ROM, maybe just implement this as a 256-entry lookup. // Maybe this should shift the pre-existing carry bit into the high end, to facilitate multi-byte shifts? opcode: 56 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: ARLO <- X + ARLO // no carry into ARHI *: T <- A *: A <- MEM(AR) *: A <- A + A; latchNZC // A BCDEFGH0 c=0: A <- A + A + 1; latchNZC // B CDEFGH0A c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // C DEFGH0AB c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // D EFGH0ABC c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // E FGH0ABCD c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // F GH0ABCDE c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // G H0ABCDEF c=1: A <- A + A; latchNZC c=0: MEM(AR) <- A + A + 1; latchNZC // H 0ABCDEFG c=1: MEM(AR) <- A + A; latchNZC *: A <- T; nextop // ROL Accumulator // C <- [76543210] <- C opcode: 2A c=0: A <- A + A + 1; latchNZC; nextop // /7 6543210C c=1: A <- A + A; latchNZC; nextop // ROL contents of absolute memory address // C <- [76543210] <- C opcode: 2E *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- A *: A <- MEM(AR) c=0: MEM(AR) <- A + A + 1; latchNZC // /7 6543210C c=1: MEM(AR) <- A + A; latchNZC *: A <- T; nextop // ROL zero page // C <- [76543210] <- C opcode: 26 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: T <- A *: A <- MEM(AR) c=0: MEM(AR) <- A + A + 1; latchNZC // /7 6543210C c=1: MEM(AR) <- A + A; latchNZC *: A <- T; nextop // ROL contents of absolute memory address, X-indexed // C <- [76543210] <- C opcode: 3E *: T <- A *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop: could optimize *: A <- MEM(AR) c=0: MEM(AR) <- A + A + 1; latchNZC // /7 6543210C c=1: MEM(AR) <- A + A; latchNZC *: A <- T; nextop // ROR Accumulator // C -> [76543210] -> C // This is pretty slow. If there's space in ROM, maybe just implement this as a 256-entry lookup. // Maybe this should shift the pre-existing carry bit into the high end, to facilitate multi-byte shifts? opcode: 6A c=0: A <- A + A + 1; latchNZC // /7 6543210/C c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /6 543210/C7 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /5 43210/C76 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /4 3210/C765 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /3 210/C7654 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /2 10/C76543 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /1 0/C765432 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC; nextop // /0 /C7654321 c=1: A <- A + A; latchNZC; nextop // ROR contents of absolute memory address // C -> [76543210] -> C // This is pretty slow. If there's space in ROM, maybe just implement this as a 256-entry lookup. // Maybe this should shift the pre-existing carry bit into the high end, to facilitate multi-byte shifts? opcode: 6E *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- A *: A <- MEM(AR) c=0: A <- A + A + 1; latchNZC // /7 6543210/C c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /6 543210/C7 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /5 43210/C76 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /4 3210/C765 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /3 210/C7654 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /2 10/C76543 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /1 0/C765432 c=1: A <- A + A; latchNZC c=0: MEM(AR) <- A + A + 1; latchNZC // /0 /C7654321 c=1: MEM(AR) <- A + A; latchNZC *: A <- T; nextop // ROR zero page // C -> [76543210] -> C // This is pretty slow. If there's space in ROM, maybe just implement this as a 256-entry lookup. // Maybe this should shift the pre-existing carry bit into the high end, to facilitate multi-byte shifts? opcode: 66 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: T <- A *: A <- MEM(AR) c=0: A <- A + A + 1; latchNZC // /7 6543210/C c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /6 543210/C7 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /5 43210/C76 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /4 3210/C765 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /3 210/C7654 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /2 10/C76543 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /1 0/C765432 c=1: A <- A + A; latchNZC c=0: MEM(AR) <- A + A + 1; latchNZC // /0 /C7654321 c=1: MEM(AR) <- A + A; latchNZC *: A <- T; nextop // ROR contents of absolute memory address, X-indexed // C -> [76543210] -> C // This is pretty slow. If there's space in ROM, maybe just implement this as a 256-entry lookup. // Maybe this should shift the pre-existing carry bit into the high end, to facilitate multi-byte shifts? opcode: 7E *: T <- A *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop: could optimize *: A <- MEM(AR) c=0: A <- A + A + 1; latchNZC // /7 6543210/C c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /6 543210/C7 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /5 43210/C76 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /4 3210/C765 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /3 210/C7654 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /2 10/C76543 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /1 0/C765432 c=1: A <- A + A; latchNZC c=0: MEM(AR) <- A + A + 1; latchNZC // /0 /C7654321 c=1: MEM(AR) <- A + A; latchNZC *: A <- T; nextop // ROR zero page, X-indexed // C -> [76543210] -> C // This is pretty slow. If there's space in ROM, maybe just implement this as a 256-entry lookup. // Maybe this should shift the pre-existing carry bit into the high end, to facilitate multi-byte shifts? opcode: 76 *: T <- A *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: ARLO <- X + ARLO // no carry into ARHI *: A <- MEM(AR) c=0: A <- A + A + 1; latchNZC // /7 6543210/C c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /6 543210/C7 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /5 43210/C76 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /4 3210/C765 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /3 210/C7654 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /2 10/C76543 c=1: A <- A + A; latchNZC c=0: A <- A + A + 1; latchNZC // /1 0/C765432 c=1: A <- A + A; latchNZC c=0: MEM(AR) <- A + A + 1; latchNZC // /0 /C7654321 c=1: MEM(AR) <- A + A; latchNZC *: A <- T; nextop // ASR Accumulator // Arithmetic shift right Accumulator one bit. Shifted-out low bit goes to carry flag, inverted. // 7 -> [76543210] -> C // This is pretty slow. If there's space in ROM, maybe just implement this as a 256-entry lookup. //opcode: ?? // *: T <- A + A; latchNZC //c=0: A <- A + A + 1; latchNZC // A BCDEFGHA //c=1: A <- A + A; latchNZC //c=0: A <- A + A + 1; latchNZC // B CDEFGHAA //c=1: A <- A + A; latchNZC //c=0: A <- A + A + 1; latchNZC // C DEFGHAAB //c=1: A <- A + A; latchNZC //c=0: A <- A + A + 1; latchNZC // D EFGHAABC //c=1: A <- A + A; latchNZC //c=0: A <- A + A + 1; latchNZC // E FGHAABCD //c=1: A <- A + A; latchNZC //c=0: A <- A + A + 1; latchNZC // F GHAABCDE //c=1: A <- A + A; latchNZC //c=0: A <- A + A + 1; latchNZC // G HAABCDEF //c=1: A <- A + A; latchNZC //c=0: A <- A + A + 1; latchNZC; nextop // H AABCDEFG //c=1: A <- A + A; latchNZC; nextop // SPX // Swap the contents of the processor status register (condition codes) with X. // Staus register format is reversed: 0000CNZV opcode: EF c=0: X <- X + X; shiftCC c=1: X <- X + X + 1; shiftCC c=0: X <- X + X; shiftCC c=1: X <- X + X + 1; shiftCC c=0: X <- X + X; shiftCC c=1: X <- X + X + 1; shiftCC c=0: X <- X + X; shiftCC; nextop c=1: X <- X + X + 1; shiftCC; nextop // SEC // Set carry opcode: 38 *: T <- X *: X <- 0 // C=0 n=0: X <- X + X n=1: X <- X + X + 1 z=0: X <- X + X z=1: X <- X + X + 1 v=0: X <- X + X v=1: X <- X + X + 1 *: X <- X + X; shiftCC *: X <- X + X; shiftCC *: X <- X + X; shiftCC *: X <- T; shiftCC; nextop // CLC // Clear carry flag opcode: 18 *: T <- X *: X <- 0 + 1 // C=1 n=0: X <- X + X n=1: X <- X + X + 1 z=0: X <- X + X z=1: X <- X + X + 1 v=0: X <- X + X v=1: X <- X + X + 1 *: X <- X + X; shiftCC *: X <- X + X; shiftCC *: X <- X + X; shiftCC *: X <- T; shiftCC; nextop // CLV // Clear overflow flag opcode: B8 *: T <- X c=0: X <- 0 c=1: X <- 0 + 1 n=0: X <- X + X n=1: X <- X + X + 1 z=0: X <- X + X z=1: X <- X + X + 1 *: X <- X + X + 1 // V=1 *: X <- X + X; shiftCC *: X <- X + X; shiftCC *: X <- X + X; shiftCC *: X <- T; shiftCC; nextop // PHP // Push the contents of the processor status register onto the stack. // Staus register format is reversed: 0000CNZV opcode: 08 *: T <- A c=0: A <- 0 c=1: A <- 0 + 1 n=0: A <- A + A n=1: A <- A + A + 1 z=0: A <- A + A z=1: A <- A + A + 1 v=0: MEM(SP) <- A + A; SP-- v=1: MEM(SP) <- A + A + 1; SP-- *: A <- T; nextop // PLP // Pull the contents of the processor status register from the stack. // Staus register format is reversed: 0000CNZV opcode: 28 *: T <- X; SP++ *: X <- MEM(SP) *: X <- X + X; shiftCC *: X <- X + X; shiftCC *: X <- X + X; shiftCC *: X <- T; shiftCC; nextop // BRK // Disables interrupts, pushes ARBANK, pushes 3-byte PC, and jumps to the interrupt service // routine whose address is at $00FFFE. // // NOTE: BRK does not push the condition codes, A, X, or Y. The ISR // must do this. The ISR is also responsible for saving the SP, then setting // up the interrupt SP. opcode: 00 *: T <- ARBANK; disableInt // push ARBANK *: MEM(SP) <- T; SP-- *: T <- PCBANK *: MEM(SP) <- T; SP-- *: T <- PCHI *: MEM(SP) <- T; SP-- *: T <- PCLO *: MEM(SP) <- T; SP-- *: ARLO <- 0 + 1 // ARLO = 1 *: PCHI <- 0 - 1 // PCHI = $FF *: PCLO <- 0 - ARLO - 1 // PCLO = $FE *: PCBANK <- 0 *: T <- MEM(PC); PC++ *: PCHI <- MEM(PC) *: PCLO <- T *: nextop // RTI // Pops the 3-byte PC and backs it up by one byte, so the interrupted instruction // will be retried. Pops ARBANK, enables interrupts, and jumps to the popped PC. // // NOTE: RTI does not restore the condition codes, A, X, or Y. The ISR // must do this. The ISR is also responsible for restoring the SP. opcode: 40 *: T <- X *: SP++ *: X <- MEM(SP); SP++ *: PCLO <- X - 1 // back up PC, latch address carry *: X <- MEM(SP); SP++ a=0: PCHI <- X a=1: PCHI <- X - 1 *: PCBANK <- MEM(SP); SP++ *: ARBANK <- MEM(SP); enableInt // pop ARBANK *: X <- T; nextop // CMP imm // Compare immediate value with accumulator opcode: C9 *: T <- MEM(PC); PC++ *: T <- A - T; latchNZC; nextop // CMP absolute // Compare value at absolute address with accumulator opcode: CD *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- MEM(AR) *: T <- A - T; latchNZC; nextop // CMP zero page opcode: C5 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: T <- MEM(AR) *: T <- A - T; latchNZC; nextop // CMP absolute, X // Compare value at absolute address, X indexed with accumulator opcode: DD *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI *: T <- MEM(AR) *: T <- A - T; latchNZC; nextop // CMP absolute, Y // Compare value at absolute address, Y indexed with accumulator opcode: D9 *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- X // can't assign from Y directly to an address register. *: X <- Y *: ARLO <- X + ARLO *: X <- T a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI *: T <- MEM(AR) *: T <- A - T; latchNZC; nextop // CMP stack relative // Interpret the next byte of the program as a positive offset from the stack pointer, // and compare the Accumulator to the byte at the location in memory obtained by adding // the offset to the stack pointer. opcode: C3 *: ARLO <- SPLO *: ARHI <- SPHI *: T <- X *: X <- MEM(PC); PC++ *: ARLO <- X + ARLO *: X <- T a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: T <- MEM(AR) *: T <- A - T; latchNZC; nextop // CMP indirect,Y // Interpret the next byte of the program as the location in zero page memory; // interpret the two bytes beginning at that memory location as the lo, hi bytes of a second // location in memory, and compare the Accumulator to the byte at the location obtained by adding Y // to that second address. opcode: D1 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: T <- MEM(AR); AR++ *: ARHI <- MEM(AR) *: ARLO <- T // can't assign from Y directly to an address register. *: T <- X // can't assign from Y directly to an address register. *: X <- Y *: ARLO <- X + ARLO *: X <- T a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: T <- MEM(AR) *: T <- A - T; latchNZC; nextop // CPX imm // Compare immediate value with X opcode: E0 *: T <- MEM(PC); PC++ *: T <- X - T; latchNZC; nextop // CPX abs // Compare value at absolute address with X opcode: EC *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- MEM(AR) *: T <- X - T; latchNZC; nextop // CPX zero page opcode: E4 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: T <- MEM(AR) *: T <- X - T; latchNZC; nextop // CPY imm // Compare immediate value with Y opcode: C0 *: T <- MEM(PC); PC++ *: T <- Y - T; latchNZC; nextop // CPY absolute // Compare value at absolute address with Y opcode: CC *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- MEM(AR) *: T <- Y - T; latchNZC; nextop // CPY zero page opcode: C4 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: T <- MEM(AR) *: T <- Y - T; latchNZC; nextop // CLI // Clear interrupt disable (actually sets interrupt enable) opcode: 58 *: enableInt *: nextop // SEI // Set interrupt disable (actually clears interrupt enable) opcode: 78 *: disableInt *: nextop // ORA imm // Perform a bitwise OR of the accumulator with an immediate value, // latching the condition codes and storing the result in the accumulator. opcode: 09 *: T <- MEM(PC); PC++ *: A <- ALU(A,T,E,1,1); latchNZ; nextop // ALU(left, right, function, carry_in, mode) // ORA abs // Perform a bitwise OR of the accumulator with a byte at an absolute memory address, // latching the condition codes and storing the result in the accumulator. opcode: 0D *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- MEM(AR) *: A <- ALU(A,T,E,1,1); latchNZ; nextop // ALU(left, right, function, carry_in, mode) // ORA zero page // Perform a bitwise OR of the accumulator with a byte at an absolute memory address, // latching the condition codes and storing the result in the accumulator. opcode: 05 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: T <- MEM(AR) *: A <- ALU(A,T,E,1,1); latchNZ; nextop // ALU(left, right, function, carry_in, mode) // ORA abs,X // Perform a bitwise OR of the accumulator with at an absolute memory address offset by X, // latching the condition codes and storing the result in the accumulator. opcode: 1D *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: T <- MEM(AR) a=0: T <- MEM(AR) a=1: A <- ALU(A,T,E,1,1); latchNZ; nextop // ALU(left, right, function, carry_in, mode) a=0: A <- ALU(A,T,E,1,1); latchNZ; nextop // ALU(left, right, function, carry_in, mode) a=1: nextop; // control will never get here // ORA stack relative // Interpret the next byte of the program as a positive offset from the stack pointer, // and performs a bitwise OR of the Accumulator with the byte at the location in memory // obtained by adding the offset to the stack pointer. opcode: 03 *: ARLO <- SPLO *: ARHI <- SPHI *: T <- X *: X <- MEM(PC); PC++ *: ARLO <- X + ARLO *: X <- T a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: T <- MEM(AR) *: A <- ALU(A,T,E,1,1); latchNZ; nextop // ALU(left, right, function, carry_in, mode) // AND // Perform a bitwise AND of the accumulator with an immediate value, // latching the condition codes and storing the result in the accumulator. opcode: 29 *: T <- MEM(PC); PC++ *: A <- ALU(A,T,B,1,1); latchNZ; nextop // ALU(left, right, function, carry_in, mode) // AND abs // Perform a bitwise AND of the accumulator with a byte at an absolute memory address, // latching the condition codes and storing the result in the accumulator. opcode: 2D *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- MEM(AR) *: A <- ALU(A,T,B,1,1); latchNZ; nextop // ALU(left, right, function, carry_in, mode) // AND zero page // Perform a bitwise AND of the accumulator with a byte at an absolute memory address, // latching the condition codes and storing the result in the accumulator. opcode: 25 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: T <- MEM(AR) *: A <- ALU(A,T,B,1,1); latchNZ; nextop // ALU(left, right, function, carry_in, mode) // AND abs,X // Perform a bitwise AND of the accumulator with at an absolute memory address offset by X, // latching the condition codes and storing the result in the accumulator. opcode: 3D *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: T <- MEM(AR) a=0: T <- MEM(AR) a=1: A <- ALU(A,T,B,1,1); latchNZ; nextop // ALU(left, right, function, carry_in, mode) a=0: A <- ALU(A,T,B,1,1); latchNZ; nextop // ALU(left, right, function, carry_in, mode) a=1: nextop; // control will never get here // AND stack relative // Interpret the next byte of the program as a positive offset from the stack pointer, // and performs a bitwise AND of the Accumulator with the byte at the location in memory // obtained by adding the offset to the stack pointer. opcode: 23 *: ARLO <- SPLO *: ARHI <- SPHI *: T <- X *: X <- MEM(PC); PC++ *: ARLO <- X + ARLO *: X <- T a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: T <- MEM(AR) *: A <- ALU(A,T,B,1,1); latchNZ; nextop // ALU(left, right, function, carry_in, mode) // EOR // Perform a bitwise EXCLUSIVE OR of the accumulator with an immediate value, // latching the condition codes and storing the result in the accumulator. opcode: 49 *: T <- MEM(PC); PC++ *: A <- ALU(A,T,6,1,1); latchNZ; nextop // ALU(left, right, function, carry_in, mode) // EOR abs // Perform a bitwise XOR of the accumulator with a byte at an absolute memory address, // latching the condition codes and storing the result in the accumulator. opcode: 4D *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- MEM(AR) *: A <- ALU(A,T,6,1,1); latchNZ; nextop // ALU(left, right, function, carry_in, mode) // EOR zero page // Perform a bitwise XOR of the accumulator with a byte at an absolute memory address, // latching the condition codes and storing the result in the accumulator. opcode: 45 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: T <- MEM(AR) *: A <- ALU(A,T,6,1,1); latchNZ; nextop // ALU(left, right, function, carry_in, mode) // EOR abs,X // Perform a bitwise XOR of the accumulator with at an absolute memory address offset by X, // latching the condition codes and storing the result in the accumulator. opcode: 5D *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: T <- MEM(AR) a=0: T <- MEM(AR) a=1: A <- ALU(A,T,6,1,1); latchNZ; nextop // ALU(left, right, function, carry_in, mode) a=0: A <- ALU(A,T,6,1,1); latchNZ; nextop // ALU(left, right, function, carry_in, mode) a=1: nextop; // control will never get here // EOR stack relative // Interpret the next byte of the program as a positive offset from the stack pointer, // and performs a bitwise XOR of the Accumulator with the byte at the location in memory // obtained by adding the offset to the stack pointer. opcode: 43 *: ARLO <- SPLO *: ARHI <- SPHI *: T <- X *: X <- MEM(PC); PC++ *: ARLO <- X + ARLO *: X <- T a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: T <- MEM(AR) *: A <- ALU(A,T,6,1,1); latchNZ; nextop // ALU(left, right, function, carry_in, mode) // EOR indirect,Y // Interpret the byte of the program as the zero page location in memory; // interpret the two bytes beginning at that memory location as the lo, hi bytes of a second // location in memory, and perform a bitwise XOR of the Accumulator with the byte at the location obtained by adding Y // to that second address. opcode: 51 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: T <- MEM(AR); AR++ *: ARHI <- MEM(AR) *: ARLO <- T // can't assign from Y directly to an address register. *: T <- X // can't assign from Y directly to an address register. *: X <- Y *: ARLO <- X + ARLO *: X <- T a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: T <- MEM(AR) *: A <- ALU(A,T,6,1,1); latchNZ; nextop // ALU(left, right, function, carry_in, mode) // EOR X,indirect // Interpret the byte of the program as the zero page location of a pointer to a location in memory; // Add X to the pointer, interpret the two bytes beginning at the new pointer location as the lo, hi bytes of a second // location in memory, and perform a bitwise XOR of the Accumulator with the byte at that location. opcode: 41 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: ARLO <- X + ARLO // no carry into ARHI *: T <- MEM(AR); AR++ *: ARHI <- MEM(AR) *: ARLO <- T *: T <- MEM(AR) *: A <- ALU(A,T,6,1,1); latchNZ; nextop // ALU(left, right, function, carry_in, mode) // ADC imm // Add an immediate value to the accumulator, including the current value of the carry flag. // A <- A + #imm + C opcode: 69 *: T <- MEM(PC); PC++ c=0: A <- A + T + 1; latchAllCC; nextop c=1: A <- A + T; latchAllCC; nextop // ADC absolute // Add a byte at an absolute memory address to the accumulator, including the current value of the carry flag. // A <- A + mem + C opcode: 6D *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- MEM(AR) c=0: A <- A + T + 1; latchAllCC; nextop c=1: A <- A + T; latchAllCC; nextop // ADC zero page // A <- A + mem + C opcode: 65 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: T <- MEM(AR) c=0: A <- A + T + 1; latchAllCC; nextop c=1: A <- A + T; latchAllCC; nextop // ADC absolute, X // Add a byte at an absolute memory address offset by X to the accumulator, including the current value of the carry flag. // A <- A + mem,X + C opcode: 7D *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: T <- MEM(AR) c=0: A <- A + T + 1; latchAllCC; nextop // this makes me want to puke c=1: A <- A + T; latchAllCC; nextop // ADC absolute, Y // Add a byte at an absolute memory address offset by Y to the accumulator, including the current value of the carry flag. // A <- A + mem,Y + C opcode: 79 *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- X // can't assign from Y directly to an address register. *: X <- Y *: ARLO <- X + ARLO *: X <- T a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: T <- MEM(AR) c=0: A <- A + T + 1; latchAllCC; nextop // this makes me want to puke c=1: A <- A + T; latchAllCC; nextop // ADC stack relative // Interpret the next byte of the program as a positive offset from the stack pointer, // and adds (include the current value of the carry flag) the Accumulator to the byte // at the location in memory obtained by adding the offset to the stack pointer, storing // the result in the Accumulator. opcode: 63 *: ARLO <- SPLO *: ARHI <- SPHI *: T <- X *: X <- MEM(PC); PC++ *: ARLO <- X + ARLO *: X <- T a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: T <- MEM(AR) c=0: A <- A + T + 1; latchAllCC; nextop c=1: A <- A + T; latchAllCC; nextop // SBC imm // Subtract an immediate value from the accumulator, including the current value of the carry flag. // A <- A - #imm - C opcode: E9 *: T <- MEM(PC); PC++ c=0: A <- A - T; latchAllCC; nextop c=1: A <- A - T - 1; latchAllCC; nextop // SBC absolute // Subtract a value at an absolute address from the accumulator, including the current value of the carry flag. // A <- A - mem - C opcode: ED *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- MEM(AR) c=0: A <- A - T; latchAllCC; nextop c=1: A <- A - T - 1; latchAllCC; nextop // SBC zero page // Subtract a value at an absolute address from the accumulator, including the current value of the carry flag. // A <- A - mem - C opcode: E5 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: T <- MEM(AR) c=0: A <- A - T; latchAllCC; nextop c=1: A <- A - T - 1; latchAllCC; nextop // SBC absolute, X // Subtract a value at an absolute address, X-indexed from the accumulator, including the current value of the carry flag. // A <- A - mem,x - C opcode: FD *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: ARLO <- X + ARLO a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop: could optimize *: T <- MEM(AR) c=0: A <- A - T; latchAllCC; nextop // this makes me want to puke c=1: A <- A - T - 1; latchAllCC; nextop // SBC absolute, y // Subtract a value at an absolute address, y-indexed from the accumulator, including the current value of the carry flag. // A <- A - mem,Y - C opcode: F9 *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- X // can't assign from Y directly to an address register. *: X <- Y *: ARLO <- X + ARLO *: X <- T a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop: could optimize *: T <- MEM(AR) c=0: A <- A - T; latchAllCC; nextop // this makes me want to puke c=1: A <- A - T - 1; latchAllCC; nextop // SBC stack relative // Interpret the next byte of the program as a positive offset from the stack pointer, // and subtracts (include the current value of the carry flag) the Accumulator to the byte // at the location in memory obtained by adding the offset to the stack pointer, storing // the result in the Accumulator. opcode: E3 *: ARLO <- SPLO *: ARHI <- SPHI *: T <- X *: X <- MEM(PC); PC++ *: ARLO <- X + ARLO *: X <- T a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop: could optimize *: T <- MEM(AR) c=0: A <- A - T; latchAllCC; nextop c=1: A <- A - T - 1; latchAllCC; nextop // SBC indirect,Y opcode: F1 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: T <- MEM(AR); AR++ *: ARHI <- MEM(AR) *: ARLO <- T // can't assign from Y directly to an address register. *: T <- X // can't assign from Y directly to an address register. *: X <- Y *: ARLO <- X + ARLO *: X <- T a=0: ARHI <- 0 + ARHI + 1 a=1: ARHI <- 0 + ARHI // nop *: T <- MEM(AR) *: A <- A - T; latchAllCC; nextop // SBC zero page, X // Subtract a value at an absolute address, X-indexed from the accumulator, including the current value of the carry flag. // A <- A - mem,x - C opcode: F5 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: ARLO <- X + ARLO // no carry into ARHI *: T <- MEM(AR) c=0: A <- A - T; latchAllCC; nextop // this makes me want to puke c=1: A <- A - T - 1; latchAllCC; nextop // BIT absolute // Perform a bitwise AND of the accumulator with an byte stored at an absolute address, // latching Z. Bit 7 of the memory is loaded into N, and bit 6 into V. The accumulator is not modified. opcode: 2C *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: T <- MEM(AR) *: T <- ALU(A,T,B,1,1); latchNZ // Z = A & mem *: T <- X *: X <- MEM(AR) // C=C X=7654efgh z=0: ARLO <- ALU(0,T,F,0,0) // save z in a z=1: ARLO <- 0 + T c=0: X <- X + X; latchNZC // C=/7 X=654efghC c=1: X <- X + X + 1; latchNZC c=0: X <- X + X + 1; latchNZC // C=/6 X=54efghC7 c=1: X <- X + X; latchNZC a=0: X <- X + X // C=/6 X=4efghC7Z a=1: X <- X + X + 1 c=0: X <- X + X; latchNZC // C=/4 X=efghC7Z6 c=1: X <- X + X + 1; latchNZC *: X <- X + X; shiftCC // V=C *: X <- X + X; shiftCC // Z=C, V=7 *: X <- X + X; shiftCC // N=C, Z=7, V=Z *: X <- T; shiftCC; nextop // C=C, N=7, Z=Z, V=6 // BIT zero page // Perform a bitwise AND of the accumulator with a byte stored at a zero page address, // latching Z. Bit 7 of the memory is loaded into N, and bit 6 into V. The accumulator is not modified. opcode: 24 *: ARLO <- MEM(PC); PC++ *: ARHI <- 0 *: T <- MEM(AR) *: T <- ALU(A,T,B,1,1); latchNZ // Z = A & mem *: T <- X *: X <- MEM(AR) // C=C X=7654efgh z=0: ARLO <- ALU(0,T,F,0,0) // save z in a z=1: ARLO <- 0 + T c=0: X <- X + X; latchNZC // C=/7 X=654efghC c=1: X <- X + X + 1; latchNZC c=0: X <- X + X + 1; latchNZC // C=/6 X=54efghC7 c=1: X <- X + X; latchNZC a=0: X <- X + X // C=/6 X=4efghC7Z a=1: X <- X + X + 1 c=0: X <- X + X; latchNZC // C=/4 X=efghC7Z6 c=1: X <- X + X + 1; latchNZC *: X <- X + X; shiftCC // V=C *: X <- X + X; shiftCC // Z=C, V=7 *: X <- X + X; shiftCC // N=C, Z=7, V=Z *: X <- T; shiftCC; nextop // C=C, N=7, Z=Z, V=6 // TSR // Transfer the stack pointer to the data registers. // A <- SPLO // Y <- SPHI // X <- SPBANK opcode: 0B *: A <- SPLO *: Y <- SPHI *: X <- SPBANK *: nextop // TRS // Transfer the data registers to the stack pointer. // SPLO <- A // SPHI <- Y // SPBANK <- X opcode: 1B *: SPLO <- A *: T <- Y *: SPHI <- T *: SPBANK <- X *: nextop // TSX // Transfer the stack pointer low byte to the X register. // X <- SPLO opcode: BA *: X <- SPLO *: nextop // TXS // Transfer the X register to the stack pointer low byte. // SPLO <- X opcode: 9A *: SPLO <- X *: nextop // ----- new microinstructions added 10/4/08 ----- // JML // jump to absolute long address opcode: 5C *: T <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ // use ARHI as a temporary *: PCBANK <- MEM(PC) *: PCHI <- ARHI *: PCLO <- T *: nextop // JSL // long subroutine jump. Note this actually pushes return address - 3: // RTL must compensate. opcode: 22 *: T <- PCBANK *: MEM(SP) <- T; SP-- *: T <- PCHI *: MEM(SP) <- T; SP-- *: T <- PCLO *: MEM(SP) <- T; SP-- *: T <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ // use ARHI as a temporary *: PCBANK <- MEM(PC) *: PCHI <- ARHI *: PCLO <- T *: nextop // RTL // return from a long subroutine jump opcode: 6B *: SP++ *: PCLO <- MEM(SP); SP++ *: PCHI <- MEM(SP); SP++ *: PCBANK <- MEM(SP) *: PC++ *: PC++ *: PC++ *: nextop // PHB // push ARBANK opcode: 8B *: T <- ARBANK *: MEM(SP) <- T; SP-- *: nextop // PLB // pull ARBANK opcode: AB *: SP++ *: ARBANK <- MEM(SP) *: nextop // LDA_S // Load Accumulator from (SP), and increment the pointer opcode: C2 *: A <- MEM(SP); SP++ *: nextop // STA_S // Store Accumulator into (SP), and increment the pointer opcode: E2 *: MEM(SP) <- A; SP++ *: nextop // LDA absolute long opcode: AF *: T <- ARBANK *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: ARBANK <- MEM(PC); PC++ *: A <- MEM(AR) *: ARBANK <- T *: ARHI <- 0 // hardware bug work-around: clear ARHI to avoid later spurious reads from $003FXX *: T <- A; latchNZ; nextop // STA absolute long opcode: 8F *: T <- ARBANK *: ARLO <- MEM(PC); PC++ *: ARHI <- MEM(PC); PC++ *: ARBANK <- MEM(PC); PC++ *: MEM(AR) <- A *: ARBANK <- T *: ARHI <- 0; nextop // hardware bug work-around: clear ARHI to avoid later spurious reads from $003FXX // ??? // increment YA //opcode: ?? // *: A <- A + 1; latchAllCC //c=0: Y <- Y + 1; latchAllCC; nextop //c=1: nextop // ??? // add immediate value plus carry to YA // YA <- YA + #imm + C //opcode: ?? // *: T <- MEM(PC); PC++ //c=0: A <- A + T + 1; latchAllCC //c=1: A <- A + T; latchAllCC //c=0: Y <- Y + 1; latchAllCC; nextop //c=1: nextop // ??? // add X plus carry to YA // YA <- YA + X + C //opcode: ?? //c=0: A <- A + X + 1; latchAllCC //c=1: A <- A + X; latchAllCC //c=0: Y <- Y + 1; latchAllCC; nextop //c=1: nextop // LDXYA // load X with (YA) //opcode: ?? //*: ARLO <- A //*: ARHI <- Y //*: X <- MEM(AR) //*: T <- X; latchNZ; nextop // STXYA // store X in (YA) //opcode: ?? //*: ARLO <- A //*: ARHI <- Y //*: MEM(AR) <- X //*: nextop