Hey there.
I'm writing a 6502 emulator for my Arduino 2560 Mega and have ran across a bug that I think is in my bit-shifter. I actually porting the code from a Javascript emulator and adjusting it to C++ as best as I can.
The idea is that the ROL is a command that shifts all bits in an 8 bit register left one position. The Carry is shifted into bit 0 and the original bit 7 is shifted into the Carry.
Here's the case.
case 0x2a: // ROL
sf = carrySet(); //becomes 1 if carry is set, else 0
setCarryFlagFromBit7(regA); //I think this is where it's broken
regA = regA << 1; //shift everything left 1
regA += sf; //add the carry if it's there
ROR(regA); //This adjusts the status flags after the operation if the result is zero or negative (This works ok)
break;
now to define what the variables are.
#defile UMASK 0xFF //deletes the top half of my ints with an & operation
#define C_FLAG 0b00000001 //Carry Flag
int regA = 0; // "A" register
int regP = 0; //Status Register
and now the routines that support the case
int carrySet() {
return regP & C_FLAG; //returns 1 if carry is set, else 0
}
void setCarryFlagFromBit7(int value)
{
regP = (regP & ~C_FLAG) | ((value>>7)&1); //I have no idea what this is doing
}
Now for the eye-rolling stuff. Even though regP and regA are 16-bit ints, I treat them as 8-bit because I've been told that GCC will always cast any bitwise operations as a 16 bit number. I think that's what's screwing up by shifters. However, I'm trying to read the code from the javascript and I have no idea what the "meat" of the code is doing. The setCarryFlagFromBit7() function is the only code I don't understand, so I'm going to assume that it's wrong. I also have a UMASK defined as 0xFF that I often "&" with my registers to make sure that only the bottom 8 bits are ever used. I'm pretty sure I need to apply that here, but don't exactly know where.
On the flip side, the right shifter is also just as cryptic.
case 0x6a: // ROR
sf = regP&1; // save the carry
setCarryFlagFromBit0(regA); //I don't understand how this works
regA = regA >> 1; //shift regA right
if( sf ) regA |= 0x80; //don't know what it's doing here
ROR(regA); //This adjusts the status flags after the operation if the result is zero or negative (This works ok)
break;
and the support code for the right shifter
void setCarryFlagFromBit0(int value)
{
regP = (regP & ~C_FLAG) | (value&1); //no idea what this is doing either.
}
Can someone look at this and point out what is wrong/how it works/how to fix?
==EDIT==
I attached my source code for those who want to look at it.
joshxcore.ino (62.7 KB)