Status flags: Difference between revisions

From NESdev Wiki
Jump to navigationJump to search
(→‎The B flag: Separate out the warning about Visual6502's space-saving approach to save space in the main text)
(Tries to add more clarity, particularly around the always-1 bit and B flag. Moves the table of contents to a more sensible place.)
Line 1: Line 1:
The '''flags''' register, also called '''processor status''' or just '''P''', is one of the six architectural registers on the 6502 family CPU.
The '''flags''' register, also called '''processor status''' or just '''P''', is one of the six architectural registers on the 6502 family CPU. It is composed of six one-bit registers; instructions modify one or more bits and leave others unchanged.
It is composed of six one-bit registers; instructions modify one or more bits and leave others unchanged.
 
== Flags ==


Instructions that save or restore the flags map them to bits in the architectural 'P' register as follows:
Instructions that save or restore the flags map them to bits in the architectural 'P' register as follows:
Line 6: Line 7:
  7  bit  0
  7  bit  0
  ---- ----
  ---- ----
  NVss DIZC
  NV1B DIZC
  |||| ||||
  |||| ||||
  |||| |||+- [[#C: Carry|Carry]]
  |||| |||+- [[#C: Carry|Carry]]
Line 12: Line 13:
  |||| |+--- [[#I: Interrupt Disable|Interrupt Disable]]
  |||| |+--- [[#I: Interrupt Disable|Interrupt Disable]]
  |||| +---- [[#D: Decimal|Decimal]]
  |||| +---- [[#D: Decimal|Decimal]]
  ||++------ No CPU effect, see: [[#The B flag|the B flag]]
  |||+------ (No CPU effect; see: [[#The B flag|the B flag]])
||+------- (No CPU effect; always pushed as 1)
  |+-------- [[#V: Overflow|Overflow]]
  |+-------- [[#V: Overflow|Overflow]]
  +--------- [[#N: Negative|Negative]]
  +--------- [[#N: Negative|Negative]]
Line 19: Line 21:
* [[Interrupts]], including the NMI and also the pseudo-interrupt BRK instruction, implicitly push the status register to the stack.
* [[Interrupts]], including the NMI and also the pseudo-interrupt BRK instruction, implicitly push the status register to the stack.
* Interrupts returning with RTI will implicitly pull the saved status register from the stack.
* Interrupts returning with RTI will implicitly pull the saved status register from the stack.
* The two bits with no CPU effect are ignored when pulling flags from the stack; there are no corresponding registers for them in the CPU.
* When P is displayed as a single 8-bit register by debuggers, there is no convention for what values to use for bits 5 and 4 and their values should not be considered meaningful.


== C: Carry ==
=== C: Carry ===
 
----
* After ADC, this is the carry result of the addition.
* After ADC, this is the carry result of the addition.
* After SBC or CMP, this flag will be set if no borrow was the result, or alternatively a "greater than or equal" result.
* After SBC or CMP, this flag will be set if no borrow was the result, or alternatively a "greater than or equal" result.
Line 28: Line 32:
* Can be set or cleared directly with SEC, CLC.
* Can be set or cleared directly with SEC, CLC.


== Z: Zero ==
=== Z: Zero ===
 
----
* After most instructions that have a value result, this flag will either be set or cleared based on whether or not that value is equal to zero.
* After most instructions that have a value result, this flag will either be set or cleared based on whether or not that value is equal to zero.


== I: Interrupt Disable ==
=== I: Interrupt Disable ===
 
----
* When set, all [[interrupts]] except the [[NMI]] are inhibited.
* When set, all [[interrupts]] except the [[NMI]] are inhibited.
* Can be set or cleared directly with SEI, CLI.
* Can be set or cleared directly with SEI, CLI.
Line 39: Line 43:
* If the [[IRQ|/IRQ]] line is low (IRQ pending) when this flag is cleared, an interrupt will immediately be triggered.
* If the [[IRQ|/IRQ]] line is low (IRQ pending) when this flag is cleared, an interrupt will immediately be triggered.


== D: Decimal ==
=== D: Decimal ===
 
----
* On the NES, this flag has no effect.
* On the NES, decimal mode is disabled and so this flag has no effect. However, it still exists and can be observed and modified, as normal.
* On the original 6502, this flag causes some arithmetic instructions to use [[wikipedia:Binary-coded_decimal|binary-coded decimal]] representation to make base 10 calculations easier.
* On the original 6502, this flag causes some arithmetic instructions to use [[wikipedia:Binary-coded_decimal|binary-coded decimal]] representation to make base 10 calculations easier.
* Can be set or cleared directly with SED, CLD.
* Can be set or cleared directly with SED, CLD.


== V: Overflow ==
=== V: Overflow ===
 
----
* ADC and SBC will set this flag if the signed result would be invalid<ref>[http://www.6502.org/tutorials/vflag.html Article: The Overflow (V) Flag Explained]</ref>, necessary for making signed comparisons<ref>[http://www.6502.org/tutorials/compare_beyond.html#5 Article: Beyond 8-bit Unsigned Comparisons], Signed Comparisons</ref>.
* ADC and SBC will set this flag if the signed result would be invalid<ref>[http://www.6502.org/tutorials/vflag.html Article: The Overflow (V) Flag Explained]</ref>, necessary for making signed comparisons<ref>[http://www.6502.org/tutorials/compare_beyond.html#5 Article: Beyond 8-bit Unsigned Comparisons], Signed Comparisons</ref>.
* BIT will load bit 6 of the addressed value directly into the V flag.
* BIT will load bit 6 of the addressed value directly into the V flag.
* Can be cleared directly with CLV. There is no corresponding set instruction.
* Can be cleared directly with CLV. There is no corresponding set instruction.


== N: Negative ==
=== N: Negative ===
 
----
* After most instructions that have a value result, this flag will contain bit 7 of that result.
* After most instructions that have a value result, this flag will contain bit 7 of that result.
* BIT will load bit 7 of the addressed value directly into the N flag.
* BIT will load bit 7 of the addressed value directly into the N flag.


== The B flag ==
=== The B flag ===
 
----
While there are only six flags in the processor status register within the CPU, the value pushed to the stack has two additional bits.
While there are only six flags in the processor status register within the CPU, the value pushed to the stack contains additional state called the B flag that can be useful to software. The value of B depends on what caused the flags to be pushed. Note that this flag does not represent a register that can hold a value, but rather a transient signal in the CPU controlling whether or not it was processing an interrupt when the flags were pushed. Interrupts (/[[IRQ]] and /[[NMI]]) push a value with bit 4 cleared to 0; instructions (BRK and PHP) push a value with bit 4 set to 1.
These do not represent a register that can hold a value but can be used to distinguish how the flags were pushed.
Bit 5 is always pushed as 1.
Bit 4, called the "B flag", represents a signal in the CPU controlling whether or not it was processing an interrupt when the flags were pushed.
Interrupts (/[[IRQ]] and /[[NMI]]) push a value with bit 4 cleared to 0; instructions (PHP and BRK) push a value with bit 4 set to 1.
 
The B flag is not part of the processor status register.
It represents a transient state, not a state that persists from one instruction to another.
The CPU pushes bit 4 based on what caused the push and disregards bits 5 and 4 when reading flags from the stack in the PLP or RTI instruction.


{| class="tabular"
{| class="tabular"
|-
|-
! Instruction || Bits 5 and 4 || Side effects after pushing
! Instruction || B || Side effects after pushing
|-
|-
| PHP || 11 || None
| /[[IRQ]] || 0 || I is set to 1
|-
|-
| BRK || 11 || I is set to 1
| /[[NMI]] || 0 || I is set to 1
|-
|-
| /[[IRQ]] || 10 || I is set to 1
| BRK || 1 || I is set to 1
|-
|-
| /[[NMI]] || 10 || I is set to 1
| PHP || 1 || None
|}
|}


Line 85: Line 81:
Some debugging tools, such as [[Visual6502wiki/JssimUserHelp|Visual6502]], display the B flag as bit 4 of P to save space on screen.
Some debugging tools, such as [[Visual6502wiki/JssimUserHelp|Visual6502]], display the B flag as bit 4 of P to save space on screen.
The user can see it turn off at the start of an interrupt and back on after the CPU reads the vector.
The user can see it turn off at the start of an interrupt and back on after the CPU reads the vector.
Unlike bits 5 and 4, bit 3 actually exists in P, even though it doesn't affect the ALU operation on the 2A03 or 2A07 CPU the way it does in MOS Technology's own chips.


== External links ==
== External links ==

Revision as of 02:48, 13 September 2023

The flags register, also called processor status or just P, is one of the six architectural registers on the 6502 family CPU. It is composed of six one-bit registers; instructions modify one or more bits and leave others unchanged.

Flags

Instructions that save or restore the flags map them to bits in the architectural 'P' register as follows:

7  bit  0
---- ----
NV1B DIZC
|||| ||||
|||| |||+- Carry
|||| ||+-- Zero
|||| |+--- Interrupt Disable
|||| +---- Decimal
|||+------ (No CPU effect; see: the B flag)
||+------- (No CPU effect; always pushed as 1)
|+-------- Overflow
+--------- Negative
  • The PHP (Push Processor Status) and PLP (Pull Processor Status) instructions can be used to retrieve or set this register directly via the stack.
  • Interrupts, including the NMI and also the pseudo-interrupt BRK instruction, implicitly push the status register to the stack.
  • Interrupts returning with RTI will implicitly pull the saved status register from the stack.
  • The two bits with no CPU effect are ignored when pulling flags from the stack; there are no corresponding registers for them in the CPU.
  • When P is displayed as a single 8-bit register by debuggers, there is no convention for what values to use for bits 5 and 4 and their values should not be considered meaningful.

C: Carry


  • After ADC, this is the carry result of the addition.
  • After SBC or CMP, this flag will be set if no borrow was the result, or alternatively a "greater than or equal" result.
  • After a shift instruction (ASL, LSR, ROL, ROR), this contains the bit that was shifted out.
  • Increment and decrement instructions do not affect the carry flag.
  • Can be set or cleared directly with SEC, CLC.

Z: Zero


  • After most instructions that have a value result, this flag will either be set or cleared based on whether or not that value is equal to zero.

I: Interrupt Disable


  • When set, all interrupts except the NMI are inhibited.
  • Can be set or cleared directly with SEI, CLI.
  • Automatically set by the CPU when an IRQ is triggered, and restored to its previous state by RTI.
  • If the /IRQ line is low (IRQ pending) when this flag is cleared, an interrupt will immediately be triggered.

D: Decimal


  • On the NES, decimal mode is disabled and so this flag has no effect. However, it still exists and can be observed and modified, as normal.
  • On the original 6502, this flag causes some arithmetic instructions to use binary-coded decimal representation to make base 10 calculations easier.
  • Can be set or cleared directly with SED, CLD.

V: Overflow


  • ADC and SBC will set this flag if the signed result would be invalid[1], necessary for making signed comparisons[2].
  • BIT will load bit 6 of the addressed value directly into the V flag.
  • Can be cleared directly with CLV. There is no corresponding set instruction.

N: Negative


  • After most instructions that have a value result, this flag will contain bit 7 of that result.
  • BIT will load bit 7 of the addressed value directly into the N flag.

The B flag


While there are only six flags in the processor status register within the CPU, the value pushed to the stack contains additional state called the B flag that can be useful to software. The value of B depends on what caused the flags to be pushed. Note that this flag does not represent a register that can hold a value, but rather a transient signal in the CPU controlling whether or not it was processing an interrupt when the flags were pushed. Interrupts (/IRQ and /NMI) push a value with bit 4 cleared to 0; instructions (BRK and PHP) push a value with bit 4 set to 1.

Instruction B Side effects after pushing
/IRQ 0 I is set to 1
/NMI 0 I is set to 1
BRK 1 I is set to 1
PHP 1 None

The only way for an IRQ handler to distinguish /IRQ from BRK is to read the flags byte from the stack and test bit 4. The slowness of this is one reason why BRK wasn't used as a syscall mechanism. Instead, it was more often used to trigger a patching mechanism that hung off the /IRQ vector: a single byte in PROM, UVEPROM, flash, etc. would be forced to 0, and the IRQ handler would pick something to do instead based on the program counter.

Some debugging tools, such as Visual6502, display the B flag as bit 4 of P to save space on screen. The user can see it turn off at the start of an interrupt and back on after the CPU reads the vector.

External links

References