18

Assuming that this diagram is correct:

enter image description here

Instructions like INC, INX, and INY can easily perform increment using ALU sum with data on B input, 0 on A input and carry_in set.

But how do instructions like DEC, DEX and DEY work?

It can decrement by adding -1 which is 0xFF, and it can have 0xFF by inverting 0 BUT 0 can only be set on A input and inverting can only be done on B input.

So how does it perform a decrement?

22

But how instructions like DEC, DEX and DEY works ?

By adding $FF provided by the precharged internal data bus to the register content.


In Detail:

  • The internal databus is precharged with $FF during PHI2 (*1)
  • During the next phase it's loaded into the B register (signal DB/ADD)
  • At the same time the index register is transfered via SB (*/SB) to the A register (SB/ADD)
  • SUMS is pulled thus $FF is added to the register content, effectively decrementing it (*2).
  • The result is transfered back via SB (ADD/SB7 + ADD/SB(0..6)) to either index register (SB/*).

Background 1: NMOS switching (Abbreviated Version)

While using the precharge to supply a $FF constant is a real nifty feature, it's more of a hack base on a side effect to speed up NMOS operation.

The precharge exists due the way MOS-FET and NMOS Logic work. Effectively each FET (and line) is a (comparable) large capacitor. Loading and unloading takes time in relation to resistance in the circuit. In NMOS logic the transistor is placed between the output and ground. On the other side the output is connected to Vcc (+5V) via a resistor.

When the Transistor switches on, the output is grounded with a very low resistance, puting the output extrem fast toward Low. When it's switched off, the output is loaded via the resistor. Thus changing a signal line from Low to High takes considerable longer than going from High to Low.

By precharging lines with High value ahead of time and then pulling them down when a signal is to be transmitted, minimizes switch time to the lower of both, resulting in faster operation.


Background 2: Use of Precharge for Constant Generation on 6502

On the 6502 precharge is thus present on all 4 internal busses (DB, ADL, ADH, SB). Beside providing $FF for decrement on DB, it's well used on ADH and ADL to generate constant values:

  • Constant generated on DB
    • $FF by default
  • Constants generated on ADH:
    • $FF for vector pull - by default
    • $01 for stack page addressing - by pulling 0/ADH(1-7)
    • $00 for zero page addressing - by pulling 0/ADH(1-7) and 0/ADH0
  • Constants generated on ADL:
    • $FE/$FF for INT - by default value plus 0/ADL0 on first access
    • $FC/$FD for Reset - by 0/ADL1 plus 0/ADL0 on first access
    • $FA/$FB for NMI - by 0/ADL2 plus 0/ADL0 on first access

Another special use is with transfering ALU results to SB. The ALU does not shift-in Carry on a ROR, but always sets bit 7 to Zero. So when the ALU result is transfered after a ROR, bit 7 is only transfered if carry was cleared. Otherwise transfer for bit 7 is supressed, replacing it by a precharged One.

Precharge behaviour is a major reason why the 6502 is not static, as the precharged values will vanish after some time, making many operations invalid.


Background 3: Hanson Diagramm

It has been asked where the signal names originated. They are taken from the famous Hanson diagram - as cited by the OP (*3) - which is nowadays the de-facto standard for interpreting the 6502 (despite having a few little inconsistencies; *4). It was part of an equally famous 1995 article by Mr. Hanson about making D-Latches in VHDL. To my knowledge the diagram was first drawn up in 1982 during studies of the original 6502 blueprints.

The names are rather straight forward, like Y/SB meaning connect Y output to Special Bus (the register data bus), or SB/Y to enable loading Y from SB. Next to all modern sources use these names, or derivations thereof. Most notable maybe the Visual 6502 simulation (used in DPcontrol output; see the nodenames.js source for all names used; *5).


*1 - Note the Prechage MOSFET box in the top left quadrant, beside DB, right below the Data Output Register box

*2 - It's an unsigned 8 bit addition (n + 255) mod 256.

*3 - Please use, whenever possible the cleaned up version provided by Mr. Hanson at http://www.witwright.com/DonPub/6502-Block-Diagram.pdf. The often used copies of copies of scans are quite ugly and hard to read.

*4 - For example there is a signal generated if DB is negative or the flipflops shown as part of the logic don't fully add up, but these are details that only come up when trying to recreate the CPU.

*5 - Searching it is quite handy to find meaning and usage - as the Visual 6502 in general is a great tool to peek into the 6502.

| improve this answer | |
  • 1
    Thanks, for the DEC instruction, memory read (input data latch) goes by DB to B and A is precharged with $FF by precharge MOSFET under stack pointer register ? – Johnmph Jan 15 at 5:19
  • 1
    Did the 6502 save any circuitry by making the read-modify-write sequence for INC and DEC usable with the "accumulator" addressing mode? I find there are an annoying number of cases where the omission of those instructions converts what should be a 1 byte/2 cycle op into 3 bytes/4 cycles. – supercat Jan 15 at 17:20
  • 1
    @supercat Simply no. It's one of several instructions that could have been added right away with not more than another row in ROM. I would attribute it (like some of the other) to kind of Betriebsblindheit - they were too much focused on seeing the A as the only work register while X/Y are only there for indexing. Each and every A instruction could have been made to work on X/Y as well by just adding appropriate columns to the decode ROM (as well as using A to index). All three registers are equal (except for the decimal adjuster at A). Having an ADY #8 to walk structures would have been nice. – Raffzahn Jan 15 at 18:22
  • 1
    @lvd taken from the famous Hanson diagram - as cited by the OP - which is the de-facto standard for interpreting the 6502 (despite having a few little inconsistencies). It was part of an equally famous article by Mr. Hanson in 1995 about D-Latches in VHDL. To my knowledge it was drawn up in 1982 from the 6502 blueprints. The names are rather straight foreward, like Y/SB meaning connect Y output to Special Bus (the register data bus), or SB/Y for loading Y from SB. – Raffzahn Jan 15 at 19:01
  • 1
    Thanks for the update! – lvd Jan 15 at 20:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.