Questions
Questions
Hello Everyone. Some of you may already know me as WedNESday from the nesdev forums. I have some 6502 questions that are better asked here than there. This is for my 6502 emulator;
1. What are the Power Up values of the registers/memory?
2. Is the Interrupt Disable flag set on a RESET/NMI?
3. In decimal the N, V and Z flags are not set on ADC/SBC. But are they cleared?
4. What are the differences between 6502 and 6502A (or other numbers/letters)?
5. Are all 6502 models the same no matter whom the manufacturer? (as my 6502 emulator is for the Acorn Electron, C64 and NES)
6. When a KIL/JAM/HLT instruction occurs can the CPU recover with an interrupt? If so, should the return address be greater by 1? Before an interrupt occurs, should I just increase the Clock Cycle counter by 1 until one does occur?
1. What are the Power Up values of the registers/memory?
2. Is the Interrupt Disable flag set on a RESET/NMI?
3. In decimal the N, V and Z flags are not set on ADC/SBC. But are they cleared?
4. What are the differences between 6502 and 6502A (or other numbers/letters)?
5. Are all 6502 models the same no matter whom the manufacturer? (as my 6502 emulator is for the Acorn Electron, C64 and NES)
6. When a KIL/JAM/HLT instruction occurs can the CPU recover with an interrupt? If so, should the return address be greater by 1? Before an interrupt occurs, should I just increase the Clock Cycle counter by 1 until one does occur?
Re: Questions
Alucard wrote:
1. What are the Power Up values of the registers/memory?
Quote:
Is the Interrupt Disable flag set on a RESET/NMI?
Quote:
In decimal the N, V and Z flags are not set on ADC/SBC. But are they cleared?
Quote:
What are the differences between 6502 and 6502A (or other numbers/letters)?
Quote:
Are all 6502 models the same no matter whom the manufacturer? (as my 6502 emulator is for the Acorn Electron, C64 and NES)
It's best to consult the specific platform's documentation for details.
I should note that Commodore's CPUs were considered the benchmark/canon implementations of the various CPUs, because Commodore Semiconductor Group bought out MOS Technology (the manufacturers and incubator of the 6502 architecture itself). The current authority on the 6502/65816 architecture now that Commodore is no more is Western Design Center, where Bill Mensche (CEO, and co-inventor of the 6502) is working to continue the product line (and quite successfully too!).
Quote:
When a KIL/JAM/HLT instruction occurs can the CPU recover with an interrupt?
- GARTHWILSON
- Forum Moderator
- Posts: 8775
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
> > 1. What are the Power Up values of the registers/memory?
>
> NMOS version is undefined. CMOS version, I believe, zeros out
> all the registers, except for S, which is set to $0100. I could
> be wrong though; I don't have the 65C02 manual in front of
> me at the moment.
I've never seen anything in any of the data sheets about initial values of A, X, Y, and most of the flags, or even S. Both NMOS and CMOS set the interrupt-disable flag and load PC with the reset vector. The CMOS versions also clear the decimal flag.
> 2. Is the Interrupt Disable flag set on a RESET/NMI?
Yes, and IRQ as well.
> 3. In decimal the N, V and Z flags are not set on ADC/SBC. But
> are they cleared?
They will be affected by ADC & SBC, but invalid. Is that your understanding, kc5tja? (but undefined at reset.) With the CMOS versions, Z will be correct. V and N follow the logic rules for them, but probably will not be relevant. In signed decimal arithmetic, I would take N=1 (negative numbers to mean 50-99), but N just reflects the high bit status, which means decimal 80-99.
> 5. Are all 6502 models the same no matter who the
> manufacturer? (as my 6502 emulator is for the Acorn Electron,
> C64 and NES)
If you specifically want to make an emulator (although I suspect you mean a simulator, which is all software, unlike the emulator) for just the NMOS ones, that's one thing. But do be aware that the CMOS 6502 not only takes a lot less power, but has the bugs and quirks fixed and has more instructions and addressing modes. Also:
>
> NMOS version is undefined. CMOS version, I believe, zeros out
> all the registers, except for S, which is set to $0100. I could
> be wrong though; I don't have the 65C02 manual in front of
> me at the moment.
I've never seen anything in any of the data sheets about initial values of A, X, Y, and most of the flags, or even S. Both NMOS and CMOS set the interrupt-disable flag and load PC with the reset vector. The CMOS versions also clear the decimal flag.
> 2. Is the Interrupt Disable flag set on a RESET/NMI?
Yes, and IRQ as well.
> 3. In decimal the N, V and Z flags are not set on ADC/SBC. But
> are they cleared?
They will be affected by ADC & SBC, but invalid. Is that your understanding, kc5tja? (but undefined at reset.) With the CMOS versions, Z will be correct. V and N follow the logic rules for them, but probably will not be relevant. In signed decimal arithmetic, I would take N=1 (negative numbers to mean 50-99), but N just reflects the high bit status, which means decimal 80-99.
> 5. Are all 6502 models the same no matter who the
> manufacturer? (as my 6502 emulator is for the Acorn Electron,
> C64 and NES)
If you specifically want to make an emulator (although I suspect you mean a simulator, which is all software, unlike the emulator) for just the NMOS ones, that's one thing. But do be aware that the CMOS 6502 not only takes a lot less power, but has the bugs and quirks fixed and has more instructions and addressing modes. Also:
- RDY is bidirectional now, pulled low internally by the WAIt instruction
RDY can be used to stop write instructions too
there's an onboard oscillator which you can use with a crystal or RC
an outboard clock source can be a simple, single-phase square wave
clock can be stopped indefinitely
Unused input pins like NMI have internal pull-ups so you don't need the external resistor or connection
RST is a schmitt-trigger input
RST can be held low indefinitely, unlike the NMOS which should not be held low more than 50ms.
Thanks for the replies. Just to clarify one thing though. You all say that the N, V and Z flags are undefined in decimal ADC/SBC. Currently, I clear the three flags whenever a ADC/SBC opcodes is encountered. If decimal mode is set then they are not affected. Is this right? Or do the flags equal something random?
Alucard wrote:
Thanks for the replies. Just to clarify one thing though. You all say that the N, V and Z flags are undefined in decimal ADC/SBC. Currently, I clear the three flags whenever a ADC/SBC opcodes is encountered. If decimal mode is set then they are not affected. Is this right? Or do the flags equal something random?
- GARTHWILSON
- Forum Moderator
- Posts: 8775
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Regarding V: I think you'll be interested in the discussion we had at http://www.6502.org/forum/viewtopic.php?t=254 (which is two pages so far). Do read through completely though, because some of the things initially posted seemed to be erroneous and we got that figured out as the discussion progressed.
There is a V flag tutorial at http://www.6502.org/tutorials/vflag.html .
There is a V flag tutorial at http://www.6502.org/tutorials/vflag.html .
Alucard wrote:
If decimal mode is set then they are not affected. Is this right?
I've got a write up about decimal mode that I haven't gotten around to finishing. It includes a program intended for writing and checking simulators. It's a 6502 assembly program that uses binary arithmetic to replicate the N, V, and Z flag results that would occur in decimal mode then checks this with the actual flag results in decimal mode. Thus, you can check your simulator to make sure it replicates decimal arithmetic behavior completely. You can also copy the program logic into the simulator itself to calculate the N, V, Z, results in decimal mode. It's not documented well at the moment, but there's nothing intentionally tricky. I can send you the source code if you'd like. The code I posted in the thread Garth mentioned gives the flavor of how it works.
Since the N, V, and Z flag results in decimal mode fall under the category of undocumented behavior, to me, it is fair game if a simulator does NOT replicate this or any other undocumented behavior. However, there are a few programs that do make use of specific instances of undocumented behavior. For example, one method for distiniguishing a (NMOS) 6502 from a 65C02 is to use an ADC of 99 + 1 in decimal mode and look at the Z flag result (which will be zero on a 6502 and one on a 65C02).
kc5tja wrote:
Well, the three flags are probably set as if the ALU were working in binary mode.
So are they sometimes set correctly, and other times not? When are the N and V flags set when decimal mode is on because it can't be the same as binary mode. I am still confused right now so I will post some of my code. BCDAccumulator and BCDByte make sure that the number is not hexadecimal.
The N, V and Z flags are never set. Would this be acceptable?
Code: Select all
inline void OpticCode69()
{
CPU.Byte = CPU.Memory[Immediate];
CPU.P &= 0x3D;
if( CPU.P & 0x08 )
{
BCDAccumulator();
BCDByte();
if( CPU.A + CPU.Byte + (CPU.P & 0x01) > 0x99 )
CPU.TMP = 1; else CPU.TMP = 0;
CPU.A += CPU.Byte + (CPU.P & 0x01);
BCDAccumulator();
CPU.P &= 0xFE;
CPU.P += CPU.TMP;
}
else
{
// Omitted...
}
CPU.PC += 2;
CPU.CC += 2;
}
If you're writing a software version of a particular variant of the 6502, it should do whatever the actual 6502 would do for ADC/SBC in decimal mode (even if it's odd or seems incorrect), since code you're running could depend on whatver values the actual 6502 would put into the status flags after those operations.
Hey blargg it's your best buddy (lol...) from nesdev here WedNESday.
My 6502 emulator is not just for the NES it is for any system so there are no specifics. I still feel that my questions have been unanswered though. I know that N, V and Z are undefined in decimal ADC/SBC, so if we tried...
...ten times would the results be random? e.g. first time around 3/10 the zero flag was set, the second time around 5/10 the zero flag was set etc. etc.
My 6502 emulator is not just for the NES it is for any system so there are no specifics. I still feel that my questions have been unanswered though. I know that N, V and Z are undefined in decimal ADC/SBC, so if we tried...
Code: Select all
SED
LDA #$50
ADC #$50
- GARTHWILSON
- Forum Moderator
- Posts: 8775
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Quote:
My 6502 emulator is not just for the NES it is for any system so there are no specifics.
Quote:
I know that N, V and Z are undefined in decimal ADC/SBC
Read the thread Garth mentioned. To calculate the accumulator result and the carry you use one set of rules. There is a different set of rules for the other flags. With the same inputs you get the same results every time.
In my post about halfway down the first page in the other thread there are two programs given, and a list of seven steps for determining the V flag in decimal mode. Those same seven steps can be used to predict the value of the ADC N flag result in decimal mode -- just subtitute N for V in steps 6 and 7. The other 4 undocumented cases -- the SBC N, V, and Z flag results, and the ADC Z flag result -- are the same as if the two numbers were subtracted (SBC) or added (ADC) in binary mode. In other words, the Z flag after:
is the same as the Z flag after:
So, in both cases the Z flag will be zero (i.e. BNE will branch). To summarize:
After ADC:
Accumulator: determined by BCD addition result
C flag: determined by BCD addition result
N flag: see the seven step method in the other thread
V flag: see the seven step method in the other thread
Z flag: same value as when the two numbers are added in binary mode
After SBC:
Accumulator: determined by BCD subtraction result
C flag: determined by BCD subtraction result
N flag: same value as when the two numbers are subtracted in binary mode
V flag: same value as when the two numbers are subtracted in binary mode
Z flag: same value as when the two numbers are subtracted in binary mode
You can use this infomation to synthesize the decimal mode flag results using only binary arithmetic. That is what the two programs mentioned earlier do.
On the 6502, the only documented behavior is the accumulator result and the carry flag when given valid BCD numbers (i.e. both BCD digits are in the range 0-9). So, a simulator can be considered "correct" if these cases give the correct result. However, as blargg mentioned, it can be useful to replicate the undocumented behavior, since there are programs out there that use undocumented decimal mode behavior. Relying on undocumented behavior does not make for a robust program, so when such a program doesn't behave as expected on a simulator, to me, that is a problem with the program, not the simulator. Anyway, here are a couple of examples:
Example #1: distinguishing a 6502 from a 65C02.
The ADC clears Z flag on a 6502, but sets the Z flag on a 65C02. This is undocumented behavior on a 6502, but it IS documented behavior on a 65C02.
Incidentally, if you always cleared the Z flag in decimal mode, this particular example would still behave correctly.
Example #2: converting a hex digit 0-F to ASCII
A straightforward way to convert $00-$09 to $30-$39 and $0A-$0F to $41-$46 is:
A couple of bytes can be saved by resorting to undocumented behavior:
In this version, the undocumented behavior relied upon is addition when one of the digits in the range A-F.
I can't recall any other examples off the top of my head. There is very little existing code that would be broken by not replicating undocumented behavior.
If you have additional questions feel free to ask. I've worked out all of the cases for 8-bit and 16-bit (i.e. on the 65816 when the m flag is zero) decimal mode addition and subtraction and have verified every possible combination on the 6502 (Rockwell and Synertek), the 65C02, and the 65816 works as I've described. Now if only I'd stop writing long-winded forum posts and finish the decimal mode write-up...
In my post about halfway down the first page in the other thread there are two programs given, and a list of seven steps for determining the V flag in decimal mode. Those same seven steps can be used to predict the value of the ADC N flag result in decimal mode -- just subtitute N for V in steps 6 and 7. The other 4 undocumented cases -- the SBC N, V, and Z flag results, and the ADC Z flag result -- are the same as if the two numbers were subtracted (SBC) or added (ADC) in binary mode. In other words, the Z flag after:
Code: Select all
SED
CLC
LDA #$50
ADC #$50
Code: Select all
CLD
CLC
LDA #$50
ADC #$50
After ADC:
Accumulator: determined by BCD addition result
C flag: determined by BCD addition result
N flag: see the seven step method in the other thread
V flag: see the seven step method in the other thread
Z flag: same value as when the two numbers are added in binary mode
After SBC:
Accumulator: determined by BCD subtraction result
C flag: determined by BCD subtraction result
N flag: same value as when the two numbers are subtracted in binary mode
V flag: same value as when the two numbers are subtracted in binary mode
Z flag: same value as when the two numbers are subtracted in binary mode
You can use this infomation to synthesize the decimal mode flag results using only binary arithmetic. That is what the two programs mentioned earlier do.
On the 6502, the only documented behavior is the accumulator result and the carry flag when given valid BCD numbers (i.e. both BCD digits are in the range 0-9). So, a simulator can be considered "correct" if these cases give the correct result. However, as blargg mentioned, it can be useful to replicate the undocumented behavior, since there are programs out there that use undocumented decimal mode behavior. Relying on undocumented behavior does not make for a robust program, so when such a program doesn't behave as expected on a simulator, to me, that is a problem with the program, not the simulator. Anyway, here are a couple of examples:
Example #1: distinguishing a 6502 from a 65C02.
Code: Select all
CLC
LDA #$99
ADC #$01
BEQ THIS_IS_A_65C02 ; or it's a 65802 or a 65816
BNE THIS_IS_A_6502
Incidentally, if you always cleared the Z flag in decimal mode, this particular example would still behave correctly.
Example #2: converting a hex digit 0-F to ASCII
A straightforward way to convert $00-$09 to $30-$39 and $0A-$0F to $41-$46 is:
Code: Select all
CMP #$0A
BCC SKIP
ADC #$06 ; this adds 7 since the carry is set
SKIP ADC #$30
Code: Select all
SED
CMP #$0A
ADC #$30
CLD
I can't recall any other examples off the top of my head. There is very little existing code that would be broken by not replicating undocumented behavior.
If you have additional questions feel free to ask. I've worked out all of the cases for 8-bit and 16-bit (i.e. on the 65816 when the m flag is zero) decimal mode addition and subtraction and have verified every possible combination on the 6502 (Rockwell and Synertek), the 65C02, and the 65816 works as I've described. Now if only I'd stop writing long-winded forum posts and finish the decimal mode write-up...
blargg wrote:
Undefined = not defined; it doesn't mean random. It most likely means "whatever values get put there as a result of the processor design".
There is no such thing as "undefined instructions" either. They only exist in the minds of those who claim having discovered them and should never be relied on.
I trust my somewhat flawed English is comprehensible to all.
Thanks for the responses, I have some more questions;
1. Is the accumulator converted to a BCD number if the Decimal flag is set and it contains a non decimal number?
2. With illegal opcode AAX, do you set the N and Z flags? Half the documents say yes and the other half say no.
3. How is the N flag affected on illegal opcodes that make a shift right 1-bit at the last moment? Do you check for the MSB before the shift? For example;
4. Are illegal opcodes that contain things like DEC + ADC/SBC affected by the Decimal flag? (i.e. do you check for the flag and then do the same as you would in ADC/SBC)
1. Is the accumulator converted to a BCD number if the Decimal flag is set and it contains a non decimal number?
2. With illegal opcode AAX, do you set the N and Z flags? Half the documents say yes and the other half say no.
3. How is the N flag affected on illegal opcodes that make a shift right 1-bit at the last moment? Do you check for the MSB before the shift? For example;
Code: Select all
A &= Immediate;
A >>= 1; // MSB == 0