Invert Carry

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

Invert Carry

Post by Symoon »

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
Squad Leader
Posts: 774
Joined: Sat May 21, 2011 7:21 pm
Location: Between UK and France
Contact:

Re: Invert Carry

Post by Godzil »

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?

What about

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

User avatar
Symoon
Archivist
Posts: 2301
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: Invert Carry

Post by Symoon »

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 !
User avatar
Dbug
Site Admin
Posts: 4437
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: Invert Carry

Post by Dbug »

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
Squad Leader
Posts: 774
Joined: Sat May 21, 2011 7:21 pm
Location: Between UK and France
Contact:

Re: Invert Carry

Post by Godzil »

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.

Edit: added cycles counts;
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..
User avatar
iss
Wing Commander
Posts: 1637
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

Re: Invert Carry

Post by iss »

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'.
User avatar
Symoon
Archivist
Posts: 2301
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: Invert Carry

Post by Symoon »

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
Squad Leader
Posts: 774
Joined: Sat May 21, 2011 7:21 pm
Location: Between UK and France
Contact:

Re: Invert Carry

Post by Godzil »

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.
User avatar
Symoon
Archivist
Posts: 2301
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: Invert Carry

Post by Symoon »

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
User avatar
Symoon
Archivist
Posts: 2301
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: Invert Carry

Post by Symoon »

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...
User avatar
Dbug
Site Admin
Posts: 4437
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: Invert Carry

Post by Dbug »

You really need to use a standard notation for the values :)

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

So:
LDA #$2F <- loads the immediate value 2F represented in hexadecimal
LDA $2F <- loads what is at the address 2F represented in hexadecimal

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 :)
User avatar
Symoon
Archivist
Posts: 2301
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: Invert Carry

Post by Symoon »

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
Pilot Officer
Posts: 96
Joined: Sun Nov 24, 2013 9:58 pm

Re: Invert Carry

Post by christian »

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)
User avatar
Dbug
Site Admin
Posts: 4437
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: Invert Carry

Post by Dbug »

christian wrote:Total 10 cycles
Only Carry inverted, and ACC not modified (if i'm right)
I like it.
Very elegant :)
User avatar
Symoon
Archivist
Posts: 2301
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France

Re: Invert Carry

Post by Symoon »

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...
Post Reply