mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-21 02:32:06 +00:00
Run clang-format on everything (#1332)
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#include "link/sdas_obj.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
@@ -12,20 +14,19 @@
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include "linkdefs.hpp"
|
||||
#include "helpers.hpp"
|
||||
#include "linkdefs.hpp"
|
||||
#include "platform.hpp"
|
||||
|
||||
#include "link/assign.hpp"
|
||||
#include "link/main.hpp"
|
||||
#include "link/sdas_obj.hpp"
|
||||
#include "link/section.hpp"
|
||||
#include "link/symbol.hpp"
|
||||
|
||||
enum NumberType {
|
||||
HEX = 16, // X
|
||||
DEC = 10, // D
|
||||
OCT = 8, // Q
|
||||
OCT = 8, // Q
|
||||
};
|
||||
|
||||
static void consumeLF(FileStackNode const &where, uint32_t lineNo, FILE *file) {
|
||||
@@ -35,8 +36,8 @@ static void consumeLF(FileStackNode const &where, uint32_t lineNo, FILE *file) {
|
||||
|
||||
static char const *delim = " \f\n\r\t\v"; // Whitespace according to the C and POSIX locales
|
||||
|
||||
static int nextLine(std::vector<char> &lineBuf, uint32_t &lineNo,
|
||||
FileStackNode const &where, FILE *file) {
|
||||
static int
|
||||
nextLine(std::vector<char> &lineBuf, uint32_t &lineNo, FileStackNode const &where, FILE *file) {
|
||||
retry:
|
||||
++lineNo;
|
||||
int firstChar = getc(file);
|
||||
@@ -91,7 +92,9 @@ static uint32_t readNumber(char const *str, char const *&endptr, enum NumberType
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t parseNumber(FileStackNode const &where, uint32_t lineNo, char const *str, enum NumberType base) {
|
||||
static uint32_t parseNumber(
|
||||
FileStackNode const &where, uint32_t lineNo, char const *str, enum NumberType base
|
||||
) {
|
||||
if (str[0] == '\0')
|
||||
fatal(&where, lineNo, "Expected number, got empty string");
|
||||
|
||||
@@ -103,7 +106,8 @@ static uint32_t parseNumber(FileStackNode const &where, uint32_t lineNo, char co
|
||||
return res;
|
||||
}
|
||||
|
||||
static uint8_t parseByte(FileStackNode const &where, uint32_t lineNo, char const *str, enum NumberType base) {
|
||||
static uint8_t
|
||||
parseByte(FileStackNode const &where, uint32_t lineNo, char const *str, enum NumberType base) {
|
||||
uint32_t num = parseNumber(where, lineNo, str, base);
|
||||
|
||||
if (num > UINT8_MAX)
|
||||
@@ -113,49 +117,58 @@ static uint8_t parseByte(FileStackNode const &where, uint32_t lineNo, char const
|
||||
|
||||
enum AreaFlags {
|
||||
AREA_TYPE = 2, // 0: Concatenate, 1: overlay
|
||||
AREA_ISABS, // 0: Relative (???) address, 1: absolute address
|
||||
AREA_PAGING, // Unsupported
|
||||
AREA_ISABS, // 0: Relative (???) address, 1: absolute address
|
||||
AREA_PAGING, // Unsupported
|
||||
|
||||
AREA_ALL_FLAGS = 1 << AREA_TYPE | 1 << AREA_ISABS | 1 << AREA_PAGING,
|
||||
};
|
||||
|
||||
enum RelocFlags {
|
||||
RELOC_SIZE, // 0: 16-bit, 1: 8-bit
|
||||
RELOC_ISSYM, // 0: Area, 1: Symbol
|
||||
RELOC_ISPCREL, // 0: Normal, 1: PC-relative
|
||||
RELOC_EXPR16, // Only for 8-bit size; 0: 8-bit expr, 1: 16-bit expr
|
||||
RELOC_SIGNED, // 0: signed, 1: unsigned
|
||||
RELOC_ZPAGE, // Unsupported
|
||||
RELOC_NPAGE, // Unsupported
|
||||
RELOC_SIZE, // 0: 16-bit, 1: 8-bit
|
||||
RELOC_ISSYM, // 0: Area, 1: Symbol
|
||||
RELOC_ISPCREL, // 0: Normal, 1: PC-relative
|
||||
RELOC_EXPR16, // Only for 8-bit size; 0: 8-bit expr, 1: 16-bit expr
|
||||
RELOC_SIGNED, // 0: signed, 1: unsigned
|
||||
RELOC_ZPAGE, // Unsupported
|
||||
RELOC_NPAGE, // Unsupported
|
||||
RELOC_WHICHBYTE, // 8-bit size with 16-bit expr only; 0: LOW(), 1: HIGH()
|
||||
RELOC_EXPR24, // Only for 8-bit size; 0: follow RELOC_EXPR16, 1: 24-bit expr
|
||||
RELOC_BANKBYTE, // 8-bit size with 24-bit expr only; 0: follow RELOC_WHICHBYTE, 1: BANK()
|
||||
RELOC_EXPR24, // Only for 8-bit size; 0: follow RELOC_EXPR16, 1: 24-bit expr
|
||||
RELOC_BANKBYTE, // 8-bit size with 24-bit expr only; 0: follow RELOC_WHICHBYTE, 1: BANK()
|
||||
|
||||
RELOC_ALL_FLAGS = 1 << RELOC_SIZE | 1 << RELOC_ISSYM | 1 << RELOC_ISPCREL | 1 << RELOC_EXPR16
|
||||
| 1 << RELOC_SIGNED | 1 << RELOC_ZPAGE | 1 << RELOC_NPAGE | 1 << RELOC_WHICHBYTE
|
||||
| 1 << RELOC_EXPR24 | 1 << RELOC_BANKBYTE,
|
||||
| 1 << RELOC_SIGNED | 1 << RELOC_ZPAGE | 1 << RELOC_NPAGE
|
||||
| 1 << RELOC_WHICHBYTE | 1 << RELOC_EXPR24 | 1 << RELOC_BANKBYTE,
|
||||
};
|
||||
|
||||
void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol> &fileSymbols) {
|
||||
std::vector<char> line(256);
|
||||
char const *token;
|
||||
|
||||
#define getToken(ptr, ...) do { \
|
||||
token = strtok((ptr), delim); \
|
||||
if (!token) \
|
||||
fatal(&where, lineNo, __VA_ARGS__); \
|
||||
} while (0)
|
||||
#define expectEol(...) do { \
|
||||
token = strtok(nullptr, delim); \
|
||||
if (token) \
|
||||
fatal(&where, lineNo, __VA_ARGS__); \
|
||||
} while (0)
|
||||
#define expectToken(expected, lineType) do { \
|
||||
getToken(nullptr, "'%c' line is too short", (lineType)); \
|
||||
if (strcasecmp(token, (expected)) != 0) \
|
||||
fatal(&where, lineNo, "Malformed '%c' line: expected \"%s\", got \"%s\"", \
|
||||
(lineType), (expected), token); \
|
||||
} while (0)
|
||||
#define getToken(ptr, ...) \
|
||||
do { \
|
||||
token = strtok((ptr), delim); \
|
||||
if (!token) \
|
||||
fatal(&where, lineNo, __VA_ARGS__); \
|
||||
} while (0)
|
||||
#define expectEol(...) \
|
||||
do { \
|
||||
token = strtok(nullptr, delim); \
|
||||
if (token) \
|
||||
fatal(&where, lineNo, __VA_ARGS__); \
|
||||
} while (0)
|
||||
#define expectToken(expected, lineType) \
|
||||
do { \
|
||||
getToken(nullptr, "'%c' line is too short", (lineType)); \
|
||||
if (strcasecmp(token, (expected)) != 0) \
|
||||
fatal( \
|
||||
&where, \
|
||||
lineNo, \
|
||||
"Malformed '%c' line: expected \"%s\", got \"%s\"", \
|
||||
(lineType), \
|
||||
(expected), \
|
||||
token \
|
||||
); \
|
||||
} while (0)
|
||||
|
||||
uint32_t lineNo = 0;
|
||||
int lineType = nextLine(line, lineNo, where, file);
|
||||
@@ -175,8 +188,12 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
numberType = OCT;
|
||||
break;
|
||||
default:
|
||||
fatal(&where, lineNo, "This does not look like a SDCC object file (unknown integer format '%c')",
|
||||
lineType);
|
||||
fatal(
|
||||
&where,
|
||||
lineNo,
|
||||
"This does not look like a SDCC object file (unknown integer format '%c')",
|
||||
lineType
|
||||
);
|
||||
}
|
||||
|
||||
switch (line[0]) {
|
||||
@@ -237,9 +254,10 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
|
||||
case 'A': {
|
||||
if (fileSections.size() == expectedNbAreas)
|
||||
warning(&where, lineNo, "Got more 'A' lines than the expected %" PRIu32,
|
||||
expectedNbAreas);
|
||||
Section *curSection = new(std::nothrow) Section();
|
||||
warning(
|
||||
&where, lineNo, "Got more 'A' lines than the expected %" PRIu32, expectedNbAreas
|
||||
);
|
||||
Section *curSection = new (std::nothrow) Section();
|
||||
|
||||
if (!curSection)
|
||||
fatal(&where, lineNo, "Failed to alloc new area: %s", strerror(errno));
|
||||
@@ -249,12 +267,11 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
// The following is required for fragment offsets to be reliably predicted
|
||||
for (FileSection &entry : fileSections) {
|
||||
if (!strcmp(token, entry.section->name.c_str()))
|
||||
fatal(&where, lineNo, "Area \"%s\" already defined earlier",
|
||||
token);
|
||||
fatal(&where, lineNo, "Area \"%s\" already defined earlier", token);
|
||||
}
|
||||
char const *sectionName = token; // We'll deal with the section's name depending on type
|
||||
|
||||
fileSections.push_back({ .section = curSection, .writeIndex = 0 });
|
||||
fileSections.push_back({.section = curSection, .writeIndex = 0});
|
||||
|
||||
expectToken("size", 'A');
|
||||
|
||||
@@ -263,8 +280,12 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
uint32_t tmp = parseNumber(where, lineNo, token, numberType);
|
||||
|
||||
if (tmp > UINT16_MAX)
|
||||
fatal(&where, lineNo, "Area \"%s\" is larger than the GB address space!?",
|
||||
curSection->name.c_str());
|
||||
fatal(
|
||||
&where,
|
||||
lineNo,
|
||||
"Area \"%s\" is larger than the GB address space!?",
|
||||
curSection->name.c_str()
|
||||
);
|
||||
curSection->size = tmp;
|
||||
|
||||
expectToken("flags", 'A');
|
||||
@@ -276,7 +297,8 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
curSection->isAddressFixed = tmp & (1 << AREA_ISABS);
|
||||
curSection->isBankFixed = curSection->isAddressFixed;
|
||||
curSection->modifier = curSection->isAddressFixed || (tmp & (1 << AREA_TYPE))
|
||||
? SECTION_NORMAL : SECTION_FRAGMENT;
|
||||
? SECTION_NORMAL
|
||||
: SECTION_FRAGMENT;
|
||||
// If the section is absolute, its name might not be unique; thus, mangle the name
|
||||
if (curSection->modifier == SECTION_NORMAL) {
|
||||
curSection->name.append(where.name());
|
||||
@@ -320,7 +342,7 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
} else {
|
||||
curSection->type = SECTTYPE_INVALID; // This means "indeterminate"
|
||||
}
|
||||
curSection->isAlignFixed = false; // No such concept!
|
||||
curSection->isAlignFixed = false; // No such concept!
|
||||
curSection->fileSymbols = &fileSymbols; // IDs are instead per-section
|
||||
curSection->nextu = nullptr;
|
||||
break;
|
||||
@@ -328,8 +350,12 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
|
||||
case 'S': {
|
||||
if (fileSymbols.size() == expectedNbSymbols)
|
||||
warning(&where, lineNo, "Got more 'S' lines than the expected %" PRIu32,
|
||||
expectedNbSymbols);
|
||||
warning(
|
||||
&where,
|
||||
lineNo,
|
||||
"Got more 'S' lines than the expected %" PRIu32,
|
||||
expectedNbSymbols
|
||||
);
|
||||
Symbol &symbol = fileSymbols.emplace_back();
|
||||
|
||||
// Init other members
|
||||
@@ -347,16 +373,11 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
// Symbols in sections are labels; their value is an offset
|
||||
Section *section = fileSections.back().section;
|
||||
if (section->isAddressFixed) {
|
||||
assert(value >= section->org &&
|
||||
value <= section->org + section->size);
|
||||
assert(value >= section->org && value <= section->org + section->size);
|
||||
value -= section->org;
|
||||
}
|
||||
symbol.data = Label{
|
||||
// No need to set the `sectionID`, since we set the pointer
|
||||
.sectionID = 0,
|
||||
.offset = value,
|
||||
.section = section
|
||||
};
|
||||
// No need to set the `sectionID`, since we set the pointer
|
||||
symbol.data = Label{.sectionID = 0, .offset = value, .section = section};
|
||||
} else {
|
||||
// Symbols without sections are just constants
|
||||
symbol.data = value;
|
||||
@@ -377,23 +398,30 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
// The same symbol can only be defined twice if neither
|
||||
// definition is in a floating section
|
||||
auto visitor = Visitor{
|
||||
[](int32_t value) -> std::tuple<Section *, int32_t> {
|
||||
return {nullptr, value};
|
||||
},
|
||||
[](Label label) -> std::tuple<Section *, int32_t> {
|
||||
return {label.section, label.offset};
|
||||
}
|
||||
[](int32_t value) -> std::tuple<Section *, int32_t> {
|
||||
return {nullptr, value};
|
||||
},
|
||||
[](Label label) -> std::tuple<Section *, int32_t> {
|
||||
return {label.section, label.offset};
|
||||
},
|
||||
};
|
||||
auto [symbolSection, symbolValue] = std::visit(visitor, symbol.data);
|
||||
auto [otherSection, otherValue] = std::visit(visitor, other->data);
|
||||
|
||||
|
||||
if ((otherSection && !otherSection->isAddressFixed)
|
||||
|| (symbolSection && !symbolSection->isAddressFixed)) {
|
||||
sym_AddSymbol(symbol); // This will error out
|
||||
} else if (otherValue != symbolValue) {
|
||||
error(&where, lineNo,
|
||||
"Definition of \"%s\" conflicts with definition in %s (%" PRId32 " != %" PRId32 ")",
|
||||
symbol.name.c_str(), other->objFileName, symbolValue, otherValue);
|
||||
error(
|
||||
&where,
|
||||
lineNo,
|
||||
"Definition of \"%s\" conflicts with definition in %s (%" PRId32
|
||||
" != %" PRId32 ")",
|
||||
symbol.name.c_str(),
|
||||
other->objFileName,
|
||||
symbolValue,
|
||||
otherValue
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Add a new definition
|
||||
@@ -443,8 +471,13 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
getToken(nullptr, "'R' line is too short");
|
||||
areaIdx |= (uint16_t)parseByte(where, lineNo, token, numberType) << 8;
|
||||
if (areaIdx >= fileSections.size())
|
||||
fatal(&where, lineNo, "'R' line references area #%" PRIu16 ", but there are only %zu (so far)",
|
||||
areaIdx, fileSections.size());
|
||||
fatal(
|
||||
&where,
|
||||
lineNo,
|
||||
"'R' line references area #%" PRIu16 ", but there are only %zu (so far)",
|
||||
areaIdx,
|
||||
fileSections.size()
|
||||
);
|
||||
assert(!fileSections.empty()); // There should be at least one, from the above check
|
||||
Section *section = fileSections[areaIdx].section;
|
||||
uint16_t *writeIndex = &fileSections[areaIdx].writeIndex;
|
||||
@@ -453,16 +486,29 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
|
||||
if (section->isAddressFixed) {
|
||||
if (addr < section->org)
|
||||
fatal(&where, lineNo, "'T' line reports address $%04" PRIx16 " in \"%s\", which starts at $%04" PRIx16,
|
||||
addr, section->name.c_str(), section->org);
|
||||
fatal(
|
||||
&where,
|
||||
lineNo,
|
||||
"'T' line reports address $%04" PRIx16
|
||||
" in \"%s\", which starts at $%04" PRIx16,
|
||||
addr,
|
||||
section->name.c_str(),
|
||||
section->org
|
||||
);
|
||||
addr -= section->org;
|
||||
}
|
||||
// Lines are emitted that violate this check but contain no "payload";
|
||||
// ignore those. "Empty" lines shouldn't trigger allocation, either.
|
||||
if (data.size() != ADDR_SIZE) {
|
||||
if (addr != *writeIndex)
|
||||
fatal(&where, lineNo, "'T' lines which don't append to their section are not supported (%" PRIu16 " != %" PRIu16 ")",
|
||||
addr, *writeIndex);
|
||||
fatal(
|
||||
&where,
|
||||
lineNo,
|
||||
"'T' lines which don't append to their section are not supported (%" PRIu16
|
||||
" != %" PRIu16 ")",
|
||||
addr,
|
||||
*writeIndex
|
||||
);
|
||||
if (section->data.empty()) {
|
||||
assert(section->size != 0);
|
||||
section->data.resize(section->size);
|
||||
@@ -487,18 +533,29 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
|
||||
if ((flags & 0xF0) == 0xF0) {
|
||||
getToken(nullptr, "Incomplete relocation");
|
||||
flags = (flags & 0x0F) | (uint16_t)parseByte(where, lineNo, token, numberType) << 4;
|
||||
flags =
|
||||
(flags & 0x0F) | (uint16_t)parseByte(where, lineNo, token, numberType) << 4;
|
||||
}
|
||||
|
||||
getToken(nullptr, "Incomplete relocation");
|
||||
uint8_t offset = parseByte(where, lineNo, token, numberType);
|
||||
|
||||
if (offset < ADDR_SIZE)
|
||||
fatal(&where, lineNo, "Relocation index cannot point to header (%" PRIu16 " < %u)",
|
||||
offset, ADDR_SIZE);
|
||||
fatal(
|
||||
&where,
|
||||
lineNo,
|
||||
"Relocation index cannot point to header (%" PRIu16 " < %u)",
|
||||
offset,
|
||||
ADDR_SIZE
|
||||
);
|
||||
if (offset >= data.size())
|
||||
fatal(&where, lineNo, "Relocation index is out of bounds (%" PRIu16 " >= %zu)",
|
||||
offset, data.size());
|
||||
fatal(
|
||||
&where,
|
||||
lineNo,
|
||||
"Relocation index is out of bounds (%" PRIu16 " >= %zu)",
|
||||
offset,
|
||||
data.size()
|
||||
);
|
||||
|
||||
getToken(nullptr, "Incomplete relocation");
|
||||
uint16_t idx = parseByte(where, lineNo, token, numberType);
|
||||
@@ -520,11 +577,17 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
patch.offset = offset - writtenOfs + *writeIndex;
|
||||
if (section->patches.size() > 1) {
|
||||
uint32_t prevOffset = section->patches[section->patches.size() - 2].offset;
|
||||
if (prevOffset>= patch.offset)
|
||||
fatal(&where, lineNo, "Relocs not sorted by offset are not supported (%" PRIu32 " >= %" PRIu32 ")",
|
||||
prevOffset, patch.offset);
|
||||
if (prevOffset >= patch.offset)
|
||||
fatal(
|
||||
&where,
|
||||
lineNo,
|
||||
"Relocs not sorted by offset are not supported (%" PRIu32 " >= %" PRIu32
|
||||
")",
|
||||
prevOffset,
|
||||
patch.offset
|
||||
);
|
||||
}
|
||||
patch.pcSection = section; // No need to fill `pcSectionID`, then
|
||||
patch.pcSection = section; // No need to fill `pcSectionID`, then
|
||||
patch.pcOffset = patch.offset - 1; // For `jr`s
|
||||
|
||||
patch.type = (flags & 1 << RELOC_SIZE) ? PATCHTYPE_BYTE : PATCHTYPE_WORD;
|
||||
@@ -533,8 +596,13 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
|
||||
assert(offset < data.size());
|
||||
if (data.size() - offset < nbBaseBytes)
|
||||
fatal(&where, lineNo, "Reloc would patch out of bounds (%" PRIu8 " > %zu)",
|
||||
nbBaseBytes, data.size() - offset);
|
||||
fatal(
|
||||
&where,
|
||||
lineNo,
|
||||
"Reloc would patch out of bounds (%" PRIu8 " > %zu)",
|
||||
nbBaseBytes,
|
||||
data.size() - offset
|
||||
);
|
||||
for (uint8_t i = 0; i < nbBaseBytes; ++i)
|
||||
baseValue = baseValue | data[offset + i] << (8 * i);
|
||||
|
||||
@@ -542,8 +610,13 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
// Generate a RPN expression from the info and flags
|
||||
if (flags & 1 << RELOC_ISSYM) {
|
||||
if (idx >= fileSymbols.size())
|
||||
fatal(&where, lineNo, "Reloc refers to symbol #%" PRIu16 " out of %zu",
|
||||
idx, fileSymbols.size());
|
||||
fatal(
|
||||
&where,
|
||||
lineNo,
|
||||
"Reloc refers to symbol #%" PRIu16 " out of %zu",
|
||||
idx,
|
||||
fileSymbols.size()
|
||||
);
|
||||
Symbol const &sym = fileSymbols[idx];
|
||||
|
||||
// SDCC has a bunch of "magic symbols" that start with a
|
||||
@@ -552,13 +625,18 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
if (sym.name.starts_with("b_")) {
|
||||
// Look for the symbol being referenced, and use its index instead
|
||||
for (idx = 0; idx < fileSymbols.size(); ++idx) {
|
||||
if (sym.name.ends_with(fileSymbols[idx].name) &&
|
||||
1 + sym.name.length() == fileSymbols[idx].name.length())
|
||||
if (sym.name.ends_with(fileSymbols[idx].name)
|
||||
&& 1 + sym.name.length() == fileSymbols[idx].name.length())
|
||||
break;
|
||||
}
|
||||
if (idx == fileSymbols.size())
|
||||
fatal(&where, lineNo, "\"%s\" is missing a reference to \"%s\"",
|
||||
sym.name.c_str(), &sym.name.c_str()[1]);
|
||||
fatal(
|
||||
&where,
|
||||
lineNo,
|
||||
"\"%s\" is missing a reference to \"%s\"",
|
||||
sym.name.c_str(),
|
||||
&sym.name.c_str()[1]
|
||||
);
|
||||
patch.rpnExpression.resize(5);
|
||||
patch.rpnExpression[0] = RPN_BANK_SYM;
|
||||
patch.rpnExpression[1] = idx;
|
||||
@@ -568,11 +646,19 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
} else if (sym.name.starts_with("l_")) {
|
||||
patch.rpnExpression.resize(1 + sym.name.length() - 2 + 1);
|
||||
patch.rpnExpression[0] = RPN_SIZEOF_SECT;
|
||||
memcpy((char *)&patch.rpnExpression[1], &sym.name.c_str()[2], sym.name.length() - 2 + 1);
|
||||
memcpy(
|
||||
(char *)&patch.rpnExpression[1],
|
||||
&sym.name.c_str()[2],
|
||||
sym.name.length() - 2 + 1
|
||||
);
|
||||
} else if (sym.name.starts_with("s_")) {
|
||||
patch.rpnExpression.resize(1 + sym.name.length() - 2 + 1);
|
||||
patch.rpnExpression[0] = RPN_STARTOF_SECT;
|
||||
memcpy((char *)&patch.rpnExpression[1], &sym.name.c_str()[2], sym.name.length() - 2 + 1);
|
||||
memcpy(
|
||||
(char *)&patch.rpnExpression[1],
|
||||
&sym.name.c_str()[2],
|
||||
sym.name.length() - 2 + 1
|
||||
);
|
||||
} else {
|
||||
patch.rpnExpression.resize(5);
|
||||
patch.rpnExpression[0] = RPN_SYM;
|
||||
@@ -583,8 +669,13 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
}
|
||||
} else {
|
||||
if (idx >= fileSections.size())
|
||||
fatal(&where, lineNo, "Reloc refers to area #%" PRIu16 " out of %zu",
|
||||
idx, fileSections.size());
|
||||
fatal(
|
||||
&where,
|
||||
lineNo,
|
||||
"Reloc refers to area #%" PRIu16 " out of %zu",
|
||||
idx,
|
||||
fileSections.size()
|
||||
);
|
||||
// It gets funky. If the area is absolute, *actually*, we
|
||||
// must not add its base address, as the assembler will
|
||||
// already have added it in `baseValue`.
|
||||
@@ -625,10 +716,18 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
// are present, so we must skip two of them
|
||||
if (flags & 1 << RELOC_EXPR16) {
|
||||
if (*writeIndex + (offset - writtenOfs) > section->size)
|
||||
fatal(&where, lineNo, "'T' line writes past \"%s\"'s end (%u > %" PRIu16 ")",
|
||||
section->name.c_str(), *writeIndex + (offset - writtenOfs), section->size);
|
||||
fatal(
|
||||
&where,
|
||||
lineNo,
|
||||
"'T' line writes past \"%s\"'s end (%u > %" PRIu16 ")",
|
||||
section->name.c_str(),
|
||||
*writeIndex + (offset - writtenOfs),
|
||||
section->size
|
||||
);
|
||||
// Copy all bytes up to those (plus the byte that we'll overwrite)
|
||||
memcpy(§ion->data[*writeIndex], &data[writtenOfs], offset - writtenOfs + 1);
|
||||
memcpy(
|
||||
§ion->data[*writeIndex], &data[writtenOfs], offset - writtenOfs + 1
|
||||
);
|
||||
*writeIndex += offset - writtenOfs + 1;
|
||||
writtenOfs = offset + 3; // Skip all three `baseValue` bytes, though
|
||||
}
|
||||
@@ -644,7 +743,9 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
patch.rpnExpression.push_back(16 >> 8);
|
||||
patch.rpnExpression.push_back(16 >> 16);
|
||||
patch.rpnExpression.push_back(16 >> 24);
|
||||
patch.rpnExpression.push_back((flags & 1 << RELOC_SIGNED) ? RPN_SHR : RPN_USHR);
|
||||
patch.rpnExpression.push_back(
|
||||
(flags & 1 << RELOC_SIGNED) ? RPN_SHR : RPN_USHR
|
||||
);
|
||||
} else {
|
||||
if (flags & 1 << RELOC_EXPR16 && flags & 1 << RELOC_WHICHBYTE) {
|
||||
patch.rpnExpression.push_back(RPN_CONST);
|
||||
@@ -652,7 +753,9 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
patch.rpnExpression.push_back(8 >> 8);
|
||||
patch.rpnExpression.push_back(8 >> 16);
|
||||
patch.rpnExpression.push_back(8 >> 24);
|
||||
patch.rpnExpression.push_back((flags & 1 << RELOC_SIGNED) ? RPN_SHR : RPN_USHR);
|
||||
patch.rpnExpression.push_back(
|
||||
(flags & 1 << RELOC_SIGNED) ? RPN_SHR : RPN_USHR
|
||||
);
|
||||
}
|
||||
patch.rpnExpression.push_back(RPN_CONST);
|
||||
patch.rpnExpression.push_back(0xFF);
|
||||
@@ -665,8 +768,12 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
assert(patch.type == PATCHTYPE_WORD);
|
||||
fatal(&where, lineNo, "16-bit PC-relative relocations are not supported");
|
||||
} else if (flags & (1 << RELOC_EXPR16 | 1 << RELOC_EXPR24)) {
|
||||
fatal(&where, lineNo, "Flags 0x%x are not supported for 16-bit relocs",
|
||||
flags & (1 << RELOC_EXPR16 | 1 << RELOC_EXPR24));
|
||||
fatal(
|
||||
&where,
|
||||
lineNo,
|
||||
"Flags 0x%x are not supported for 16-bit relocs",
|
||||
flags & (1 << RELOC_EXPR16 | 1 << RELOC_EXPR24)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -674,8 +781,14 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
if (writtenOfs != data.size()) {
|
||||
assert(data.size() > writtenOfs);
|
||||
if (*writeIndex + (data.size() - writtenOfs) > section->size)
|
||||
fatal(&where, lineNo, "'T' line writes past \"%s\"'s end (%zu > %" PRIu16 ")",
|
||||
section->name.c_str(), *writeIndex + (data.size() - writtenOfs), section->size);
|
||||
fatal(
|
||||
&where,
|
||||
lineNo,
|
||||
"'T' line writes past \"%s\"'s end (%zu > %" PRIu16 ")",
|
||||
section->name.c_str(),
|
||||
*writeIndex + (data.size() - writtenOfs),
|
||||
section->size
|
||||
);
|
||||
memcpy(§ion->data[*writeIndex], &data[writtenOfs], data.size() - writtenOfs);
|
||||
*writeIndex += data.size() - writtenOfs;
|
||||
}
|
||||
@@ -694,11 +807,21 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
if (!data.empty())
|
||||
warning(&where, lineNo, "Last 'T' line had no 'R' line (ignored)");
|
||||
if (fileSections.size() < expectedNbAreas)
|
||||
warning(&where, lineNo, "Expected %" PRIu32 " 'A' lines, got only %zu", expectedNbAreas,
|
||||
fileSections.size());
|
||||
warning(
|
||||
&where,
|
||||
lineNo,
|
||||
"Expected %" PRIu32 " 'A' lines, got only %zu",
|
||||
expectedNbAreas,
|
||||
fileSections.size()
|
||||
);
|
||||
if (fileSymbols.size() < expectedNbSymbols)
|
||||
warning(&where, lineNo, "Expected %" PRIu32 " 'S' lines, got only %zu", expectedNbSymbols,
|
||||
fileSymbols.size());
|
||||
warning(
|
||||
&where,
|
||||
lineNo,
|
||||
"Expected %" PRIu32 " 'S' lines, got only %zu",
|
||||
expectedNbSymbols,
|
||||
fileSymbols.size()
|
||||
);
|
||||
|
||||
nbSectionsToAssign += fileSections.size();
|
||||
|
||||
@@ -707,8 +830,14 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
|
||||
|
||||
// RAM sections can have a size, but don't get any data (they shouldn't have any)
|
||||
if (entry.writeIndex != section->size && entry.writeIndex != 0)
|
||||
fatal(&where, lineNo, "\"%s\" was not fully written (%" PRIu16 " < %" PRIu16 ")",
|
||||
section->name.c_str(), entry.writeIndex, section->size);
|
||||
fatal(
|
||||
&where,
|
||||
lineNo,
|
||||
"\"%s\" was not fully written (%" PRIu16 " < %" PRIu16 ")",
|
||||
section->name.c_str(),
|
||||
entry.writeIndex,
|
||||
section->size
|
||||
);
|
||||
|
||||
sect_AddSection(*section);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user