Implement mid-section alignment directive

Fixes #254.
This commit is contained in:
ISSOtm
2020-04-08 12:28:53 +02:00
parent 2b0c34ecb5
commit 665412c073
7 changed files with 65 additions and 0 deletions

View File

@@ -44,6 +44,7 @@ void out_EndLoadSection(void);
struct Section *sect_GetSymbolSection(void);
uint32_t sect_GetOutputOffset(void);
void sect_AlignPC(uint8_t alignment, uint16_t offset);
void out_AbsByte(uint8_t b);
void out_AbsByteGroup(uint8_t const *s, int32_t length);

View File

@@ -774,6 +774,26 @@ simple_pseudoop : include
| popo
| pusho
| opt
| align
;
align : T_OP_ALIGN uconst {
if ($2 > 16)
yyerror("Alignment must be between 0 and 16, not %u",
$2);
else
sect_AlignPC($2, 0);
}
| T_OP_ALIGN uconst ',' uconst {
if ($2 > 16)
yyerror("Alignment must be between 0 and 16, not %u",
$2);
else if ($4 >= 1 << $2)
yyerror("Offset must be between 0 and %u, not %u",
(1 << $2) - 1, $4);
else
sect_AlignPC($2, $4);
}
;
opt : T_POP_OPT {

View File

@@ -354,6 +354,28 @@ uint32_t sect_GetOutputOffset(void)
return curOffset + loadOffset;
}
void sect_AlignPC(uint8_t alignment, uint16_t offset)
{
struct Section *sect = sect_GetSymbolSection();
if (sect->nOrg != -1) {
if ((sym_GetValue(pPCSymbol) - offset) % (1 << alignment))
yyerror("Section's fixed address fails required alignment (PC = $%04x)",
sym_GetValue(pPCSymbol));
} else if (sect->nAlign != 0) {
if ((((sect->alignOfs + curOffset) % (1 << sect->nAlign)) - offset) % (1 << alignment)) {
yyerror("Section's alignment fails required alignment (offset from section start = $%04x)",
curOffset);
} else if (alignment > sect->nAlign) {
sect->nAlign = alignment;
sect->alignOfs = (offset - curOffset) % (1 << alignment);
}
} else {
sect->nAlign = alignment;
sect->alignOfs = offset;
}
}
static inline void growSection(uint32_t growth)
{
curOffset += growth;

22
test/asm/align-pc.asm Normal file
View File

@@ -0,0 +1,22 @@
SECTION "fixed org", SRAM[$BEAD]
ds 42
static_assert @ == $BED7
align 5,$17
; Should land at $0001
SECTION "align", ROM0,ALIGN[1,1]
db 69
align 1 ; This wants to go at $0000, $0002, $0004...
; Should land at $0003
SECTION "under-aligned", ROM0,ALIGN[1,1]
dw $BEEF
align 2,1 ; This wants to go at $0001, $0005, $0009...
; Should land at $0005
SECTION "forced align", ROM0
dw $DEAD
align 2,3 ; This wants to go at $0003, $0007, $000B...

0
test/asm/align-pc.err Normal file
View File

0
test/asm/align-pc.out Normal file
View File

View File