6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu Nov 21, 2024 9:51 pm

All times are UTC




Post new topic Reply to topic  [ 19 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Mon Jan 30, 2023 8:01 pm 
Offline

Joined: Fri Jul 07, 2017 11:14 pm
Posts: 12
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.

Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 30, 2023 8:33 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10985
Location: England
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/


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 30, 2023 8:47 pm 
Offline

Joined: Fri Jul 07, 2017 11:14 pm
Posts: 12
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.


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 30, 2023 11:01 pm 
Offline
User avatar

Joined: Tue Oct 25, 2016 8:56 pm
Posts: 362
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.


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 31, 2023 4:57 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10985
Location: England
Thanks! (I'm not sure when I might start to remember it so clearly!)


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 31, 2023 5:54 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1949
Location: Sacramento, CA, USA
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.)

_________________
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)


Last edited by barrym95838 on Thu Feb 02, 2023 9:29 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 31, 2023 8:50 am 
Offline
User avatar

Joined: Tue Oct 25, 2016 8:56 pm
Posts: 362
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.


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 31, 2023 2:09 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10985
Location: England
I wish we could get away from that whole thing. It would only take the goodwill of one person.


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 31, 2023 2:59 pm 
Offline

Joined: Fri Jul 07, 2017 11:14 pm
Posts: 12
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 .


Top
 Profile  
Reply with quote  
PostPosted: Wed Feb 01, 2023 10:08 am 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1488
Location: Scotland
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:
#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:
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/


Top
 Profile  
Reply with quote  
PostPosted: Wed Feb 01, 2023 11:45 am 
Offline

Joined: Fri Jul 07, 2017 11:14 pm
Posts: 12
Hello Gordon
I tested your code , it is great

Update :

can your code be extended to test / set overflow flag as well ?


Top
 Profile  
Reply with quote  
PostPosted: Fri Feb 03, 2023 1:47 pm 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1488
Location: Scotland
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:
#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/


Top
 Profile  
Reply with quote  
PostPosted: Fri Feb 03, 2023 3:32 pm 
Offline
User avatar

Joined: Tue Nov 16, 2010 8:00 am
Posts: 2353
Location: Gouda, The Netherlands
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.


Top
 Profile  
Reply with quote  
PostPosted: Fri Feb 03, 2023 7:45 pm 
Offline

Joined: Fri Jul 07, 2017 11:14 pm
Posts: 12
@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 .


Top
 Profile  
Reply with quote  
PostPosted: Wed Feb 22, 2023 2:52 pm 
Offline
User avatar

Joined: Thu Mar 24, 2022 8:52 pm
Posts: 11
@drogon, are you aware that your union and its usage assumes a little endian machine on which this code is running?

Using
Code:
  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:
  c = (temp.t16 & 0xFF00u) >> 8;

instead, or
Code:
  c = temp.t16 >= 0x100u;


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 19 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 7 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: