mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Improve linker script align (#1271)
An offset is now supported, and invalid values are no longer silently truncated, aligning behaviour with other instances of the directive.
This commit is contained in:
@@ -68,15 +68,25 @@ and
|
|||||||
.Ic DS :
|
.Ic DS :
|
||||||
.Bl -bullet
|
.Bl -bullet
|
||||||
.It
|
.It
|
||||||
.Ic ORG
|
.Ic ORG Ar addr
|
||||||
sets the address in which new sections will be placed.
|
sets the address in which new sections will be placed to
|
||||||
|
.Ar addr .
|
||||||
It can not be lower than the current address.
|
It can not be lower than the current address.
|
||||||
.It
|
.It
|
||||||
.Ic ALIGN
|
.Ic ALIGN Ar addr
|
||||||
|
or
|
||||||
|
.Ic ALIGN Ar addr , Ar offset
|
||||||
will increase the address until it is aligned to the specified boundary
|
will increase the address until it is aligned to the specified boundary
|
||||||
.Po it tries to set to 0 the number of bits specified after the directive:
|
.Po it tries to set to
|
||||||
|
.Ar offset
|
||||||
|
the number of bits specified by
|
||||||
|
.Ar align :
|
||||||
|
for example,
|
||||||
.Ql ALIGN 8
|
.Ql ALIGN 8
|
||||||
will align to $100
|
will align to $100 ,
|
||||||
|
and
|
||||||
|
.Ql ALIGN 8 , 10
|
||||||
|
will align to $10A
|
||||||
.Pc .
|
.Pc .
|
||||||
.It
|
.It
|
||||||
.Ic DS
|
.Ic DS
|
||||||
|
|||||||
@@ -51,6 +51,7 @@
|
|||||||
|
|
||||||
%token YYEOF 0 "end of file"
|
%token YYEOF 0 "end of file"
|
||||||
%token newline
|
%token newline
|
||||||
|
%token COMMA ","
|
||||||
%token ORG "ORG"
|
%token ORG "ORG"
|
||||||
INCLUDE "INCLUDE"
|
INCLUDE "INCLUDE"
|
||||||
ALIGN "ALIGN"
|
ALIGN "ALIGN"
|
||||||
@@ -83,6 +84,7 @@ directive: section_type { setSectionType($1); }
|
|||||||
| section_type number { setSectionType($1, $2); }
|
| section_type number { setSectionType($1, $2); }
|
||||||
| ORG number { setAddr($2); }
|
| ORG number { setAddr($2); }
|
||||||
| ALIGN number { alignTo($2, 0); }
|
| ALIGN number { alignTo($2, 0); }
|
||||||
|
| ALIGN number COMMA number { alignTo($2, $4); }
|
||||||
| DS number { pad($2); }
|
| DS number { pad($2); }
|
||||||
| string { placeSection($1); }
|
| string { placeSection($1); }
|
||||||
;
|
;
|
||||||
@@ -197,6 +199,8 @@ try_again: // Can't use a `do {} while(0)` loop, otherwise compilers (wrongly) t
|
|||||||
} else {
|
} else {
|
||||||
return yy::parser::make_YYEOF();
|
return yy::parser::make_YYEOF();
|
||||||
}
|
}
|
||||||
|
} else if (c == ',') {
|
||||||
|
return yy::parser::make_COMMA();
|
||||||
} else if (isNewline(c)) {
|
} else if (isNewline(c)) {
|
||||||
// Handle CRLF.
|
// Handle CRLF.
|
||||||
if (c == '\r' && context.file.sgetc() == '\n') {
|
if (c == '\r' && context.file.sgetc() == '\n') {
|
||||||
@@ -372,18 +376,37 @@ static void alignTo(uint32_t alignment, uint32_t alignOfs) {
|
|||||||
auto const &typeInfo = sectionTypeInfo[activeType];
|
auto const &typeInfo = sectionTypeInfo[activeType];
|
||||||
auto &pc = curAddr[activeType][activeBankIdx];
|
auto &pc = curAddr[activeType][activeBankIdx];
|
||||||
|
|
||||||
// TODO: maybe warn if truncating?
|
if (alignment > 16) {
|
||||||
alignOfs %= 1 << alignment;
|
scriptError(context, "Cannot align: The alignment (%" PRIu32 ") must be less than 16\n",
|
||||||
|
alignment);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let it wrap around, this'll trip the final check if alignment == 16.
|
||||||
|
uint16_t length = alignOfs - pc;
|
||||||
|
|
||||||
|
if (alignment < 16) {
|
||||||
|
uint32_t alignSize = 1u << alignment;
|
||||||
|
|
||||||
|
if (alignOfs >= alignSize) {
|
||||||
|
scriptError(context, "Cannot align: The alignment offset (%" PRIu32
|
||||||
|
") must be less than alignment size (%" PRIu32 ")\n",
|
||||||
|
alignOfs, 1 << alignment);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
assert(pc >= typeInfo.startAddr);
|
assert(pc >= typeInfo.startAddr);
|
||||||
uint16_t length = alignment < 16 ? (uint16_t)(alignOfs - pc) % (1u << alignment)
|
length %= alignSize;
|
||||||
: alignOfs - pc; // Let it wrap around, this'll trip the check.
|
|
||||||
if (uint16_t offset = pc - typeInfo.startAddr; length > typeInfo.size - offset) {
|
|
||||||
scriptError(context, "Cannot align: the next suitable address after $%04" PRIx16 " is $%04" PRIx16 ", past $%04" PRIx16,
|
|
||||||
pc, (uint16_t)(pc + length), (uint16_t)(endaddr(activeType) + 1));
|
|
||||||
} else {
|
|
||||||
pc += length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uint16_t offset = pc - typeInfo.startAddr; length > typeInfo.size - offset) {
|
||||||
|
scriptError(context, "Cannot align: the next suitable address after $%04"
|
||||||
|
PRIx16 " is $%04" PRIx16 ", past $%04" PRIx16,
|
||||||
|
pc, (uint16_t)(pc + length), (uint16_t)(endaddr(activeType) + 1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pc += length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pad(uint32_t length) {
|
static void pad(uint32_t length) {
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
error: ./section-attributes-mismatch.link(3): The linker script assigns section "sec" to address $0018, but that would be ALIGN[4, 8] instead of the requested ALIGN[4, 0]
|
error: ./section-attributes-mismatch.link(3): The linker script assigns section "sec" to address $0018, but that would be ALIGN[4, 8] instead of the requested ALIGN[4, 2]
|
||||||
Linking failed with 1 error
|
Linking failed with 1 error
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
SECTION "sec",ROM0,ALIGN[4]
|
SECTION "sec",ROM0,ALIGN[4,2]
|
||||||
ds 8, $42
|
ds 6, $42
|
||||||
SECTION "secfix",ROM0[$20]
|
SECTION "secfix",ROM0[$20]
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
ROM0
|
ROM0
|
||||||
align 4
|
align 4, 2
|
||||||
"sec"
|
"sec"
|
||||||
ds $18
|
ds $18
|
||||||
org $20
|
org $20
|
||||||
|
align 5
|
||||||
"secfix"
|
"secfix"
|
||||||
|
|||||||
Reference in New Issue
Block a user