Bit shifting

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)

Hello,

halkun:
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.

Why do you believe there is a bug there?

I'm running an assembly Monitor written in 6502 machine code on the device, and the parts that use the bit shifters are not giving the expected results. For example, there is a function that prints out the binary representation of the status flag by rotating through a copy of it and printing a 1 when the carry is set and 0 when its not.

Also, I don't like having code that I don't understand. So even if the shifters are working right, I would like to know why.

There are other errors too, that I think are edge-case 1-off errors. I'm looking into those too. These might be the things generating the errors too, I just wanted to start with the that was most likely that I didn't understand.

halkun:
I've been told that GCC will always cast any bitwise operations as a 16 bit number.

Where were you told that?

Ach. The old 6502. I think that was the first chip I wrote machine code for.

	regP = (regP & ~C_FLAG) | ((value>>7)&1);   //I have no idea what this is doing

~C_FLAG --> perform a bitwise-not on the value --> 0b11111110

(regP & ~C_FLAG) --> perform a bitwise-and --> regP & 0b11111110 --> the least significant bit is forced to zero

value>>7 --> bitwise-shift value to the right 7 bits; move bit 7 to bit 0

((value>>7)&1) --> bitwise-and --> isolate bit 0; all the other bits become zero

(regP & ~C_FLAG) | ((value>>7)&1) --> force regP bit 0 to be zero; move value bit 7 to bit 0; isolate it; combine the two values using a bitwise-or

Looks correct to me.

Looks correct to me.

And to me.

I recommend you use type uint8_t (8 bit unsigned) for the registers. Yes, they will get promoted to 16 bits when you do arithmetic or logical operation on them, but at least you know that the top byte starts out as zero. As it stands, your right shift code is incorrect unless you can guarantee that the top byte of the regA is zero at the start.

Right-shifting signed values is banned by typical C coding standards, because the value of the bits shifted into the top is implementation-dependent if the initial value is negative.