Skip to content

Commit e8e0e3f

Browse files
authored
align attribute for symbols (#480)
* Allow setting custom alignment to a symbol * black * Update docs/Adding-Symbols.md * Update docs/Adding-Symbols.md
1 parent a6d55eb commit e8e0e3f

File tree

5 files changed

+59
-2
lines changed

5 files changed

+59
-2
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
### 0.36.0
44

5+
* Add new symbol attribute: `align`.
6+
* Emit an alignment directive for the given symbol during disassembly.
7+
* The given alignment must be positive, be a power of two and The symbol's address must already be aligned to the given custom alignment, otherwise splat will emit an error and halt.
58
* New yaml option: `include_asm_macro_style`:
69
* Allows configuring the style used by the generated `INCLUDE_ASM` macro. It currently allows two possible values:
710
* `default`: Uses the default definition for the macro. This is the default.

docs/Adding-Symbols.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,29 @@ __opPCc__Q23std34_RefCountedPtr<c,Q23std9_Array<c>>CFv = 0x00202850; // filename
209209
```
210210

211211
Gets written to `func_00202850.s`
212+
213+
### `align`
214+
215+
Emit an alignment directive for the given symbol during disassembly.
216+
217+
Even though an explicit alignment directive is not necessary in most situations, it may be desirable to have one on shiftable builds of partially matched projects. This allows ensuring the symbol's required alignment even when it is still being disassembled.
218+
219+
Some situations that may require an explicit alignment directive include textures in N64 (0x8 alignment) or symbols sent to the IOP on PS2 (0x40 alignment).
220+
221+
The symbol's address must already be aligned to the given custom alignment, or the value will be discarded.
222+
223+
This value must be a power of two, otherwise it will be discarded.
224+
225+
**Example**
226+
227+
```ini
228+
rgb_texture = 0x82013118; // align:0x8
229+
```
230+
231+
Produces a disassembly similar to the following:
232+
233+
```mips
234+
.align 3
235+
dlabel rgb_texture
236+
# ...
237+
```

docs/Configuration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ Defaults to `True`, meaning `bss` sections will be put on `NOLOAD` segments.
588588

589589
Specify that segments should be aligned before starting them.
590590

591-
This option specifies the desired alignment value, or `null` if no aligment should be imposed on the segment start.
591+
This option specifies the desired alignment value, or `null` if no alignment should be imposed on the segment start.
592592

593593
This behavior can be customized per segment too. See [ld_align_segment_start](Segments.md#ld_align_segment_start) on the Segments section.
594594

docs/Segments.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ Defaults to the value of the global option.
542542

543543
Specify the current segment should be aligned before starting it.
544544

545-
This option specifies the desired alignment value, or `null` if no aligment should be imposed on the segment start.
545+
This option specifies the desired alignment value, or `null` if no alignment should be imposed on the segment start.
546546

547547
If not set, then the global configuration is used. See [ld_align_segment_start](Configuration.md#ld_align_segment_start) on the Configuration section.
548548

src/splat/util/symbols.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,28 @@ def get_seg_for_rom(rom: int) -> Optional["Segment"]:
192192
if attr_name == "function_owner":
193193
sym.function_owner = attr_val
194194
continue
195+
if attr_name == "align":
196+
align = int(attr_val, 0)
197+
198+
if align < 0:
199+
log.parsing_error_preamble(path, line_num, line)
200+
log.error(
201+
f"The given alignment for '{sym.name}' (0x{sym.vram_start:08X}) is negative."
202+
)
203+
align_shift = (align & (-align)).bit_length() - 1
204+
if (1 << align_shift) != align:
205+
log.parsing_error_preamble(path, line_num, line)
206+
log.error(
207+
f"The given alignment '0x{align:X}' for symbol '{sym.name}' (0x{sym.vram_start:08X}) is not a power of two."
208+
)
209+
if sym.vram_start % align != 0:
210+
log.parsing_error_preamble(path, line_num, line)
211+
log.error(
212+
f"The symbol '{sym.name}' (0x{sym.vram_start:08X}) is not aligned already to the given alignment '0x{align:X}'."
213+
)
214+
215+
sym.given_align = align
216+
continue
195217
except:
196218
log.parsing_error_preamble(path, line_num, line)
197219
log.write(
@@ -520,6 +542,8 @@ def add_symbol_to_spim_segment(
520542
context_sym.nameEnd = sym.given_name_end
521543
if sym.given_visibility:
522544
context_sym.visibility = sym.given_visibility
545+
if sym.given_align:
546+
context_sym.setAlignment(sym.given_align)
523547

524548
return context_sym
525549

@@ -568,6 +592,8 @@ def add_symbol_to_spim_section(
568592
context_sym.nameEnd = sym.given_name_end
569593
if sym.given_visibility:
570594
context_sym.visibility = sym.given_visibility
595+
if sym.given_align:
596+
context_sym.setAlignment(sym.given_align)
571597

572598
return context_sym
573599

@@ -667,6 +693,8 @@ class Symbol:
667693
given_filename: Optional[str] = None
668694
given_visibility: Optional[str] = None
669695

696+
given_align: Optional[int] = None
697+
670698
_generated_default_name: Optional[str] = None
671699
_last_type: Optional[str] = None
672700

0 commit comments

Comments
 (0)