Check my understanding of page crossing w/indexed addressing

Let's talk about anything related to the 6502 microprocessor.
Post Reply
Dan Moos
Posts: 277
Joined: 11 Mar 2017
Location: Lynden, WA

Check my understanding of page crossing w/indexed addressing

Post by Dan Moos »

Working on my emulator. I'm trying to make my instructions require the correct amount of cycles. Tell me if the following is correct.


Let's say the instruction is LDA, Absolute X addressing.

After I ingest the LSB of the address, I just check if (LSB + X) > 0xff, and if it is, I add a cycle.

Sound good?

EDIT: I realize my math isn't taking the LSB wrapping around into account. Assume my code does.

EDIT: Is the carry flag a better way to check?

EDIT:Never mind concerning the carry flag. I forgot the carry flag only changes when I tell it to (which I will in this case of course).
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: Check my understanding of page crossing w/indexed addres

Post by barrym95838 »

Dan Moos wrote:
I forgot the carry flag only changes when I tell it to (which I will in this case of course).
LDA should never affect the 65xx carry flag, regardless of addressing mode.

Regarding page-crossing indexing, the cycle counts do typically increase by one, but I seem to remember an exception or two, where the non-page-crossing timing was the same as the page-crossing timing for certain instructions. I'm link-challenged at the moment, so someone please correct me if I'm wrong.
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Check my understanding of page crossing w/indexed addres

Post by BigEd »

> I just check if (LSB + X) > 0xff, and if it is, I add a cycle.

Sounds right to me - you will of course need to be sure about signedness and byte-sizedness of your inputs there. What you're looking for is a carry from the LSB of the effective address to the MSB. (Which is unrelated to the C bit of your model.) Another way to do that, perhaps, is to see if the MSB in is different from the MSB out. Much depends on the data types in your code, as to what is efficient and maintainable.
Dan Moos
Posts: 277
Joined: 11 Mar 2017
Location: Lynden, WA

Re: Check my understanding of page crossing w/indexed addres

Post by Dan Moos »

Here's the actual code I've come up with:

Code: Select all

//LDA Absolute, X. 3 bytes 4 cycles (+1 if page cross)
if (Address_Mode == ABSOLUTE_X) { 
	uint8_t MSB, LSB, LSB_Temp;
	cycle(1);
	LSB_Temp = DataBus ;
	LSB = DataBus + X;
	cycle(1);
	MSB = DataBus;
	if (LSB < LSB_Temp) { //add cycle if page crossed
		MSB++;
		cycle(0);
	}
	cycle(0);
	AddressBus = (MSB << 8) | LSB;
	A = Memory[AddressBus];
	if (A == 0)
		PS |= ZERO_FLAG;
	else
		PS &= ~(ZERO_FLAG);
	if (A & 0b10000000)
		PS |= NEGATIVE_FLAG;
	else
		PS &= ~(NEGATIVE_FLAG);
	cycle(1);
}
seems to work. Cycle(1) advances the PC and puts it on the address bus. Cycle(0) does nothing (for now).
White Flame
Posts: 704
Joined: 24 Jul 2012

Re: Check my understanding of page crossing w/indexed addres

Post by White Flame »

Probably the best reference for writing accurate NMOS 6502 emulators is 64doc. It'll step through what goes on every single cycle of an instruction, and you can simplify from there if you're just going for total number of cycles. For instance, LDA abs,X does a redundant read if a page boundary is crossed by the indexing:

Code: Select all

  Absolute indexed addressing

     Read instructions (LDA, LDX, LDY, EOR, AND, ORA, ADC, SBC, CMP, BIT,
                        LAX, LAE, SHS, NOP)

        #   address  R/W description
       --- --------- --- ------------------------------------------
        1     PC      R  fetch opcode, increment PC
        2     PC      R  fetch low byte of address, increment PC
        3     PC      R  fetch high byte of address,
                         add index register to low address byte,
                         increment PC
        4  address+I* R  read from effective address,
                         fix the high byte of effective address
        5+ address+I  R  re-read from effective address

       Notes: I denotes either index register (X or Y).

              * The high byte of the effective address may be invalid
                at this time, i.e. it may be smaller by $100.

              + This cycle will be executed only if the effective address
                was invalid during cycle #4, i.e. page boundary was crossed.
Also, computing the N & Z flags are pretty much always done together, so creating an inline function or macro for computing those two is useful.
Post Reply