6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Oct 06, 2024 7:31 am

All times are UTC




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: SBC Emulation
PostPosted: Fri Jun 04, 2004 2:10 pm 
Offline

Joined: Fri May 21, 2004 5:23 pm
Posts: 17
Location: Burlington, ON
Hi,

I've noticed two things with regard to SBC in a few 6502 emulators on the Internet that I can't explain:

[1] When setting or clearing the overflow flag during SBC, some emulators shift the carry bit to the bit-4 position.

[2] When performing BCD calculations during SBC, 66 (hex) is subtracted from the accumulator.

Can anyone shed some light on these items? It would be a big help... :wink:

Thanks a lot,

Andrew


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Jun 04, 2004 11:08 pm 
Offline
User avatar

Joined: Thu Mar 11, 2004 7:42 am
Posts: 362
[1] Could you be more specific? This doesn't sound familiar, but I'll give it a shot if you tell me what each step is.

[2] One way to get the BCD result is to calculate the hex (binary) result first, then adjust that result by subtracting 00, 06, 60, or 66, depending on the subtraction. For example:

00-01, hex result = FF, BCD result = 99 = FF - 66
00-10, hex result = F0, BCD result = 90 = F0 - 60
10-01, hex result = 0F, BCD result = 09 = 0F - 06
08-01, hex result = 07, BCD result = 07 = 07 - 00


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Jun 04, 2004 11:26 pm 
Offline

Joined: Fri May 21, 2004 5:23 pm
Posts: 17
Location: Burlington, ON
Hi dclxvi,

dclxvi wrote:
[1] Could you be more specific? This doesn't sound familiar, but I'll give it a shot if you tell me what each step is.


The code segment goes something like this:

Code:
Result = Accumulator + 1's Complement of Memory Byte + (Carry Flag * 16)
If the Result is greater than 127 or less than -128 Then
   Set the Overflow Flag
Otherwise
   Clear the Overflow Flag


The multiplying by 16 is what's throwing me off.

dclxvi wrote:
[2] One way to get the BCD result is to calculate the hex (binary) result first, then adjust that result by subtracting 00, 06, 60, or 66, depending on the subtraction. For example:

00-01, hex result = FF, BCD result = 99 = FF - 66
00-10, hex result = F0, BCD result = 90 = F0 - 60
10-01, hex result = 0F, BCD result = 09 = 0F - 06
08-01, hex result = 07, BCD result = 07 = 07 - 00


Again, here's some pseudocode:
Code:
If the Decimal Flag is set Then
   Subtract 66h from the Accumulator
   Clear the Carry Flag
   If the lower 4-bits of the Accumulator is > 9 Then
      Add 6h onto the Accumulator

   If the upper 4-bits of the Accumulator is > 90 Then
      Add 60h onto the Accumulator
      Set the Carry Flag


I hope you don't think I'm off my rocker :wink:...

As always, thanks for your help dclxvi,

Andrew


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Jun 05, 2004 9:08 pm 
Offline
User avatar

Joined: Thu Mar 11, 2004 7:42 am
Posts: 362
andrewem wrote:
The code segment goes something like this:

Code:
Result = Accumulator + 1's Complement of Memory Byte + (Carry Flag * 16)
If the Result is greater than 127 or less than -128 Then
   Set the Overflow Flag
Otherwise
   Clear the Overflow Flag


The multiplying by 16 is what's throwing me off.


That's not quite enough context to know for sure, but to do a BCD calculation, you have to work one hex digit at a time. You can work a byte a time with a binary calculation, but the emulator may be doing a digit at time just in case decimal mode is in effect. When you work one digit at a time, you have to account for a carry between the two digits in a byte, i.e. between bit 3 and bit 4 of the byte. When working on the upper digits, that "carry between the digits" would go into bit 4, rather than bit 0. Also see below.

andrewem wrote:
Again, here's some pseudocode:
Code:
If the Decimal Flag is set Then
   Subtract 66h from the Accumulator
   Clear the Carry Flag
   If the lower 4-bits of the Accumulator is > 9 Then
      Add 6h onto the Accumulator

   If the upper 4-bits of the Accumulator is > 90 Then
      Add 60h onto the Accumulator
      Set the Carry Flag


To convert the binary (hex) result of LDA N1 SBC N2, you're checking for two conditions:

#1: If the lower digit of N2 < the lower digit of N1, then subtract $06 from the binary result
#2: If N2 < N1, then subtract $60 from the binary result

(Actually, those are for SEC SBC. For CLC SBC, use <= instead of < in both condtions.) Since these two conditions are independent of one another, there are four possiblities: neither conditions is true, #1 only is true, #2 only is true, or both are true. For each case:

Neither: $00 is subtracted from the binary to produce the decimal result subtracted
#1 only: $06 is subtracted from the binary to produce the decimal result subtracted
#2 only: $60 is subtracted from the binary to produce the decimal result subtracted
Both: $66 is subtracted from the binary to produce the decimal result

Ordinarily you would start from the "neither" case and check each condition one at time to cover the other three cases. The pseudocode is starting from the "both" case, then checking each condition to cover the other three cases, since:

-$66 + $00 = - $66
-$66 + $06 = - $60
-$66 + $60 = - $06
-$66 + $06 + $60 = - $00

You may also find that "General Discussions -> Flag setting on the 65C02 in decimal mode" in the forum is helpful.

Most other microprocessors that directly support BCD don't have a decimal mode. They use an instruction usually called DAA which stands for some combination of Decimal, Adjust, Accumulator, and Addition, which would follow the ADC instruction. On some of these processors, there is a corresponding DAS instruction for subtraction. These processors have two carry flags: the normal between byte carry, and a between digit carry. Using these carry flags and the binary result, they adjust the binary result accordingly. It may be easier to understand how BCD works (and how 6502 emulators implement BCD) by looking at DAA and DAS documentation. Intel (8086 family) and Motorola (68HC08 and later families) both have manuals on their web pages that contain this sort of detail. Naturally, this sort of thing is usually in a multi-megabyte .pdf manual, which is pain to download if you only want to look up one instruction. I can look up the exact manual titles if you can't figure out which ones to download.

By having a decimal mode on the 6502, the BCD result gets directly generated, rather than having to derive it from the binary result. So the specifics of how BCD works aren't often covered, certainly not to that they are on microprocessor with a DAA instruction.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Jun 08, 2004 9:26 pm 
Offline

Joined: Sun Aug 24, 2003 7:17 pm
Posts: 111
There are two different matters:

-how does the 6502 work
-how do the emulators work

The first point is absolutely clear from the original excellent MOS documentation, no problem there!

Now anybody can write an simulator and make it available in the Internet. No guarantee that this software is correct! I checked Daryl Richter's simulator (original from Apple!!) that otherwise works very well. But SBC with BCD flag set is not correctly simulated!
I put $00 in the accumulator, set the carry flag (SEC) and the decimal flag (SED). The operation

SBC #$60

then resulted in $76! But this is wrong, the result should be $40!

As BCD arithmetics is not much used, for example in an Apple running Basic, these bugs are not necessarily detected!

If strange things appear to happen with a simulator, you better use another one!


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC


Who is online

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