commanderx16 / x16-emulator

Emulator for the Commander X16 8-bit computer
384 stars 61 forks source link

PLP can set the break flag #472

Open Yazwh0 opened 1 year ago

Yazwh0 commented 1 year ago

Using the code below, we push $ff onto the stack, and then pull it back into the processor status. Doing so keeps the Break flag set. The example below then pushes it back and pulls it to X, to verify that it is $ff, and not a display bug. The code does the same thing to show the flags in the debugger.

    sei

    lda #$ff
    pha
    plp
    php
    plx            ; <--- should be $ef, current shows $ff
    lda #$ff
    pha
    plp           ; <--- all flags are set
    stp

image

lgblgblgb commented 1 year ago

For real there is no break flag at all in the CPU (it's a common misunderstanding ...). Unlike other flags like carry, there is no real flag bit implemented in this case. The way it works: on pushing the flag register onto the stack, the nature of the operation tells if the "B flag" (bit 4) pushed onto the stack will contain 0 or 1. If the cause is a hardware event (IRQ,NMI) then the bit 4 of pushed data will be reset, if it's software (ie an opcode, not a hardware interrupt) which was the cause (BRK or PHP) then it will be set. However you cannot pull back data from the accu expecting that the CPU holds a bit in its flags as "B flag" register which is set/reset then. For real, the CPU flag register has only 6 bits of meaningful flags, the B flag is merely virtual in the sense that it can be set/reset in the form of the pushed data onto the stack, and the nature of that operation (software/hardware) dictates its state.

The other problem that emulators, debuggers, etc often shows the state of the B flag, which is a "lie" again since for real there is not even a flag like that implemented in the CPU at the hardware level ...

Maybe a much better explanation than mine: https://www.nesdev.org/wiki/Status_flags#The_B_flag