Page 1 of 2
6502 Emulation of ADC in C
Posted: Mon Jan 30, 2023 8:01 pm
by Sailor
uint8_t m,a,c;---------// a=accumulator , m = some memory value , c = carry flag
int tmp_a;-------------------// to store a copy of accumulator
c=0;--------------------------// carry flag initial value
m=0x1;----------------------// memory variable initial value
a=0xFE;----------------------// accumulator variable initial value
tmp_a=a;--------------------// take a copy of accumulator contents
a+=m+c;--------------------// doing the usual addition with carry flag
tmp_a+=m+c;---------------// temporary var can hold a the actual result even if it exceeds 255
if (tmp_a>0xFF)-------------// so that we can check whether carry flag is set or not
c=1;
if (tmp_a<0xFF)
c=0;
I've made this code to emulate ADC (a general idea so far) , it looks a simple method
it works just fine as I tested it with a lot of values
it successfully sets and resets the carry flag
I just wonder is it a nice idea ? or it would affect the emulation's performance ?
Re: 6502 Emulation of ADC in C
Posted: Mon Jan 30, 2023 8:33 pm
by BigEd
It seems about right to me. Exactly what the performance will be depends very much on the compiler (and how much you ask it to optimise.)
I think personally I'd prefer to do the addition once, with the wider destination, and then transfer it to the actual narrow accumulator. But that's just a preference - you might be aiming to write very clear code, or to write very fast code. Probably you can't do both at once!
I should confess I'm a bit hazy on exactly what C specifies when you overflow a narrow result, in the signed and unsigned cases. I'd need to look it up.
Matt Godbolt's Compiler Explorer is a nice way to see the effects of small code changes
https://godbolt.org/
Re: 6502 Emulation of ADC in C
Posted: Mon Jan 30, 2023 8:47 pm
by Sailor
That's right , as an emulation's newbie , I will start to write very clear code at the beginning ,
Then , after I get a sufficient capabilities I would write the fastest one.
Re: 6502 Emulation of ADC in C
Posted: Mon Jan 30, 2023 11:01 pm
by Alarm Siren
It seems about right to me. Exactly what the performance will be depends very much on the compiler (and how much you ask it to optimise.)
I think personally I'd prefer to do the addition once, with the wider destination, and then transfer it to the actual narrow accumulator. But that's just a preference - you might be aiming to write very clear code, or to write very fast code. Probably you can't do both at once!
I should confess I'm a bit hazy on exactly what C specifies when you overflow a narrow result, in the signed and unsigned cases. I'd need to look it up.
Matt Godbolt's Compiler Explorer is a nice way to see the effects of small code changes
https://godbolt.org/
In C unsigned overflow is defined to wrap around. Signed overflow is undefined / implementation specific.
Re: 6502 Emulation of ADC in C
Posted: Tue Jan 31, 2023 4:57 am
by BigEd
Thanks! (I'm not sure when I might start to remember it so clearly!)
Re: 6502 Emulation of ADC in C
Posted: Tue Jan 31, 2023 5:54 am
by barrym95838
You might consider the learning opportunity of attempting to make it more generally useful by emulating its effects regarding the other flags, i.e., N, V, Z and D. No pressure, though ... you should be encouraged to proceed at your own pace.
(If you change your [quote] and [/quote] to [code] and [/code] in your head post you can get a more desirable result.)
Re: 6502 Emulation of ADC in C
Posted: Tue Jan 31, 2023 8:50 am
by Alarm Siren
I see what you did there

Re: 6502 Emulation of ADC in C
Posted: Tue Jan 31, 2023 2:09 pm
by BigEd
I wish we could get away from that whole thing. It would only take the goodwill of one person.
Re: 6502 Emulation of ADC in C
Posted: Tue Jan 31, 2023 2:59 pm
by Sailor
I wish we could get away from that whole thing. It would only take the goodwill of one person.
OK .. I've ignored the negative posts
Thanks BigEd .
Re: 6502 Emulation of ADC in C
Posted: Wed Feb 01, 2023 10:08 am
by drogon
From the "more than one way to do it department", so just having a ponder over this in an otherwise idle moment... I think i'd use unsigned values all the way to lessen the potential for any sign extensions that might happen, and avoid tests and shifts, so something like:
Code: Select all
#include <stdio.h>
#include <stdint.h>
int main (void)
{
uint8_t a,m,c ;
union
{
uint16_t t16 ;
uint8_t tt0 [2] ;
} temp ;
m = 0xFF ; c = 0 ; a = 0xFE ; // Test values
temp.t16 = a + m + c ;
a = temp.tt0 [0] ;
c = temp.tt0 [1] ;
printf ("A: %02X, M: %02X, C: %02X, temp: %04X\n", a, m, c, temp.t16) ;
return 0 ;
}
Test output:
The compiler ought to be able to optimise that into something quite efficient... Hopefully.
-Gordon
Re: 6502 Emulation of ADC in C
Posted: Wed Feb 01, 2023 11:45 am
by Sailor
Hello Gordon
I tested your code , it is great
Update :
can your code be extended to test / set overflow flag as well ?
Re: 6502 Emulation of ADC in C
Posted: Fri Feb 03, 2023 1:47 pm
by drogon
Hello Gordon
I tested your code , it is great
Update :
can your code be extended to test / set overflow flag as well ?
The overflow (V) flag is a somewhat tricky one and often mis-understood. I suggest you do a lot of reading and this is a good place to start:
http://www.righto.com/2012/12/the-6502- ... ained.html
Adapting my code to set it on an ADC - well, it's literally one line of code, but a somewhat complex line of code at that.
Adding this into the code would give you a true/false result:
Code: Select all
#include <stdio.h>
#include <stdint.h>
int main (void)
{
uint8_t a,m,c,v ;
union
{
uint16_t t16 ;
uint8_t tt0 [2] ;
} temp ;
m = 0x7E ; c = 0 ; a = 0x82 ; // Test values
temp.t16 = a + m + c ;
v = (m ^ temp.t16) & (a ^ temp.t16) & 0x80 ;
a = temp.tt0 [0] ;
c = temp.tt0 [1] ;
printf ("A: %02X, M: %02X, C: %02X, V: %02X, temp: %04X\n", a, m, c, v, temp.t16) ;
printf (" Carry: %s\n", c ? "Yes" : "No") ;
printf ("Overflow: %s\n", v ? "Yes" : "No") ;
return 0 ;
}
Note that this yields a true (non-zero) or false (zero) result. It's actually either 0X80 or 0x00, so don't test for 1 or 0. Do test it if you use it.
-Gordon
Re: 6502 Emulation of ADC in C
Posted: Fri Feb 03, 2023 3:32 pm
by Arlet
If you're using GCC, you may be able to use the builtin overflow functions.
https://gcc.gnu.org/onlinedocs/gcc/Inte ... ltins.html
If the platform supports it, these should be translated to native overflow flag detections.
Re: 6502 Emulation of ADC in C
Posted: Fri Feb 03, 2023 7:45 pm
by Sailor
@Gordon , your code is great as usual ,
I've already read a lot about overflow flag , and how to test it and got the following facts :
1. it occurs when adding two signed numbers with similar sign , resulting in a number different in sign .
2. it occurs when (carry in) bit different than (carry out) bit (bit6 through bit7) after the addition .
3. it's similar to carry flag test , except it's for signed numbers .
6502 don't care or even have recognition between signed OR unsigned numbers though
it maybe mean 0 - 127 are positive numbers , while 128 - 255 are negative (while testing for overflow) ?
@Arlet , Yes I am using TDM GCC 4.9.2 compiler with DEV C++ IDE
and that feature looks awesome , it would simplify the whole code a lot
Many thanks guys for your help .
Re: 6502 Emulation of ADC in C
Posted: Wed Feb 22, 2023 2:52 pm
by strik
@drogon, are you aware that your union and its usage assumes a little endian machine on which this code is running?
Using
Code: Select all
a = temp.t16 & 0xFFu;
c = (temp.t16 >> 8) & 0xFFu;
and, even better, getting rid of this union at all would be much more portable.
I hope the compiler will be able to optimize it to the same code on a little endian machine, and to a similar code on a big endian machine.
If there is a speed penalty, ANDing before the shift for c also help to use
instead, or