Jump to content



0

I don't understand extra cycles for crossing Page boundaries


5 replies to this topic

#1 Propane13 ONLINE  

Propane13

    Stargunner

  • 1,385 posts
  • Location:Philly

Posted Fri May 16, 2008 11:11 PM

I'm having issues trying to understand extra cycles taken for page boundaries.

Say I have this code after a WSYNC

FunRoutine:
LDA (Temp),Y
STA GRP1
LDA (Temp2),Y
STA COLUP1

What does it mean to cross a page boundary?

Does it mean that if Temp points to $F850, the page boundary is crossed when Y = $B0 (such that we'd be on page $F9)?
Or, does it mean that the data is more than 1 page away from FunRoutine, hence the indirect-lookup is > 256 bytes away?
Or, does it mean something else?

What's the best way to make sure that extra cycle isn't taken? Is it something I can do with ALIGN 256?

Thanks!
-John

#2 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 20,458 posts
  • Location:The land of Gorch

Posted Fri May 16, 2008 11:56 PM

See also http://www.atariage....showtopic=86087

#3 Rybags ONLINE  

Rybags

    Quadrunner

  • 10,312 posts
  • Location:Australia

Posted Sat May 17, 2008 12:24 AM

It means the high byte of the effective address changes.

e.g. LDA $FEF0,X will in most cases cross a page boundary (the effective address is at $FFxx when X >=$10)

LDA ($C0),Y where $C0,C1 = $F0,$FE - same deal.

It doesn't matter at all where data is in relation to the program counter. The only case that an effective address matters in that way is with branch instructions.

#4 supercat OFFLINE  

supercat

    Quadrunner

  • 6,367 posts

Posted Sat May 17, 2008 12:27 AM

View PostPropane13, on Sat May 17, 2008 12:11 AM, said:

What does it mean to cross a page boundary?

To cross a page boundary means to access a memory location whose high byte needs to be recomputed. There are two reasons that extra cycles are necessary:

-1- On an absolute indexed or indirect indexed operation, the CPU can perform the address computation on the low byte of the address while the high byte is being fetched. There isn't enough time to do anything with the high byte before the next cycle, other than simply shoving it onto the address bus. If the next cycle is a read, the processor can allow it to proceed at what may or may not be the right address; if it turns out the address was wrong, the processor will toss out the value it just read and access the correct address on the next cycle. On a write, it's not possible to do the speculative memory access (if the processor writes the wrong location, it can't just say 'oops' and have the memory re-hold its previous contents), so the first cycle stifles the write (turning it into a read whose value is ignored) thus requiring that the write occur on the next cycle.

-2- Aside from a dedicated circuit to increment the program counter, the CPU just has one 8-bit adder which is used for all other incrementing, decrementing, etc. When a branch is taken, the CPU will compute the new value for the low byte of the program counter during the third cycle of the instruction. If the high byte of the program counter needs to be computed, the processor will have to do that on the next cycle.

Personally, I don't mind the wasted cycle on indexed-mode page crossings. The only way to eliminate the 'extra' cycle in such cases would be to slow everything down whether a page crossing occurs or not. The wasted cycle on branches is annoying, though. I wonder how much extra circuitry would have been required to eliminate it? Given that the program counter already has an increment circuit for the high byte, I think it would just require adapting it so it could decrement as well.

#5 Propane13 ONLINE  

Propane13

    Stargunner

  • 1,385 posts
  • Location:Philly

Posted Sun May 18, 2008 8:11 AM

Ok; I get it now! Thanks to everyone for their info.

This brings me to a follow-up question.
I have some data that looks like the following

DataA
.byte SomeNumber (40 of these)

DataB
.byte SomeNumber (40 of these)

DataC
.byte SomeNumber (40 of these)

etc...

I want to make sure that these sections of data do not cross page boundaries.

The simple way to do this is to group these into sets of 6 (6x40 = 240, < 256), and use ALIGN 256
However, this is space inefficient-- my first block will be forced to re-align to a new page, when it may be fine (halfway down the previous page, for example).
So, I may need to constantly tweak ALIGN locations depending on how the rest of my code space moves.
What I was thinking would be nice would be something like this:

if <the next X bytes do not cross a page boundary then ALIGN 256
DataA
.byte SomeNumber (X of these)
endif

That way, my code dynamically adjusts its data for page boundaries, and I don't have to put these code in fixed locations right away.

Does DASM have anything like this? Personally, I think this would be very useful.
If not, could this be done with a macro? Possibly checking the result of X minus the value of DataA's LSB and seeing if it's negative (and if so, do an ALIGN 256)?

Thanks!
-John

#6 supercat OFFLINE  

supercat

    Quadrunner

  • 6,367 posts

Posted Sun May 18, 2008 11:47 AM

View PostPropane13, on Sun May 18, 2008 8:11 AM, said:

I want to make sure that these sections of data do not cross page boundaries.

I use:
				mac	 pcheck
				if ([*-1] ^ {1}) & $FF00
				echo "PCHECK: PAGE CROSSING","WARNING ",{1}," at ",*
				endif
				endm
Use the pcheck macro at the end of an area which should fit within a page, and give it a pointer to the start of the area.

Another possibility is to use my pagesafe macro:
wastage .set 0
				mac	 pagesafe
				if (* & $FF)+{1} > 255
				echo "Wasting ",(256-*) & $FF," bytes at ",(*+255) & $FF00
wastage .set wastage+((256-*) & $FF)
				ds (256-*) & $FF
				endif
				endm
Use the pagesafe macro before an area that should fit within a page, and give it the number of bytes in that area. It will start a new page if necessary, and keep a count of how many bytes have been skipped.

Both macros will require you to do some manual shuffling to actually obtain optimal distribution. They reduce considerably the amount of work required, though.

Incidentally, I also define macros for branches, e.g.
				mac	 sbne
				bne	 {1}
				if (* ^ {1}) & $FF00
				echo "PAGE CROSSING","WARNING ",{1}," at ",*
				endif
				endm

Unfortunately, these macros don't seem to work with local labels.

BTW, the reason I use "PAGE CROSSING" and "WARNING" as separate arguments is that doing so makes it possible to search the listing file for "G WA" since the "PAGE CROSSING WARNING" message is not contained intact within the macros themselves.




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users