CPU status flag behavior: Difference between revisions

From NESdev Wiki
Jump to navigationJump to search
m (→‎The B flag: no syscall)
(→‎The B flag: in http://nesdev.parodius.com/bbs/viewtopic.php?p=64224#64224 koitsu said this page was "highly convoluted")
Line 18: Line 18:


== The B flag ==
== The B flag ==
There is no "B flag". Bits 5 and 4 of flags do not exist.
There are six and only six flags in the processor status register.
Despite what some 6502 references might appear to claim on a first reading, there is no "B flag" in the CPU.


Two signals and two instructions can push flags to the stack. When they do so, they fill the unused bits with the following:
Two interrupts (/[[IRQ]] and /[[NMI]]) and two instructions (PHP and BRK) push the flags to the stack. Bit 5 is always set to 1, and bit 4 is 1 if from an instruction (PHP or BRK) or 0 if from an interrupt (/IRQ or /NMI).
{| class="tabular"
{| class="tabular"
|-
|-
Line 33: Line 34:
| /[[NMI]] || 10 || I is set to 1
| /[[NMI]] || 10 || I is set to 1
|}
|}
Two instructions (PLP and RTI) pull a byte from the stack and set flags, but they ignore bits 5 and 4.
Two instructions (PLP and RTI) pull a byte from the stack and set flags. They ignore bits 5 and 4.


The only way for an IRQ handler to distinguish /IRQ from BRK is to read the flags from the stack and test bit 4.
The only way for an IRQ handler to distinguish /IRQ from BRK is to read the flags from the stack and test bit 4.
The slowness of this is one reason why BRK wasn't used as a syscall mechanism.
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.
== External links ==
*[http://nesdev.parodius.com/bbs/viewtopic.php?p=64224#64224 koitsu's explanation]

Revision as of 00:14, 15 July 2010

The flags register, also called processor status or just P, is one of the six architectural registers on the 6502 family CPU.

There are six bits in P:

7654 3210
||   ||||
||   |||+- C: 1 if last addition or shift resulted in a carry, or if
||   |||   last subtraction resulted in 
||   ||+-- Z: 1 if last operation resulted in a 0 value
||   |+--- I: Interrupt priority level
||   |     (0: /IRQ and /NMI get through; 1: only /NMI gets through)
||   +---- D: 1 to make ADC and SBC use binary-coded decimal arithmetic
||         (ignored on second-source 6502 like that in the NES)
|+-------- V: 1 if last ADC or SBC resulted in signed overflow, or
|          D6 from last BIT read as 0
+--------- N: Set to bit 7 of the last operation

The B flag

There are six and only six flags in the processor status register. Despite what some 6502 references might appear to claim on a first reading, there is no "B flag" in the CPU.

Two interrupts (/IRQ and /NMI) and two instructions (PHP and BRK) push the flags to the stack. Bit 5 is always set to 1, and bit 4 is 1 if from an instruction (PHP or BRK) or 0 if from an interrupt (/IRQ or /NMI).

Instruction Bits 5 and 4 Side effects after pushing
PHP 11 None
BRK 11 I is set to 1
/IRQ 10 I is set to 1
/NMI 10 I is set to 1

Two instructions (PLP and RTI) pull a byte from the stack and set flags. They ignore bits 5 and 4.

The only way for an IRQ handler to distinguish /IRQ from BRK is to read the flags 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.

External links