6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Apr 28, 2024 10:22 pm

All times are UTC




Post new topic Reply to topic  [ 39 posts ]  Go to page Previous  1, 2, 3  Next
Author Message
PostPosted: Wed Dec 13, 2017 11:07 pm 
Offline

Joined: Wed Oct 06, 2010 9:05 am
Posts: 95
Location: Palma, Spain
Thanks Mike! I already have the BCD versions too, I just didn't post them as it looked like whartung wasn't concerned about them (maybe targetting NES or something?).

Code:
void cpu_6502_base::do_adc_bcd(const byte val)
{
   const uint lo_bin = (a & 0x0FU) + (val & 0x0FU) + c;
   const uint lo = (lo_bin >= 0x0AU) ? ((lo_bin + 0x06U) & 0x0FU) + 0x10U : lo_bin;
   const uint hilo_bin = (a & 0xF0U) + (val & 0xF0U) + lo;
   const uint hilo = (hilo_bin >= 0xA0U) ? hilo_bin + 0x60U : hilo_bin;

   n = !!(hilo_bin & 0x80U);
   v = !!((a ^ hilo_bin) & (val ^ hilo_bin) & 0x80U);
   z = !((a + val + c) & 0xFFU);
   c = (hilo_bin >= 0xA0U);
   a = hilo & 0xFFU;
}

void cpu_6502_base::do_sbc_bcd(const byte val)
{
   const uint lo_bin = (a & 0x0FU) + (val & 0x0FU) + c;
   const uint lo = (lo_bin < 0x10U) ? ((lo_bin + 0x0AU) & 0x0FU) : lo_bin;
   const uint hilo_bin = (a & 0xF0U) + (val & 0xF0U) + lo;
   const uint hilo = (hilo_bin < 0x100U) ? hilo_bin + 0xA0U : hilo_bin;

   n = !!(hilo_bin & 0x80U);
   v = !!((a ^ hilo_bin) & (val ^ hilo_bin) & 0x80U);
   z = !((a + val + c) & 0xFFU);
   c = hilo_bin >> 8;
   a = hilo & 0xFFU;
}

Nearly the same logic, but not quite the same enough!

Just looking at your code in that other thread: does that also set all the flags correctly like the NMOS 6502 (and also give the correct results with non-BCD inputs)? If so, that is some proper magic going on there!


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 13, 2017 11:34 pm 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1927
Location: Sacramento, CA, USA
RichTW wrote:
... Just looking at your code in that other thread: does that also set all the flags correctly like the NMOS 6502 (and also give the correct results with non-BCD inputs)? If so, that is some proper magic going on there!

I never performed a thorough check to see if my attempt behaved exactly like an NMOS 6502 for all possible inputs and outputs, but I would be very surprised if it did.

Mike B.


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 06, 2018 2:54 pm 
Offline
User avatar

Joined: Sun Sep 08, 2013 10:24 am
Posts: 740
Location: A missile silo somewhere under southern England
Does anyone have any ADC / SBC test routines that I can run against my code? Everything checks out that I've thrown at it, but I'd like to be sure.


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 06, 2018 3:10 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10793
Location: England
Try Bruce's tests, or Wolfgang's tests maybe.
http://visual6502.org/wiki/index.php?ti ... stPrograms


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 06, 2018 4:50 pm 
Offline
User avatar

Joined: Sun Sep 08, 2013 10:24 am
Posts: 740
Location: A missile silo somewhere under southern England
Thanks BigEd. Will give them a go.


Top
 Profile  
Reply with quote  
PostPosted: Sun Oct 04, 2020 3:04 pm 
Offline

Joined: Sat Jul 09, 2016 6:01 pm
Posts: 180
The only 6502 generates the inverted carry flag after SBC and CMP. I am curious about this. Does anybody know a reason for this? I am aware that it is a bit easier to implement but one additional NOT logic gate is not a problem even in the super-simple 6502. I hope if it is still not known somebody will ask Bill Mensch about this. Thank you.

_________________
my blog about processors


Top
 Profile  
Reply with quote  
PostPosted: Sun Oct 04, 2020 4:32 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10793
Location: England
I suspect if we called Carry by an extended name: Carry/notBorrow, in analogy with Read/notWrite, we'd find this less of an issue.

The important thing about ADC and SBC is that they should be easy to use for multi byte arithmetic, so the sense of Carry/notBorrow as an input should be the same as the sense of the output.

We SEC before an initial SBC because the neutral value of Carry/notBorrow for a subtraction is to be set, signifying no borrow. And this is natural, when we implement subtract by inverting one input to the ALU: to subtract 00, we add FF, and if we want that to have no effect, we need to put in an additional 1.

It's very natural having constructed an adder to implement subtraction by complementing one input.

I suspect these conventions spring directly from the 1950s machines, where it was enough if the machine could be instructed to do what was needed, no matter how unintuitive the commands might be.

From a 1970s perspective, Carry/notBorrow is quite unobjectionable. Only from a much later perspective, when programmers are brought up with high level languages, might it seem unnecessarily clumsy.


Top
 Profile  
Reply with quote  
PostPosted: Sun Oct 04, 2020 4:51 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 690
Location: North Tejas
litwr wrote:
The only 6502 generates the inverted carry flag after SBC and CMP. I am curious about this. Does anybody know a reason for this? I am aware that it is a bit easier to implement but one additional NOT logic gate is not a problem even in the super-simple 6502.


My understanding is that to save transistors, MOS left out subtract circuitry. Instead, they implemented subtraction by adding the inverse of the subtrahend.

Normally, a two's complement number is negated by inverting the bits and adding one.

Instead of more circuitry or an extra cycle to add the one, they decided that if there was a borrow, there was no need to add the one; if there was no borrow, adding one is needed. Inverting the sense of the carry flag allows the reuse of the adc logic already present.


Top
 Profile  
Reply with quote  
PostPosted: Mon Oct 05, 2020 1:32 am 
Offline

Joined: Mon Sep 17, 2018 2:39 am
Posts: 132
Hi!

litwr wrote:
The only 6502 generates the inverted carry flag after SBC and CMP. I am curious about this. Does anybody know a reason for this?

It is simply a convention, the CPU designer can choose if "Carry = Borrow" or if "Carry = 1 - Borrow".

The 6502, PIC, ARM and PowerPC are examples of CPU where Carry is the inverted Borrow. The Z80 and x86 are examples of CPU where Carry is used as Borrow. And there is MIPS, that does not have flags at all.

So, I would say that nowadays, most used CPUs use the 6502 convention.


Top
 Profile  
Reply with quote  
PostPosted: Mon Oct 05, 2020 6:57 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1927
Location: Sacramento, CA, USA
BillG wrote:
My understanding is that to save transistors, MOS left out subtract circuitry. Instead, they implemented subtraction by adding the inverse of the subtrahend.

My understanding is similar, but I don't know how SBC in BCD mode deals with this little situation, since the circuitry would need to somehow form the nines-complement of the subtrahend, right?
Code:
0000 -> 1001
0001 -> 1000
0010 -> 0111
0011 -> 0110
0100 -> 0101
0101 -> 0100
0110 -> 0011
0111 -> 0010
1000 -> 0001
1001 -> 0000

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


Top
 Profile  
Reply with quote  
PostPosted: Mon Oct 05, 2020 7:30 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10793
Location: England
Th 6502's decimal circuits are built as a post-operation adjustment, with inputs (and outputs) including the half-carry. The basic idea, I think, is to add or to subtract 6 from each digit, or leave it alone. Some discussion here: viewtopic.php?f=1&t=4975


Top
 Profile  
Reply with quote  
PostPosted: Mon Oct 05, 2020 9:51 am 
Offline

Joined: Sat Jul 09, 2016 6:01 pm
Posts: 180
dmsc wrote:
It is simply a convention, the CPU designer can choose if "Carry = Borrow" or if "Carry = 1 - Borrow".

The 6502, PIC, ARM and PowerPC are examples of CPU where Carry is the inverted Borrow. The Z80 and x86 are examples of CPU where Carry is used as Borrow. And there is MIPS, that does not have flags at all.

So, I would say that nowadays, most used CPUs use the 6502 convention.

Sorry, I missed the ARM and I didn't know that the PIC and PowerPC also inverts the carry. Thank you. I can only add that Moto's (680x, 68k) and DEC's (PDP-11, VAX) processors also use not inverted carry. I didn't know about the carry on the DEC Alpha. The IBM System/360 doesn't invert carry. The Microblaze architecture inverts carry but it can't directly check it that makes work a bit easier.
The inverted carry helps to make division faster. I used it in my division routines for the 6502 and ARM in my pi-spigot project. I dare to think that my divisions are among the fastest known. IMHO it is good to have the inverted carry on a processor without hardware division.
It is interesting, did somebody of the 6502 team know about advantages of the inverted carry? It seems that the 6502 was the first processor with the inverted carry.

_________________
my blog about processors


Top
 Profile  
Reply with quote  
PostPosted: Mon Oct 05, 2020 2:10 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
I think they just went for the solution with the simplest hardware implementation and the smallest number of required opcodes. That it happens to also be advantageous for certain algorithms is merely a happy accident.


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 06, 2020 4:14 pm 
Offline

Joined: Sat Jul 09, 2016 6:01 pm
Posts: 180
Chromatix wrote:
I think they just went for the solution with the simplest hardware implementation and the smallest number of required opcodes. That it happens to also be advantageous for certain algorithms is merely a happy accident.

It might have been so but it is difficult for me to believe that they broke the concept, which was used by IBM, DEC, Intel, and Motorola, just to save 3 transistors.

_________________
my blog about processors


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 06, 2020 4:30 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10793
Location: England
The 6502 team were trying to build a better 6800. If they knew from experience that coding multi byte subtraction was a pain on the 6800, and this helped to fixed that, that could be the answer. Similarly, perhaps, the way the 6502 does not update flags on stores, is an optimisation which could come from experience.


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

All times are UTC


Who is online

Users browsing this forum: No registered users and 27 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: