How effecient is ld65 at packing aligned symbols?

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

Post Reply
spaceharrier
Posts: 40
Joined: Wed Jan 19, 2022 9:52 am

How effecient is ld65 at packing aligned symbols?

Post by spaceharrier »

I have about a handful of spots in my code in which I pack a bunch of functions onto the same 256-byte aligned page, as per the following example:

Code: Select all


foo_jump: .byte <foo1, <foo2, <foo3, ...
bar_jump: .byte <foo1, <foo2, <foo3, ...

.align $100

foo1: ...
foo2: ...
foo3: ...

...... other code

.align $100
bar1: ...
bar2: ...
bar3: ...


This is so that I only need to update a jump pointer's low byte. Should I place these aligned sections sequentially in the source file and move the code in-between, or is the linker smart enough to try to efficiently pack them?
calima
Posts: 1745
Joined: Tue Oct 06, 2015 10:16 am

Re: How effecient is ld65 at packing aligned symbols?

Post by calima »

It doesn't have any support for packing. It just sequentially places.
User avatar
rainwarrior
Posts: 8731
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: How effecient is ld65 at packing aligned symbols?

Post by rainwarrior »

ld65 doesn't re-order anything. It will all go into the output in the order of memory regions, then segments within those memory regions, then in the order of linked files, then in the order within the file.

However, there's probably a few more options available to you to help manage this.

If the tables aren't more than 128 bytes in size, you might try a smaller align (e.g. 8 or 16 or 32) that demands less padding.

Another way to do this is create one aligned segment, use .align on the first block, but then just put asserts on everything that follows instead of aligning each one. That way the linker will give an error whenever a page crossing is created, and you can manually add padding, or find useful material to use in the padded space.

This is a trial-and-error approach, but by keeping all the stuff that needs to be aligned together and separate, I have found that the amount of times this kind of thing needs to be manually re-padded are usually very few. The advantage is that with fewer things using an explicit .align, a lot of stuff like this can more efficiently fit into the middle of a page.

Something like this:

Code: Select all

.segment "ALIGNED"
.align 256
block1: ...

.segment "CODE"
... ; this code can be modified without worrying about disturbing the aligned stuff

.segment "ALIGNED"
block2: ...
.assert (>*)=(>block2), error, "block2 page crossing"
; with the assert, it doesn't really matter where block2 starts, as long as it's anywhere within the page

.segment "CODE"
...

.segment "ALIGNED"
; maybe block3 ended up asserting at first,  so we manually pad by relocating some other code/data here
...

.align 256 ; automatically pad the remaining bytes to re-align
block3: ...
.assert (>*)=(>block3), error, "block3 page crossing"

.segment "CODE"
...

.segment "ALIGNED"
; for aligned code, usually necessary for timing page crossings, often the affected branches only span a few bytes.
; in cases like this, often the branches are fine, or only need a tiny amount of padding to find a suitable place for the code.
.res 3 ; manually pad by 3 bytes
func1:
    ldx #55
:
    asl
    dex
    beq :-
    .assert (>*)=(>:-), error, "page crossing"
    rts
Post Reply