6502 Emulation of ADC in C

Topics pertaining to the emulation or simulation of the 65xx microprocessors and their peripheral chips.
Sailor
Posts: 12
Joined: 07 Jul 2017

6502 Emulation of ADC in C

Post by Sailor »

Quote:
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 ?
Last edited by Sailor on Mon Jan 30, 2023 10:11 pm, edited 1 time in total.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: 6502 Emulation of ADC in C

Post 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/
Sailor
Posts: 12
Joined: 07 Jul 2017

Re: 6502 Emulation of ADC in C

Post 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.
User avatar
Alarm Siren
Posts: 363
Joined: 25 Oct 2016

Re: 6502 Emulation of ADC in C

Post by Alarm Siren »

BigEd wrote:
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.
Want to design a PCB for your project? I strongly recommend KiCad. Its free, its multiplatform, and its easy to learn!
Also, I maintain KiCad libraries of Retro Computing and Arduino components you might find useful.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: 6502 Emulation of ADC in C

Post by BigEd »

Thanks! (I'm not sure when I might start to remember it so clearly!)
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: 6502 Emulation of ADC in C

Post 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.)
Last edited by barrym95838 on Thu Feb 02, 2023 9:29 am, edited 1 time in total.
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)
User avatar
Alarm Siren
Posts: 363
Joined: 25 Oct 2016

Re: 6502 Emulation of ADC in C

Post by Alarm Siren »

barrym95838 wrote:
*mulating
I see what you did there 8)
Want to design a PCB for your project? I strongly recommend KiCad. Its free, its multiplatform, and its easy to learn!
Also, I maintain KiCad libraries of Retro Computing and Arduino components you might find useful.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: 6502 Emulation of ADC in C

Post by BigEd »

I wish we could get away from that whole thing. It would only take the goodwill of one person.
Sailor
Posts: 12
Joined: 07 Jul 2017

Re: 6502 Emulation of ADC in C

Post by Sailor »

BigEd wrote:
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 .
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: 6502 Emulation of ADC in C

Post 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:

Code: Select all

A: FD, M: FF, C: 01, temp: 01FD
The compiler ought to be able to optimise that into something quite efficient... Hopefully. :-)

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Sailor
Posts: 12
Joined: 07 Jul 2017

Re: 6502 Emulation of ADC in C

Post by Sailor »

Hello Gordon
I tested your code , it is great

Update :

can your code be extended to test / set overflow flag as well ?
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: 6502 Emulation of ADC in C

Post by drogon »

Sailor wrote:
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
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
User avatar
Arlet
Posts: 2353
Joined: 16 Nov 2010
Location: Gouda, The Netherlands
Contact:

Re: 6502 Emulation of ADC in C

Post 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.
Sailor
Posts: 12
Joined: 07 Jul 2017

Re: 6502 Emulation of ADC in C

Post 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 .
User avatar
strik
Posts: 15
Joined: 24 Mar 2022

Re: 6502 Emulation of ADC in C

Post 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

Code: Select all

  c = (temp.t16 & 0xFF00u) >> 8;
instead, or

Code: Select all

  c = temp.t16 >= 0x100u;
Post Reply