shithub: rgbds

Download patch

ref: 665412c07352379651334fc59cb75a6661242a35
parent: 2b0c34ecb57e0187541b327020d09f41370cfe54
author: ISSOtm <[email protected]>
date: Wed Apr 8 08:28:53 EDT 2020

Implement mid-section alignment directive

Fixes #254.

--- a/include/asm/section.h
+++ b/include/asm/section.h
@@ -44,6 +44,7 @@
 
 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);
--- a/src/asm/asmy.y
+++ b/src/asm/asmy.y
@@ -774,6 +774,26 @@
 		| 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 {
--- a/src/asm/section.c
+++ b/src/asm/section.c
@@ -354,6 +354,28 @@
 	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;
--- /dev/null
+++ b/test/asm/align-pc.asm
@@ -1,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...