## Invert Carry

Here you can ask questions or provide insights about how to use efficiently 6502 assembly code on the Oric.
Symoon
Archivist
Posts: 1510
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France
Contact:

### Invert Carry

Hi,

I need help ! Is there a fast trick to invert the value of C (carry) without having to test it and use CLC/SEC ?

What I'm trying to do:
I'm doing a CMP XX which sets:
- C to 1 if the accumulator is superior to XX
- C to 0 if the accumulatore is inferior to XX

But then I would like to ROR in memory the reverse of these C values, in the shortest (time and bytes) possible way.

(EDIT: I mixed results, corrected)

Godzil
Posts: 758
Joined: Sat May 21, 2011 7:21 pm
Location: Between UK and France
Contact:

### Re: Invert Carry

Symoon wrote:Hi,

I need help ! Is there a fast trick to invert the value of C (carry) without having to test it and use CLC/SEC ?

What I'm trying to do:
I'm doing a CMP XX which sets:
- C to 1 if the accumulator is superior to XX
- C to 0 if the accumulatore is inferior to XX

But then I would like to ROR in memory the reverse of these C values, in the shortest (time and bytes) possible way.

(EDIT: I mixed results, corrected)
I'm not sure of what you want to do, what do you mean by ROR-ing in memory the reverse of the C value?

Because yes, CMP update the C flag, you want to ROR your data and put the reverse of the current C value that's right?

Si if A is > to XX and you do the CMP XX, if will set C to 1, then you want to ROR A so you will end with

A = (A >> 1 ) | (~C << 7)

is that right?

Code: Select all

``````   CMP   XX
BCC   nocarry
LSR   A
OR    \$80
JMP   end
nocarry:
LSR   A
end:
``````
There are probably better way to do, especially to keep only one LSR, but I'm tired right now. You can do something ugly ala:

Code: Select all

``````   CMP   XX
BCC   nocarry
CLC
jmp next
nocarry:
SEC
next:
ROR A

``````

Symoon
Archivist
Posts: 1510
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France
Contact:

### Re: Invert Carry

Godzil wrote:Because yes, CMP update the C flag, you want to ROR your data and put the reverse of the current C value that's right?
Yes that's it, I'm RORing a byte in memory (not the accumulator).

Here's exactly what I'm doing right now:

Code: Select all

``````ADR	Cycl	Hex		Code		Comment
04B7	2     C9 A4     CMP #A4	Sets C
04B9	2/3   B0 04     BCS +4
04BB	2     38        SEC		inverts C if C=0
04BC	3     4C xx xx  JMP xx
04BF	2     18        CLC		inverts C if C=1
04C0	3     4C xx xx  JMP xx
[...]
xxxx	5     66 2F     ROR 2F	inserts the new value to 2F byte``````
But this takes 12 bytes (I could do better with BCS/BCC instead of JMP) and (worse) up to 8 cycles between CMP and ROR. What I was hoping to find was a "magical trick" to do it in a single instruction (with some SBC for instance?), which would then be:

Code: Select all

``````04B7	2     C9 A4     CMP #A4     Sets C
04B9	2     xx yy     "magic"     inverts C whatever its value
04BD	3     4C xx xx  JMP xx	``````
which would save the BCS cycle time, and takes 7 or 8 bytes instead of 12.
I was thinking, instead of CMP, using two consecutive SBC instructions (the accmuluator can be altered, no problem)
SBC #A4 (will set C)
SBC something (to try and reverse C)
but I'm in a hurry right now so no time to check this carefully !

Dbug
Posts: 2821
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

### Re: Invert Carry

Not tested:

Code: Select all

``````cmp whatever

php                    ; 4 cycles, Push the status flag on the stack (Carry is the bit zero
pla                     ; 4 cycles, Read back the value in the accumulator
eor #1                ; 2 cycles, Flip the Carry flag value
lsr                      ; 2 cycles, Move the new value back to the carry flag

ror value``````

Godzil
Posts: 758
Joined: Sat May 21, 2011 7:21 pm
Location: Between UK and France
Contact:

### Re: Invert Carry

I'm not sure about DBug solution (It's a bit early.. )

But before I see his answer I came to that:

Code: Select all

``````  CMP \$A4     ; Compare value from A4     | 3 cycles (zeropage)
ROR \$2F     ; Do the ROR into 2F        | 5 cycles (zeropage)
PHA         ; Save A (if needed)        | 3 cycles
LDA #\$80    ; Going to reverse bit 7    | 2 cycles (direct mode)
EOR \$2F     ; Revese the bit            | 3 cycles (zeropage)
STA \$2F     ; Store result              | 3 cycles (zeropage)
PLA         ; Restore old A             | 4 cycles
``````
I don't have the cycle count, it maybe counter productive. If the content of A doesn't matter you can remove the PHA/PLA.

23 cycles counting saving A, 16 without (I'm counting the CMP and ROR operation without them it 15 / 8
By the way, dbug maybe my source is wrong, but it says pushing to the stack is 3 cycles, pop-ing is 4..

iss
Posts: 775
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

### Re: Invert Carry

Inverting Carry actually means to switch the places of CMP's operands.

Code: Select all

``````sta zp_temp
lda #\$A4
cmp zp_temp
ror \$2F
``````
You need just one more zero page free cell 'zp_temp'.

Symoon
Archivist
Posts: 1510
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France
Contact:

### Re: Invert Carry

Thanks for the replies - amazing to see so may ways to achive something

Here's another try, which I'm not sure yet if it works anytime:

Hint: I know for sure C=1 when I begin this code (that helps, I should have told you but I only noticed it because I needed it for this attempt...)

Code: Select all

``````SBC#\$A4  2 cylces
SBC#\$5B  2 cycles
ROR``````
=> this affects A in some cases (not important). 5B is FF-A4.
What do you guys think?

Now I'm going to look at your solutions (yes, I'm slow, still not very familiar with ASM).

EDIT: sorry I'm not very familiar with ASM syntax (I code in machine code directly !), and I notice I have probably confused some of you with #A4, which is actually the VALUE #A4, not the content of the memory in #A4. So I should probably have writtent somthing like #\$A4 ?

Godzil
Posts: 758
Joined: Sat May 21, 2011 7:21 pm
Location: Between UK and France
Contact:

### Re: Invert Carry

Symoon wrote: EDIT: sorry I'm not very familiar with ASM syntax (I code in machine code directly !), and I notice I have probably confused some of you with #A4, which is actually the VALUE #A4, not the content of the memory in #A4. So I should probably have writtent somthing like #\$A4 ?
Sorry it's me, reading code while not beeing fully waked mean reading incorrect things, I think I read \$A4 instead of #A4, which is incorect in most assembler, but is clear that you want immediate value and not zero page based.

Symoon
Archivist
Posts: 1510
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France
Contact:

### Re: Invert Carry

Still trying to find if the double SBC is OK - seems to be the shortest way (in time) to do it.
It seems that when the result of the 1st SBC is done (replacing the CMP), the 2nd SBC inverts C correctly - but this is strictly theoretical.

Edit: too bad, actually I'm not sure C is always =1 before the 1st SBC. So this method is not 100% correct. Sh*t

Code: Select all

``````Before           Result
A    C   Ops       A   C
80	1	SBC #A4	DC	0    1st instruction - sets C according to A and #A4
DC	0	SBC #5B	80	1    2nd instruction - inverts C

B0	1	SBC #A4	0C	1
0C	1	SBC #5B	B1	0

A3	1	SBC #A4	FF	0
FF	0	SBC #5B	A3	1

A4	1	SBC #A4	00	1
00	1	SBC #5B	A5	0

A5	1	SBC #A4	01	1
01	1	SBC #5B	A6	0``````

Symoon
Archivist
Posts: 1510
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France
Contact:

### Re: Invert Carry

Okay, another option...
Am I wrong saying that I also can ROR in 2F the C values as they are, and once done do this:
LDA 2F
EOR FF

?
This is not exactly the topic questions but I just realise this is much more efficient...

Dbug
Posts: 2821
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

### Re: Invert Carry

You really need to use a standard notation for the values

The majority of the compilers around use:
"#" for immediate values

So:

It's also what you find in the ROM disassembly in the "Oric Advanced User Guide" and "Au Coeur de l'Oric Atmos".

Twilighte was using his own assembler with non standard syntax, and even him finally switched to something sane after Jede and I said complained about it

Symoon
Archivist
Posts: 1510
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France
Contact:

### Re: Invert Carry

Dbug wrote:You really need to use a standard notation for the values
You're right!
My problem is that I use Assembler so sparsely, that each time I go back to it, I forgot and mix with the Basic standard of # for hexadecmial notation

christian
Posts: 59
Joined: Sun Nov 24, 2013 9:58 pm

### Re: Invert Carry

Hi, maybe something like this:

Code: Select all

``````CMP #\$A4  ;                    (2 cycles)
ROL       ; Put C in b0 of ACC (2 cycles)
EOR #\$01  ; Invert b0          (2 cycles)
ROR       ; Put b0 in C        (2 cycles)
ROR \$2F   ; ROR C to \$2F       (2 cycles)
``````
Total 10 cycles
Only Carry inverted, and ACC not modified (if i'm right)

Dbug
Posts: 2821
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

### Re: Invert Carry

christian wrote:Total 10 cycles
Only Carry inverted, and ACC not modified (if i'm right)
I like it.
Very elegant

Symoon
Archivist
Posts: 1510
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France
Contact:

### Re: Invert Carry

Indeed!
Thanks for your help guys, sorry I didn't come back on this in detail but it certainly helped me carrying on the project I'm focued on. Significant progress but the hardest part is there:
- complicated code and (very) complicated testing to finish
- back to work soon so no more spare time again...