Problem with the logic besides the SBC instruction emulation

Topics pertaining to the emulation or simulation of the 65xx microprocessors and their peripheral chips.
Post Reply
ehguacho
Posts: 29
Joined: 24 Jun 2009

Problem with the logic besides the SBC instruction emulation

Post by ehguacho »

i came across this code to emulate the SBC instruction:

Code: Select all

uint temp = (uint)(ACC - src - C_FLAG);
Z_FLAG = !(temp & 0xff);
N_FLAG = (temp & 0x80);
V_FLAG = ((ACC ^ temp) & (Memoria[PC] ^ temp) & 0x80)
C_FLAG = (temp < 0x100);
ACC = (byte)(temp & 0xff);
i tested the code it do work perfectly, but what about this line?

Code: Select all

V_FLAG = ((ACC ^ temp) & (Memoria[PC] ^ temp) & 0x80)
already read the doc in 6502.org that covers the V flag, but i still can't understand the logic besides how the V flag is set in that code line.

anyone smarter than me to help me out? :(
sorry about my english, i'm from Argentina :S

http://felliniycia.comule.com/
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Post by GARTHWILSON »

I'm not sure I understand the question, but have you looked at http://6502.org/tutorials/vflag.html ?
Quote:
sorry about my english, i'm from Argentina :S
¡Eh, gaucho! You estaba en Jujuy, Salta, y Tucumán unos ocho años cuando fui niño, y aprendí a leer y escribir primero en castellano y luego en inglés. Desafortunadamente, tengo casi nada de vocabulario técnico en castellano.
ehguacho
Posts: 29
Joined: 24 Jun 2009

Post by ehguacho »

yes i did Garth, actually that's the doc if was reffering to.

looks like that expression was whipped up from a Karnaugh map or something like that, who knows... :shock:
sorry about my english, i'm from Argentina :S

http://felliniycia.comule.com/
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Post by GARTHWILSON »

You can also get the explanation on pages 135-136 of the excellent programming manual at http://www.westerndesigncenter.com/wdc/ ... manual.pdf , something everyone here should have. It's a 1.7MB file. (Hmmm... that doesn't seem possible since it's 469 pages! Oh well, 1.7MB is what the computer says.)
User avatar
BigDumbDinosaur
Posts: 9428
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Post by BigDumbDinosaur »

GARTHWILSON wrote:
It's a 1.7MB file. (Hmmm... that doesn't seem possible since it's 469 pages! Oh well, 1.7MB is what the computer says.)
That the size my system reports.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Post by ElEctric_EyE »

oh, nice. I wasn't aware of this manual. Thanks Garth! This is how I really learn about a processor, maybe set me on a path to the '816...
kc5tja
Posts: 1706
Joined: 04 Jan 2003

Post by kc5tja »

That must be some freakin' insane compression. Even if you round up to 2MB, that weighs in at less than 5KB per page, average!
GordonZaft
Posts: 6
Joined: 10 Aug 2010
Location: Arizona, USA

Post by GordonZaft »

there's a lot of whitespace in the doc.
kc5tja
Posts: 1706
Joined: 04 Jan 2003

Post by kc5tja »

I hope that's intended to be humorous, for PDFs don't record whitespace. :) PDFs are scene graphs.
GordonZaft
Posts: 6
Joined: 10 Aug 2010
Location: Arizona, USA

Post by GordonZaft »

(okay, the forum lost this post once before, hopefully this one will stick)

It's not intended to be humorous. I am certainly not "up" on PDF tech but reading Wikipedia (http://en.wikipedia.org/wiki/Pdf#Technical_overview) seems to suggest that strings in the doc are stored as... strings. The large amount of whitespace in the document as it appears shouldn't take up storage space, since it's due to the font specifications used for the text in the doc.
User avatar
dclxvi
Posts: 362
Joined: 11 Mar 2004

Re: Problem with the logic besides the SBC instruction emula

Post by dclxvi »

ehguacho wrote:

Code: Select all

uint temp = (uint)(ACC - src - C_FLAG);
Z_FLAG = !(temp & 0xff);
N_FLAG = (temp & 0x80);
V_FLAG = ((ACC ^ temp) & (Memoria[PC] ^ temp) & 0x80)
C_FLAG = (temp < 0x100);
ACC = (byte)(temp & 0xff);
That code doesn't look correct.

First, the formula is A = A - M - 1 + C, where M (memory) is the operand of the SBC instruction. So the C flag should be inverted prior to the temp calculation (to be fair, since this is only an excerpt of code, maybe it was).

Second, for a calculation such as $10-$20, temp would be $F0 (-16), so there should be no overflow, but the V_FLAG calculation would be non-zero. Yet $20-$10 also has no overflow, but V_FLAG would be zero (which is correct).

Third, -- this is not necessarily an error, just an observation -- it's strange that src is used in the temp calculation but the Memoria array is used in the V_FLAG calculation.

Anyway, one way to determine the formula for the V flag is from the truth table for 1-bit subtraction. (In this table, N is the N flag, i.e. the A output.) A 1-bit twos complement number ranges from -1 to 0.

Code: Select all

A M c | N C V
------+------
0 0 0 | 1 0 0   0 -  0 - 1 + 0 = -1
0 0 1 | 0 1 0   0 -  0 - 1 + 1 =  0
0 1 0 | 0 0 0   0 - -1 - 1 + 0 =  0
0 1 1 | 1 0 1   0 - -1 - 1 + 1 =  1
1 0 0 | 0 1 1  -1 -  0 - 1 + 0 = -2
1 0 1 | 1 1 0  -1 -  0 - 1 + 1 = -1
1 1 0 | 1 0 0  -1 - -1 - 1 + 0 = -1
1 1 1 | 0 1 0  -1 - -1 - 1 + 1 =  0
Just as you can extend 8-bit to subtraction to 16 bits with a sequence like:

Code: Select all

LDA NUM1
SBC NUM2
STA NUM3
LDA NUM1
SBC NUM2
STA NUM3
a 1-bit subtraction can be extended to 2 bits, 3 bits, etc. in the same sort of way. So the 1-bit subtraction truth table above is actually sufficient to describe 8-bit addition. c represents the carry from the addition of the first 7 bits, A and M are the hi bits of the A and the operand, and then N, C, and V represent the N, C, and V flag results. (If you're having trouble seeing this, you could work out the 32 cases for a 2-bit addition by hand -- the input bits will be A1, A0, M1, M0, and c -- and you'll find that the formulas below still hold true.)

From the truth table, you can derive common formulas for the V flag:

V = C XOR c
V = ((NOT A) AND M AND N) OR (A AND (NOT M) AND (NOT N))

The latter formula is the same as:

V = (A XOR M) AND (A XOR N)

so replacing the second temp with ACC should do the trick.
ehguacho
Posts: 29
Joined: 24 Jun 2009

Re: Problem with the logic besides the SBC instruction emula

Post by ehguacho »

dclxvi wrote:
First, the formula is A = A - M - 1 + C
that's not way the i've found the formula. that "-1" doesn't appears in any doc i've checked.
dclxvi wrote:
it's strange that src is used in the temp calculation but the Memoria array is used in the V_FLAG calculation
my mistake. forgot to chanage that "Memoria[PC]" for "src" while copying the text from my source code to the post.

thanks for your reply! even if the formula isn't the correct one, now i know from where it came up :)
sorry about my english, i'm from Argentina :S

http://felliniycia.comule.com/
User avatar
BitWise
In Memoriam
Posts: 996
Joined: 02 Mar 2004
Location: Berkshire, UK
Contact:

Post by BitWise »

Quote:
First, the formula is A = A - M - 1 + C
The 6502 ALU doesn't have subtraction circuitry, it calculates

Code: Select all

A = A + ~M + C
The ones complement ~M is (roughly) equivalent to -1 - M, giving

Code: Select all

A = A + (-1 - M) + C = A - M + C - 1
Which kind of explains why you have to clear the carry when you have a borrow (e.g C = 0 so that last bit become + 0 - 1 = -1)
Andrew Jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs
User avatar
dclxvi
Posts: 362
Joined: 11 Mar 2004

Post by dclxvi »

A quick note on the various formulas here: the A + ~M + C formula that BitWise mentioned is indeed how the 6502 actually operates. In most documentation that I've seen, the formula is usually written as A - M - (NOT C) -- in other words, A - M when the carry is set, and A - M - 1 when the carry is clear. Since C can only be 0 or 1, NOT C is the same as 1 - C. So all of these formulas are equivalent, even though that may not be easy to see unless you work out the algebra.

I usually use the A - M - 1 + C form, even though it is somewhat unconventional, because you can plug in a value from -128 to 127 for A and M, and a value from 0 to 1 for C, and then the overflow is set when result outside the range -128 to 127. Likewise, if use plug in a value in the range 0 to 255 for A and M, the carry will be clear when the value is less than 0. Other people may find different forms more convenient for their purposes.
ehguacho
Posts: 29
Joined: 24 Jun 2009

Post by ehguacho »

and again thanks dclxvi. probably there's some typos in some docs.

usually the operation is written some docs (the correct ones) as "A = A - M - (IF_CARRY() ? 0 : 1)".
then, if C is set the formula goes "A = A - M" and "A = A - M - 1" if it's not set, wich is the correct behavior.
sorry about my english, i'm from Argentina :S

http://felliniycia.comule.com/
Post Reply