Page 1 of 1
Branch instructions
Posted: Wed Sep 02, 2020 1:32 am
by DanielS
Hey guys.
Does a branch instruction have to come right after a compare?
Or can there be other instructions between them as long as they don't affect the carry or zero flags?
Example...
Code: Select all
lda #$ff
cmp #$ff
; some other code
beq somewhere_if_a_equals_ff
Re: Branch instructions
Posted: Wed Sep 02, 2020 1:41 am
by DanielS
Looks like perhaps I can push the processor flags, do stuff, then pull them.
Code: Select all
lda #$ff
cmp #$ff
php
; do stuff
plp
beq somethere_if_a_equals_ff
Re: Branch instructions
Posted: Wed Sep 02, 2020 2:45 am
by Dr Jefyll
Looks like perhaps I can push the processor flags, do stuff, then pull them.
Yes, you can -- but it won't always be necessary.
Your previous post has the right idea. There can be other instructions between them as long as they don't affect the carry or zero flags. (But if they *do* affect the flag you're interested in, that's when pushing then later popping the flags may be the best alternative. I say "may" because it's often possible to rearrange the instruction order instead.)
Cheers,
Jeff
Re: Branch instructions
Posted: Wed Sep 02, 2020 2:48 am
by GARTHWILSON
The flags will persist as long as the instructions executed don't alter them. For example, if you have something that leaves the V flag for you to branch on later, and the intervening instructions only affect Z, C, and N, there's no reason to push the processor status and then pull it off the stack later.
Note of course that pushing and pulling the status is an automatic part of the interrupt sequence and RTI, so you don't need to bracket an ISR with PHP and PLP. In fact, there are situations where doing so could even cause problems.
Re: Branch instructions
Posted: Wed Sep 02, 2020 2:55 am
by BillG
Does a branch instruction have to come right after a compare?
Or can there be other instructions between them as long as they don't affect the carry or zero flags?
There can be any number of instructions in between the setting of a flag and a test for it.
For example, the code on this post
viewtopic.php?p=77950#p77950
sets the carry flag on line 54 and uses it on line 61.
Re: Branch instructions
Posted: Wed Sep 02, 2020 3:02 am
by DanielS
Here's an example...
Code: Select all
_validate_1 ; left, right, down
cpx ch_left
php
ldy #0
plp
beq _valid
cpx ch_right
php
ldy #2
plp
beq _valid
cpx ch_down
php
ldy #4
plp
beq _valid
jmp _invalid
Y needs to be used in the next section. If I do it this way then I can avoid many, seemingly unnecessary, BEQs. The value of Y is based on the value of X.
Maybe this is a hacky way of doing it but it seems to work.
Re: Branch instructions
Posted: Wed Sep 02, 2020 3:09 am
by BillG
Here's an example...
Code: Select all
_validate_1 ; left, right, down
cpx ch_left
php
ldy #0
plp
beq _valid
cpx ch_right
php
ldy #2
plp
beq _valid
cpx ch_down
php
ldy #4
plp
beq _valid
jmp _invalid
Y needs to be used in the next section. If I do it this way then I can avoid many, seemingly unnecessary, BEQs. The value of Y is based on the value of X.
Maybe this is a hacky way of doing it but it seems to work.
Can't you just do
Code: Select all
_validate_1 ; left, right, down
ldy #0
cpx ch_left
beq _valid
ldy #2
cpx ch_right
beq _valid
ldy #4
cpx ch_down
beq _valid
jmp _invalid
Re: Branch instructions
Posted: Wed Sep 02, 2020 3:13 am
by DanielS
Can't you just do
Code: Select all
_validate_1 ; left, right, down
ldy #0
cpx ch_left
beq _valid
ldy #2
cpx ch_right
beq _valid
ldy #4
cpx ch_down
beq _valid
jmp _invalid
Damn. Yes I can. That never occurred to me. I'm still in the C++ mindset I guess so the "simple" things here are, for now, elusive.
Re: Branch instructions
Posted: Wed Sep 02, 2020 4:09 am
by IamRob
More often than not, you can rearrange the code so that the processor byte never needs to be pushed or pulled.
Re: Branch instructions
Posted: Wed Sep 02, 2020 4:29 am
by BigDumbDinosaur
Hey guys.
Does a branch instruction have to come right after a compare?
Or can there be other instructions between them as long as they don't affect the carry or zero flags?
Example...
Code: Select all
lda #$ff
cmp #$ff
; some other code
beq somewhere_if_a_equals_ff
Short answer is no. The long answer is as long the relevant status register bit (Z in this case) is not affected by intervening instructions your branch will be reliable.
Re: Branch instructions
Posted: Wed Sep 02, 2020 7:15 am
by barrym95838
Lemme see if I can recite from memory all the ones that don't affect Z ... nop clc sec cli sei cld sed clv sta stx sty pha php jmp bxx jsr rts txs ... not many. I remember being frustrated at the 68xx for inexplicably messing with Z during a store operation, but not for pula or pulb. It's actually just a minor inconvenience, but so irksome, IMO.
Re: Branch instructions
Posted: Wed Sep 02, 2020 12:50 pm
by cjs
Lemme see if I can recite from memory all the ones that don't affect Z ... nop clc sec cli sei cld sed clv sta stx sty pha php jmp bxx jsr rts txs ... not many.
I found it useful to create
a little table listing the flags and all the instructions that affect each one:
Code: Select all
C SEC CLC
ADC SBC ASL LSR ROL ROR
BIT CMP CPX CPY
NZ LDA LDX LDY TAX TXA TAY TYA TSX PLA
ADC SBC INC DEC INX DEX INY DEY AND ORA EOR ASL LSR ROL ROR
BIT CMP CPX CPY
V CLV
ADC SBC
BIT
D SED CLD
I SEI CLI BRK
(4) BRK
I remember being frustrated at the 68xx for inexplicably messing with Z during a store operation, but not for pula or pulb. It's actually just a minor inconvenience, but so irksome, IMO.
Yeah, totally irksome. But probably not as inconvenient as not having PSHX and PULX instructions (though the 6801/6803 added those).
Re: Branch instructions
Posted: Wed Sep 02, 2020 5:40 pm
by barrym95838
Yeah, totally irksome. But probably not as inconvenient as not having PSHX and PULX instructions (though the 6801/6803 added those).
Oof, yeah, that's a real eye-roller. How many quadrillions of total machine cycles have been spent executing the awkward work-around for that one? The average temperature on Earth is probably .00001° hotter because of it ...
