<p> Following is a list of the flags, starting from the 8th bit of the</p>
<p> P register (bit 7, value $80):</p>
<p> N Negative flag</p>
<p> This flag will be set after any arithmetic operations</p>
<p> (when any of the registers A, X or Y is being loaded</p>
<p> with a value). Generally, the N flag will be copied from</p>
<p> the topmost bit of the register being loaded.</p>
<p><br></p>
<p> Note that TXS (Transfer X to S) is not an arithmetic</p>
<p> operation. Also note that the BIT instruction affects</p>
<p> the Negative flag just like arithmetic operations.</p>
<p> Finally, the Negative flag behaves differently in</p>
<p> Decimal operations (see description below).</p>
<p> V oVerflow flag</p>
<p> Like the Negative flag, this flag is intended to be used</p>
<p> with 8-bit signed integer numbers. The flag will be</p>
<p> affected by addition and subtraction, the instructions</p>
<p> PLP, CLV and BIT, and the hardware signal -SO. Note that</p>
<p> there is no SEV instruction, even though the MOS</p>
<p> engineers loved to use East European abbreviations, like</p>
<p> DDR (Deutsche Demokratische Republik vs. Data Direction</p>
<p> Register). (The Russian abbreviation for their former</p>
<p> trade association COMECON is SEV.) The -SO (Set</p>
<p> Overflow) signal is available on some processors, at</p>
<p> least the 6502, to set the V flag. This enables response</p>
<p> to an I/O activity in equal or less than three clock</p>
<p> cycles when using a BVC instruction branching to itself</p>
<p> The CLV instruction clears the V flag, and the PLP and</p>
<p> BIT instructions copy the flag value from the bit 6 of</p>
<p> the topmost stack entry or from memory.</p>
<p><br></p>
<p> After a binary addition or subtraction, the V flag will</p>
<p> be set on a sign overflow, cleared otherwise. What is a</p>
<p> sign overflow? For instance, if you are trying to add</p>
<p> 123 and 45 together, the result (168) does not fit in a</p>
<p> 8-bit signed integer (upper limit 127 and lower limit</p>
<p> -128). Similarly, adding -123 to -45 causes the</p>
<p> overflow, just like subtracting -45 from 123 or 123 from</p>
<p> -45 would do.</p>
<p><br></p>
<p> Like the N flag, the V flag will not be set as expected</p>
<p> in the Decimal mode. Later in this document is a precise</p>
<p> A common misbelief is that the V flag could only be set</p>
<p> by arithmetic operations, not cleared.</p>
<p> To the current knowledge, this flag is always 1.</p>
<p> B Break flag</p>
<p> This flag is used to distinguish software (BRK)</p>
<p> interrupts from hardware interrupts (IRQ or NMI). The B</p>
<p> flag is always set except when the P register is being</p>
<p> pushed on stack when jumping to an interrupt routine to</p>
<p> process only a hardware interrupt.</p>
<p><br></p>
<p> The official NMOS 65xx documentation claims that the BRK</p>
<p> instruction could only cause a jump to the IRQ vector</p>
<p> ($FFFE). However, if an NMI interrupt occurs while</p>
<p> executing a BRK instruction, the processor will jump to</p>
<p> the NMI vector ($FFFA), and the P register will be</p>
<p> pushed on the stack with the B flag set.</p>
<p> D Decimal mode flag</p>
<p> This flag is used to select the (Binary Coded) Decimal</p>
<p> mode for addition and subtraction. In most applications,</p>
<p> the flag is zero.</p>
<p><br></p>
<p> The Decimal mode has many oddities, and it operates</p>
<p> differently on CMOS processors. See the description of</p>
<p> the ADC, SBC and ARR instructions below.</p>
<p> I Interrupt disable flag</p>
<p> This flag can be used to prevent the processor from</p>
<p> jumping to the IRQ handler vector ($FFFE) whenever the</p>
<p> hardware line -IRQ is active. The flag will be</p>
<p> automatically set after taking an interrupt, so that the</p>
<p> processor would not keep jumping to the interrupt</p>
<p> routine if the -IRQ signal remains low for several clock</p>
<p> Z Zero flag</p>
<p> The Zero flag will be affected in the same cases than</p>
<p> the Negative flag. Generally, it will be set if an</p>
<p> arithmetic register is being loaded with the value zero,</p>
<p> and cleared otherwise. The flag will behave differently</p>
<p> in Decimal operations.</p>
<p> C Carry flag</p>
<p> This flag is used in additions, subtractions,</p>
<p> comparisons and bit rotations. In additions and</p>
<p> subtractions, it acts as a 9th bit and lets you to chain</p>
<p> operations to calculate with bigger than 8-bit numbers.</p>
<p> When subtracting, the Carry flag is the negative of</p>
<p> Borrow: if an overflow occurs, the flag will be clear,</p>
<p> otherwise set. Comparisons are a special case of</p>
<p> subtraction: they assume Carry flag set and Decimal flag</p>
<p> clear, and do not store the result of the subtraction</p>
<p> There are four kinds of bit rotations. All of them store</p>
<p> the bit that is being rotated off to the Carry flag. The</p>
<p> left shifting instructions are ROL and ASL. ROL copies</p>
<p> the initial Carry flag to the lowmost bit of the byte;</p>
<p> ASL always clears it. Similarly, the ROR and LSR</p>
<p> instructions shift to the right.</p>
<p> A Accumulator</p>
<p> The accumulator is the main register for arithmetic and logic</p>
<p> operations. Unlike the index registers X and Y, it has a direct</p>
<p> connection to the Arithmetic and Logic Unit (ALU). This is why</p>
<p> many operations are only available for the accumulator, not the</p>
<p> index registers.</p>
<p> X Index register X</p>
<p> This is the main register for addressing data with indices. It has</p>
<p> a special addressing mode, indexed indirect, which lets you to</p>
<p> have a vector table on the zero page.</p>
<p> Y Index register Y</p>
<p> The Y register has the least operations available. On the other</p>
<p> hand, only it has the indirect indexed addressing mode that</p>
<p> enables access to any memory place without having to use</p>
<p><spanclass=rvts10> ANE $8B A = (A | #$EE) & X & #byte</span></p>
<p><spanclass=rvts10> same as</span></p>
<p><spanclass=rvts10> A = ((A & #$11 & X) | ( #$EE & X)) & #byte</span></p>
<p> In real 6510/8502 the internal parameter #$11</p>
<p> may occasionally be #$10, #$01 or even #$00.</p>
<p> This occurs when the video chip starts DMA</p>
<p> between the opcode fetch and the parameter fetch</p>
<p> of the instruction. The value probably depends</p>
<p> on the data that was left on the bus by the VIC-II.</p>
<p><spanclass=rvts10> LXA $AB C=Lehti: A = X = ANE</span></p>
<p><spanclass=rvts10> Alternate: A = X = (A & #byte)</span></p>
<p> TXA and TAX have to be responsible for these.</p>
<p><spanclass=rvts10> SHA $93,$9F Store (A & X & (ADDR_HI + 1))</span></p>
<p><spanclass=rvts10> SHX $9E Store (X & (ADDR_HI + 1))</span></p>
<p><spanclass=rvts10> SHY $9C Store (Y & (ADDR_HI + 1))</span></p>
<p><spanclass=rvts10> SHS $9B SHA and TXS, where X is replaced by (A & X).</span></p>
<p> Note: The value to be stored is copied also</p>
<p> to ADDR_HI if page boundary is crossed.</p>
<p><br></p>
<p> SBX $CB Carry and Decimal flags are ignored but the</p>
<p> Carry flag will be set in substraction. This</p>
<p> is due to the CMP command, which is executed</p>
<p> instead of the real SBC.</p>
<p><br></p>
<p> ARR $6B This instruction first performs an AND</p>
<p> between the accumulator and the immediate</p>
<p> parameter, then it shifts the accumulator to</p>
<p> the right. However, this is not the whole</p>
<p> truth. See the description below.</p>
<p><br></p>
<p>Many undocumented commands do not use AND between registers, the CPU</p>
<p>just throws the bytes to a bus simultaneously and lets the</p>
<p>open-collector drivers perform the AND. I.e. the command called 'SAX',</p>
<p>which is in the STORE section (opcodes $A0...$BF), stores the result</p>
<p>of (A & X) by this way.</p>
<p><br></p>
<p>More fortunate is its opposite, 'LAX' which just loads a byte</p>
<p><spanclass=rvts10> AL, /* low nybble of accumulator */</span></p>
<p><spanclass=rvts10> AH, /* high nybble of accumulator */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> C, /* Carry flag */</span></p>
<p><spanclass=rvts10> Z, /* Zero flag */</span></p>
<p><spanclass=rvts10> V, /* oVerflow flag */</span></p>
<p><spanclass=rvts10> N, /* Negative flag */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> t, /* temporary value */</span></p>
<p><spanclass=rvts10> s; /* value to be ARRed with Accumulator */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> t = A & s; /* Perform the AND. */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> AH = t >> 4; /* Separate the high */</span></p>
<p><spanclass=rvts10> AL = t & 15; /* and low nybbles. */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> N = C; /* Set the N and */</span></p>
<p><spanclass=rvts10> Z = !(A = (t >> 1) | (C << 7)); /* Z flags traditionally */</span></p>
<p><spanclass=rvts10> V = (t ^ A) & 64; /* and V flag in a weird way. */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> if (AL + (AL & 1) > 5) /* BCD "fixup" for low nybble. */</span></p>
<p><spanclass=rvts10> A = (A & 0xF0) | ((A + 6) & 0xF);</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> if (C = AH + (AH & 1) > 5) /* Set the Carry flag. */</span></p>
<p><spanclass=rvts10> A = (A + 0x60) & 0xFF; /* BCD "fixup" for high nybble. */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> $CB SBX X <- (A & X) - Immediate</span></p>
<p><spanclass=rvts10> AL, /* low nybble of accumulator */</span></p>
<p><spanclass=rvts10> AH, /* high nybble of accumulator */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> C, /* Carry flag */</span></p>
<p><spanclass=rvts10> Z, /* Zero flag */</span></p>
<p><spanclass=rvts10> V, /* oVerflow flag */</span></p>
<p><spanclass=rvts10> N, /* Negative flag */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> s; /* value to be added to Accumulator */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> AL = (A & 15) + (s & 15) + C; /* Calculate the lower nybble. */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> AH = (A >> 4) + (s >> 4) + (AL > 15); /* Calculate the upper nybble. */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> if (AL > 9) AL += 6; /* BCD fixup for lower nybble. */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> Z = ((A + s + C) & 255 != 0); /* Zero flag is set just</span></p>
<p><spanclass=rvts10> like in Binary mode. */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> /* Negative and Overflow flags are set with the same logic than in</span></p>
<p><spanclass=rvts10> Binary mode, but after fixing the lower nybble. */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> N = (AH & 8 != 0);</span></p>
<p><spanclass=rvts10> V = ((AH << 4) ^ A) & 128 && !((A ^ s) & 128);</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> if (AH > 9) AH += 6; /* BCD fixup for upper nybble. */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> /* Carry is the only flag set after fixing the result. */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> C = (AH > 15);</span></p>
<p><spanclass=rvts10> A = ((AH << 4) | (AL & 15)) & 255;</span></p>
<p><spanclass=rvts10> AL, /* low nybble of accumulator */</span></p>
<p><spanclass=rvts10> AH, /* high nybble of accumulator */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> C, /* Carry flag */</span></p>
<p><spanclass=rvts10> Z, /* Zero flag */</span></p>
<p><spanclass=rvts10> V, /* oVerflow flag */</span></p>
<p><spanclass=rvts10> N, /* Negative flag */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> s; /* value to be added to Accumulator */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> AL = (A & 15) - (s & 15) - !C; /* Calculate the lower nybble. */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> if (AL & 16) AL -= 6; /* BCD fixup for lower nybble. */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> AH = (A >> 4) - (s >> 4) - (AL & 16); /* Calculate the upper nybble. */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> if (AH & 16) AH -= 6; /* BCD fixup for upper nybble. */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> /* The flags are set just like in Binary mode. */</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> C = (A - s - !C) & 256 != 0;</span></p>
<p><spanclass=rvts10> Z = (A - s - !C) & 255 != 0;</span></p>
<p><spanclass=rvts10> V = ((A - s - !C) ^ s) & 128 && (A ^ s) & 128;</span></p>
<p><spanclass=rvts10> N = (A - s - !C) & 128 != 0;</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> A = ((AH << 4) | (AL & 15)) & 255;</span></p>
<p><spanclass=rvts10> 3 $0100,S W push PCH on stack (with B flag set), decrement S</span></p>
<p><spanclass=rvts10> 4 $0100,S W push PCL on stack, decrement S</span></p>
<p><spanclass=rvts10> 5 $0100,S W push P on stack, decrement S</span></p>
<p><spanclass=rvts10> 4 $0100,S W push PCH on stack, decrement S</span></p>
<p><spanclass=rvts10> 5 $0100,S W push PCL on stack, decrement S</span></p>
<p><spanclass=rvts10> 6 PC R copy low address byte to PCL, fetch high address</span></p>
<p><spanclass=rvts10> byte to PCH</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> Accumulator or implied addressing</span></p>
<p><spanclass=rvts10> 3 PC R copy low address byte to PCL, fetch high address</span></p>
<p><spanclass=rvts10> byte to PCH</span></p>
<p><spanclass=rvts10> 3 PC R fetch high byte of address, increment PC</span></p>
<p><spanclass=rvts10> 4 address R read from effective address</span></p>
<p><spanclass=rvts10> 5 address W write the value back to effective address,</span></p>
<p><spanclass=rvts10> and do the operation on it</span></p>
<p><spanclass=rvts10> 6 address W write the new value to effective address</span></p>
<p><spanclass=rvts10> 3 address R read from effective address</span></p>
<p><spanclass=rvts10> 4 address W write the value back to effective address,</span></p>
<p><spanclass=rvts10> and do the operation on it</span></p>
<p><spanclass=rvts10> 5 address W write the new value to effective address</span></p>
<p><spanclass=rvts10> 3 address R read from address, add index register to it</span></p>
<p><spanclass=rvts10> 4 address+I* R read from effective address</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> Notes: I denotes either index register (X or Y).</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> * The high byte of the effective address is always zero,</span></p>
<p><spanclass=rvts10> i.e. page boundary crossings are not handled.</span></p>
<p><spanclass=rvts10> 3 address R read from address, add index register X to it</span></p>
<p><spanclass=rvts10> 4 address+X* R read from effective address</span></p>
<p><spanclass=rvts10> 5 address+X* W write the value back to effective address,</span></p>
<p><spanclass=rvts10> and do the operation on it</span></p>
<p><spanclass=rvts10> 6 address+X* W write the new value to effective address</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> Note: * The high byte of the effective address is always zero,</span></p>
<p><spanclass=rvts10> i.e. page boundary crossings are not handled.</span></p>
<p><spanclass=rvts10> 3 address R read from address, add index register to it</span></p>
<p><spanclass=rvts10> 4 address+I* W write to effective address</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> Notes: I denotes either index register (X or Y).</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> * The high byte of the effective address is always zero,</span></p>
<p><spanclass=rvts10> i.e. page boundary crossings are not handled.</span></p>
<p><spanclass=rvts10> 3 PC R fetch high byte of address,</span></p>
<p><spanclass=rvts10> add index register to low address byte,</span></p>
<p><spanclass=rvts10> 4 address+I* R read from effective address,</span></p>
<p><spanclass=rvts10> fix the high byte of effective address</span></p>
<p><spanclass=rvts10> 5+ address+I R re-read from effective address</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> Notes: I denotes either index register (X or Y).</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> * The high byte of the effective address may be invalid</span></p>
<p><spanclass=rvts10> at this time, i.e. it may be smaller by $100.</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> + This cycle will be executed only if the effective address</span></p>
<p><spanclass=rvts10> was invalid during cycle #4, i.e. page boundary was crossed.</span></p>
<p><spanclass=rvts10> 3 PC R fetch high byte of address,</span></p>
<p><spanclass=rvts10> add index register X to low address byte,</span></p>
<p><spanclass=rvts10> 4 address+X* R read from effective address,</span></p>
<p><spanclass=rvts10> fix the high byte of effective address</span></p>
<p><spanclass=rvts10> 5 address+X R re-read from effective address</span></p>
<p><spanclass=rvts10> 6 address+X W write the value back to effective address,</span></p>
<p><spanclass=rvts10> and do the operation on it</span></p>
<p><spanclass=rvts10> 7 address+X W write the new value to effective address</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> Notes: * The high byte of the effective address may be invalid</span></p>
<p><spanclass=rvts10> at this time, i.e. it may be smaller by $100.</span></p>
<p><spanclass=rvts10> 3 PC R fetch high byte of address,</span></p>
<p><spanclass=rvts10> add index register to low address byte,</span></p>
<p><spanclass=rvts10> 4 address+I* R read from effective address,</span></p>
<p><spanclass=rvts10> fix the high byte of effective address</span></p>
<p><spanclass=rvts10> 5 address+I W write to effective address</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> Notes: I denotes either index register (X or Y).</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> * The high byte of the effective address may be invalid</span></p>
<p><spanclass=rvts10> at this time, i.e. it may be smaller by $100. Because</span></p>
<p><spanclass=rvts10> the processor cannot undo a write to an invalid</span></p>
<p><spanclass=rvts10> address, it always reads from the address first.</span></p>
<p><spanclass=rvts10> 3 PC R Fetch opcode of next instruction,</span></p>
<p><spanclass=rvts10> If branch is taken, add operand to PCL.</span></p>
<p><spanclass=rvts10> 4+ PC* R Fetch opcode of next instruction.</span></p>
<p><spanclass=rvts10> Fix PCH. If it did not change, increment PC.</span></p>
<p><spanclass=rvts10> 5! PC R Fetch opcode of next instruction,</span></p>
<p><spanclass=rvts10> Notes: The opcode fetch of the next instruction is included to</span></p>
<p><spanclass=rvts10> this diagram for illustration purposes. When determining</span></p>
<p><spanclass=rvts10> real execution times, remember to subtract the last</span></p>
<p><spanclass=rvts10> * The high byte of Program Counter (PCH) may be invalid</span></p>
<p><spanclass=rvts10> at this time, i.e. it may be smaller or bigger by $100.</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> + If branch is taken, this cycle will be executed.</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> ! If branch occurs to different page, this cycle will be</span></p>
<p><spanclass=rvts10> 3 pointer R read from the address, add X to it</span></p>
<p><spanclass=rvts10> 6 address R read from effective address</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> Note: The effective address is always fetched from zero page,</span></p>
<p><spanclass=rvts10> i.e. the zero page boundary crossing is not handled.</span></p>
<p><spanclass=rvts10> 3 pointer R read from the address, add X to it</span></p>
<p><spanclass=rvts10> 6 address R read from effective address</span></p>
<p><spanclass=rvts10> 7 address W write the value back to effective address,</span></p>
<p><spanclass=rvts10> and do the operation on it</span></p>
<p><spanclass=rvts10> 8 address W write the new value to effective address</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> Note: The effective address is always fetched from zero page,</span></p>
<p><spanclass=rvts10> i.e. the zero page boundary crossing is not handled.</span></p>
<p><spanclass=rvts10> 3 pointer R read from the address, add X to it</span></p>
<p><spanclass=rvts10> 6 address W write to effective address</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> Note: The effective address is always fetched from zero page,</span></p>
<p><spanclass=rvts10> i.e. the zero page boundary crossing is not handled.</span></p>
<p><spanclass=rvts10> add Y to low byte of effective address</span></p>
<p><spanclass=rvts10> 5 address+Y* R read from effective address,</span></p>
<p><spanclass=rvts10> fix high byte of effective address</span></p>
<p><spanclass=rvts10> 6+ address+Y R read from effective address</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> Notes: The effective address is always fetched from zero page,</span></p>
<p><spanclass=rvts10> i.e. the zero page boundary crossing is not handled.</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> * The high byte of the effective address may be invalid</span></p>
<p><spanclass=rvts10> at this time, i.e. it may be smaller by $100.</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> + This cycle will be executed only if the effective address</span></p>
<p><spanclass=rvts10> was invalid during cycle #5, i.e. page boundary was crossed.</span></p>
<p><spanclass=rvts10> add Y to low byte of effective address</span></p>
<p><spanclass=rvts10> 5 address+Y* R read from effective address,</span></p>
<p><spanclass=rvts10> fix high byte of effective address</span></p>
<p><spanclass=rvts10> 6 address+Y R read from effective address</span></p>
<p><spanclass=rvts10> 7 address+Y W write the value back to effective address,</span></p>
<p><spanclass=rvts10> and do the operation on it</span></p>
<p><spanclass=rvts10> 8 address+Y W write the new value to effective address</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> Notes: The effective address is always fetched from zero page,</span></p>
<p><spanclass=rvts10> i.e. the zero page boundary crossing is not handled.</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> * The high byte of the effective address may be invalid</span></p>
<p><spanclass=rvts10> at this time, i.e. it may be smaller by $100.</span></p>
<p><spanclass=rvts10> add Y to low byte of effective address</span></p>
<p><spanclass=rvts10> 5 address+Y* R read from effective address,</span></p>
<p><spanclass=rvts10> fix high byte of effective address</span></p>
<p><spanclass=rvts10> 6 address+Y W write to effective address</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> Notes: The effective address is always fetched from zero page,</span></p>
<p><spanclass=rvts10> i.e. the zero page boundary crossing is not handled.</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> * The high byte of the effective address may be invalid</span></p>
<p><spanclass=rvts10> at this time, i.e. it may be smaller by $100.</span></p>
<p><spanclass=rvts10> 4 pointer R fetch low address to latch</span></p>
<p><spanclass=rvts10> 5 pointer+1* R fetch PCH, copy latch to PCL</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> Note: * The PCH will always be fetched from the same page</span></p>
<p><spanclass=rvts10> than PCL, i.e. page boundary crossing is not handled.</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> How Real Programmers Acknowledge Interrupts</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> With RMW instructions:</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> ; beginning of combined raster/timer interrupt routine</span></p>
<p><spanclass=rvts10> LSR $D019 ; clear VIC interrupts, read raster interrupt flag to C</span></p>
<p><spanclass=rvts10> BCS raster ; jump if VIC caused an interrupt</span></p>
<p><spanclass=rvts10> 5 xx $D019 W write the value back, rotate right</span></p>
<p><spanclass=rvts10> 6 xx/2 $D019 W write the new value back</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> The 5th cycle acknowledges the interrupt by writing the same</span></p>
<p><spanclass=rvts10> value back. If only raster interrupts are used, the 6th cycle</span></p>
<p><spanclass=rvts10> has no effect on the VIC. (It might acknowledge also some</span></p>
<p><spanclass=rvts10> other interrupts.)</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> With indexed addressing:</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> ; acknowledge interrupts to both CIAs</span></p>
<p><spanclass=rvts10> 3 DC PC+2 R fetch address high, add X to address low</span></p>
<p><spanclass=rvts10> 4 xx $DC0D R read from address, fix high byte of address</span></p>
<p><spanclass=rvts10> 5 yy $DD0D R read from right address</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> ; acknowledge interrupts to CIA 2</span></p>
<p><spanclass=rvts10> 3 DC PC+2 R fetch address high, add X to address low</span></p>
<p><spanclass=rvts10> 4 xx $DD0D R read from address, fix high byte of address</span></p>
<p><spanclass=rvts10> 5 ac $DE0D W write to right address</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> With branch instructions:</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> ; acknowledge interrupts to CIA 2</span></p>
<p><spanclass=rvts10> LDA #$00 ; clear N flag</span></p>
<p><spanclass=rvts10> STA $DD0A</span></p>
<p><spanclass=rvts10> STA $DD08 ; load the ToD values from the latches</span></p>
<p><spanclass=rvts10> LDA $DD0B ; freeze the ToD display</span></p>
<p><spanclass=rvts10> STA $DC0D ; assure that $DC0D is $00</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> Operational diagram of BPL $DC9D:</span></p>
<p><spanclass=rvts10> STA $DD0D ; disable all interrupt sources of CIA2</span></p>
<p><spanclass=rvts10> AND #$BE ; ensure that $DD0C remains constant</span></p>
<p><spanclass=rvts10> STA $DD0E ; and stop the timer</span></p>
<p><spanclass=rvts10> STA $DD0C ; parameter of BPL</span></p>
<p><spanclass=rvts10> STA $DD0B ; BPL</span></p>
<p><spanclass=rvts10> STA $DD0A ; RTI/parameter of LSR</span></p>
<p><spanclass=rvts10> STA $DD09 ; LSR</span></p>
<p><spanclass=rvts10> STA $DD08 ; load the ToD values from the latches</span></p>
<p><spanclass=rvts10> LDA $DD0B ; freeze the ToD display</span></p>
<p><spanclass=rvts10> STA $0319 ; change NMI vector to $DD09</span></p>
<p><spanclass=rvts10> LDA #$FF ; Try changing this instruction's operand</span></p>
<p><spanclass=rvts10> STA $DD05 ; (see comment below).</span></p>
<p><spanclass=rvts10> STA $DD04 ; set interrupt frequency to 1/65536 cycles</span></p>
<p><spanclass=rvts10> STA $DD0E ; start timer</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> LDA #$00 ; To see that the interrupts really occur,</span></p>
<p><spanclass=rvts10> STA $D011 ; use something like this and see how</span></p>
<p><spanclass=rvts10> LOOP DEC $D020 ; changing the byte loaded to $DD05 from</span></p>
<p><spanclass=rvts10> BNE LOOP ; #$FF to #$0F changes the image.</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> When an NMI occurs, the processor jumps to Kernal code, which jumps to</span></p>
<p><spanclass=rvts10> ($0318), which points to the following routine:</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> DD09 LSR $40 ; clear N flag</span></p>
<p><spanclass=rvts10> LDA $01 ; disable ROM and enable I/O</span></p>
<p><spanclass=rvts10> AND #$FD</span></p>
<p><spanclass=rvts10> ORA #$05</span></p>
<p><spanclass=rvts10> STA $01</span></p>
<p><spanclass=rvts10> STA $DD0D ; disable CIA 2's all interrupt sources</span></p>
<p><spanclass=rvts10> AND #$BE ; ensure that $DD0C remains constant</span></p>
<p><spanclass=rvts10> STA $DD0E ; and stop the timer</span></p>
<p><spanclass=rvts10> STA $DD0C ; store RTI to $DD0C</span></p>
<p><spanclass=rvts10> STA $FFFB ; change NMI vector to $DD0C</span></p>
<p><spanclass=rvts10> LDA #$FF ; Try changing this instruction's operand</span></p>
<p><spanclass=rvts10> STA $DD05 ; (see comment below).</span></p>
<p><spanclass=rvts10> STA $DD04 ; set interrupt frequency to 1/65536 cycles</span></p>
<p><spanclass=rvts10> STA $DD0E ; start timer</span></p>
<p><spanclass=rvts10><br></span></p>
<p><spanclass=rvts10> LDA #$00 ; To see that the interrupts really occur,</span></p>
<p><spanclass=rvts10> STA $D011 ; use something like this and see how</span></p>
<p><spanclass=rvts10> LOOP DEC $D020 ; changing the byte loaded to $DD05 from</span></p>
<p><spanclass=rvts10> BNE LOOP ; #$FF to #$0F changes the image.</span></p>
<p><spanclass=rvts10> DD09 LSR $xx ; xx is any appropriate BCD value 00-59.</span></p>
<pclass=rvps4><spanclass=rvts13>This help file has been generated by the freeware version of </span><aclass=rvts14href="http://www.ibe-software.com/products/software/helpndoc/"target="_blank">HelpNDoc</a></p>