What is the purpuse of CLC and SEC?

Discussion of hardware and software development for Super NES and Super Famicom.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

What is the purpuse of CLC and SEC?

Post by Drew Sebastino »

I know it sets and clears the carry flag in the processor status bits, but how does that affect anything? I looked at what the carry flag was for, and this is what I found:
Carry flag

This flag is set on unsigned overflow for ADC ($00 roll over to $FF) or when underflow for SBC does not happen. It also gets set depending on the result of ASL/LSR/ROL/ROR and more.
How does this affect ADC or SBC? Sorry if this is painstakingly obvious, but I've been using these for well over half a year without even knowing what purpose they serve.
User avatar
Khaz
Posts: 314
Joined: Thu Dec 25, 2014 10:26 pm
Location: Canada

Re: What is the purpuse of CLC and SEC?

Post by Khaz »

ADC is short for "ADd with Carry". Meaning that, the result you get from an ADC is the Accumulator plus the operand, PLUS the carry bit. So if you don't CLC before you ADC, and there's a chance the carry bit might be set, your addition may be off by one.

Similarly, because of how binary subtraction works, SEC is the opposite: When you subtract, it is expected the carry bit is set before you start.

The reason why you'd WANT adc to include the carry bit is so that you can chain together repeated additions, carrying in the carry bit from the previous ADC, to add numbers larger than 16 bits.
User avatar
koitsu
Posts: 4203
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: What is the purpuse of CLC and SEC?

Post by koitsu »

For further details, please see this -- it is long, and verbose, and should be read, not skimmed: http://www.6502.org/tutorials/vflag.html#2.4

(The behaviour on 65816 is the same, regardless of the fact that registers can be/are 16-bit)

There is also http://wiki.nesdev.com/w/images/7/76/Programmanual.pdf -- please see Chapter 9 (page 122) onward. Again: read, do not skim.
User avatar
rainwarrior
Posts: 8062
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: What is the purpuse of CLC and SEC?

Post by rainwarrior »

The carry is needed when you want to operate on values bigger than one byte. It works exactly like you were probably taught in school, except instead of working with decimal digits (0-9) you're using byte digits (0-255).

When you add two numbers together, and the result is too big to fit in a byte, the carry flag is set, so you can pass it on to the next addition step.

Code: Select all

; Example 16-bit addition
;  503 +  311
; $1F7 + $137

lda #<503        ; A = $F7 = 247  (low 8 bits of 503)
clc              ; carry = 0
adc #<311        ; A += $37 + carry
sta result_low   ; result_low = $2E, carry = 1
lda #>503        ; A = $01 = 1 (high 8 bits of 503)
adc #>311        ; A += $01 + carry
sta result_high  ; result_high = $03

; result_low + (256 * result_high) = $32E = 814
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: What is the purpuse of CLC and SEC?

Post by tokumaru »

rainwarrior wrote:The carry is needed when you want to operate on values bigger than one byte.
Or word, since this is the SNESdev forum and Espozo works mostly with the 65816.
User avatar
rainwarrior
Posts: 8062
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: What is the purpuse of CLC and SEC?

Post by rainwarrior »

Yes, it's the same concept with whatever size you have for your digits.

BTW you should CLC before ADC, and SEC before SBC in most cases when you're doing single-digit math too. There are some other uses for CLC and SEC, but their main purpose is to prepare for ADC/SBC. It might have been nice to have separate ADD and SUB instructions with an implicit CLC/SEC; the closest we have to that is CMP, which acts like SEC+SBC, but it doesn't return the result to A.

Also, I find it weird that the INC/DEC family of instructions don't set the carry flag. I can't think of any reason why the shouldn't, but they don't.
ccovell
Posts: 1041
Joined: Sun Mar 19, 2006 9:44 pm
Location: Japan
Contact:

Re: What is the purpuse of CLC and SEC?

Post by ccovell »

Well, if INC/DEC affected the carry, it would probably take more cycles (not good). Also, you might want to INC/DEC X or Y in between memory-indexed additions with the Accumulator, so different flag behaviour between INC A and INC X would be kinda weird.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: What is the purpuse of CLC and SEC?

Post by Drew Sebastino »

For all the clc and sec's adding extra cycles throughout the code, it would probably have been faster to have gotten rid of the carry flag and just made it to where you had to do some sort of crazy maneuver for 32 bit instructions. It would have been awesome if there was a way to turn it off. I guess it affects all the instructions like bcc, bcs, and cmp though...

Just thinking though, if you have a routine where you're adding and you know that the result is never going to be greater than 256, couldn't you just not do sec at all?
tokumaru wrote:Or word, since this is the SNESdev forum and Espozo works mostly with the 65816.
I only work with the 65816. I don't know any information about the 6502.

About 32 bit instructions, I can't think of a single time where I'd want to use them on the SNES. It would be slow as all get out anyway.
User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Re: What is the purpuse of CLC and SEC?

Post by Kasumi »

Espozo wrote:Just thinking though, if you have a routine where you're adding and you know that the result is never going to be greater than 256, couldn't you just not do sec at all?
It'd be clc for addition. And note that the state of the carry BEFORE the add/subtract affects the outcome, so you can only avoid it if you know the PREVIOUS result has initialized the carry correctly.

Code: Select all

clc
lda #$00
adc #$10

;Carry guaranteed clear
;clc;So no CLC needed for the next add
lda whatever
adc whatever2
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: What is the purpuse of CLC and SEC?

Post by Drew Sebastino »

Kasumi wrote:
Espozo wrote:Just thinking though, if you have a routine where you're adding and you know that the result is never going to be greater than 256, couldn't you just not do sec at all?
It'd be clc for addition.
Dang it! Why am I being so stupid today... :oops:

Thank you for answering my question though. It looks like I better look through my code...
psycopathicteen
Posts: 3001
Joined: Wed May 19, 2010 6:12 pm

Re: What is the purpuse of CLC and SEC?

Post by psycopathicteen »

I could never understand why they didn't have a normal ADD and SUB instruction like every other CPU at the time. If they ran out of instructions, they could've took some addressing modes out, like $00,s and ($00,s),y.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: What is the purpuse of CLC and SEC?

Post by tepples »

WDC's datasheet for the 65816 specifically mentions reentrant and recursive subroutines as reasons for the dd,S and (dd,S),Y addressing modes.
User avatar
rainwarrior
Posts: 8062
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: What is the purpuse of CLC and SEC?

Post by rainwarrior »

ccovell wrote:Well, if INC/DEC affected the carry, it would probably take more cycles (not good). Also, you might want to INC/DEC X or Y in between memory-indexed additions with the Accumulator, so different flag behaviour between INC A and INC X would be kinda weird.
Incrementing an index not wanting to affect carry makes sense. That's a good thought, thanks.

I doubt a carry flag would have taken any more cycles. Stuff like that can usually be done in parallel. ADC immediate is only 2 cycles and affects 7 different flags, I'm sure INX/INY could have had managed the carry flag in 2 cycles, if they wanted it to.
Espozo wrote:For all the clc and sec's adding extra cycles throughout the code, it would probably have been faster to have gotten rid of the carry flag and just made it to where you had to do some sort of crazy maneuver for 32 bit instructions. It would have been awesome if there was a way to turn it off.
You really would need the dedicated ADD/SUB instructions I suggested. The problem is that if you can't fold the carry in with the addition like in ADC, the only way to apply the carry is to do another ADD based on a branch. With 2-digit adds this is bad, with 3 it's really bad. For every carry you add, you have to check if there's another carry, all the way to the end of the line. Here's 2 and 3-digit adds as if we had ADD (SEC+ADC) instead of ADC:

Code: Select all

; a1:a0 += b1:b0
add2:
	lda a0
	add b0
	sta a0
	lda a1
	bcc @digit1
	; apply carry to a1
	add #1
@digit1:
	add b1
	sta a1
	rts

; a2:a1:a0 += b2:b1:b0
add3:
	lda a0
	add b0
	sta a0
	lda a1
	bcc @digit1
	; apply carry to a1
	add #1
	sta a1
	bcc @digit1
	; carry add caused another carry, apply to a2
	lda a2
	add #1
	sta a2
	lda a1
@digit1:
	adc b1
	sta a1
	bcc @digit2
	; apply carry to a2
	lda a2
	add #1
@digit2:
	add b2
	sta a2
	rts
If you think about the 6502 being 8-bit, and you consider how often you need to deal with multi-digit numbers, you should be able to see why it's more useful to have ADC/SBC than ADD/SUB (if you're forced to choose). On 16 bit architecture, especially in games, there's a lot less need for multi-digit numbers (256x less, probably?) and on 32 bit architectures you hardly ever need them, but on the 6502 it was pretty essential to make that case reasonable.

Maybe the sad part is that dedicated ADD/SUB instructions would have been able to do the implicit CLC/SEC without adding the extra 2 cycles or 1 byte of code, just like CMP is able to.

But... I can dream about a better 6502 all day. I'm stuck with the one I've already got.
User avatar
rainwarrior
Posts: 8062
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: What is the purpuse of CLC and SEC?

Post by rainwarrior »

tepples wrote:WDC's datasheet for the 65816 specifically mentions reentrant and recursive subroutines as reasons for the dd,S and (dd,S),Y addressing modes.
I would loooove to be able to use the stack pointer as an index on the 6502. :S
User avatar
Memblers
Site Admin
Posts: 3901
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis
Contact:

Re: What is the purpuse of CLC and SEC?

Post by Memblers »

Sometimes I use SEC and CLC before an RTS, if I only need to return one bit of status from the subroutine. It's kind of a pointless optimization, saving 1 or 2 bytes while code size usually doesn't matter.
Post Reply