llvm-mos / llvm-mos-sdk

SDK for developing with the llvm-mos compiler

Home Page:https://www.llvm-mos.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[NES] Separate out `.aligned` section

mysterymath opened this issue · comments

The OAM buffer used for OAMDMA must be page aligned, which is typically much larger than the required alignment of other NES structures. This is particularly true given the NES's paucity of RAM; alignment requirements run the risk of wasting considerable space.

The general rule of thumb is to sort sections by decreasing alignment requirement; this tends to waste the least space. In this case, the OAM buffer is placed in .noinit, but it will likely have a greater alignment than the preceeding sections. That means that up to a page will be wasted aligning it.

Ideally, it would be possible to arrange the output sections by decreasing alignment, but history has not afforded us this option with GNU-compatible linker scripts. Their order is also very customary at this point, and changes to it are surprising.

Instead, a separate .oam_buf section should be created at the beginning of the common NES linker script to hold the OAM DMA buffer. It would still be up to the user whether to define anything there, but it would give an opportunity for the core libraries (and best practice) to put the OAM buffer first, which will end up placing it at 0x200. This is customary for the vast majority of commercial NES titles as well (according to @jroweboy).

Generalizing this a bit, the root of the issue is that .text, .rodata, .data, .bss, and .noinit traditionally come in that fixed order, and this is insensitive to alignment. (.noinit is an newer invention with less history, but the key here is that the order is fixed.) The x flag is irrelevant on the 6502, so .text and .rodata must be contiguous, as should .data, .bss, and .noinit. However, one would generally like the highest alignment sections to go first.

We can't effectively have more than one .data or .bss section, since they have expensive initializers. But, we could create an .early-noinit section that comes before the cluster; high alignment noinit data could be placed there to avoid wasting space.

Ah, this is a bad idea on loaded program architectures like the commodore 64. The reason for the traditional ordering is almost certainly that all of the earlier sections contain data, while the later ones do not. That mean that the program image can be contiguously copied from disk, and an early noinit section breaks that.

I think we should keep this NES-specific for now; we can generalize it later to other ROM targets if need be. We can make the naming slightly less general: .aligned_buffers.