mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Replace RGBASM non-null pointers with references
This commit is contained in:
@@ -15,6 +15,6 @@ void charmap_Pop();
|
|||||||
void charmap_Add(char *mapping, uint8_t value);
|
void charmap_Add(char *mapping, uint8_t value);
|
||||||
bool charmap_HasChar(char const *input);
|
bool charmap_HasChar(char const *input);
|
||||||
void charmap_Convert(char const *input, std::vector<uint8_t> &output);
|
void charmap_Convert(char const *input, std::vector<uint8_t> &output);
|
||||||
size_t charmap_ConvertNext(char const **input, std::vector<uint8_t> *output);
|
size_t charmap_ConvertNext(char const *&input, std::vector<uint8_t> *output);
|
||||||
|
|
||||||
#endif // RGBDS_ASM_CHARMAP_H
|
#endif // RGBDS_ASM_CHARMAP_H
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ std::string *fstk_FindFile(char const *path);
|
|||||||
|
|
||||||
bool yywrap();
|
bool yywrap();
|
||||||
void fstk_RunInclude(char const *path);
|
void fstk_RunInclude(char const *path);
|
||||||
void fstk_RunMacro(char const *macroName, MacroArgs *args);
|
void fstk_RunMacro(char const *macroName, MacroArgs &args);
|
||||||
void fstk_RunRept(uint32_t count, int32_t reptLineNo, char const *body, size_t size);
|
void fstk_RunRept(uint32_t count, int32_t reptLineNo, char const *body, size_t size);
|
||||||
void fstk_RunFor(char const *symName, int32_t start, int32_t stop, int32_t step,
|
void fstk_RunFor(char const *symName, int32_t start, int32_t stop, int32_t step,
|
||||||
int32_t reptLineNo, char const *body, size_t size);
|
int32_t reptLineNo, char const *body, size_t size);
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ uint32_t lexer_GetLineNo();
|
|||||||
uint32_t lexer_GetColNo();
|
uint32_t lexer_GetColNo();
|
||||||
void lexer_DumpStringExpansions();
|
void lexer_DumpStringExpansions();
|
||||||
int yylex();
|
int yylex();
|
||||||
bool lexer_CaptureRept(CaptureBody *capture);
|
bool lexer_CaptureRept(CaptureBody &capture);
|
||||||
bool lexer_CaptureMacroBody(CaptureBody *capture);
|
bool lexer_CaptureMacroBody(CaptureBody &capture);
|
||||||
|
|
||||||
#endif // RGBDS_ASM_LEXER_H
|
#endif // RGBDS_ASM_LEXER_H
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ extern const char *objectName;
|
|||||||
void out_RegisterNode(FileStackNode *node);
|
void out_RegisterNode(FileStackNode *node);
|
||||||
void out_ReplaceNode(FileStackNode *node);
|
void out_ReplaceNode(FileStackNode *node);
|
||||||
void out_SetFileName(char *s);
|
void out_SetFileName(char *s);
|
||||||
void out_CreatePatch(uint32_t type, Expression const *expr, uint32_t ofs, uint32_t pcShift);
|
void out_CreatePatch(uint32_t type, Expression const &expr, uint32_t ofs, uint32_t pcShift);
|
||||||
void out_CreateAssert(enum AssertionType type, Expression const *expr, char const *message, uint32_t ofs);
|
void out_CreateAssert(enum AssertionType type, Expression const &expr, char const *message, uint32_t ofs);
|
||||||
void out_WriteObject();
|
void out_WriteObject();
|
||||||
|
|
||||||
#endif // RGBDS_ASM_OUTPUT_H
|
#endif // RGBDS_ASM_OUTPUT_H
|
||||||
|
|||||||
@@ -23,27 +23,27 @@ struct Expression {
|
|||||||
bool isDiffConstant(Symbol const *symName) const;
|
bool isDiffConstant(Symbol const *symName) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
void rpn_Symbol(Expression *expr, char const *symName);
|
void rpn_Number(Expression &expr, uint32_t val);
|
||||||
void rpn_Number(Expression *expr, uint32_t i);
|
void rpn_Symbol(Expression &expr, char const *symName);
|
||||||
void rpn_LOGNOT(Expression *expr, const Expression *src);
|
void rpn_LOGNOT(Expression &expr, const Expression &src);
|
||||||
void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1, const Expression *src2);
|
void rpn_BinaryOp(enum RPNCommand op, Expression &expr, const Expression &src1, const Expression &src2);
|
||||||
void rpn_HIGH(Expression *expr, const Expression *src);
|
void rpn_HIGH(Expression &expr, const Expression &src);
|
||||||
void rpn_LOW(Expression *expr, const Expression *src);
|
void rpn_LOW(Expression &expr, const Expression &src);
|
||||||
void rpn_ISCONST(Expression *expr, const Expression *src);
|
void rpn_ISCONST(Expression &expr, const Expression &src);
|
||||||
void rpn_NEG(Expression *expr, const Expression *src);
|
void rpn_NEG(Expression &expr, const Expression &src);
|
||||||
void rpn_NOT(Expression *expr, const Expression *src);
|
void rpn_NOT(Expression &expr, const Expression &src);
|
||||||
void rpn_BankSymbol(Expression *expr, char const *symName);
|
void rpn_BankSymbol(Expression &expr, char const *symName);
|
||||||
void rpn_BankSection(Expression *expr, char const *sectionName);
|
void rpn_BankSection(Expression &expr, char const *sectionName);
|
||||||
void rpn_BankSelf(Expression *expr);
|
void rpn_BankSelf(Expression &expr);
|
||||||
void rpn_SizeOfSection(Expression *expr, char const *sectionName);
|
void rpn_SizeOfSection(Expression &expr, char const *sectionName);
|
||||||
void rpn_StartOfSection(Expression *expr, char const *sectionName);
|
void rpn_StartOfSection(Expression &expr, char const *sectionName);
|
||||||
void rpn_SizeOfSectionType(Expression *expr, enum SectionType type);
|
void rpn_SizeOfSectionType(Expression &expr, enum SectionType type);
|
||||||
void rpn_StartOfSectionType(Expression *expr, enum SectionType type);
|
void rpn_StartOfSectionType(Expression &expr, enum SectionType type);
|
||||||
|
|
||||||
void rpn_Free(Expression *expr);
|
void rpn_Free(Expression &expr);
|
||||||
|
|
||||||
void rpn_CheckHRAM(Expression *expr, const Expression *src);
|
void rpn_CheckHRAM(Expression &expr, const Expression &src);
|
||||||
void rpn_CheckRST(Expression *expr, const Expression *src);
|
void rpn_CheckRST(Expression &expr, const Expression &src);
|
||||||
void rpn_CheckNBit(Expression const *expr, uint8_t n);
|
void rpn_CheckNBit(Expression const &expr, uint8_t n);
|
||||||
|
|
||||||
#endif // RGBDS_ASM_RPN_H
|
#endif // RGBDS_ASM_RPN_H
|
||||||
|
|||||||
@@ -53,9 +53,9 @@ extern Section *currentSection;
|
|||||||
|
|
||||||
Section *sect_FindSectionByName(char const *name);
|
Section *sect_FindSectionByName(char const *name);
|
||||||
void sect_NewSection(char const *name, enum SectionType type, uint32_t org,
|
void sect_NewSection(char const *name, enum SectionType type, uint32_t org,
|
||||||
SectionSpec const *attributes, enum SectionModifier mod);
|
SectionSpec const &attrs, enum SectionModifier mod);
|
||||||
void sect_SetLoadSection(char const *name, enum SectionType type, uint32_t org,
|
void sect_SetLoadSection(char const *name, enum SectionType type, uint32_t org,
|
||||||
SectionSpec const *attributes, enum SectionModifier mod);
|
SectionSpec const &attrs, enum SectionModifier mod);
|
||||||
void sect_EndLoadSection();
|
void sect_EndLoadSection();
|
||||||
|
|
||||||
Section *sect_GetSymbolSection();
|
Section *sect_GetSymbolSection();
|
||||||
@@ -74,11 +74,11 @@ void sect_AbsByteGroup(uint8_t const *s, size_t length);
|
|||||||
void sect_AbsWordGroup(uint8_t const *s, size_t length);
|
void sect_AbsWordGroup(uint8_t const *s, size_t length);
|
||||||
void sect_AbsLongGroup(uint8_t const *s, size_t length);
|
void sect_AbsLongGroup(uint8_t const *s, size_t length);
|
||||||
void sect_Skip(uint32_t skip, bool ds);
|
void sect_Skip(uint32_t skip, bool ds);
|
||||||
void sect_RelByte(Expression *expr, uint32_t pcShift);
|
void sect_RelByte(Expression &expr, uint32_t pcShift);
|
||||||
void sect_RelBytes(uint32_t n, std::vector<Expression> &exprs);
|
void sect_RelBytes(uint32_t n, std::vector<Expression> &exprs);
|
||||||
void sect_RelWord(Expression *expr, uint32_t pcShift);
|
void sect_RelWord(Expression &expr, uint32_t pcShift);
|
||||||
void sect_RelLong(Expression *expr, uint32_t pcShift);
|
void sect_RelLong(Expression &expr, uint32_t pcShift);
|
||||||
void sect_PCRelByte(Expression *expr, uint32_t pcShift);
|
void sect_PCRelByte(Expression &expr, uint32_t pcShift);
|
||||||
void sect_BinaryFile(char const *s, int32_t startPos);
|
void sect_BinaryFile(char const *s, int32_t startPos);
|
||||||
void sect_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length);
|
void sect_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length);
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ struct Symbol {
|
|||||||
char const *getStringValue() const { return hasCallback ? strCallback() : equs->c_str(); }
|
char const *getStringValue() const { return hasCallback ? strCallback() : equs->c_str(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
void sym_ForEach(void (*func)(Symbol *));
|
void sym_ForEach(void (*func)(Symbol &));
|
||||||
|
|
||||||
void sym_SetExportAll(bool set);
|
void sym_SetExportAll(bool set);
|
||||||
Symbol *sym_AddLocalLabel(char const *symName);
|
Symbol *sym_AddLocalLabel(char const *symName);
|
||||||
|
|||||||
@@ -141,11 +141,11 @@ bool charmap_HasChar(char const *input)
|
|||||||
|
|
||||||
void charmap_Convert(char const *input, std::vector<uint8_t> &output)
|
void charmap_Convert(char const *input, std::vector<uint8_t> &output)
|
||||||
{
|
{
|
||||||
while (charmap_ConvertNext(&input, &output))
|
while (charmap_ConvertNext(input, &output))
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t charmap_ConvertNext(char const **input, std::vector<uint8_t> *output)
|
size_t charmap_ConvertNext(char const *&input, std::vector<uint8_t> *output)
|
||||||
{
|
{
|
||||||
// The goal is to match the longest mapping possible.
|
// The goal is to match the longest mapping possible.
|
||||||
// For that, advance through the trie with each character read.
|
// For that, advance through the trie with each character read.
|
||||||
@@ -155,13 +155,13 @@ size_t charmap_ConvertNext(char const **input, std::vector<uint8_t> *output)
|
|||||||
size_t matchIdx = 0;
|
size_t matchIdx = 0;
|
||||||
size_t rewindDistance = 0;
|
size_t rewindDistance = 0;
|
||||||
|
|
||||||
for (size_t nodeIdx = 0; **input;) {
|
for (size_t nodeIdx = 0; *input;) {
|
||||||
nodeIdx = charmap.nodes[nodeIdx].next[(uint8_t)**input - 1];
|
nodeIdx = charmap.nodes[nodeIdx].next[(uint8_t)*input - 1];
|
||||||
|
|
||||||
if (!nodeIdx)
|
if (!nodeIdx)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
(*input)++; // Consume that char
|
input++; // Consume that char
|
||||||
|
|
||||||
if (charmap.nodes[nodeIdx].isTerminal) {
|
if (charmap.nodes[nodeIdx].isTerminal) {
|
||||||
matchIdx = nodeIdx; // This node matches, register it
|
matchIdx = nodeIdx; // This node matches, register it
|
||||||
@@ -173,7 +173,7 @@ size_t charmap_ConvertNext(char const **input, std::vector<uint8_t> *output)
|
|||||||
|
|
||||||
// We are at a dead end (either because we reached the end of input, or of the trie),
|
// We are at a dead end (either because we reached the end of input, or of the trie),
|
||||||
// so rewind up to the last match, and output.
|
// so rewind up to the last match, and output.
|
||||||
*input -= rewindDistance; // This will rewind all the way if no match found
|
input -= rewindDistance; // This will rewind all the way if no match found
|
||||||
|
|
||||||
if (matchIdx) { // A match was found, use it
|
if (matchIdx) { // A match was found, use it
|
||||||
if (output)
|
if (output)
|
||||||
@@ -181,16 +181,16 @@ size_t charmap_ConvertNext(char const **input, std::vector<uint8_t> *output)
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
} else if (**input) { // No match found, but there is some input left
|
} else if (*input) { // No match found, but there is some input left
|
||||||
int firstChar = **input;
|
int firstChar = *input;
|
||||||
// This will write the codepoint's value to `output`, little-endian
|
// This will write the codepoint's value to `output`, little-endian
|
||||||
size_t codepointLen = readUTF8Char(output, *input);
|
size_t codepointLen = readUTF8Char(output, input);
|
||||||
|
|
||||||
if (codepointLen == 0)
|
if (codepointLen == 0)
|
||||||
error("Input string is not valid UTF-8\n");
|
error("Input string is not valid UTF-8\n");
|
||||||
|
|
||||||
// OK because UTF-8 has no NUL in multi-byte chars
|
// OK because UTF-8 has no NUL in multi-byte chars
|
||||||
*input += codepointLen;
|
input += codepointLen;
|
||||||
|
|
||||||
// Warn if this character is not mapped but any others are
|
// Warn if this character is not mapped but any others are
|
||||||
if (charmap.nodes.size() > 1)
|
if (charmap.nodes.size() > 1)
|
||||||
|
|||||||
@@ -62,23 +62,23 @@ std::string const &FileStackNode::name() const {
|
|||||||
return std::get<std::string>(data);
|
return std::get<std::string>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *dumpNodeAndParents(FileStackNode const *node)
|
static const char *dumpNodeAndParents(FileStackNode const &node)
|
||||||
{
|
{
|
||||||
char const *name;
|
char const *name;
|
||||||
|
|
||||||
if (node->type == NODE_REPT) {
|
if (node.type == NODE_REPT) {
|
||||||
assert(node->parent); // REPT nodes should always have a parent
|
assert(node.parent); // REPT nodes should always have a parent
|
||||||
std::vector<uint32_t> const &nodeIters = node->iters();
|
std::vector<uint32_t> const &nodeIters = node.iters();
|
||||||
|
|
||||||
name = dumpNodeAndParents(node->parent);
|
name = dumpNodeAndParents(*node.parent);
|
||||||
fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, name);
|
fprintf(stderr, "(%" PRIu32 ") -> %s", node.lineNo, name);
|
||||||
for (uint32_t i = nodeIters.size(); i--; )
|
for (uint32_t i = nodeIters.size(); i--; )
|
||||||
fprintf(stderr, "::REPT~%" PRIu32, nodeIters[i]);
|
fprintf(stderr, "::REPT~%" PRIu32, nodeIters[i]);
|
||||||
} else {
|
} else {
|
||||||
name = node->name().c_str();
|
name = node.name().c_str();
|
||||||
if (node->parent) {
|
if (node.parent) {
|
||||||
dumpNodeAndParents(node->parent);
|
dumpNodeAndParents(*node.parent);
|
||||||
fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, name);
|
fprintf(stderr, "(%" PRIu32 ") -> %s", node.lineNo, name);
|
||||||
} else {
|
} else {
|
||||||
fputs(name, stderr);
|
fputs(name, stderr);
|
||||||
}
|
}
|
||||||
@@ -88,7 +88,7 @@ static const char *dumpNodeAndParents(FileStackNode const *node)
|
|||||||
|
|
||||||
void FileStackNode::dump(uint32_t curLineNo) const
|
void FileStackNode::dump(uint32_t curLineNo) const
|
||||||
{
|
{
|
||||||
dumpNodeAndParents(this);
|
dumpNodeAndParents(*this);
|
||||||
fprintf(stderr, "(%" PRIu32 ")", curLineNo);
|
fprintf(stderr, "(%" PRIu32 ")", curLineNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,7 +254,7 @@ bool yywrap()
|
|||||||
// Make sure not to switch the lexer state before calling this, so the saved line no is correct.
|
// Make sure not to switch the lexer state before calling this, so the saved line no is correct.
|
||||||
// BE CAREFUL! This modifies the file stack directly, you should have set up the file info first.
|
// BE CAREFUL! This modifies the file stack directly, you should have set up the file info first.
|
||||||
// Callers should set `contextStack.top().lexerState` after this so it is not `nullptr`.
|
// Callers should set `contextStack.top().lexerState` after this so it is not `nullptr`.
|
||||||
static Context &newContext(FileStackNode *fileInfo)
|
static Context &newContext(FileStackNode &fileInfo)
|
||||||
{
|
{
|
||||||
if (contextStack.size() > maxRecursionDepth)
|
if (contextStack.size() > maxRecursionDepth)
|
||||||
fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
|
fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
|
||||||
@@ -264,13 +264,13 @@ static Context &newContext(FileStackNode *fileInfo)
|
|||||||
|
|
||||||
FileStackNode *parent = contextStack.top().fileInfo;
|
FileStackNode *parent = contextStack.top().fileInfo;
|
||||||
|
|
||||||
fileInfo->parent = parent;
|
fileInfo.parent = parent;
|
||||||
fileInfo->lineNo = lexer_GetLineNo();
|
fileInfo.lineNo = lexer_GetLineNo();
|
||||||
fileInfo->referenced = false;
|
fileInfo.referenced = false;
|
||||||
|
|
||||||
Context &context = contextStack.emplace();
|
Context &context = contextStack.emplace();
|
||||||
|
|
||||||
context.fileInfo = fileInfo;
|
context.fileInfo = &fileInfo;
|
||||||
context.isForLoop = false;
|
context.isForLoop = false;
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
@@ -303,7 +303,7 @@ void fstk_RunInclude(char const *path)
|
|||||||
delete fullPath;
|
delete fullPath;
|
||||||
|
|
||||||
uint32_t uniqueID = contextStack.top().uniqueID;
|
uint32_t uniqueID = contextStack.top().uniqueID;
|
||||||
Context &context = newContext(fileInfo);
|
Context &context = newContext(*fileInfo);
|
||||||
|
|
||||||
if (!lexer_OpenFile(context.lexerState, fileInfo->name().c_str()))
|
if (!lexer_OpenFile(context.lexerState, fileInfo->name().c_str()))
|
||||||
fatalerror("Failed to set up lexer for file include\n");
|
fatalerror("Failed to set up lexer for file include\n");
|
||||||
@@ -338,7 +338,7 @@ static void runPreIncludeFile()
|
|||||||
fileInfo->data = *fullPath;
|
fileInfo->data = *fullPath;
|
||||||
delete fullPath;
|
delete fullPath;
|
||||||
|
|
||||||
Context &context = newContext(fileInfo);
|
Context &context = newContext(*fileInfo);
|
||||||
|
|
||||||
if (!lexer_OpenFile(context.lexerState, fileInfo->name().c_str()))
|
if (!lexer_OpenFile(context.lexerState, fileInfo->name().c_str()))
|
||||||
fatalerror("Failed to set up lexer for file include\n");
|
fatalerror("Failed to set up lexer for file include\n");
|
||||||
@@ -347,7 +347,7 @@ static void runPreIncludeFile()
|
|||||||
context.uniqueID = macro_UndefUniqueID();
|
context.uniqueID = macro_UndefUniqueID();
|
||||||
}
|
}
|
||||||
|
|
||||||
void fstk_RunMacro(char const *macroName, MacroArgs *args)
|
void fstk_RunMacro(char const *macroName, MacroArgs &args)
|
||||||
{
|
{
|
||||||
Symbol *macro = sym_FindExactSymbol(macroName);
|
Symbol *macro = sym_FindExactSymbol(macroName);
|
||||||
|
|
||||||
@@ -394,13 +394,13 @@ void fstk_RunMacro(char const *macroName, MacroArgs *args)
|
|||||||
fileInfoName.append("::");
|
fileInfoName.append("::");
|
||||||
fileInfoName.append(macro->name);
|
fileInfoName.append(macro->name);
|
||||||
|
|
||||||
Context &context = newContext(fileInfo);
|
Context &context = newContext(*fileInfo);
|
||||||
|
|
||||||
lexer_OpenFileView(context.lexerState, "MACRO", macro->macro->data(), macro->macro->size(),
|
lexer_OpenFileView(context.lexerState, "MACRO", macro->macro->data(), macro->macro->size(),
|
||||||
macro->fileLine);
|
macro->fileLine);
|
||||||
lexer_SetStateAtEOL(&context.lexerState);
|
lexer_SetStateAtEOL(&context.lexerState);
|
||||||
context.uniqueID = macro_UseNewUniqueID();
|
context.uniqueID = macro_UseNewUniqueID();
|
||||||
macro_UseNewArgs(args);
|
macro_UseNewArgs(&args);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool newReptContext(int32_t reptLineNo, char const *body, size_t size)
|
static bool newReptContext(int32_t reptLineNo, char const *body, size_t size)
|
||||||
@@ -421,7 +421,7 @@ static bool newReptContext(int32_t reptLineNo, char const *body, size_t size)
|
|||||||
fileInfo->iters().insert(fileInfo->iters().end(), RANGE(contextStack.top().fileInfo->iters()));
|
fileInfo->iters().insert(fileInfo->iters().end(), RANGE(contextStack.top().fileInfo->iters()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Context &context = newContext(fileInfo);
|
Context &context = newContext(*fileInfo);
|
||||||
|
|
||||||
// Correct our line number, which currently points to the `ENDR` line
|
// Correct our line number, which currently points to the `ENDR` line
|
||||||
context.fileInfo->lineNo = reptLineNo;
|
context.fileInfo->lineNo = reptLineNo;
|
||||||
|
|||||||
@@ -2264,7 +2264,7 @@ int yylex()
|
|||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void startCapture(CaptureBody *capture)
|
static void startCapture(CaptureBody &capture)
|
||||||
{
|
{
|
||||||
assert(!lexerState->capturing);
|
assert(!lexerState->capturing);
|
||||||
lexerState->capturing = true;
|
lexerState->capturing = true;
|
||||||
@@ -2272,26 +2272,26 @@ static void startCapture(CaptureBody *capture)
|
|||||||
lexerState->disableMacroArgs = true;
|
lexerState->disableMacroArgs = true;
|
||||||
lexerState->disableInterpolation = true;
|
lexerState->disableInterpolation = true;
|
||||||
|
|
||||||
capture->lineNo = lexer_GetLineNo();
|
capture.lineNo = lexer_GetLineNo();
|
||||||
|
|
||||||
if (lexerState->isMmapped && lexerState->expansions.empty()) {
|
if (lexerState->isMmapped && lexerState->expansions.empty()) {
|
||||||
capture->body = &lexerState->mmap.ptr.unreferenced[lexerState->mmap.offset];
|
capture.body = &lexerState->mmap.ptr.unreferenced[lexerState->mmap.offset];
|
||||||
} else {
|
} else {
|
||||||
assert(lexerState->captureBuf == nullptr);
|
assert(lexerState->captureBuf == nullptr);
|
||||||
lexerState->captureBuf = new(std::nothrow) std::vector<char>();
|
lexerState->captureBuf = new(std::nothrow) std::vector<char>();
|
||||||
if (!lexerState->captureBuf)
|
if (!lexerState->captureBuf)
|
||||||
fatalerror("Failed to allocate capture buffer: %s\n", strerror(errno));
|
fatalerror("Failed to allocate capture buffer: %s\n", strerror(errno));
|
||||||
capture->body = nullptr; // Indicate to retrieve the capture buffer when done capturing
|
capture.body = nullptr; // Indicate to retrieve the capture buffer when done capturing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void endCapture(CaptureBody *capture)
|
static void endCapture(CaptureBody &capture)
|
||||||
{
|
{
|
||||||
// This being `nullptr` means we're capturing from the capture buf, which is reallocated
|
// This being `nullptr` means we're capturing from the capture buf, which is reallocated
|
||||||
// during the whole capture process, and so MUST be retrieved at the end
|
// during the whole capture process, and so MUST be retrieved at the end
|
||||||
if (!capture->body)
|
if (!capture.body)
|
||||||
capture->body = lexerState->captureBuf->data();
|
capture.body = lexerState->captureBuf->data();
|
||||||
capture->size = lexerState->captureSize;
|
capture.size = lexerState->captureSize;
|
||||||
|
|
||||||
lexerState->capturing = false;
|
lexerState->capturing = false;
|
||||||
lexerState->captureBuf = nullptr;
|
lexerState->captureBuf = nullptr;
|
||||||
@@ -2299,7 +2299,7 @@ static void endCapture(CaptureBody *capture)
|
|||||||
lexerState->disableInterpolation = false;
|
lexerState->disableInterpolation = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lexer_CaptureRept(CaptureBody *capture)
|
bool lexer_CaptureRept(CaptureBody &capture)
|
||||||
{
|
{
|
||||||
startCapture(capture);
|
startCapture(capture);
|
||||||
|
|
||||||
@@ -2357,7 +2357,7 @@ finish:
|
|||||||
return c != EOF;
|
return c != EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lexer_CaptureMacroBody(CaptureBody *capture)
|
bool lexer_CaptureMacroBody(CaptureBody &capture)
|
||||||
{
|
{
|
||||||
startCapture(capture);
|
startCapture(capture);
|
||||||
|
|
||||||
|
|||||||
@@ -138,36 +138,36 @@ static void writesection(Section const §, FILE *f)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write a symbol to a file
|
// Write a symbol to a file
|
||||||
static void writesymbol(Symbol const *sym, FILE *f)
|
static void writesymbol(Symbol const &sym, FILE *f)
|
||||||
{
|
{
|
||||||
putstring(sym->name, f);
|
putstring(sym.name, f);
|
||||||
if (!sym->isDefined()) {
|
if (!sym.isDefined()) {
|
||||||
putc(SYMTYPE_IMPORT, f);
|
putc(SYMTYPE_IMPORT, f);
|
||||||
} else {
|
} else {
|
||||||
assert(sym->src->ID != (uint32_t)-1);
|
assert(sym.src->ID != (uint32_t)-1);
|
||||||
|
|
||||||
putc(sym->isExported ? SYMTYPE_EXPORT : SYMTYPE_LOCAL, f);
|
putc(sym.isExported ? SYMTYPE_EXPORT : SYMTYPE_LOCAL, f);
|
||||||
putlong(sym->src->ID, f);
|
putlong(sym.src->ID, f);
|
||||||
putlong(sym->fileLine, f);
|
putlong(sym.fileLine, f);
|
||||||
putlong(getSectIDIfAny(sym->getSection()), f);
|
putlong(getSectIDIfAny(sym.getSection()), f);
|
||||||
putlong(sym->value, f);
|
putlong(sym.value, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void registerSymbol(Symbol *sym)
|
static void registerSymbol(Symbol &sym)
|
||||||
{
|
{
|
||||||
sym->ID = objectSymbols.size();
|
sym.ID = objectSymbols.size();
|
||||||
objectSymbols.push_back(sym);
|
objectSymbols.push_back(&sym);
|
||||||
out_RegisterNode(sym->src);
|
out_RegisterNode(sym.src);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a symbol's ID within the object file
|
// Returns a symbol's ID within the object file
|
||||||
// If the symbol does not have one, one is assigned by registering the symbol
|
// If the symbol does not have one, one is assigned by registering the symbol
|
||||||
static uint32_t getSymbolID(Symbol *sym)
|
static uint32_t getSymbolID(Symbol &sym)
|
||||||
{
|
{
|
||||||
if (sym->ID == (uint32_t)-1 && !sym_IsPC(sym))
|
if (sym.ID == (uint32_t)-1 && !sym_IsPC(&sym))
|
||||||
registerSymbol(sym);
|
registerSymbol(sym);
|
||||||
return sym->ID;
|
return sym.ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writerpn(std::vector<uint8_t> &rpnexpr, const std::vector<uint8_t> &rpn)
|
static void writerpn(std::vector<uint8_t> &rpnexpr, const std::vector<uint8_t> &rpn)
|
||||||
@@ -176,9 +176,7 @@ static void writerpn(std::vector<uint8_t> &rpnexpr, const std::vector<uint8_t> &
|
|||||||
size_t rpnptr = 0;
|
size_t rpnptr = 0;
|
||||||
|
|
||||||
for (size_t offset = 0; offset < rpn.size(); ) {
|
for (size_t offset = 0; offset < rpn.size(); ) {
|
||||||
#define popbyte() rpn[offset++]
|
uint8_t rpndata = rpn[offset++];
|
||||||
#define writebyte(byte) rpnexpr[rpnptr++] = byte
|
|
||||||
uint8_t rpndata = popbyte();
|
|
||||||
|
|
||||||
switch (rpndata) {
|
switch (rpndata) {
|
||||||
Symbol *sym;
|
Symbol *sym;
|
||||||
@@ -187,86 +185,84 @@ static void writerpn(std::vector<uint8_t> &rpnexpr, const std::vector<uint8_t> &
|
|||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
case RPN_CONST:
|
case RPN_CONST:
|
||||||
writebyte(RPN_CONST);
|
rpnexpr[rpnptr++] = RPN_CONST;
|
||||||
writebyte(popbyte());
|
rpnexpr[rpnptr++] = rpn[offset++];
|
||||||
writebyte(popbyte());
|
rpnexpr[rpnptr++] = rpn[offset++];
|
||||||
writebyte(popbyte());
|
rpnexpr[rpnptr++] = rpn[offset++];
|
||||||
writebyte(popbyte());
|
rpnexpr[rpnptr++] = rpn[offset++];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RPN_SYM:
|
case RPN_SYM:
|
||||||
i = 0;
|
i = 0;
|
||||||
do {
|
do {
|
||||||
symName[i] = popbyte();
|
symName[i] = rpn[offset++];
|
||||||
} while (symName[i++]);
|
} while (symName[i++]);
|
||||||
|
|
||||||
// The symbol name is always written expanded
|
// The symbol name is always written expanded
|
||||||
sym = sym_FindExactSymbol(symName);
|
sym = sym_FindExactSymbol(symName);
|
||||||
if (sym->isConstant()) {
|
if (sym->isConstant()) {
|
||||||
writebyte(RPN_CONST);
|
rpnexpr[rpnptr++] = RPN_CONST;
|
||||||
value = sym_GetConstantValue(symName);
|
value = sym_GetConstantValue(symName);
|
||||||
} else {
|
} else {
|
||||||
writebyte(RPN_SYM);
|
rpnexpr[rpnptr++] = RPN_SYM;
|
||||||
value = getSymbolID(sym);
|
value = getSymbolID(*sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
writebyte(value & 0xFF);
|
rpnexpr[rpnptr++] = value & 0xFF;
|
||||||
writebyte(value >> 8);
|
rpnexpr[rpnptr++] = value >> 8;
|
||||||
writebyte(value >> 16);
|
rpnexpr[rpnptr++] = value >> 16;
|
||||||
writebyte(value >> 24);
|
rpnexpr[rpnptr++] = value >> 24;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RPN_BANK_SYM:
|
case RPN_BANK_SYM:
|
||||||
i = 0;
|
i = 0;
|
||||||
do {
|
do {
|
||||||
symName[i] = popbyte();
|
symName[i] = rpn[offset++];
|
||||||
} while (symName[i++]);
|
} while (symName[i++]);
|
||||||
|
|
||||||
// The symbol name is always written expanded
|
// The symbol name is always written expanded
|
||||||
sym = sym_FindExactSymbol(symName);
|
sym = sym_FindExactSymbol(symName);
|
||||||
value = getSymbolID(sym);
|
value = getSymbolID(*sym);
|
||||||
|
|
||||||
writebyte(RPN_BANK_SYM);
|
rpnexpr[rpnptr++] = RPN_BANK_SYM;
|
||||||
writebyte(value & 0xFF);
|
rpnexpr[rpnptr++] = value & 0xFF;
|
||||||
writebyte(value >> 8);
|
rpnexpr[rpnptr++] = value >> 8;
|
||||||
writebyte(value >> 16);
|
rpnexpr[rpnptr++] = value >> 16;
|
||||||
writebyte(value >> 24);
|
rpnexpr[rpnptr++] = value >> 24;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RPN_BANK_SECT:
|
case RPN_BANK_SECT:
|
||||||
writebyte(RPN_BANK_SECT);
|
rpnexpr[rpnptr++] = RPN_BANK_SECT;
|
||||||
do {
|
do {
|
||||||
b = popbyte();
|
b = rpn[offset++];
|
||||||
writebyte(b);
|
rpnexpr[rpnptr++] = b;
|
||||||
} while (b != 0);
|
} while (b != 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RPN_SIZEOF_SECT:
|
case RPN_SIZEOF_SECT:
|
||||||
writebyte(RPN_SIZEOF_SECT);
|
rpnexpr[rpnptr++] = RPN_SIZEOF_SECT;
|
||||||
do {
|
do {
|
||||||
b = popbyte();
|
b = rpn[offset++];
|
||||||
writebyte(b);
|
rpnexpr[rpnptr++] = b;
|
||||||
} while (b != 0);
|
} while (b != 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RPN_STARTOF_SECT:
|
case RPN_STARTOF_SECT:
|
||||||
writebyte(RPN_STARTOF_SECT);
|
rpnexpr[rpnptr++] = RPN_STARTOF_SECT;
|
||||||
do {
|
do {
|
||||||
b = popbyte();
|
b = rpn[offset++];
|
||||||
writebyte(b);
|
rpnexpr[rpnptr++] = b;
|
||||||
} while (b != 0);
|
} while (b != 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
writebyte(rpndata);
|
rpnexpr[rpnptr++] = rpndata;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#undef popbyte
|
|
||||||
#undef writebyte
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void initpatch(Patch &patch, uint32_t type, Expression const *expr, uint32_t ofs)
|
static void initpatch(Patch &patch, uint32_t type, Expression const &expr, uint32_t ofs)
|
||||||
{
|
{
|
||||||
FileStackNode *node = fstk_GetFileStack();
|
FileStackNode *node = fstk_GetFileStack();
|
||||||
|
|
||||||
@@ -279,22 +275,22 @@ static void initpatch(Patch &patch, uint32_t type, Expression const *expr, uint3
|
|||||||
patch.pcSection = sect_GetSymbolSection();
|
patch.pcSection = sect_GetSymbolSection();
|
||||||
patch.pcOffset = sect_GetSymbolOffset();
|
patch.pcOffset = sect_GetSymbolOffset();
|
||||||
|
|
||||||
if (expr->isKnown) {
|
if (expr.isKnown) {
|
||||||
// If the RPN expr's value is known, output a constant directly
|
// If the RPN expr's value is known, output a constant directly
|
||||||
patch.rpn.resize(5);
|
patch.rpn.resize(5);
|
||||||
patch.rpn[0] = RPN_CONST;
|
patch.rpn[0] = RPN_CONST;
|
||||||
patch.rpn[1] = (uint32_t)(expr->val) & 0xFF;
|
patch.rpn[1] = (uint32_t)expr.val & 0xFF;
|
||||||
patch.rpn[2] = (uint32_t)(expr->val) >> 8;
|
patch.rpn[2] = (uint32_t)expr.val >> 8;
|
||||||
patch.rpn[3] = (uint32_t)(expr->val) >> 16;
|
patch.rpn[3] = (uint32_t)expr.val >> 16;
|
||||||
patch.rpn[4] = (uint32_t)(expr->val) >> 24;
|
patch.rpn[4] = (uint32_t)expr.val >> 24;
|
||||||
} else {
|
} else {
|
||||||
patch.rpn.resize(expr->rpnPatchSize);
|
patch.rpn.resize(expr.rpnPatchSize);
|
||||||
writerpn(patch.rpn, *expr->rpn);
|
writerpn(patch.rpn, *expr.rpn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new patch (includes the rpn expr)
|
// Create a new patch (includes the rpn expr)
|
||||||
void out_CreatePatch(uint32_t type, Expression const *expr, uint32_t ofs, uint32_t pcShift)
|
void out_CreatePatch(uint32_t type, Expression const &expr, uint32_t ofs, uint32_t pcShift)
|
||||||
{
|
{
|
||||||
// Add the patch to the list
|
// Add the patch to the list
|
||||||
Patch &patch = currentSection->patches.emplace_front();
|
Patch &patch = currentSection->patches.emplace_front();
|
||||||
@@ -308,7 +304,7 @@ void out_CreatePatch(uint32_t type, Expression const *expr, uint32_t ofs, uint32
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Creates an assert that will be written to the object file
|
// Creates an assert that will be written to the object file
|
||||||
void out_CreateAssert(enum AssertionType type, Expression const *expr, char const *message, uint32_t ofs)
|
void out_CreateAssert(enum AssertionType type, Expression const &expr, char const *message, uint32_t ofs)
|
||||||
{
|
{
|
||||||
Assertion &assertion = assertions.emplace_front();
|
Assertion &assertion = assertions.emplace_front();
|
||||||
|
|
||||||
@@ -322,15 +318,15 @@ static void writeassert(Assertion &assert, FILE *f)
|
|||||||
putstring(assert.message.c_str(), f);
|
putstring(assert.message.c_str(), f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeFileStackNode(FileStackNode const *node, FILE *f)
|
static void writeFileStackNode(FileStackNode const &node, FILE *f)
|
||||||
{
|
{
|
||||||
putlong(node->parent ? node->parent->ID : (uint32_t)-1, f);
|
putlong(node.parent ? node.parent->ID : (uint32_t)-1, f);
|
||||||
putlong(node->lineNo, f);
|
putlong(node.lineNo, f);
|
||||||
putc(node->type, f);
|
putc(node.type, f);
|
||||||
if (node->type != NODE_REPT) {
|
if (node.type != NODE_REPT) {
|
||||||
putstring(node->name().c_str(), f);
|
putstring(node.name().c_str(), f);
|
||||||
} else {
|
} else {
|
||||||
std::vector<uint32_t> const &nodeIters = node->iters();
|
std::vector<uint32_t> const &nodeIters = node.iters();
|
||||||
|
|
||||||
putlong(nodeIters.size(), f);
|
putlong(nodeIters.size(), f);
|
||||||
// Iters are stored by decreasing depth, so reverse the order for output
|
// Iters are stored by decreasing depth, so reverse the order for output
|
||||||
@@ -339,11 +335,11 @@ static void writeFileStackNode(FileStackNode const *node, FILE *f)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void registerUnregisteredSymbol(Symbol *symbol)
|
static void registerUnregisteredSymbol(Symbol &sym)
|
||||||
{
|
{
|
||||||
// Check for symbol->src, to skip any built-in symbol from rgbasm
|
// Check for symbol->src, to skip any built-in symbol from rgbasm
|
||||||
if (symbol->src && symbol->ID == (uint32_t)-1) {
|
if (sym.src && sym.ID == (uint32_t)-1) {
|
||||||
registerSymbol(symbol);
|
registerSymbol(sym);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,7 +370,7 @@ void out_WriteObject()
|
|||||||
for (auto it = fileStackNodes.begin(); it != fileStackNodes.end(); it++) {
|
for (auto it = fileStackNodes.begin(); it != fileStackNodes.end(); it++) {
|
||||||
FileStackNode const *node = *it;
|
FileStackNode const *node = *it;
|
||||||
|
|
||||||
writeFileStackNode(node, f);
|
writeFileStackNode(*node, f);
|
||||||
|
|
||||||
// The list is supposed to have decrementing IDs
|
// The list is supposed to have decrementing IDs
|
||||||
if (it + 1 != fileStackNodes.end() && it[1]->ID != node->ID - 1)
|
if (it + 1 != fileStackNodes.end() && it[1]->ID != node->ID - 1)
|
||||||
@@ -384,7 +380,7 @@ void out_WriteObject()
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (Symbol const *sym : objectSymbols)
|
for (Symbol const *sym : objectSymbols)
|
||||||
writesymbol(sym, f);
|
writesymbol(*sym, f);
|
||||||
|
|
||||||
for (Section § : sectionList)
|
for (Section § : sectionList)
|
||||||
writesection(sect, f);
|
writesection(sect, f);
|
||||||
|
|||||||
264
src/asm/parser.y
264
src/asm/parser.y
@@ -63,13 +63,13 @@
|
|||||||
static size_t strlenUTF8(char const *s);
|
static size_t strlenUTF8(char const *s);
|
||||||
static void strsubUTF8(char *dest, size_t destLen, char const *src, uint32_t pos,
|
static void strsubUTF8(char *dest, size_t destLen, char const *src, uint32_t pos,
|
||||||
uint32_t len);
|
uint32_t len);
|
||||||
static size_t charlenUTF8(char const *s);
|
static size_t charlenUTF8(char const *str);
|
||||||
static void charsubUTF8(char *dest, char const *src, uint32_t pos);
|
static void charsubUTF8(char *dest, char const *src, uint32_t pos);
|
||||||
static uint32_t adjustNegativePos(int32_t pos, size_t len, char const *functionName);
|
static uint32_t adjustNegativePos(int32_t pos, size_t len, char const *functionName);
|
||||||
static void strrpl(char *dest, size_t destLen, char const *src, char const *old,
|
static void strrpl(char *dest, size_t destLen, char const *src, char const *old,
|
||||||
char const *rep);
|
char const *rep);
|
||||||
static void initStrFmtArgList(StrFmtArgList *args);
|
static void initStrFmtArgList(StrFmtArgList &args);
|
||||||
static void freeStrFmtArgList(StrFmtArgList *args);
|
static void freeStrFmtArgList(StrFmtArgList &args);
|
||||||
static void strfmt(char *dest, size_t destLen, char const *spec,
|
static void strfmt(char *dest, size_t destLen, char const *spec,
|
||||||
std::vector<std::variant<uint32_t, std::string>> &args);
|
std::vector<std::variant<uint32_t, std::string>> &args);
|
||||||
static void compoundAssignment(const char *symName, enum RPNCommand op, int32_t constValue);
|
static void compoundAssignment(const char *symName, enum RPNCommand op, int32_t constValue);
|
||||||
@@ -497,7 +497,7 @@ macro : T_ID {
|
|||||||
// Parsing 'macroargs' will restore the lexer's normal mode
|
// Parsing 'macroargs' will restore the lexer's normal mode
|
||||||
lexer_SetMode(LEXER_RAW);
|
lexer_SetMode(LEXER_RAW);
|
||||||
} macroargs {
|
} macroargs {
|
||||||
fstk_RunMacro($1, $3);
|
fstk_RunMacro($1, *$3);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -708,19 +708,19 @@ assert_type : %empty { $$ = ASSERT_ERROR; }
|
|||||||
|
|
||||||
assert : T_POP_ASSERT assert_type relocexpr {
|
assert : T_POP_ASSERT assert_type relocexpr {
|
||||||
if (!$3.isKnown) {
|
if (!$3.isKnown) {
|
||||||
out_CreateAssert($2, &$3, "", sect_GetOutputOffset());
|
out_CreateAssert($2, $3, "", sect_GetOutputOffset());
|
||||||
} else if ($3.val == 0) {
|
} else if ($3.val == 0) {
|
||||||
failAssert($2);
|
failAssert($2);
|
||||||
}
|
}
|
||||||
rpn_Free(&$3);
|
rpn_Free($3);
|
||||||
}
|
}
|
||||||
| T_POP_ASSERT assert_type relocexpr T_COMMA string {
|
| T_POP_ASSERT assert_type relocexpr T_COMMA string {
|
||||||
if (!$3.isKnown) {
|
if (!$3.isKnown) {
|
||||||
out_CreateAssert($2, &$3, $5, sect_GetOutputOffset());
|
out_CreateAssert($2, $3, $5, sect_GetOutputOffset());
|
||||||
} else if ($3.val == 0) {
|
} else if ($3.val == 0) {
|
||||||
failAssertMsg($2, $5);
|
failAssertMsg($2, $5);
|
||||||
}
|
}
|
||||||
rpn_Free(&$3);
|
rpn_Free($3);
|
||||||
}
|
}
|
||||||
| T_POP_STATIC_ASSERT assert_type const {
|
| T_POP_STATIC_ASSERT assert_type const {
|
||||||
if ($3 == 0)
|
if ($3 == 0)
|
||||||
@@ -737,13 +737,13 @@ shift : T_POP_SHIFT { macro_ShiftCurrentArgs(1); }
|
|||||||
;
|
;
|
||||||
|
|
||||||
load : T_POP_LOAD sectmod string T_COMMA sectiontype sectorg sectattrs {
|
load : T_POP_LOAD sectmod string T_COMMA sectiontype sectorg sectattrs {
|
||||||
sect_SetLoadSection($3, (enum SectionType)$5, $6, &$7, $2);
|
sect_SetLoadSection($3, (enum SectionType)$5, $6, $7, $2);
|
||||||
}
|
}
|
||||||
| T_POP_ENDL { sect_EndLoadSection(); }
|
| T_POP_ENDL { sect_EndLoadSection(); }
|
||||||
;
|
;
|
||||||
|
|
||||||
rept : T_POP_REPT uconst T_NEWLINE {
|
rept : T_POP_REPT uconst T_NEWLINE {
|
||||||
$<captureTerminated>$ = lexer_CaptureRept(&captureBody);
|
$<captureTerminated>$ = lexer_CaptureRept(captureBody);
|
||||||
} endofline {
|
} endofline {
|
||||||
if ($<captureTerminated>4)
|
if ($<captureTerminated>4)
|
||||||
fstk_RunRept($2, captureBody.lineNo, captureBody.body,
|
fstk_RunRept($2, captureBody.lineNo, captureBody.body,
|
||||||
@@ -756,7 +756,7 @@ for : T_POP_FOR {
|
|||||||
} T_ID {
|
} T_ID {
|
||||||
lexer_ToggleStringExpansion(true);
|
lexer_ToggleStringExpansion(true);
|
||||||
} T_COMMA for_args T_NEWLINE {
|
} T_COMMA for_args T_NEWLINE {
|
||||||
$<captureTerminated>$ = lexer_CaptureRept(&captureBody);
|
$<captureTerminated>$ = lexer_CaptureRept(captureBody);
|
||||||
} endofline {
|
} endofline {
|
||||||
if ($<captureTerminated>8)
|
if ($<captureTerminated>8)
|
||||||
fstk_RunFor($3, $6.start, $6.stop, $6.step, captureBody.lineNo,
|
fstk_RunFor($3, $6.start, $6.stop, $6.step, captureBody.lineNo,
|
||||||
@@ -791,7 +791,7 @@ macrodef : T_POP_MACRO {
|
|||||||
} T_ID {
|
} T_ID {
|
||||||
lexer_ToggleStringExpansion(true);
|
lexer_ToggleStringExpansion(true);
|
||||||
} T_NEWLINE {
|
} T_NEWLINE {
|
||||||
$<captureTerminated>$ = lexer_CaptureMacroBody(&captureBody);
|
$<captureTerminated>$ = lexer_CaptureMacroBody(captureBody);
|
||||||
} endofline {
|
} endofline {
|
||||||
if ($<captureTerminated>6)
|
if ($<captureTerminated>6)
|
||||||
sym_AddMacro($3, captureBody.lineNo, captureBody.body,
|
sym_AddMacro($3, captureBody.lineNo, captureBody.body,
|
||||||
@@ -1006,7 +1006,7 @@ constlist_8bit : constlist_8bit_entry
|
|||||||
;
|
;
|
||||||
|
|
||||||
constlist_8bit_entry : reloc_8bit_no_str {
|
constlist_8bit_entry : reloc_8bit_no_str {
|
||||||
sect_RelByte(&$1, 0);
|
sect_RelByte($1, 0);
|
||||||
}
|
}
|
||||||
| string {
|
| string {
|
||||||
std::vector<uint8_t> output;
|
std::vector<uint8_t> output;
|
||||||
@@ -1021,7 +1021,7 @@ constlist_16bit : constlist_16bit_entry
|
|||||||
;
|
;
|
||||||
|
|
||||||
constlist_16bit_entry : reloc_16bit_no_str {
|
constlist_16bit_entry : reloc_16bit_no_str {
|
||||||
sect_RelWord(&$1, 0);
|
sect_RelWord($1, 0);
|
||||||
}
|
}
|
||||||
| string {
|
| string {
|
||||||
std::vector<uint8_t> output;
|
std::vector<uint8_t> output;
|
||||||
@@ -1036,7 +1036,7 @@ constlist_32bit : constlist_32bit_entry
|
|||||||
;
|
;
|
||||||
|
|
||||||
constlist_32bit_entry : relocexpr_no_str {
|
constlist_32bit_entry : relocexpr_no_str {
|
||||||
sect_RelLong(&$1, 0);
|
sect_RelLong($1, 0);
|
||||||
}
|
}
|
||||||
| string {
|
| string {
|
||||||
std::vector<uint8_t> output;
|
std::vector<uint8_t> output;
|
||||||
@@ -1047,35 +1047,35 @@ constlist_32bit_entry : relocexpr_no_str {
|
|||||||
;
|
;
|
||||||
|
|
||||||
reloc_8bit : relocexpr {
|
reloc_8bit : relocexpr {
|
||||||
rpn_CheckNBit(&$1, 8);
|
rpn_CheckNBit($1, 8);
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
reloc_8bit_no_str : relocexpr_no_str {
|
reloc_8bit_no_str : relocexpr_no_str {
|
||||||
rpn_CheckNBit(&$1, 8);
|
rpn_CheckNBit($1, 8);
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
reloc_8bit_offset : T_OP_ADD relocexpr {
|
reloc_8bit_offset : T_OP_ADD relocexpr {
|
||||||
rpn_CheckNBit(&$2, 8);
|
rpn_CheckNBit($2, 8);
|
||||||
$$ = $2;
|
$$ = $2;
|
||||||
}
|
}
|
||||||
| T_OP_SUB relocexpr {
|
| T_OP_SUB relocexpr {
|
||||||
rpn_NEG(&$$, &$2);
|
rpn_NEG($$, $2);
|
||||||
rpn_CheckNBit(&$$, 8);
|
rpn_CheckNBit($$, 8);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
reloc_16bit : relocexpr {
|
reloc_16bit : relocexpr {
|
||||||
rpn_CheckNBit(&$1, 16);
|
rpn_CheckNBit($1, 16);
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
reloc_16bit_no_str : relocexpr_no_str {
|
reloc_16bit_no_str : relocexpr_no_str {
|
||||||
rpn_CheckNBit(&$1, 16);
|
rpn_CheckNBit($1, 16);
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@@ -1086,167 +1086,167 @@ relocexpr : relocexpr_no_str
|
|||||||
std::vector<uint8_t> output;
|
std::vector<uint8_t> output;
|
||||||
|
|
||||||
charmap_Convert($1, output);
|
charmap_Convert($1, output);
|
||||||
rpn_Number(&$$, str2int2(output));
|
rpn_Number($$, str2int2(output));
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
relocexpr_no_str : scoped_anon_id { rpn_Symbol(&$$, $1); }
|
relocexpr_no_str : scoped_anon_id { rpn_Symbol($$, $1); }
|
||||||
| T_NUMBER { rpn_Number(&$$, $1); }
|
| T_NUMBER { rpn_Number($$, $1); }
|
||||||
| T_OP_LOGICNOT relocexpr %prec NEG {
|
| T_OP_LOGICNOT relocexpr %prec NEG {
|
||||||
rpn_LOGNOT(&$$, &$2);
|
rpn_LOGNOT($$, $2);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_LOGICOR relocexpr {
|
| relocexpr T_OP_LOGICOR relocexpr {
|
||||||
rpn_BinaryOp(RPN_LOGOR, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_LOGOR, $$, $1, $3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_LOGICAND relocexpr {
|
| relocexpr T_OP_LOGICAND relocexpr {
|
||||||
rpn_BinaryOp(RPN_LOGAND, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_LOGAND, $$, $1, $3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_LOGICEQU relocexpr {
|
| relocexpr T_OP_LOGICEQU relocexpr {
|
||||||
rpn_BinaryOp(RPN_LOGEQ, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_LOGEQ, $$, $1, $3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_LOGICGT relocexpr {
|
| relocexpr T_OP_LOGICGT relocexpr {
|
||||||
rpn_BinaryOp(RPN_LOGGT, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_LOGGT, $$, $1, $3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_LOGICLT relocexpr {
|
| relocexpr T_OP_LOGICLT relocexpr {
|
||||||
rpn_BinaryOp(RPN_LOGLT, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_LOGLT, $$, $1, $3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_LOGICGE relocexpr {
|
| relocexpr T_OP_LOGICGE relocexpr {
|
||||||
rpn_BinaryOp(RPN_LOGGE, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_LOGGE, $$, $1, $3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_LOGICLE relocexpr {
|
| relocexpr T_OP_LOGICLE relocexpr {
|
||||||
rpn_BinaryOp(RPN_LOGLE, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_LOGLE, $$, $1, $3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_LOGICNE relocexpr {
|
| relocexpr T_OP_LOGICNE relocexpr {
|
||||||
rpn_BinaryOp(RPN_LOGNE, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_LOGNE, $$, $1, $3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_ADD relocexpr {
|
| relocexpr T_OP_ADD relocexpr {
|
||||||
rpn_BinaryOp(RPN_ADD, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_ADD, $$, $1, $3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_SUB relocexpr {
|
| relocexpr T_OP_SUB relocexpr {
|
||||||
rpn_BinaryOp(RPN_SUB, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_SUB, $$, $1, $3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_XOR relocexpr {
|
| relocexpr T_OP_XOR relocexpr {
|
||||||
rpn_BinaryOp(RPN_XOR, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_XOR, $$, $1, $3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_OR relocexpr {
|
| relocexpr T_OP_OR relocexpr {
|
||||||
rpn_BinaryOp(RPN_OR, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_OR, $$, $1, $3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_AND relocexpr {
|
| relocexpr T_OP_AND relocexpr {
|
||||||
rpn_BinaryOp(RPN_AND, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_AND, $$, $1, $3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_SHL relocexpr {
|
| relocexpr T_OP_SHL relocexpr {
|
||||||
rpn_BinaryOp(RPN_SHL, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_SHL, $$, $1, $3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_SHR relocexpr {
|
| relocexpr T_OP_SHR relocexpr {
|
||||||
rpn_BinaryOp(RPN_SHR, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_SHR, $$, $1, $3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_USHR relocexpr {
|
| relocexpr T_OP_USHR relocexpr {
|
||||||
rpn_BinaryOp(RPN_USHR, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_USHR, $$, $1, $3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_MUL relocexpr {
|
| relocexpr T_OP_MUL relocexpr {
|
||||||
rpn_BinaryOp(RPN_MUL, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_MUL, $$, $1, $3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_DIV relocexpr {
|
| relocexpr T_OP_DIV relocexpr {
|
||||||
rpn_BinaryOp(RPN_DIV, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_DIV, $$, $1, $3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_MOD relocexpr {
|
| relocexpr T_OP_MOD relocexpr {
|
||||||
rpn_BinaryOp(RPN_MOD, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_MOD, $$, $1, $3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_EXP relocexpr {
|
| relocexpr T_OP_EXP relocexpr {
|
||||||
rpn_BinaryOp(RPN_EXP, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_EXP, $$, $1, $3);
|
||||||
}
|
}
|
||||||
| T_OP_ADD relocexpr %prec NEG { $$ = $2; }
|
| T_OP_ADD relocexpr %prec NEG { $$ = $2; }
|
||||||
| T_OP_SUB relocexpr %prec NEG { rpn_NEG(&$$, &$2); }
|
| T_OP_SUB relocexpr %prec NEG { rpn_NEG($$, $2); }
|
||||||
| T_OP_NOT relocexpr %prec NEG { rpn_NOT(&$$, &$2); }
|
| T_OP_NOT relocexpr %prec NEG { rpn_NOT($$, $2); }
|
||||||
| T_OP_HIGH T_LPAREN relocexpr T_RPAREN { rpn_HIGH(&$$, &$3); }
|
| T_OP_HIGH T_LPAREN relocexpr T_RPAREN { rpn_HIGH($$, $3); }
|
||||||
| T_OP_LOW T_LPAREN relocexpr T_RPAREN { rpn_LOW(&$$, &$3); }
|
| T_OP_LOW T_LPAREN relocexpr T_RPAREN { rpn_LOW($$, $3); }
|
||||||
| T_OP_ISCONST T_LPAREN relocexpr T_RPAREN { rpn_ISCONST(&$$, &$3); }
|
| T_OP_ISCONST T_LPAREN relocexpr T_RPAREN { rpn_ISCONST($$, $3); }
|
||||||
| T_OP_BANK T_LPAREN scoped_anon_id T_RPAREN {
|
| T_OP_BANK T_LPAREN scoped_anon_id T_RPAREN {
|
||||||
// '@' is also a T_ID; it is handled here
|
// '@' is also a T_ID; it is handled here
|
||||||
rpn_BankSymbol(&$$, $3);
|
rpn_BankSymbol($$, $3);
|
||||||
}
|
}
|
||||||
| T_OP_BANK T_LPAREN string T_RPAREN { rpn_BankSection(&$$, $3); }
|
| T_OP_BANK T_LPAREN string T_RPAREN { rpn_BankSection($$, $3); }
|
||||||
| T_OP_SIZEOF T_LPAREN string T_RPAREN { rpn_SizeOfSection(&$$, $3); }
|
| T_OP_SIZEOF T_LPAREN string T_RPAREN { rpn_SizeOfSection($$, $3); }
|
||||||
| T_OP_STARTOF T_LPAREN string T_RPAREN { rpn_StartOfSection(&$$, $3); }
|
| T_OP_STARTOF T_LPAREN string T_RPAREN { rpn_StartOfSection($$, $3); }
|
||||||
| T_OP_SIZEOF T_LPAREN sectiontype T_RPAREN {
|
| T_OP_SIZEOF T_LPAREN sectiontype T_RPAREN {
|
||||||
rpn_SizeOfSectionType(&$$, (enum SectionType)$3);
|
rpn_SizeOfSectionType($$, (enum SectionType)$3);
|
||||||
}
|
}
|
||||||
| T_OP_STARTOF T_LPAREN sectiontype T_RPAREN {
|
| T_OP_STARTOF T_LPAREN sectiontype T_RPAREN {
|
||||||
rpn_StartOfSectionType(&$$, (enum SectionType)$3);
|
rpn_StartOfSectionType($$, (enum SectionType)$3);
|
||||||
}
|
}
|
||||||
| T_OP_DEF {
|
| T_OP_DEF {
|
||||||
lexer_ToggleStringExpansion(false);
|
lexer_ToggleStringExpansion(false);
|
||||||
} T_LPAREN scoped_anon_id T_RPAREN {
|
} T_LPAREN scoped_anon_id T_RPAREN {
|
||||||
rpn_Number(&$$, sym_FindScopedValidSymbol($4) != nullptr);
|
rpn_Number($$, sym_FindScopedValidSymbol($4) != nullptr);
|
||||||
|
|
||||||
lexer_ToggleStringExpansion(true);
|
lexer_ToggleStringExpansion(true);
|
||||||
}
|
}
|
||||||
| T_OP_ROUND T_LPAREN const opt_q_arg T_RPAREN {
|
| T_OP_ROUND T_LPAREN const opt_q_arg T_RPAREN {
|
||||||
rpn_Number(&$$, fix_Round($3, $4));
|
rpn_Number($$, fix_Round($3, $4));
|
||||||
}
|
}
|
||||||
| T_OP_CEIL T_LPAREN const opt_q_arg T_RPAREN {
|
| T_OP_CEIL T_LPAREN const opt_q_arg T_RPAREN {
|
||||||
rpn_Number(&$$, fix_Ceil($3, $4));
|
rpn_Number($$, fix_Ceil($3, $4));
|
||||||
}
|
}
|
||||||
| T_OP_FLOOR T_LPAREN const opt_q_arg T_RPAREN {
|
| T_OP_FLOOR T_LPAREN const opt_q_arg T_RPAREN {
|
||||||
rpn_Number(&$$, fix_Floor($3, $4));
|
rpn_Number($$, fix_Floor($3, $4));
|
||||||
}
|
}
|
||||||
| T_OP_FDIV T_LPAREN const T_COMMA const opt_q_arg T_RPAREN {
|
| T_OP_FDIV T_LPAREN const T_COMMA const opt_q_arg T_RPAREN {
|
||||||
rpn_Number(&$$, fix_Div($3, $5, $6));
|
rpn_Number($$, fix_Div($3, $5, $6));
|
||||||
}
|
}
|
||||||
| T_OP_FMUL T_LPAREN const T_COMMA const opt_q_arg T_RPAREN {
|
| T_OP_FMUL T_LPAREN const T_COMMA const opt_q_arg T_RPAREN {
|
||||||
rpn_Number(&$$, fix_Mul($3, $5, $6));
|
rpn_Number($$, fix_Mul($3, $5, $6));
|
||||||
}
|
}
|
||||||
| T_OP_FMOD T_LPAREN const T_COMMA const opt_q_arg T_RPAREN {
|
| T_OP_FMOD T_LPAREN const T_COMMA const opt_q_arg T_RPAREN {
|
||||||
rpn_Number(&$$, fix_Mod($3, $5, $6));
|
rpn_Number($$, fix_Mod($3, $5, $6));
|
||||||
}
|
}
|
||||||
| T_OP_POW T_LPAREN const T_COMMA const opt_q_arg T_RPAREN {
|
| T_OP_POW T_LPAREN const T_COMMA const opt_q_arg T_RPAREN {
|
||||||
rpn_Number(&$$, fix_Pow($3, $5, $6));
|
rpn_Number($$, fix_Pow($3, $5, $6));
|
||||||
}
|
}
|
||||||
| T_OP_LOG T_LPAREN const T_COMMA const opt_q_arg T_RPAREN {
|
| T_OP_LOG T_LPAREN const T_COMMA const opt_q_arg T_RPAREN {
|
||||||
rpn_Number(&$$, fix_Log($3, $5, $6));
|
rpn_Number($$, fix_Log($3, $5, $6));
|
||||||
}
|
}
|
||||||
| T_OP_SIN T_LPAREN const opt_q_arg T_RPAREN {
|
| T_OP_SIN T_LPAREN const opt_q_arg T_RPAREN {
|
||||||
rpn_Number(&$$, fix_Sin($3, $4));
|
rpn_Number($$, fix_Sin($3, $4));
|
||||||
}
|
}
|
||||||
| T_OP_COS T_LPAREN const opt_q_arg T_RPAREN {
|
| T_OP_COS T_LPAREN const opt_q_arg T_RPAREN {
|
||||||
rpn_Number(&$$, fix_Cos($3, $4));
|
rpn_Number($$, fix_Cos($3, $4));
|
||||||
}
|
}
|
||||||
| T_OP_TAN T_LPAREN const opt_q_arg T_RPAREN {
|
| T_OP_TAN T_LPAREN const opt_q_arg T_RPAREN {
|
||||||
rpn_Number(&$$, fix_Tan($3, $4));
|
rpn_Number($$, fix_Tan($3, $4));
|
||||||
}
|
}
|
||||||
| T_OP_ASIN T_LPAREN const opt_q_arg T_RPAREN {
|
| T_OP_ASIN T_LPAREN const opt_q_arg T_RPAREN {
|
||||||
rpn_Number(&$$, fix_ASin($3, $4));
|
rpn_Number($$, fix_ASin($3, $4));
|
||||||
}
|
}
|
||||||
| T_OP_ACOS T_LPAREN const opt_q_arg T_RPAREN {
|
| T_OP_ACOS T_LPAREN const opt_q_arg T_RPAREN {
|
||||||
rpn_Number(&$$, fix_ACos($3, $4));
|
rpn_Number($$, fix_ACos($3, $4));
|
||||||
}
|
}
|
||||||
| T_OP_ATAN T_LPAREN const opt_q_arg T_RPAREN {
|
| T_OP_ATAN T_LPAREN const opt_q_arg T_RPAREN {
|
||||||
rpn_Number(&$$, fix_ATan($3, $4));
|
rpn_Number($$, fix_ATan($3, $4));
|
||||||
}
|
}
|
||||||
| T_OP_ATAN2 T_LPAREN const T_COMMA const opt_q_arg T_RPAREN {
|
| T_OP_ATAN2 T_LPAREN const T_COMMA const opt_q_arg T_RPAREN {
|
||||||
rpn_Number(&$$, fix_ATan2($3, $5, $6));
|
rpn_Number($$, fix_ATan2($3, $5, $6));
|
||||||
}
|
}
|
||||||
| T_OP_STRCMP T_LPAREN string T_COMMA string T_RPAREN {
|
| T_OP_STRCMP T_LPAREN string T_COMMA string T_RPAREN {
|
||||||
rpn_Number(&$$, strcmp($3, $5));
|
rpn_Number($$, strcmp($3, $5));
|
||||||
}
|
}
|
||||||
| T_OP_STRIN T_LPAREN string T_COMMA string T_RPAREN {
|
| T_OP_STRIN T_LPAREN string T_COMMA string T_RPAREN {
|
||||||
char const *p = strstr($3, $5);
|
char const *p = strstr($3, $5);
|
||||||
|
|
||||||
rpn_Number(&$$, p ? p - $3 + 1 : 0);
|
rpn_Number($$, p ? p - $3 + 1 : 0);
|
||||||
}
|
}
|
||||||
| T_OP_STRRIN T_LPAREN string T_COMMA string T_RPAREN {
|
| T_OP_STRRIN T_LPAREN string T_COMMA string T_RPAREN {
|
||||||
char const *p = strrstr($3, $5);
|
char const *p = strrstr($3, $5);
|
||||||
|
|
||||||
rpn_Number(&$$, p ? p - $3 + 1 : 0);
|
rpn_Number($$, p ? p - $3 + 1 : 0);
|
||||||
}
|
}
|
||||||
| T_OP_STRLEN T_LPAREN string T_RPAREN {
|
| T_OP_STRLEN T_LPAREN string T_RPAREN {
|
||||||
rpn_Number(&$$, strlenUTF8($3));
|
rpn_Number($$, strlenUTF8($3));
|
||||||
}
|
}
|
||||||
| T_OP_CHARLEN T_LPAREN string T_RPAREN {
|
| T_OP_CHARLEN T_LPAREN string T_RPAREN {
|
||||||
rpn_Number(&$$, charlenUTF8($3));
|
rpn_Number($$, charlenUTF8($3));
|
||||||
}
|
}
|
||||||
| T_OP_INCHARMAP T_LPAREN string T_RPAREN {
|
| T_OP_INCHARMAP T_LPAREN string T_RPAREN {
|
||||||
rpn_Number(&$$, charmap_HasChar($3));
|
rpn_Number($$, charmap_HasChar($3));
|
||||||
}
|
}
|
||||||
| T_LPAREN relocexpr T_RPAREN { $$ = $2; }
|
| T_LPAREN relocexpr T_RPAREN { $$ = $2; }
|
||||||
;
|
;
|
||||||
@@ -1314,7 +1314,7 @@ string : T_STRING
|
|||||||
}
|
}
|
||||||
| T_OP_STRFMT T_LPAREN strfmt_args T_RPAREN {
|
| T_OP_STRFMT T_LPAREN strfmt_args T_RPAREN {
|
||||||
strfmt($$, sizeof($$), $3.format->c_str(), *$3.args);
|
strfmt($$, sizeof($$), $3.format->c_str(), *$3.args);
|
||||||
freeStrFmtArgList(&$3);
|
freeStrFmtArgList($3);
|
||||||
}
|
}
|
||||||
| T_POP_SECTION T_LPAREN scoped_anon_id T_RPAREN {
|
| T_POP_SECTION T_LPAREN scoped_anon_id T_RPAREN {
|
||||||
Symbol *sym = sym_FindScopedValidSymbol($3);
|
Symbol *sym = sym_FindScopedValidSymbol($3);
|
||||||
@@ -1350,7 +1350,7 @@ strfmt_args : string strfmt_va_args {
|
|||||||
;
|
;
|
||||||
|
|
||||||
strfmt_va_args : %empty {
|
strfmt_va_args : %empty {
|
||||||
initStrFmtArgList(&$$);
|
initStrFmtArgList($$);
|
||||||
}
|
}
|
||||||
| strfmt_va_args T_COMMA const_no_str {
|
| strfmt_va_args T_COMMA const_no_str {
|
||||||
$1.args->push_back((uint32_t)$3);
|
$1.args->push_back((uint32_t)$3);
|
||||||
@@ -1363,7 +1363,7 @@ strfmt_va_args : %empty {
|
|||||||
;
|
;
|
||||||
|
|
||||||
section : T_POP_SECTION sectmod string T_COMMA sectiontype sectorg sectattrs {
|
section : T_POP_SECTION sectmod string T_COMMA sectiontype sectorg sectattrs {
|
||||||
sect_NewSection($3, (enum SectionType)$5, $6, &$7, $2);
|
sect_NewSection($3, (enum SectionType)$5, $6, $7, $2);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -1462,27 +1462,27 @@ cpu_command : z80_adc
|
|||||||
|
|
||||||
z80_adc : T_Z80_ADC op_a_n {
|
z80_adc : T_Z80_ADC op_a_n {
|
||||||
sect_AbsByte(0xCE);
|
sect_AbsByte(0xCE);
|
||||||
sect_RelByte(&$2, 1);
|
sect_RelByte($2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_ADC op_a_r { sect_AbsByte(0x88 | $2); }
|
| T_Z80_ADC op_a_r { sect_AbsByte(0x88 | $2); }
|
||||||
;
|
;
|
||||||
|
|
||||||
z80_add : T_Z80_ADD op_a_n {
|
z80_add : T_Z80_ADD op_a_n {
|
||||||
sect_AbsByte(0xC6);
|
sect_AbsByte(0xC6);
|
||||||
sect_RelByte(&$2, 1);
|
sect_RelByte($2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_ADD op_a_r { sect_AbsByte(0x80 | $2); }
|
| T_Z80_ADD op_a_r { sect_AbsByte(0x80 | $2); }
|
||||||
| T_Z80_ADD T_MODE_HL T_COMMA reg_ss { sect_AbsByte(0x09 | ($4 << 4)); }
|
| T_Z80_ADD T_MODE_HL T_COMMA reg_ss { sect_AbsByte(0x09 | ($4 << 4)); }
|
||||||
| T_Z80_ADD T_MODE_SP T_COMMA reloc_8bit {
|
| T_Z80_ADD T_MODE_SP T_COMMA reloc_8bit {
|
||||||
sect_AbsByte(0xE8);
|
sect_AbsByte(0xE8);
|
||||||
sect_RelByte(&$4, 1);
|
sect_RelByte($4, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
z80_and : T_Z80_AND op_a_n {
|
z80_and : T_Z80_AND op_a_n {
|
||||||
sect_AbsByte(0xE6);
|
sect_AbsByte(0xE6);
|
||||||
sect_RelByte(&$2, 1);
|
sect_RelByte($2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_AND op_a_r { sect_AbsByte(0xA0 | $2); }
|
| T_Z80_AND op_a_r { sect_AbsByte(0xA0 | $2); }
|
||||||
;
|
;
|
||||||
@@ -1495,11 +1495,11 @@ z80_bit : T_Z80_BIT const_3bit T_COMMA reg_r {
|
|||||||
|
|
||||||
z80_call : T_Z80_CALL reloc_16bit {
|
z80_call : T_Z80_CALL reloc_16bit {
|
||||||
sect_AbsByte(0xCD);
|
sect_AbsByte(0xCD);
|
||||||
sect_RelWord(&$2, 1);
|
sect_RelWord($2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_CALL ccode_expr T_COMMA reloc_16bit {
|
| T_Z80_CALL ccode_expr T_COMMA reloc_16bit {
|
||||||
sect_AbsByte(0xC4 | ($2 << 3));
|
sect_AbsByte(0xC4 | ($2 << 3));
|
||||||
sect_RelWord(&$4, 1);
|
sect_RelWord($4, 1);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -1508,7 +1508,7 @@ z80_ccf : T_Z80_CCF { sect_AbsByte(0x3F); }
|
|||||||
|
|
||||||
z80_cp : T_Z80_CP op_a_n {
|
z80_cp : T_Z80_CP op_a_n {
|
||||||
sect_AbsByte(0xFE);
|
sect_AbsByte(0xFE);
|
||||||
sect_RelByte(&$2, 1);
|
sect_RelByte($2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_CP op_a_r { sect_AbsByte(0xB8 | $2); }
|
| T_Z80_CP op_a_r { sect_AbsByte(0xB8 | $2); }
|
||||||
;
|
;
|
||||||
@@ -1548,11 +1548,11 @@ z80_inc : T_Z80_INC reg_r { sect_AbsByte(0x04 | ($2 << 3)); }
|
|||||||
|
|
||||||
z80_jp : T_Z80_JP reloc_16bit {
|
z80_jp : T_Z80_JP reloc_16bit {
|
||||||
sect_AbsByte(0xC3);
|
sect_AbsByte(0xC3);
|
||||||
sect_RelWord(&$2, 1);
|
sect_RelWord($2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_JP ccode_expr T_COMMA reloc_16bit {
|
| T_Z80_JP ccode_expr T_COMMA reloc_16bit {
|
||||||
sect_AbsByte(0xC2 | ($2 << 3));
|
sect_AbsByte(0xC2 | ($2 << 3));
|
||||||
sect_RelWord(&$4, 1);
|
sect_RelWord($4, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_JP T_MODE_HL {
|
| T_Z80_JP T_MODE_HL {
|
||||||
sect_AbsByte(0xE9);
|
sect_AbsByte(0xE9);
|
||||||
@@ -1561,11 +1561,11 @@ z80_jp : T_Z80_JP reloc_16bit {
|
|||||||
|
|
||||||
z80_jr : T_Z80_JR reloc_16bit {
|
z80_jr : T_Z80_JR reloc_16bit {
|
||||||
sect_AbsByte(0x18);
|
sect_AbsByte(0x18);
|
||||||
sect_PCRelByte(&$2, 1);
|
sect_PCRelByte($2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_JR ccode_expr T_COMMA reloc_16bit {
|
| T_Z80_JR ccode_expr T_COMMA reloc_16bit {
|
||||||
sect_AbsByte(0x20 | ($2 << 3));
|
sect_AbsByte(0x20 | ($2 << 3));
|
||||||
sect_PCRelByte(&$4, 1);
|
sect_PCRelByte($4, 1);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -1586,16 +1586,16 @@ z80_ldd : T_Z80_LDD T_LBRACK T_MODE_HL T_RBRACK T_COMMA T_MODE_A {
|
|||||||
;
|
;
|
||||||
|
|
||||||
z80_ldio : T_Z80_LDH T_MODE_A T_COMMA op_mem_ind {
|
z80_ldio : T_Z80_LDH T_MODE_A T_COMMA op_mem_ind {
|
||||||
rpn_CheckHRAM(&$4, &$4);
|
rpn_CheckHRAM($4, $4);
|
||||||
|
|
||||||
sect_AbsByte(0xF0);
|
sect_AbsByte(0xF0);
|
||||||
sect_RelByte(&$4, 1);
|
sect_RelByte($4, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_LDH op_mem_ind T_COMMA T_MODE_A {
|
| T_Z80_LDH op_mem_ind T_COMMA T_MODE_A {
|
||||||
rpn_CheckHRAM(&$2, &$2);
|
rpn_CheckHRAM($2, $2);
|
||||||
|
|
||||||
sect_AbsByte(0xE0);
|
sect_AbsByte(0xE0);
|
||||||
sect_RelByte(&$2, 1);
|
sect_RelByte($2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_LDH T_MODE_A T_COMMA c_ind {
|
| T_Z80_LDH T_MODE_A T_COMMA c_ind {
|
||||||
sect_AbsByte(0xF2);
|
sect_AbsByte(0xF2);
|
||||||
@@ -1624,24 +1624,24 @@ z80_ld : z80_ld_mem
|
|||||||
|
|
||||||
z80_ld_hl : T_Z80_LD T_MODE_HL T_COMMA T_MODE_SP reloc_8bit_offset {
|
z80_ld_hl : T_Z80_LD T_MODE_HL T_COMMA T_MODE_SP reloc_8bit_offset {
|
||||||
sect_AbsByte(0xF8);
|
sect_AbsByte(0xF8);
|
||||||
sect_RelByte(&$5, 1);
|
sect_RelByte($5, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_LD T_MODE_HL T_COMMA reloc_16bit {
|
| T_Z80_LD T_MODE_HL T_COMMA reloc_16bit {
|
||||||
sect_AbsByte(0x01 | (REG_HL << 4));
|
sect_AbsByte(0x01 | (REG_HL << 4));
|
||||||
sect_RelWord(&$4, 1);
|
sect_RelWord($4, 1);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
z80_ld_sp : T_Z80_LD T_MODE_SP T_COMMA T_MODE_HL { sect_AbsByte(0xF9); }
|
z80_ld_sp : T_Z80_LD T_MODE_SP T_COMMA T_MODE_HL { sect_AbsByte(0xF9); }
|
||||||
| T_Z80_LD T_MODE_SP T_COMMA reloc_16bit {
|
| T_Z80_LD T_MODE_SP T_COMMA reloc_16bit {
|
||||||
sect_AbsByte(0x01 | (REG_SP << 4));
|
sect_AbsByte(0x01 | (REG_SP << 4));
|
||||||
sect_RelWord(&$4, 1);
|
sect_RelWord($4, 1);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
z80_ld_mem : T_Z80_LD op_mem_ind T_COMMA T_MODE_SP {
|
z80_ld_mem : T_Z80_LD op_mem_ind T_COMMA T_MODE_SP {
|
||||||
sect_AbsByte(0x08);
|
sect_AbsByte(0x08);
|
||||||
sect_RelWord(&$2, 1);
|
sect_RelWord($2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_LD op_mem_ind T_COMMA T_MODE_A {
|
| T_Z80_LD op_mem_ind T_COMMA T_MODE_A {
|
||||||
if (optimizeLoads && $2.isKnown
|
if (optimizeLoads && $2.isKnown
|
||||||
@@ -1653,10 +1653,10 @@ z80_ld_mem : T_Z80_LD op_mem_ind T_COMMA T_MODE_SP {
|
|||||||
}
|
}
|
||||||
sect_AbsByte(0xE0);
|
sect_AbsByte(0xE0);
|
||||||
sect_AbsByte($2.val & 0xFF);
|
sect_AbsByte($2.val & 0xFF);
|
||||||
rpn_Free(&$2);
|
rpn_Free($2);
|
||||||
} else {
|
} else {
|
||||||
sect_AbsByte(0xEA);
|
sect_AbsByte(0xEA);
|
||||||
sect_RelWord(&$2, 1);
|
sect_RelWord($2, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@@ -1673,7 +1673,7 @@ z80_ld_rr : T_Z80_LD reg_rr T_COMMA T_MODE_A {
|
|||||||
|
|
||||||
z80_ld_r : T_Z80_LD reg_r T_COMMA reloc_8bit {
|
z80_ld_r : T_Z80_LD reg_r T_COMMA reloc_8bit {
|
||||||
sect_AbsByte(0x06 | ($2 << 3));
|
sect_AbsByte(0x06 | ($2 << 3));
|
||||||
sect_RelByte(&$4, 1);
|
sect_RelByte($4, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_LD reg_r T_COMMA reg_r {
|
| T_Z80_LD reg_r T_COMMA reg_r {
|
||||||
if (($2 == REG_HL_IND) && ($4 == REG_HL_IND))
|
if (($2 == REG_HL_IND) && ($4 == REG_HL_IND))
|
||||||
@@ -1705,25 +1705,25 @@ z80_ld_a : T_Z80_LD reg_r T_COMMA c_ind {
|
|||||||
}
|
}
|
||||||
sect_AbsByte(0xF0);
|
sect_AbsByte(0xF0);
|
||||||
sect_AbsByte($4.val & 0xFF);
|
sect_AbsByte($4.val & 0xFF);
|
||||||
rpn_Free(&$4);
|
rpn_Free($4);
|
||||||
} else {
|
} else {
|
||||||
sect_AbsByte(0xFA);
|
sect_AbsByte(0xFA);
|
||||||
sect_RelWord(&$4, 1);
|
sect_RelWord($4, 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error("Destination operand must be A\n");
|
error("Destination operand must be A\n");
|
||||||
rpn_Free(&$4);
|
rpn_Free($4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
z80_ld_ss : T_Z80_LD T_MODE_BC T_COMMA reloc_16bit {
|
z80_ld_ss : T_Z80_LD T_MODE_BC T_COMMA reloc_16bit {
|
||||||
sect_AbsByte(0x01 | (REG_BC << 4));
|
sect_AbsByte(0x01 | (REG_BC << 4));
|
||||||
sect_RelWord(&$4, 1);
|
sect_RelWord($4, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_LD T_MODE_DE T_COMMA reloc_16bit {
|
| T_Z80_LD T_MODE_DE T_COMMA reloc_16bit {
|
||||||
sect_AbsByte(0x01 | (REG_DE << 4));
|
sect_AbsByte(0x01 | (REG_DE << 4));
|
||||||
sect_RelWord(&$4, 1);
|
sect_RelWord($4, 1);
|
||||||
}
|
}
|
||||||
// HL is taken care of in z80_ld_hl
|
// HL is taken care of in z80_ld_hl
|
||||||
// SP is taken care of in z80_ld_sp
|
// SP is taken care of in z80_ld_sp
|
||||||
@@ -1734,7 +1734,7 @@ z80_nop : T_Z80_NOP { sect_AbsByte(0x00); }
|
|||||||
|
|
||||||
z80_or : T_Z80_OR op_a_n {
|
z80_or : T_Z80_OR op_a_n {
|
||||||
sect_AbsByte(0xF6);
|
sect_AbsByte(0xF6);
|
||||||
sect_RelByte(&$2, 1);
|
sect_RelByte($2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_OR op_a_r { sect_AbsByte(0xB0 | $2); }
|
| T_Z80_OR op_a_r { sect_AbsByte(0xB0 | $2); }
|
||||||
;
|
;
|
||||||
@@ -1795,18 +1795,18 @@ z80_rrca : T_Z80_RRCA { sect_AbsByte(0x0F); }
|
|||||||
;
|
;
|
||||||
|
|
||||||
z80_rst : T_Z80_RST reloc_8bit {
|
z80_rst : T_Z80_RST reloc_8bit {
|
||||||
rpn_CheckRST(&$2, &$2);
|
rpn_CheckRST($2, $2);
|
||||||
if (!$2.isKnown)
|
if (!$2.isKnown)
|
||||||
sect_RelByte(&$2, 0);
|
sect_RelByte($2, 0);
|
||||||
else
|
else
|
||||||
sect_AbsByte(0xC7 | $2.val);
|
sect_AbsByte(0xC7 | $2.val);
|
||||||
rpn_Free(&$2);
|
rpn_Free($2);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
z80_sbc : T_Z80_SBC op_a_n {
|
z80_sbc : T_Z80_SBC op_a_n {
|
||||||
sect_AbsByte(0xDE);
|
sect_AbsByte(0xDE);
|
||||||
sect_RelByte(&$2, 1);
|
sect_RelByte($2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_SBC op_a_r { sect_AbsByte(0x98 | $2); }
|
| T_Z80_SBC op_a_r { sect_AbsByte(0x98 | $2); }
|
||||||
;
|
;
|
||||||
@@ -1844,13 +1844,13 @@ z80_stop : T_Z80_STOP {
|
|||||||
}
|
}
|
||||||
| T_Z80_STOP reloc_8bit {
|
| T_Z80_STOP reloc_8bit {
|
||||||
sect_AbsByte(0x10);
|
sect_AbsByte(0x10);
|
||||||
sect_RelByte(&$2, 1);
|
sect_RelByte($2, 1);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
z80_sub : T_Z80_SUB op_a_n {
|
z80_sub : T_Z80_SUB op_a_n {
|
||||||
sect_AbsByte(0xD6);
|
sect_AbsByte(0xD6);
|
||||||
sect_RelByte(&$2, 1);
|
sect_RelByte($2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_SUB op_a_r { sect_AbsByte(0x90 | $2); }
|
| T_Z80_SUB op_a_r { sect_AbsByte(0x90 | $2); }
|
||||||
;
|
;
|
||||||
@@ -1863,7 +1863,7 @@ z80_swap : T_Z80_SWAP reg_r {
|
|||||||
|
|
||||||
z80_xor : T_Z80_XOR op_a_n {
|
z80_xor : T_Z80_XOR op_a_n {
|
||||||
sect_AbsByte(0xEE);
|
sect_AbsByte(0xEE);
|
||||||
sect_RelByte(&$2, 1);
|
sect_RelByte($2, 1);
|
||||||
}
|
}
|
||||||
| T_Z80_XOR op_a_r { sect_AbsByte(0xA8 | $2); }
|
| T_Z80_XOR op_a_r { sect_AbsByte(0xA8 | $2); }
|
||||||
;
|
;
|
||||||
@@ -2092,11 +2092,11 @@ static void strsubUTF8(char *dest, size_t destLen, char const *src, uint32_t pos
|
|||||||
dest[destIndex] = '\0';
|
dest[destIndex] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t charlenUTF8(char const *s)
|
static size_t charlenUTF8(char const *str)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
for (len = 0; charmap_ConvertNext(&s, nullptr); len++)
|
for (len = 0; charmap_ConvertNext(str, nullptr); len++)
|
||||||
;
|
;
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
@@ -2108,11 +2108,11 @@ static void charsubUTF8(char *dest, char const *src, uint32_t pos)
|
|||||||
|
|
||||||
// Advance to starting position in source string.
|
// Advance to starting position in source string.
|
||||||
for (uint32_t curPos = 1; charLen && curPos < pos; curPos++)
|
for (uint32_t curPos = 1; charLen && curPos < pos; curPos++)
|
||||||
charLen = charmap_ConvertNext(&src, nullptr);
|
charLen = charmap_ConvertNext(src, nullptr);
|
||||||
|
|
||||||
char const *start = src;
|
char const *start = src;
|
||||||
|
|
||||||
if (!charmap_ConvertNext(&src, nullptr))
|
if (!charmap_ConvertNext(src, nullptr))
|
||||||
warning(WARNING_BUILTIN_ARG,
|
warning(WARNING_BUILTIN_ARG,
|
||||||
"CHARSUB: Position %" PRIu32 " is past the end of the string\n", pos);
|
"CHARSUB: Position %" PRIu32 " is past the end of the string\n", pos);
|
||||||
|
|
||||||
@@ -2180,22 +2180,22 @@ static void strrpl(char *dest, size_t destLen, char const *src, char const *old,
|
|||||||
dest[i] = '\0';
|
dest[i] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
static void initStrFmtArgList(StrFmtArgList *args)
|
static void initStrFmtArgList(StrFmtArgList &args)
|
||||||
{
|
{
|
||||||
args->format = new(std::nothrow) std::string();
|
args.format = new(std::nothrow) std::string();
|
||||||
if (!args->format)
|
if (!args.format)
|
||||||
fatalerror("Failed to allocate memory for STRFMT format string: %s\n",
|
fatalerror("Failed to allocate memory for STRFMT format string: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
args->args = new(std::nothrow) std::vector<std::variant<uint32_t, std::string>>();
|
args.args = new(std::nothrow) std::vector<std::variant<uint32_t, std::string>>();
|
||||||
if (!args->args)
|
if (!args.args)
|
||||||
fatalerror("Failed to allocate memory for STRFMT arg list: %s\n",
|
fatalerror("Failed to allocate memory for STRFMT arg list: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void freeStrFmtArgList(StrFmtArgList *args)
|
static void freeStrFmtArgList(StrFmtArgList &args)
|
||||||
{
|
{
|
||||||
delete args->format;
|
delete args.format;
|
||||||
delete args->args;
|
delete args.args;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void strfmt(char *dest, size_t destLen, char const *spec,
|
static void strfmt(char *dest, size_t destLen, char const *spec,
|
||||||
@@ -2275,9 +2275,9 @@ static void compoundAssignment(const char *symName, enum RPNCommand op, int32_t
|
|||||||
Expression oldExpr, constExpr, newExpr;
|
Expression oldExpr, constExpr, newExpr;
|
||||||
int32_t newValue;
|
int32_t newValue;
|
||||||
|
|
||||||
rpn_Symbol(&oldExpr, symName);
|
rpn_Symbol(oldExpr, symName);
|
||||||
rpn_Number(&constExpr, constValue);
|
rpn_Number(constExpr, constValue);
|
||||||
rpn_BinaryOp(op, &newExpr, &oldExpr, &constExpr);
|
rpn_BinaryOp(op, newExpr, oldExpr, constExpr);
|
||||||
newValue = newExpr.getConstVal();
|
newValue = newExpr.getConstVal();
|
||||||
sym_AddVar(symName, newValue);
|
sym_AddVar(symName, newValue);
|
||||||
}
|
}
|
||||||
|
|||||||
379
src/asm/rpn.cpp
379
src/asm/rpn.cpp
@@ -22,56 +22,56 @@
|
|||||||
#include "opmath.hpp"
|
#include "opmath.hpp"
|
||||||
|
|
||||||
// Init a RPN expression
|
// Init a RPN expression
|
||||||
static void initExpression(Expression *expr)
|
static void initExpression(Expression &expr)
|
||||||
{
|
{
|
||||||
expr->reason = nullptr;
|
expr.reason = nullptr;
|
||||||
expr->isKnown = true;
|
expr.isKnown = true;
|
||||||
expr->isSymbol = false;
|
expr.isSymbol = false;
|
||||||
expr->rpn = nullptr;
|
expr.rpn = nullptr;
|
||||||
expr->rpnPatchSize = 0;
|
expr.rpnPatchSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Makes an expression "not known", also setting its error message
|
// Makes an expression "not known", also setting its error message
|
||||||
template<typename... Ts>
|
template<typename... Ts>
|
||||||
static void makeUnknown(Expression *expr, Ts ...parts)
|
static void makeUnknown(Expression &expr, Ts ...parts)
|
||||||
{
|
{
|
||||||
expr->isKnown = false;
|
expr.isKnown = false;
|
||||||
expr->reason = new std::string();
|
expr.reason = new std::string();
|
||||||
if (!expr->reason)
|
if (!expr.reason)
|
||||||
fatalerror("Failed to allocate RPN error string: %s\n", strerror(errno));
|
fatalerror("Failed to allocate RPN error string: %s\n", strerror(errno));
|
||||||
(expr->reason->append(parts), ...);
|
(expr.reason->append(parts), ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t *reserveSpace(Expression *expr, uint32_t size)
|
static uint8_t *reserveSpace(Expression &expr, uint32_t size)
|
||||||
{
|
{
|
||||||
if (!expr->rpn) {
|
if (!expr.rpn) {
|
||||||
expr->rpn = new(std::nothrow) std::vector<uint8_t>();
|
expr.rpn = new(std::nothrow) std::vector<uint8_t>();
|
||||||
if (!expr->rpn)
|
if (!expr.rpn)
|
||||||
fatalerror("Failed to allocate RPN expression: %s\n", strerror(errno));
|
fatalerror("Failed to allocate RPN expression: %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t curSize = expr->rpn->size();
|
size_t curSize = expr.rpn->size();
|
||||||
|
|
||||||
expr->rpn->resize(curSize + size);
|
expr.rpn->resize(curSize + size);
|
||||||
return &(*expr->rpn)[curSize];
|
return &(*expr.rpn)[curSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free the RPN expression
|
// Free the RPN expression
|
||||||
void rpn_Free(Expression *expr)
|
void rpn_Free(Expression &expr)
|
||||||
{
|
{
|
||||||
delete expr->rpn;
|
delete expr.rpn;
|
||||||
delete expr->reason;
|
delete expr.reason;
|
||||||
initExpression(expr);
|
initExpression(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add symbols, constants and operators to expression
|
// Add symbols, constants and operators to expression
|
||||||
void rpn_Number(Expression *expr, uint32_t i)
|
void rpn_Number(Expression &expr, uint32_t val)
|
||||||
{
|
{
|
||||||
initExpression(expr);
|
initExpression(expr);
|
||||||
expr->val = i;
|
expr.val = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_Symbol(Expression *expr, char const *symName)
|
void rpn_Symbol(Expression &expr, char const *symName)
|
||||||
{
|
{
|
||||||
Symbol *sym = sym_FindScopedSymbol(symName);
|
Symbol *sym = sym_FindScopedSymbol(symName);
|
||||||
|
|
||||||
@@ -80,14 +80,14 @@ void rpn_Symbol(Expression *expr, char const *symName)
|
|||||||
rpn_Number(expr, 0);
|
rpn_Number(expr, 0);
|
||||||
} else if (!sym || !sym->isConstant()) {
|
} else if (!sym || !sym->isConstant()) {
|
||||||
initExpression(expr);
|
initExpression(expr);
|
||||||
expr->isSymbol = true;
|
expr.isSymbol = true;
|
||||||
|
|
||||||
if (sym_IsPC(sym))
|
if (sym_IsPC(sym))
|
||||||
makeUnknown(expr, "PC is not constant at assembly time");
|
makeUnknown(expr, "PC is not constant at assembly time");
|
||||||
else
|
else
|
||||||
makeUnknown(expr, "'", symName, "' is not constant at assembly time");
|
makeUnknown(expr, "'", symName, "' is not constant at assembly time");
|
||||||
sym = sym_Ref(symName);
|
sym = sym_Ref(symName);
|
||||||
expr->rpnPatchSize += 5; // 1-byte opcode + 4-byte symbol ID
|
expr.rpnPatchSize += 5; // 1-byte opcode + 4-byte symbol ID
|
||||||
|
|
||||||
size_t nameLen = strlen(sym->name) + 1; // Don't forget NUL!
|
size_t nameLen = strlen(sym->name) + 1; // Don't forget NUL!
|
||||||
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
|
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
|
||||||
@@ -98,29 +98,29 @@ void rpn_Symbol(Expression *expr, char const *symName)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_BankSelf(Expression *expr)
|
static void bankSelf(Expression &expr)
|
||||||
{
|
{
|
||||||
initExpression(expr);
|
initExpression(expr);
|
||||||
|
|
||||||
if (!currentSection) {
|
if (!currentSection) {
|
||||||
error("PC has no bank outside a section\n");
|
error("PC has no bank outside a section\n");
|
||||||
expr->val = 1;
|
expr.val = 1;
|
||||||
} else if (currentSection->bank == (uint32_t)-1) {
|
} else if (currentSection->bank == (uint32_t)-1) {
|
||||||
makeUnknown(expr, "Current section's bank is not known");
|
makeUnknown(expr, "Current section's bank is not known");
|
||||||
expr->rpnPatchSize++;
|
expr.rpnPatchSize++;
|
||||||
*reserveSpace(expr, 1) = RPN_BANK_SELF;
|
*reserveSpace(expr, 1) = RPN_BANK_SELF;
|
||||||
} else {
|
} else {
|
||||||
expr->val = currentSection->bank;
|
expr.val = currentSection->bank;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_BankSymbol(Expression *expr, char const *symName)
|
void rpn_BankSymbol(Expression &expr, char const *symName)
|
||||||
{
|
{
|
||||||
Symbol const *sym = sym_FindScopedSymbol(symName);
|
Symbol const *sym = sym_FindScopedSymbol(symName);
|
||||||
|
|
||||||
// The @ symbol is treated differently.
|
// The @ symbol is treated differently.
|
||||||
if (sym_IsPC(sym)) {
|
if (sym_IsPC(sym)) {
|
||||||
rpn_BankSelf(expr);
|
bankSelf(expr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,10 +133,10 @@ void rpn_BankSymbol(Expression *expr, char const *symName)
|
|||||||
|
|
||||||
if (sym->getSection() && sym->getSection()->bank != (uint32_t)-1) {
|
if (sym->getSection() && sym->getSection()->bank != (uint32_t)-1) {
|
||||||
// Symbol's section is known and bank is fixed
|
// Symbol's section is known and bank is fixed
|
||||||
expr->val = sym->getSection()->bank;
|
expr.val = sym->getSection()->bank;
|
||||||
} else {
|
} else {
|
||||||
makeUnknown(expr, "\"", symName, "\"'s bank is not known");
|
makeUnknown(expr, "\"", symName, "\"'s bank is not known");
|
||||||
expr->rpnPatchSize += 5; // opcode + 4-byte sect ID
|
expr.rpnPatchSize += 5; // opcode + 4-byte sect ID
|
||||||
|
|
||||||
size_t nameLen = strlen(sym->name) + 1; // Room for NUL!
|
size_t nameLen = strlen(sym->name) + 1; // Room for NUL!
|
||||||
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
|
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
|
||||||
@@ -147,130 +147,130 @@ void rpn_BankSymbol(Expression *expr, char const *symName)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_BankSection(Expression *expr, char const *sectionName)
|
void rpn_BankSection(Expression &expr, char const *sectionName)
|
||||||
{
|
{
|
||||||
initExpression(expr);
|
initExpression(expr);
|
||||||
|
|
||||||
Section *section = sect_FindSectionByName(sectionName);
|
Section *section = sect_FindSectionByName(sectionName);
|
||||||
|
|
||||||
if (section && section->bank != (uint32_t)-1) {
|
if (section && section->bank != (uint32_t)-1) {
|
||||||
expr->val = section->bank;
|
expr.val = section->bank;
|
||||||
} else {
|
} else {
|
||||||
makeUnknown(expr, "Section \"", sectionName, "\"'s bank is not known");
|
makeUnknown(expr, "Section \"", sectionName, "\"'s bank is not known");
|
||||||
|
|
||||||
size_t nameLen = strlen(sectionName) + 1; // Room for NUL!
|
size_t nameLen = strlen(sectionName) + 1; // Room for NUL!
|
||||||
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
|
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
|
||||||
|
|
||||||
expr->rpnPatchSize += nameLen + 1;
|
expr.rpnPatchSize += nameLen + 1;
|
||||||
*ptr++ = RPN_BANK_SECT;
|
*ptr++ = RPN_BANK_SECT;
|
||||||
memcpy(ptr, sectionName, nameLen);
|
memcpy(ptr, sectionName, nameLen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_SizeOfSection(Expression *expr, char const *sectionName)
|
void rpn_SizeOfSection(Expression &expr, char const *sectionName)
|
||||||
{
|
{
|
||||||
initExpression(expr);
|
initExpression(expr);
|
||||||
|
|
||||||
Section *section = sect_FindSectionByName(sectionName);
|
Section *section = sect_FindSectionByName(sectionName);
|
||||||
|
|
||||||
if (section && section->isSizeKnown()) {
|
if (section && section->isSizeKnown()) {
|
||||||
expr->val = section->size;
|
expr.val = section->size;
|
||||||
} else {
|
} else {
|
||||||
makeUnknown(expr, "Section \"", sectionName, "\"'s size is not known");
|
makeUnknown(expr, "Section \"", sectionName, "\"'s size is not known");
|
||||||
|
|
||||||
size_t nameLen = strlen(sectionName) + 1; // Room for NUL!
|
size_t nameLen = strlen(sectionName) + 1; // Room for NUL!
|
||||||
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
|
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
|
||||||
|
|
||||||
expr->rpnPatchSize += nameLen + 1;
|
expr.rpnPatchSize += nameLen + 1;
|
||||||
*ptr++ = RPN_SIZEOF_SECT;
|
*ptr++ = RPN_SIZEOF_SECT;
|
||||||
memcpy(ptr, sectionName, nameLen);
|
memcpy(ptr, sectionName, nameLen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_StartOfSection(Expression *expr, char const *sectionName)
|
void rpn_StartOfSection(Expression &expr, char const *sectionName)
|
||||||
{
|
{
|
||||||
initExpression(expr);
|
initExpression(expr);
|
||||||
|
|
||||||
Section *section = sect_FindSectionByName(sectionName);
|
Section *section = sect_FindSectionByName(sectionName);
|
||||||
|
|
||||||
if (section && section->org != (uint32_t)-1) {
|
if (section && section->org != (uint32_t)-1) {
|
||||||
expr->val = section->org;
|
expr.val = section->org;
|
||||||
} else {
|
} else {
|
||||||
makeUnknown(expr, "Section \"", sectionName, "\"'s start is not known");
|
makeUnknown(expr, "Section \"", sectionName, "\"'s start is not known");
|
||||||
|
|
||||||
size_t nameLen = strlen(sectionName) + 1; // Room for NUL!
|
size_t nameLen = strlen(sectionName) + 1; // Room for NUL!
|
||||||
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
|
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
|
||||||
|
|
||||||
expr->rpnPatchSize += nameLen + 1;
|
expr.rpnPatchSize += nameLen + 1;
|
||||||
*ptr++ = RPN_STARTOF_SECT;
|
*ptr++ = RPN_STARTOF_SECT;
|
||||||
memcpy(ptr, sectionName, nameLen);
|
memcpy(ptr, sectionName, nameLen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_SizeOfSectionType(Expression *expr, enum SectionType type)
|
void rpn_SizeOfSectionType(Expression &expr, enum SectionType type)
|
||||||
{
|
{
|
||||||
initExpression(expr);
|
initExpression(expr);
|
||||||
makeUnknown(expr, "Section type's size is not known");
|
makeUnknown(expr, "Section type's size is not known");
|
||||||
|
|
||||||
uint8_t *ptr = reserveSpace(expr, 2);
|
uint8_t *ptr = reserveSpace(expr, 2);
|
||||||
|
|
||||||
expr->rpnPatchSize += 2;
|
expr.rpnPatchSize += 2;
|
||||||
*ptr++ = RPN_SIZEOF_SECTTYPE;
|
*ptr++ = RPN_SIZEOF_SECTTYPE;
|
||||||
*ptr++ = type;
|
*ptr++ = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_StartOfSectionType(Expression *expr, enum SectionType type)
|
void rpn_StartOfSectionType(Expression &expr, enum SectionType type)
|
||||||
{
|
{
|
||||||
initExpression(expr);
|
initExpression(expr);
|
||||||
makeUnknown(expr, "Section type's start is not known");
|
makeUnknown(expr, "Section type's start is not known");
|
||||||
|
|
||||||
uint8_t *ptr = reserveSpace(expr, 2);
|
uint8_t *ptr = reserveSpace(expr, 2);
|
||||||
|
|
||||||
expr->rpnPatchSize += 2;
|
expr.rpnPatchSize += 2;
|
||||||
*ptr++ = RPN_STARTOF_SECTTYPE;
|
*ptr++ = RPN_STARTOF_SECTTYPE;
|
||||||
*ptr++ = type;
|
*ptr++ = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_CheckHRAM(Expression *expr, const Expression *src)
|
void rpn_CheckHRAM(Expression &expr, const Expression &src)
|
||||||
{
|
{
|
||||||
*expr = *src;
|
expr = src;
|
||||||
expr->isSymbol = false;
|
expr.isSymbol = false;
|
||||||
|
|
||||||
if (!expr->isKnown) {
|
if (!expr.isKnown) {
|
||||||
expr->rpnPatchSize++;
|
expr.rpnPatchSize++;
|
||||||
*reserveSpace(expr, 1) = RPN_HRAM;
|
*reserveSpace(expr, 1) = RPN_HRAM;
|
||||||
} else if (expr->val >= 0xFF00 && expr->val <= 0xFFFF) {
|
} else if (expr.val >= 0xFF00 && expr.val <= 0xFFFF) {
|
||||||
// That range is valid, but only keep the lower byte
|
// That range is valid, but only keep the lower byte
|
||||||
expr->val &= 0xFF;
|
expr.val &= 0xFF;
|
||||||
} else if (expr->val < 0 || expr->val > 0xFF) {
|
} else if (expr.val < 0 || expr.val > 0xFF) {
|
||||||
error("Source address $%" PRIx32 " not between $FF00 to $FFFF\n", expr->val);
|
error("Source address $%" PRIx32 " not between $FF00 to $FFFF\n", expr.val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_CheckRST(Expression *expr, const Expression *src)
|
void rpn_CheckRST(Expression &expr, const Expression &src)
|
||||||
{
|
{
|
||||||
*expr = *src;
|
expr = src;
|
||||||
|
|
||||||
if (expr->isKnown) {
|
if (expr.isKnown) {
|
||||||
// A valid RST address must be masked with 0x38
|
// A valid RST address must be masked with 0x38
|
||||||
if (expr->val & ~0x38)
|
if (expr.val & ~0x38)
|
||||||
error("Invalid address $%" PRIx32 " for RST\n", expr->val);
|
error("Invalid address $%" PRIx32 " for RST\n", expr.val);
|
||||||
// The target is in the "0x38" bits, all other bits are set
|
// The target is in the "0x38" bits, all other bits are set
|
||||||
expr->val |= 0xC7;
|
expr.val |= 0xC7;
|
||||||
} else {
|
} else {
|
||||||
expr->rpnPatchSize++;
|
expr.rpnPatchSize++;
|
||||||
*reserveSpace(expr, 1) = RPN_RST;
|
*reserveSpace(expr, 1) = RPN_RST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks that an RPN expression's value fits within N bits (signed or unsigned)
|
// Checks that an RPN expression's value fits within N bits (signed or unsigned)
|
||||||
void rpn_CheckNBit(Expression const *expr, uint8_t n)
|
void rpn_CheckNBit(Expression const &expr, uint8_t n)
|
||||||
{
|
{
|
||||||
assert(n != 0); // That doesn't make sense
|
assert(n != 0); // That doesn't make sense
|
||||||
assert(n < CHAR_BIT * sizeof(int)); // Otherwise `1 << n` is UB
|
assert(n < CHAR_BIT * sizeof(int)); // Otherwise `1 << n` is UB
|
||||||
|
|
||||||
if (expr->isKnown) {
|
if (expr.isKnown) {
|
||||||
int32_t val = expr->val;
|
int32_t val = expr.val;
|
||||||
|
|
||||||
if (val < -(1 << n) || val >= 1 << n)
|
if (val < -(1 << n) || val >= 1 << n)
|
||||||
warning(WARNING_TRUNCATION_1, "Expression must be %u-bit\n", n);
|
warning(WARNING_TRUNCATION_1, "Expression must be %u-bit\n", n);
|
||||||
@@ -288,15 +288,15 @@ int32_t Expression::getConstVal() const
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_LOGNOT(Expression *expr, const Expression *src)
|
void rpn_LOGNOT(Expression &expr, const Expression &src)
|
||||||
{
|
{
|
||||||
*expr = *src;
|
expr = src;
|
||||||
expr->isSymbol = false;
|
expr.isSymbol = false;
|
||||||
|
|
||||||
if (expr->isKnown) {
|
if (expr.isKnown) {
|
||||||
expr->val = !expr->val;
|
expr.val = !expr.val;
|
||||||
} else {
|
} else {
|
||||||
expr->rpnPatchSize++;
|
expr.rpnPatchSize++;
|
||||||
*reserveSpace(expr, 1) = RPN_LOGNOT;
|
*reserveSpace(expr, 1) = RPN_LOGNOT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -328,164 +328,165 @@ bool Expression::isDiffConstant(Symbol const *sym) const
|
|||||||
*
|
*
|
||||||
* @return The constant result if it can be computed, or -1 otherwise.
|
* @return The constant result if it can be computed, or -1 otherwise.
|
||||||
*/
|
*/
|
||||||
static int32_t tryConstMask(Expression const *lhs, Expression const *rhs)
|
static int32_t tryConstMask(Expression const &lhs, Expression const &rhs)
|
||||||
{
|
{
|
||||||
Symbol const *sym = lhs->symbolOf();
|
Symbol const *lhsSymbol = lhs.symbolOf();
|
||||||
Expression const *expr = rhs;
|
Symbol const *rhsSymbol = lhsSymbol ? nullptr : rhs.symbolOf();
|
||||||
|
bool lhsIsSymbol = lhsSymbol && lhsSymbol->getSection();
|
||||||
|
bool rhsIsSymbol = rhsSymbol && rhsSymbol->getSection();
|
||||||
|
|
||||||
|
if (!lhsIsSymbol && !rhsIsSymbol)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (!sym || !sym->getSection()) {
|
|
||||||
// If the lhs isn't a symbol, try again the other way around
|
// If the lhs isn't a symbol, try again the other way around
|
||||||
sym = rhs->symbolOf();
|
Symbol const &sym = lhsIsSymbol ? *lhsSymbol : *rhsSymbol;
|
||||||
expr = lhs;
|
Expression const &expr = lhsIsSymbol ? rhs : lhs; // Opposite side of `sym`
|
||||||
|
|
||||||
if (!sym || !sym->getSection())
|
assert(sym.isNumeric());
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
assert(sym->isNumeric());
|
|
||||||
|
|
||||||
if (!expr->isKnown)
|
if (!expr.isKnown)
|
||||||
return -1;
|
return -1;
|
||||||
// We can now safely use `expr->val`
|
// We can now safely use `expr.val`
|
||||||
Section const *sect = sym->getSection();
|
Section const § = *sym.getSection();
|
||||||
int32_t unknownBits = (1 << 16) - (1 << sect->align); // The max alignment is 16
|
int32_t unknownBits = (1 << 16) - (1 << sect.align); // The max alignment is 16
|
||||||
|
|
||||||
// The mask must ignore all unknown bits
|
// The mask must ignore all unknown bits
|
||||||
if ((expr->val & unknownBits) != 0)
|
if ((expr.val & unknownBits) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// `sym->getValue()` attempts to add the section's address, but that's "-1"
|
// `sym.getValue()` attempts to add the section's address, but that's "-1"
|
||||||
// because the section is floating (otherwise we wouldn't be here)
|
// because the section is floating (otherwise we wouldn't be here)
|
||||||
assert(sect->org == (uint32_t)-1);
|
assert(sect.org == (uint32_t)-1);
|
||||||
int32_t symbolOfs = sym->getValue() + 1;
|
int32_t symbolOfs = sym.getValue() + 1;
|
||||||
|
|
||||||
return (symbolOfs + sect->alignOfs) & ~unknownBits;
|
return (symbolOfs + sect.alignOfs) & ~unknownBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1, const Expression *src2)
|
void rpn_BinaryOp(enum RPNCommand op, Expression &expr, const Expression &src1, const Expression &src2)
|
||||||
{
|
{
|
||||||
expr->isSymbol = false;
|
expr.isSymbol = false;
|
||||||
int32_t constMaskVal;
|
int32_t constMaskVal;
|
||||||
|
|
||||||
// First, check if the expression is known
|
// First, check if the expression is known
|
||||||
expr->isKnown = src1->isKnown && src2->isKnown;
|
expr.isKnown = src1.isKnown && src2.isKnown;
|
||||||
if (expr->isKnown) {
|
if (expr.isKnown) {
|
||||||
initExpression(expr); // Init the expression to something sane
|
initExpression(expr); // Init the expression to something sane
|
||||||
|
|
||||||
// If both expressions are known, just compute the value
|
// If both expressions are known, just compute the value
|
||||||
uint32_t uleft = src1->val, uright = src2->val;
|
uint32_t uleft = src1.val, uright = src2.val;
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case RPN_LOGOR:
|
case RPN_LOGOR:
|
||||||
expr->val = src1->val || src2->val;
|
expr.val = src1.val || src2.val;
|
||||||
break;
|
break;
|
||||||
case RPN_LOGAND:
|
case RPN_LOGAND:
|
||||||
expr->val = src1->val && src2->val;
|
expr.val = src1.val && src2.val;
|
||||||
break;
|
break;
|
||||||
case RPN_LOGEQ:
|
case RPN_LOGEQ:
|
||||||
expr->val = src1->val == src2->val;
|
expr.val = src1.val == src2.val;
|
||||||
break;
|
break;
|
||||||
case RPN_LOGGT:
|
case RPN_LOGGT:
|
||||||
expr->val = src1->val > src2->val;
|
expr.val = src1.val > src2.val;
|
||||||
break;
|
break;
|
||||||
case RPN_LOGLT:
|
case RPN_LOGLT:
|
||||||
expr->val = src1->val < src2->val;
|
expr.val = src1.val < src2.val;
|
||||||
break;
|
break;
|
||||||
case RPN_LOGGE:
|
case RPN_LOGGE:
|
||||||
expr->val = src1->val >= src2->val;
|
expr.val = src1.val >= src2.val;
|
||||||
break;
|
break;
|
||||||
case RPN_LOGLE:
|
case RPN_LOGLE:
|
||||||
expr->val = src1->val <= src2->val;
|
expr.val = src1.val <= src2.val;
|
||||||
break;
|
break;
|
||||||
case RPN_LOGNE:
|
case RPN_LOGNE:
|
||||||
expr->val = src1->val != src2->val;
|
expr.val = src1.val != src2.val;
|
||||||
break;
|
break;
|
||||||
case RPN_ADD:
|
case RPN_ADD:
|
||||||
expr->val = uleft + uright;
|
expr.val = uleft + uright;
|
||||||
break;
|
break;
|
||||||
case RPN_SUB:
|
case RPN_SUB:
|
||||||
expr->val = uleft - uright;
|
expr.val = uleft - uright;
|
||||||
break;
|
break;
|
||||||
case RPN_XOR:
|
case RPN_XOR:
|
||||||
expr->val = src1->val ^ src2->val;
|
expr.val = src1.val ^ src2.val;
|
||||||
break;
|
break;
|
||||||
case RPN_OR:
|
case RPN_OR:
|
||||||
expr->val = src1->val | src2->val;
|
expr.val = src1.val | src2.val;
|
||||||
break;
|
break;
|
||||||
case RPN_AND:
|
case RPN_AND:
|
||||||
expr->val = src1->val & src2->val;
|
expr.val = src1.val & src2.val;
|
||||||
break;
|
break;
|
||||||
case RPN_SHL:
|
case RPN_SHL:
|
||||||
if (src2->val < 0)
|
if (src2.val < 0)
|
||||||
warning(WARNING_SHIFT_AMOUNT,
|
warning(WARNING_SHIFT_AMOUNT,
|
||||||
"Shifting left by negative amount %" PRId32 "\n",
|
"Shifting left by negative amount %" PRId32 "\n",
|
||||||
src2->val);
|
src2.val);
|
||||||
|
|
||||||
if (src2->val >= 32)
|
if (src2.val >= 32)
|
||||||
warning(WARNING_SHIFT_AMOUNT,
|
warning(WARNING_SHIFT_AMOUNT,
|
||||||
"Shifting left by large amount %" PRId32 "\n", src2->val);
|
"Shifting left by large amount %" PRId32 "\n", src2.val);
|
||||||
|
|
||||||
expr->val = op_shift_left(src1->val, src2->val);
|
expr.val = op_shift_left(src1.val, src2.val);
|
||||||
break;
|
break;
|
||||||
case RPN_SHR:
|
case RPN_SHR:
|
||||||
if (src1->val < 0)
|
if (src1.val < 0)
|
||||||
warning(WARNING_SHIFT,
|
warning(WARNING_SHIFT,
|
||||||
"Shifting right negative value %" PRId32 "\n", src1->val);
|
"Shifting right negative value %" PRId32 "\n", src1.val);
|
||||||
|
|
||||||
if (src2->val < 0)
|
if (src2.val < 0)
|
||||||
warning(WARNING_SHIFT_AMOUNT,
|
warning(WARNING_SHIFT_AMOUNT,
|
||||||
"Shifting right by negative amount %" PRId32 "\n",
|
"Shifting right by negative amount %" PRId32 "\n",
|
||||||
src2->val);
|
src2.val);
|
||||||
|
|
||||||
if (src2->val >= 32)
|
if (src2.val >= 32)
|
||||||
warning(WARNING_SHIFT_AMOUNT,
|
warning(WARNING_SHIFT_AMOUNT,
|
||||||
"Shifting right by large amount %" PRId32 "\n",
|
"Shifting right by large amount %" PRId32 "\n",
|
||||||
src2->val);
|
src2.val);
|
||||||
|
|
||||||
expr->val = op_shift_right(src1->val, src2->val);
|
expr.val = op_shift_right(src1.val, src2.val);
|
||||||
break;
|
break;
|
||||||
case RPN_USHR:
|
case RPN_USHR:
|
||||||
if (src2->val < 0)
|
if (src2.val < 0)
|
||||||
warning(WARNING_SHIFT_AMOUNT,
|
warning(WARNING_SHIFT_AMOUNT,
|
||||||
"Shifting right by negative amount %" PRId32 "\n",
|
"Shifting right by negative amount %" PRId32 "\n",
|
||||||
src2->val);
|
src2.val);
|
||||||
|
|
||||||
if (src2->val >= 32)
|
if (src2.val >= 32)
|
||||||
warning(WARNING_SHIFT_AMOUNT,
|
warning(WARNING_SHIFT_AMOUNT,
|
||||||
"Shifting right by large amount %" PRId32 "\n",
|
"Shifting right by large amount %" PRId32 "\n",
|
||||||
src2->val);
|
src2.val);
|
||||||
|
|
||||||
expr->val = op_shift_right_unsigned(src1->val, src2->val);
|
expr.val = op_shift_right_unsigned(src1.val, src2.val);
|
||||||
break;
|
break;
|
||||||
case RPN_MUL:
|
case RPN_MUL:
|
||||||
expr->val = uleft * uright;
|
expr.val = uleft * uright;
|
||||||
break;
|
break;
|
||||||
case RPN_DIV:
|
case RPN_DIV:
|
||||||
if (src2->val == 0)
|
if (src2.val == 0)
|
||||||
fatalerror("Division by zero\n");
|
fatalerror("Division by zero\n");
|
||||||
|
|
||||||
if (src1->val == INT32_MIN && src2->val == -1) {
|
if (src1.val == INT32_MIN && src2.val == -1) {
|
||||||
warning(WARNING_DIV,
|
warning(WARNING_DIV,
|
||||||
"Division of %" PRId32 " by -1 yields %" PRId32 "\n",
|
"Division of %" PRId32 " by -1 yields %" PRId32 "\n",
|
||||||
INT32_MIN, INT32_MIN);
|
INT32_MIN, INT32_MIN);
|
||||||
expr->val = INT32_MIN;
|
expr.val = INT32_MIN;
|
||||||
} else {
|
} else {
|
||||||
expr->val = op_divide(src1->val, src2->val);
|
expr.val = op_divide(src1.val, src2.val);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RPN_MOD:
|
case RPN_MOD:
|
||||||
if (src2->val == 0)
|
if (src2.val == 0)
|
||||||
fatalerror("Modulo by zero\n");
|
fatalerror("Modulo by zero\n");
|
||||||
|
|
||||||
if (src1->val == INT32_MIN && src2->val == -1)
|
if (src1.val == INT32_MIN && src2.val == -1)
|
||||||
expr->val = 0;
|
expr.val = 0;
|
||||||
else
|
else
|
||||||
expr->val = op_modulo(src1->val, src2->val);
|
expr.val = op_modulo(src1.val, src2.val);
|
||||||
break;
|
break;
|
||||||
case RPN_EXP:
|
case RPN_EXP:
|
||||||
if (src2->val < 0)
|
if (src2.val < 0)
|
||||||
fatalerror("Exponentiation by negative power\n");
|
fatalerror("Exponentiation by negative power\n");
|
||||||
|
|
||||||
expr->val = op_exponent(src1->val, src2->val);
|
expr.val = op_exponent(src1.val, src2.val);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RPN_NEG:
|
case RPN_NEG:
|
||||||
@@ -505,36 +506,36 @@ void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1,
|
|||||||
fatalerror("%d is not a binary operator\n", op);
|
fatalerror("%d is not a binary operator\n", op);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (op == RPN_SUB && src1->isDiffConstant(src2->symbolOf())) {
|
} else if (op == RPN_SUB && src1.isDiffConstant(src2.symbolOf())) {
|
||||||
Symbol const *symbol1 = src1->symbolOf();
|
Symbol const &symbol1 = *src1.symbolOf();
|
||||||
Symbol const *symbol2 = src2->symbolOf();
|
Symbol const &symbol2 = *src2.symbolOf();
|
||||||
|
|
||||||
expr->val = symbol1->getValue() - symbol2->getValue();
|
expr.val = symbol1.getValue() - symbol2.getValue();
|
||||||
expr->isKnown = true;
|
expr.isKnown = true;
|
||||||
} else if (op == RPN_AND && (constMaskVal = tryConstMask(src1, src2)) != -1) {
|
} else if (op == RPN_AND && (constMaskVal = tryConstMask(src1, src2)) != -1) {
|
||||||
expr->val = constMaskVal;
|
expr.val = constMaskVal;
|
||||||
expr->isKnown = true;
|
expr.isKnown = true;
|
||||||
} else {
|
} else {
|
||||||
// If it's not known, start computing the RPN expression
|
// If it's not known, start computing the RPN expression
|
||||||
|
|
||||||
// Convert the left-hand expression if it's constant
|
// Convert the left-hand expression if it's constant
|
||||||
if (src1->isKnown) {
|
if (src1.isKnown) {
|
||||||
uint32_t lval = src1->val;
|
uint32_t lval = src1.val;
|
||||||
uint8_t bytes[] = {RPN_CONST, (uint8_t)lval, (uint8_t)(lval >> 8),
|
uint8_t bytes[] = {RPN_CONST, (uint8_t)lval, (uint8_t)(lval >> 8),
|
||||||
(uint8_t)(lval >> 16), (uint8_t)(lval >> 24)};
|
(uint8_t)(lval >> 16), (uint8_t)(lval >> 24)};
|
||||||
expr->rpnPatchSize = sizeof(bytes);
|
expr.rpnPatchSize = sizeof(bytes);
|
||||||
expr->rpn = nullptr;
|
expr.rpn = nullptr;
|
||||||
memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes));
|
memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes));
|
||||||
|
|
||||||
// Use the other expression's un-const reason
|
// Use the other expression's un-const reason
|
||||||
expr->reason = src2->reason;
|
expr.reason = src2.reason;
|
||||||
delete src1->reason;
|
delete src1.reason;
|
||||||
} else {
|
} else {
|
||||||
// Otherwise just reuse its RPN buffer
|
// Otherwise just reuse its RPN buffer
|
||||||
expr->rpnPatchSize = src1->rpnPatchSize;
|
expr.rpnPatchSize = src1.rpnPatchSize;
|
||||||
expr->rpn = src1->rpn;
|
expr.rpn = src1.rpn;
|
||||||
expr->reason = src1->reason;
|
expr.reason = src1.reason;
|
||||||
delete src2->reason;
|
delete src2.reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now, merge the right expression into the left one
|
// Now, merge the right expression into the left one
|
||||||
@@ -543,17 +544,17 @@ void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1,
|
|||||||
uint32_t patchSize = 0;
|
uint32_t patchSize = 0;
|
||||||
|
|
||||||
// If the right expression is constant, merge a shim instead
|
// If the right expression is constant, merge a shim instead
|
||||||
uint32_t rval = src2->val;
|
uint32_t rval = src2.val;
|
||||||
uint8_t bytes[] = {RPN_CONST, (uint8_t)rval, (uint8_t)(rval >> 8),
|
uint8_t bytes[] = {RPN_CONST, (uint8_t)rval, (uint8_t)(rval >> 8),
|
||||||
(uint8_t)(rval >> 16), (uint8_t)(rval >> 24)};
|
(uint8_t)(rval >> 16), (uint8_t)(rval >> 24)};
|
||||||
if (src2->isKnown) {
|
if (src2.isKnown) {
|
||||||
ptr = bytes;
|
ptr = bytes;
|
||||||
len = sizeof(bytes);
|
len = sizeof(bytes);
|
||||||
patchSize = sizeof(bytes);
|
patchSize = sizeof(bytes);
|
||||||
} else {
|
} else {
|
||||||
ptr = src2->rpn->data(); // Pointer to the right RPN
|
ptr = src2.rpn->data(); // Pointer to the right RPN
|
||||||
len = src2->rpn->size(); // Size of the right RPN
|
len = src2.rpn->size(); // Size of the right RPN
|
||||||
patchSize = src2->rpnPatchSize;
|
patchSize = src2.rpnPatchSize;
|
||||||
}
|
}
|
||||||
// Copy the right RPN and append the operator
|
// Copy the right RPN and append the operator
|
||||||
uint8_t *buf = reserveSpace(expr, len + 1);
|
uint8_t *buf = reserveSpace(expr, len + 1);
|
||||||
@@ -563,71 +564,71 @@ void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1,
|
|||||||
memcpy(buf, ptr, len);
|
memcpy(buf, ptr, len);
|
||||||
buf[len] = op;
|
buf[len] = op;
|
||||||
|
|
||||||
delete src2->rpn; // If there was none, this is `delete nullptr`
|
delete src2.rpn; // If there was none, this is `delete nullptr`
|
||||||
expr->rpnPatchSize += patchSize + 1;
|
expr.rpnPatchSize += patchSize + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_HIGH(Expression *expr, const Expression *src)
|
void rpn_HIGH(Expression &expr, const Expression &src)
|
||||||
{
|
{
|
||||||
*expr = *src;
|
expr = src;
|
||||||
expr->isSymbol = false;
|
expr.isSymbol = false;
|
||||||
|
|
||||||
if (expr->isKnown) {
|
if (expr.isKnown) {
|
||||||
expr->val = (uint32_t)expr->val >> 8 & 0xFF;
|
expr.val = (uint32_t)expr.val >> 8 & 0xFF;
|
||||||
} else {
|
} else {
|
||||||
uint8_t bytes[] = {RPN_CONST, 8, 0, 0, 0, RPN_SHR,
|
uint8_t bytes[] = {RPN_CONST, 8, 0, 0, 0, RPN_SHR,
|
||||||
RPN_CONST, 0xFF, 0, 0, 0, RPN_AND};
|
RPN_CONST, 0xFF, 0, 0, 0, RPN_AND};
|
||||||
expr->rpnPatchSize += sizeof(bytes);
|
expr.rpnPatchSize += sizeof(bytes);
|
||||||
memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes));
|
memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_LOW(Expression *expr, const Expression *src)
|
void rpn_LOW(Expression &expr, const Expression &src)
|
||||||
{
|
{
|
||||||
*expr = *src;
|
expr = src;
|
||||||
expr->isSymbol = false;
|
expr.isSymbol = false;
|
||||||
|
|
||||||
if (expr->isKnown) {
|
if (expr.isKnown) {
|
||||||
expr->val = expr->val & 0xFF;
|
expr.val = expr.val & 0xFF;
|
||||||
} else {
|
} else {
|
||||||
uint8_t bytes[] = {RPN_CONST, 0xFF, 0, 0, 0, RPN_AND};
|
uint8_t bytes[] = {RPN_CONST, 0xFF, 0, 0, 0, RPN_AND};
|
||||||
|
|
||||||
expr->rpnPatchSize += sizeof(bytes);
|
expr.rpnPatchSize += sizeof(bytes);
|
||||||
memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes));
|
memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_ISCONST(Expression *expr, const Expression *src)
|
void rpn_ISCONST(Expression &expr, const Expression &src)
|
||||||
{
|
{
|
||||||
initExpression(expr);
|
initExpression(expr);
|
||||||
expr->val = src->isKnown;
|
expr.val = src.isKnown;
|
||||||
expr->isKnown = true;
|
expr.isKnown = true;
|
||||||
expr->isSymbol = false;
|
expr.isSymbol = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_NEG(Expression *expr, const Expression *src)
|
void rpn_NEG(Expression &expr, const Expression &src)
|
||||||
{
|
{
|
||||||
*expr = *src;
|
expr = src;
|
||||||
expr->isSymbol = false;
|
expr.isSymbol = false;
|
||||||
|
|
||||||
if (expr->isKnown) {
|
if (expr.isKnown) {
|
||||||
expr->val = -(uint32_t)expr->val;
|
expr.val = -(uint32_t)expr.val;
|
||||||
} else {
|
} else {
|
||||||
expr->rpnPatchSize++;
|
expr.rpnPatchSize++;
|
||||||
*reserveSpace(expr, 1) = RPN_NEG;
|
*reserveSpace(expr, 1) = RPN_NEG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_NOT(Expression *expr, const Expression *src)
|
void rpn_NOT(Expression &expr, const Expression &src)
|
||||||
{
|
{
|
||||||
*expr = *src;
|
expr = src;
|
||||||
expr->isSymbol = false;
|
expr.isSymbol = false;
|
||||||
|
|
||||||
if (expr->isKnown) {
|
if (expr.isKnown) {
|
||||||
expr->val = ~expr->val;
|
expr.val = ~expr.val;
|
||||||
} else {
|
} else {
|
||||||
expr->rpnPatchSize++;
|
expr.rpnPatchSize++;
|
||||||
*reserveSpace(expr, 1) = RPN_NOT;
|
*reserveSpace(expr, 1) = RPN_NOT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,16 +74,16 @@ attr_(warn_unused_result) static bool checkcodesection()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
attr_(warn_unused_result) static bool checkSectionSize(Section const *sect, uint32_t size)
|
attr_(warn_unused_result) static bool checkSectionSize(Section const §, uint32_t size)
|
||||||
{
|
{
|
||||||
uint32_t maxSize = sectionTypeInfo[sect->type].size;
|
uint32_t maxSize = sectionTypeInfo[sect.type].size;
|
||||||
|
|
||||||
// If the new size is reasonable, keep going
|
// If the new size is reasonable, keep going
|
||||||
if (size <= maxSize)
|
if (size <= maxSize)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
error("Section '%s' grew too big (max size = 0x%" PRIX32
|
error("Section '%s' grew too big (max size = 0x%" PRIX32
|
||||||
" bytes, reached 0x%" PRIX32 ").\n", sect->name.c_str(), maxSize, size);
|
" bytes, reached 0x%" PRIX32 ").\n", sect.name.c_str(), maxSize, size);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,12 +97,12 @@ attr_(warn_unused_result) static bool reserveSpace(uint32_t delta_size)
|
|||||||
|
|
||||||
// If the section has already overflowed, skip the check to avoid erroring out ad nauseam
|
// If the section has already overflowed, skip the check to avoid erroring out ad nauseam
|
||||||
if (currentSection->size != UINT32_MAX
|
if (currentSection->size != UINT32_MAX
|
||||||
&& !checkSectionSize(currentSection, curOffset + loadOffset + delta_size))
|
&& !checkSectionSize(*currentSection, curOffset + loadOffset + delta_size))
|
||||||
// Mark the section as overflowed, to avoid repeating the error
|
// Mark the section as overflowed, to avoid repeating the error
|
||||||
currentSection->size = UINT32_MAX;
|
currentSection->size = UINT32_MAX;
|
||||||
|
|
||||||
if (currentLoadSection && currentLoadSection->size != UINT32_MAX
|
if (currentLoadSection && currentLoadSection->size != UINT32_MAX
|
||||||
&& !checkSectionSize(currentLoadSection, curOffset + delta_size))
|
&& !checkSectionSize(*currentLoadSection, curOffset + delta_size))
|
||||||
currentLoadSection->size = UINT32_MAX;
|
currentLoadSection->size = UINT32_MAX;
|
||||||
|
|
||||||
return currentSection->size != UINT32_MAX
|
return currentSection->size != UINT32_MAX
|
||||||
@@ -119,13 +119,12 @@ Section *sect_FindSectionByName(char const *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define mask(align) ((1U << (align)) - 1)
|
#define mask(align) ((1U << (align)) - 1)
|
||||||
#define fail(...) \
|
#define fail(...) do { \
|
||||||
do { \
|
|
||||||
error(__VA_ARGS__); \
|
error(__VA_ARGS__); \
|
||||||
nbSectErrors++; \
|
nbSectErrors++; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static unsigned int mergeSectUnion(Section *sect, enum SectionType type, uint32_t org,
|
static unsigned int mergeSectUnion(Section §, enum SectionType type, uint32_t org,
|
||||||
uint8_t alignment, uint16_t alignOffset)
|
uint8_t alignment, uint16_t alignOffset)
|
||||||
{
|
{
|
||||||
assert(alignment < 16); // Should be ensured by the caller
|
assert(alignment < 16); // Should be ensured by the caller
|
||||||
@@ -138,39 +137,38 @@ static unsigned int mergeSectUnion(Section *sect, enum SectionType type, uint32_
|
|||||||
|
|
||||||
if (org != (uint32_t)-1) {
|
if (org != (uint32_t)-1) {
|
||||||
// If both are fixed, they must be the same
|
// If both are fixed, they must be the same
|
||||||
if (sect->org != (uint32_t)-1 && sect->org != org)
|
if (sect.org != (uint32_t)-1 && sect.org != org)
|
||||||
fail("Section already declared as fixed at different address $%04"
|
fail("Section already declared as fixed at different address $%04"
|
||||||
PRIx32 "\n", sect->org);
|
PRIx32 "\n", sect.org);
|
||||||
else if (sect->align != 0 && (mask(sect->align) & (org - sect->alignOfs)))
|
else if (sect.align != 0 && (mask(sect.align) & (org - sect.alignOfs)))
|
||||||
fail("Section already declared as aligned to %u bytes (offset %"
|
fail("Section already declared as aligned to %u bytes (offset %"
|
||||||
PRIu16 ")\n", 1U << sect->align, sect->alignOfs);
|
PRIu16 ")\n", 1U << sect.align, sect.alignOfs);
|
||||||
else
|
else
|
||||||
// Otherwise, just override
|
// Otherwise, just override
|
||||||
sect->org = org;
|
sect.org = org;
|
||||||
|
|
||||||
} else if (alignment != 0) {
|
} else if (alignment != 0) {
|
||||||
// Make sure any fixed address given is compatible
|
// Make sure any fixed address given is compatible
|
||||||
if (sect->org != (uint32_t)-1) {
|
if (sect.org != (uint32_t)-1) {
|
||||||
if ((sect->org - alignOffset) & mask(alignment))
|
if ((sect.org - alignOffset) & mask(alignment))
|
||||||
fail("Section already declared as fixed at incompatible address $%04"
|
fail("Section already declared as fixed at incompatible address $%04"
|
||||||
PRIx32 "\n", sect->org);
|
PRIx32 "\n", sect.org);
|
||||||
// Check if alignment offsets are compatible
|
// Check if alignment offsets are compatible
|
||||||
} else if ((alignOffset & mask(sect->align))
|
} else if ((alignOffset & mask(sect.align)) != (sect.alignOfs & mask(alignment))) {
|
||||||
!= (sect->alignOfs & mask(alignment))) {
|
|
||||||
fail("Section already declared with incompatible %u"
|
fail("Section already declared with incompatible %u"
|
||||||
"-byte alignment (offset %" PRIu16 ")\n",
|
"-byte alignment (offset %" PRIu16 ")\n",
|
||||||
1U << sect->align, sect->alignOfs);
|
1U << sect.align, sect.alignOfs);
|
||||||
} else if (alignment > sect->align) {
|
} else if (alignment > sect.align) {
|
||||||
// If the section is not fixed, its alignment is the largest of both
|
// If the section is not fixed, its alignment is the largest of both
|
||||||
sect->align = alignment;
|
sect.align = alignment;
|
||||||
sect->alignOfs = alignOffset;
|
sect.alignOfs = alignOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nbSectErrors;
|
return nbSectErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int mergeFragments(Section *sect, uint32_t org, uint8_t alignment, uint16_t alignOffset)
|
static unsigned int mergeFragments(Section §, uint32_t org, uint8_t alignment, uint16_t alignOffset)
|
||||||
{
|
{
|
||||||
assert(alignment < 16); // Should be ensured by the caller
|
assert(alignment < 16); // Should be ensured by the caller
|
||||||
unsigned int nbSectErrors = 0;
|
unsigned int nbSectErrors = 0;
|
||||||
@@ -179,55 +177,55 @@ static unsigned int mergeFragments(Section *sect, uint32_t org, uint8_t alignmen
|
|||||||
// combination of both.
|
// combination of both.
|
||||||
// The merging is however performed at the *end* of the original section!
|
// The merging is however performed at the *end* of the original section!
|
||||||
if (org != (uint32_t)-1) {
|
if (org != (uint32_t)-1) {
|
||||||
uint16_t curOrg = org - sect->size;
|
uint16_t curOrg = org - sect.size;
|
||||||
|
|
||||||
// If both are fixed, they must be the same
|
// If both are fixed, they must be the same
|
||||||
if (sect->org != (uint32_t)-1 && sect->org != curOrg)
|
if (sect.org != (uint32_t)-1 && sect.org != curOrg)
|
||||||
fail("Section already declared as fixed at incompatible address $%04"
|
fail("Section already declared as fixed at incompatible address $%04"
|
||||||
PRIx32 "\n", sect->org);
|
PRIx32 "\n", sect.org);
|
||||||
else if (sect->align != 0 && (mask(sect->align) & (curOrg - sect->alignOfs)))
|
else if (sect.align != 0 && (mask(sect.align) & (curOrg - sect.alignOfs)))
|
||||||
fail("Section already declared as aligned to %u bytes (offset %"
|
fail("Section already declared as aligned to %u bytes (offset %"
|
||||||
PRIu16 ")\n", 1U << sect->align, sect->alignOfs);
|
PRIu16 ")\n", 1U << sect.align, sect.alignOfs);
|
||||||
else
|
else
|
||||||
// Otherwise, just override
|
// Otherwise, just override
|
||||||
sect->org = curOrg;
|
sect.org = curOrg;
|
||||||
|
|
||||||
} else if (alignment != 0) {
|
} else if (alignment != 0) {
|
||||||
int32_t curOfs = (alignOffset - sect->size) % (1U << alignment);
|
int32_t curOfs = (alignOffset - sect.size) % (1U << alignment);
|
||||||
|
|
||||||
if (curOfs < 0)
|
if (curOfs < 0)
|
||||||
curOfs += 1U << alignment;
|
curOfs += 1U << alignment;
|
||||||
|
|
||||||
// Make sure any fixed address given is compatible
|
// Make sure any fixed address given is compatible
|
||||||
if (sect->org != (uint32_t)-1) {
|
if (sect.org != (uint32_t)-1) {
|
||||||
if ((sect->org - curOfs) & mask(alignment))
|
if ((sect.org - curOfs) & mask(alignment))
|
||||||
fail("Section already declared as fixed at incompatible address $%04"
|
fail("Section already declared as fixed at incompatible address $%04"
|
||||||
PRIx32 "\n", sect->org);
|
PRIx32 "\n", sect.org);
|
||||||
// Check if alignment offsets are compatible
|
// Check if alignment offsets are compatible
|
||||||
} else if ((curOfs & mask(sect->align)) != (sect->alignOfs & mask(alignment))) {
|
} else if ((curOfs & mask(sect.align)) != (sect.alignOfs & mask(alignment))) {
|
||||||
fail("Section already declared with incompatible %u"
|
fail("Section already declared with incompatible %u"
|
||||||
"-byte alignment (offset %" PRIu16 ")\n",
|
"-byte alignment (offset %" PRIu16 ")\n",
|
||||||
1U << sect->align, sect->alignOfs);
|
1U << sect.align, sect.alignOfs);
|
||||||
} else if (alignment > sect->align) {
|
} else if (alignment > sect.align) {
|
||||||
// If the section is not fixed, its alignment is the largest of both
|
// If the section is not fixed, its alignment is the largest of both
|
||||||
sect->align = alignment;
|
sect.align = alignment;
|
||||||
sect->alignOfs = curOfs;
|
sect.alignOfs = curOfs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nbSectErrors;
|
return nbSectErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mergeSections(Section *sect, enum SectionType type, uint32_t org, uint32_t bank,
|
static void mergeSections(Section §, enum SectionType type, uint32_t org, uint32_t bank,
|
||||||
uint8_t alignment, uint16_t alignOffset, enum SectionModifier mod)
|
uint8_t alignment, uint16_t alignOffset, enum SectionModifier mod)
|
||||||
{
|
{
|
||||||
unsigned int nbSectErrors = 0;
|
unsigned int nbSectErrors = 0;
|
||||||
|
|
||||||
if (type != sect->type)
|
if (type != sect.type)
|
||||||
fail("Section already exists but with type %s\n", sectionTypeInfo[sect->type].name.c_str());
|
fail("Section already exists but with type %s\n", sectionTypeInfo[sect.type].name.c_str());
|
||||||
|
|
||||||
if (sect->modifier != mod) {
|
if (sect.modifier != mod) {
|
||||||
fail("Section already declared as %s section\n", sectionModNames[sect->modifier]);
|
fail("Section already declared as %s section\n", sectionModNames[sect.modifier]);
|
||||||
} else {
|
} else {
|
||||||
switch (mod) {
|
switch (mod) {
|
||||||
case SECTION_UNION:
|
case SECTION_UNION:
|
||||||
@@ -239,17 +237,17 @@ static void mergeSections(Section *sect, enum SectionType type, uint32_t org, ui
|
|||||||
// Common checks
|
// Common checks
|
||||||
|
|
||||||
// If the section's bank is unspecified, override it
|
// If the section's bank is unspecified, override it
|
||||||
if (sect->bank == (uint32_t)-1)
|
if (sect.bank == (uint32_t)-1)
|
||||||
sect->bank = bank;
|
sect.bank = bank;
|
||||||
// If both specify a bank, it must be the same one
|
// If both specify a bank, it must be the same one
|
||||||
else if (bank != (uint32_t)-1 && sect->bank != bank)
|
else if (bank != (uint32_t)-1 && sect.bank != bank)
|
||||||
fail("Section already declared with different bank %" PRIu32 "\n",
|
fail("Section already declared with different bank %" PRIu32 "\n",
|
||||||
sect->bank);
|
sect.bank);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SECTION_NORMAL:
|
case SECTION_NORMAL:
|
||||||
fail("Section already defined previously at ");
|
fail("Section already defined previously at ");
|
||||||
sect->src->dump(sect->fileLine);
|
sect.src->dump(sect.fileLine);
|
||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -257,7 +255,7 @@ static void mergeSections(Section *sect, enum SectionType type, uint32_t org, ui
|
|||||||
|
|
||||||
if (nbSectErrors)
|
if (nbSectErrors)
|
||||||
fatalerror("Cannot create section \"%s\" (%u error%s)\n",
|
fatalerror("Cannot create section \"%s\" (%u error%s)\n",
|
||||||
sect->name.c_str(), nbSectErrors, nbSectErrors == 1 ? "" : "s");
|
sect.name.c_str(), nbSectErrors, nbSectErrors == 1 ? "" : "s");
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef fail
|
#undef fail
|
||||||
@@ -289,11 +287,11 @@ static Section *createSection(char const *name, enum SectionType type, uint32_t
|
|||||||
|
|
||||||
// Find a section by name and type. If it doesn't exist, create it.
|
// Find a section by name and type. If it doesn't exist, create it.
|
||||||
static Section *getSection(char const *name, enum SectionType type, uint32_t org,
|
static Section *getSection(char const *name, enum SectionType type, uint32_t org,
|
||||||
SectionSpec const *attrs, enum SectionModifier mod)
|
SectionSpec const &attrs, enum SectionModifier mod)
|
||||||
{
|
{
|
||||||
uint32_t bank = attrs->bank;
|
uint32_t bank = attrs.bank;
|
||||||
uint8_t alignment = attrs->alignment;
|
uint8_t alignment = attrs.alignment;
|
||||||
uint16_t alignOffset = attrs->alignOfs;
|
uint16_t alignOffset = attrs.alignOfs;
|
||||||
|
|
||||||
// First, validate parameters, and normalize them if applicable
|
// First, validate parameters, and normalize them if applicable
|
||||||
|
|
||||||
@@ -354,7 +352,7 @@ static Section *getSection(char const *name, enum SectionType type, uint32_t org
|
|||||||
Section *sect = sect_FindSectionByName(name);
|
Section *sect = sect_FindSectionByName(name);
|
||||||
|
|
||||||
if (sect) {
|
if (sect) {
|
||||||
mergeSections(sect, type, org, bank, alignment, alignOffset, mod);
|
mergeSections(*sect, type, org, bank, alignment, alignOffset, mod);
|
||||||
} else {
|
} else {
|
||||||
sect = createSection(name, type, org, bank, alignment, alignOffset, mod);
|
sect = createSection(name, type, org, bank, alignment, alignOffset, mod);
|
||||||
}
|
}
|
||||||
@@ -392,7 +390,7 @@ bool Section::isSizeKnown() const
|
|||||||
|
|
||||||
// Set the current section by name and type
|
// Set the current section by name and type
|
||||||
void sect_NewSection(char const *name, enum SectionType type, uint32_t org,
|
void sect_NewSection(char const *name, enum SectionType type, uint32_t org,
|
||||||
SectionSpec const *attribs, enum SectionModifier mod)
|
SectionSpec const &attrs, enum SectionModifier mod)
|
||||||
{
|
{
|
||||||
if (currentLoadSection)
|
if (currentLoadSection)
|
||||||
fatalerror("Cannot change the section within a `LOAD` block\n");
|
fatalerror("Cannot change the section within a `LOAD` block\n");
|
||||||
@@ -402,7 +400,7 @@ void sect_NewSection(char const *name, enum SectionType type, uint32_t org,
|
|||||||
fatalerror("Section '%s' is already on the stack\n", name);
|
fatalerror("Section '%s' is already on the stack\n", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Section *sect = getSection(name, type, org, attribs, mod);
|
Section *sect = getSection(name, type, org, attrs, mod);
|
||||||
|
|
||||||
changeSection();
|
changeSection();
|
||||||
curOffset = mod == SECTION_UNION ? 0 : sect->size;
|
curOffset = mod == SECTION_UNION ? 0 : sect->size;
|
||||||
@@ -412,7 +410,7 @@ void sect_NewSection(char const *name, enum SectionType type, uint32_t org,
|
|||||||
|
|
||||||
// Set the current section by name and type
|
// Set the current section by name and type
|
||||||
void sect_SetLoadSection(char const *name, enum SectionType type, uint32_t org,
|
void sect_SetLoadSection(char const *name, enum SectionType type, uint32_t org,
|
||||||
SectionSpec const *attribs, enum SectionModifier mod)
|
SectionSpec const &attrs, enum SectionModifier mod)
|
||||||
{
|
{
|
||||||
// Important info: currently, UNION and LOAD cannot interact, since UNION is prohibited in
|
// Important info: currently, UNION and LOAD cannot interact, since UNION is prohibited in
|
||||||
// "code" sections, whereas LOAD is restricted to them.
|
// "code" sections, whereas LOAD is restricted to them.
|
||||||
@@ -437,7 +435,7 @@ void sect_SetLoadSection(char const *name, enum SectionType type, uint32_t org,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Section *sect = getSection(name, type, org, attribs, mod);
|
Section *sect = getSection(name, type, org, attrs, mod);
|
||||||
|
|
||||||
currentLoadScope = sym_GetCurrentSymbolScope();
|
currentLoadScope = sym_GetCurrentSymbolScope();
|
||||||
changeSection();
|
changeSection();
|
||||||
@@ -557,7 +555,7 @@ static void writelong(uint32_t b)
|
|||||||
writebyte(b >> 24);
|
writebyte(b >> 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void createPatch(enum PatchType type, Expression const *expr, uint32_t pcShift)
|
static void createPatch(enum PatchType type, Expression const &expr, uint32_t pcShift)
|
||||||
{
|
{
|
||||||
out_CreatePatch(type, expr, sect_GetOutputOffset(), pcShift);
|
out_CreatePatch(type, expr, sect_GetOutputOffset(), pcShift);
|
||||||
}
|
}
|
||||||
@@ -683,18 +681,18 @@ void sect_Skip(uint32_t skip, bool ds)
|
|||||||
|
|
||||||
// Output a relocatable byte. Checking will be done to see if it
|
// Output a relocatable byte. Checking will be done to see if it
|
||||||
// is an absolute value in disguise.
|
// is an absolute value in disguise.
|
||||||
void sect_RelByte(Expression *expr, uint32_t pcShift)
|
void sect_RelByte(Expression &expr, uint32_t pcShift)
|
||||||
{
|
{
|
||||||
if (!checkcodesection())
|
if (!checkcodesection())
|
||||||
return;
|
return;
|
||||||
if (!reserveSpace(1))
|
if (!reserveSpace(1))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!expr->isKnown) {
|
if (!expr.isKnown) {
|
||||||
createPatch(PATCHTYPE_BYTE, expr, pcShift);
|
createPatch(PATCHTYPE_BYTE, expr, pcShift);
|
||||||
writebyte(0);
|
writebyte(0);
|
||||||
} else {
|
} else {
|
||||||
writebyte(expr->val);
|
writebyte(expr.val);
|
||||||
}
|
}
|
||||||
rpn_Free(expr);
|
rpn_Free(expr);
|
||||||
}
|
}
|
||||||
@@ -712,7 +710,7 @@ void sect_RelBytes(uint32_t n, std::vector<Expression> &exprs)
|
|||||||
Expression &expr = exprs[i % exprs.size()];
|
Expression &expr = exprs[i % exprs.size()];
|
||||||
|
|
||||||
if (!expr.isKnown) {
|
if (!expr.isKnown) {
|
||||||
createPatch(PATCHTYPE_BYTE, &expr, i);
|
createPatch(PATCHTYPE_BYTE, expr, i);
|
||||||
writebyte(0);
|
writebyte(0);
|
||||||
} else {
|
} else {
|
||||||
writebyte(expr.val);
|
writebyte(expr.val);
|
||||||
@@ -720,48 +718,48 @@ void sect_RelBytes(uint32_t n, std::vector<Expression> &exprs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (Expression &expr : exprs)
|
for (Expression &expr : exprs)
|
||||||
rpn_Free(&expr);
|
rpn_Free(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output a relocatable word. Checking will be done to see if
|
// Output a relocatable word. Checking will be done to see if
|
||||||
// it's an absolute value in disguise.
|
// it's an absolute value in disguise.
|
||||||
void sect_RelWord(Expression *expr, uint32_t pcShift)
|
void sect_RelWord(Expression &expr, uint32_t pcShift)
|
||||||
{
|
{
|
||||||
if (!checkcodesection())
|
if (!checkcodesection())
|
||||||
return;
|
return;
|
||||||
if (!reserveSpace(2))
|
if (!reserveSpace(2))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!expr->isKnown) {
|
if (!expr.isKnown) {
|
||||||
createPatch(PATCHTYPE_WORD, expr, pcShift);
|
createPatch(PATCHTYPE_WORD, expr, pcShift);
|
||||||
writeword(0);
|
writeword(0);
|
||||||
} else {
|
} else {
|
||||||
writeword(expr->val);
|
writeword(expr.val);
|
||||||
}
|
}
|
||||||
rpn_Free(expr);
|
rpn_Free(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output a relocatable longword. Checking will be done to see if
|
// Output a relocatable longword. Checking will be done to see if
|
||||||
// is an absolute value in disguise.
|
// is an absolute value in disguise.
|
||||||
void sect_RelLong(Expression *expr, uint32_t pcShift)
|
void sect_RelLong(Expression &expr, uint32_t pcShift)
|
||||||
{
|
{
|
||||||
if (!checkcodesection())
|
if (!checkcodesection())
|
||||||
return;
|
return;
|
||||||
if (!reserveSpace(2))
|
if (!reserveSpace(2))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!expr->isKnown) {
|
if (!expr.isKnown) {
|
||||||
createPatch(PATCHTYPE_LONG, expr, pcShift);
|
createPatch(PATCHTYPE_LONG, expr, pcShift);
|
||||||
writelong(0);
|
writelong(0);
|
||||||
} else {
|
} else {
|
||||||
writelong(expr->val);
|
writelong(expr.val);
|
||||||
}
|
}
|
||||||
rpn_Free(expr);
|
rpn_Free(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output a PC-relative relocatable byte. Checking will be done to see if it
|
// Output a PC-relative relocatable byte. Checking will be done to see if it
|
||||||
// is an absolute value in disguise.
|
// is an absolute value in disguise.
|
||||||
void sect_PCRelByte(Expression *expr, uint32_t pcShift)
|
void sect_PCRelByte(Expression &expr, uint32_t pcShift)
|
||||||
{
|
{
|
||||||
if (!checkcodesection())
|
if (!checkcodesection())
|
||||||
return;
|
return;
|
||||||
@@ -769,11 +767,11 @@ void sect_PCRelByte(Expression *expr, uint32_t pcShift)
|
|||||||
return;
|
return;
|
||||||
Symbol const *pc = sym_GetPC();
|
Symbol const *pc = sym_GetPC();
|
||||||
|
|
||||||
if (!expr->isDiffConstant(pc)) {
|
if (!expr.isDiffConstant(pc)) {
|
||||||
createPatch(PATCHTYPE_JR, expr, pcShift);
|
createPatch(PATCHTYPE_JR, expr, pcShift);
|
||||||
writebyte(0);
|
writebyte(0);
|
||||||
} else {
|
} else {
|
||||||
Symbol const *sym = expr->symbolOf();
|
Symbol const *sym = expr.symbolOf();
|
||||||
// The offset wraps (jump from ROM to HRAM, for example)
|
// The offset wraps (jump from ROM to HRAM, for example)
|
||||||
int16_t offset;
|
int16_t offset;
|
||||||
|
|
||||||
|
|||||||
@@ -42,10 +42,10 @@ bool sym_IsPC(Symbol const *sym)
|
|||||||
return sym == PCSymbol;
|
return sym == PCSymbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sym_ForEach(void (*callback)(Symbol *))
|
void sym_ForEach(void (*callback)(Symbol &))
|
||||||
{
|
{
|
||||||
for (auto &it : symbols)
|
for (auto &it : symbols)
|
||||||
callback(&it.second);
|
callback(it.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t Callback_NARG()
|
static int32_t Callback_NARG()
|
||||||
@@ -77,37 +77,37 @@ int32_t Symbol::getValue() const
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dumpFilename(Symbol const *sym)
|
static void dumpFilename(Symbol const &sym)
|
||||||
{
|
{
|
||||||
if (sym->src)
|
if (sym.src)
|
||||||
sym->src->dump(sym->fileLine);
|
sym.src->dump(sym.fileLine);
|
||||||
else if (sym->fileLine == 0)
|
else if (sym.fileLine == 0)
|
||||||
fputs("<command-line>", stderr);
|
fputs("<command-line>", stderr);
|
||||||
else
|
else
|
||||||
fputs("<builtin>", stderr);
|
fputs("<builtin>", stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a symbol's definition filename and line
|
// Set a symbol's definition filename and line
|
||||||
static void setSymbolFilename(Symbol *sym)
|
static void setSymbolFilename(Symbol &sym)
|
||||||
{
|
{
|
||||||
sym->src = fstk_GetFileStack(); // This is `nullptr` for built-ins
|
sym.src = fstk_GetFileStack(); // This is `nullptr` for built-ins
|
||||||
sym->fileLine = sym->src ? lexer_GetLineNo() : 0; // This is 1 for built-ins
|
sym.fileLine = sym.src ? lexer_GetLineNo() : 0; // This is 1 for built-ins
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update a symbol's definition filename and line
|
// Update a symbol's definition filename and line
|
||||||
static void updateSymbolFilename(Symbol *sym)
|
static void updateSymbolFilename(Symbol &sym)
|
||||||
{
|
{
|
||||||
FileStackNode *oldSrc = sym->src;
|
FileStackNode *oldSrc = sym.src;
|
||||||
|
|
||||||
setSymbolFilename(sym);
|
setSymbolFilename(sym);
|
||||||
// If the old node was referenced, ensure the new one is
|
// If the old node was referenced, ensure the new one is
|
||||||
if (oldSrc && oldSrc->referenced && oldSrc->ID != (uint32_t)-1)
|
if (oldSrc && oldSrc->referenced && oldSrc->ID != (uint32_t)-1)
|
||||||
out_RegisterNode(sym->src);
|
out_RegisterNode(sym.src);
|
||||||
// TODO: unref the old node, and use `out_ReplaceNode` instead of deleting it
|
// TODO: unref the old node, and use `out_ReplaceNode` instead of deleting it
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new symbol by name
|
// Create a new symbol by name
|
||||||
static Symbol *createsymbol(char const *symName)
|
static Symbol &createsymbol(char const *symName)
|
||||||
{
|
{
|
||||||
Symbol &sym = symbols[symName];
|
Symbol &sym = symbols[symName];
|
||||||
|
|
||||||
@@ -118,10 +118,10 @@ static Symbol *createsymbol(char const *symName)
|
|||||||
sym.isBuiltin = false;
|
sym.isBuiltin = false;
|
||||||
sym.hasCallback = false;
|
sym.hasCallback = false;
|
||||||
sym.section = nullptr;
|
sym.section = nullptr;
|
||||||
setSymbolFilename(&sym);
|
setSymbolFilename(sym);
|
||||||
sym.ID = -1;
|
sym.ID = -1;
|
||||||
|
|
||||||
return &sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates the full name of a local symbol in a given scope, by prepending
|
// Creates the full name of a local symbol in a given scope, by prepending
|
||||||
@@ -137,11 +137,11 @@ static void fullSymbolName(char *output, size_t outputSize,
|
|||||||
fatalerror("Symbol name is too long: '%s%s'\n", scopeName, localName);
|
fatalerror("Symbol name is too long: '%s%s'\n", scopeName, localName);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void assignStringSymbol(Symbol *sym, char const *value)
|
static void assignStringSymbol(Symbol &sym, char const *value)
|
||||||
{
|
{
|
||||||
sym->type = SYM_EQUS;
|
sym.type = SYM_EQUS;
|
||||||
sym->equs = new(std::nothrow) std::string(value);
|
sym.equs = new(std::nothrow) std::string(value);
|
||||||
if (!sym->equs)
|
if (!sym.equs)
|
||||||
fatalerror("No memory for string equate: %s\n", strerror(errno));
|
fatalerror("No memory for string equate: %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,11 +188,6 @@ Symbol const *sym_GetPC()
|
|||||||
return PCSymbol;
|
return PCSymbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isReferenced(Symbol const *sym)
|
|
||||||
{
|
|
||||||
return sym->ID != (uint32_t)-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Purge a symbol
|
// Purge a symbol
|
||||||
void sym_Purge(std::string const &symName)
|
void sym_Purge(std::string const &symName)
|
||||||
{
|
{
|
||||||
@@ -202,7 +197,7 @@ void sym_Purge(std::string const &symName)
|
|||||||
error("'%s' not defined\n", symName.c_str());
|
error("'%s' not defined\n", symName.c_str());
|
||||||
} else if (sym->isBuiltin) {
|
} else if (sym->isBuiltin) {
|
||||||
error("Built-in symbol '%s' cannot be purged\n", symName.c_str());
|
error("Built-in symbol '%s' cannot be purged\n", symName.c_str());
|
||||||
} else if (isReferenced(sym)) {
|
} else if (sym->ID != (uint32_t)-1) {
|
||||||
error("Symbol \"%s\" is referenced and thus cannot be purged\n", symName.c_str());
|
error("Symbol \"%s\" is referenced and thus cannot be purged\n", symName.c_str());
|
||||||
} else {
|
} else {
|
||||||
// Do not keep a reference to the label's name after purging it
|
// Do not keep a reference to the label's name after purging it
|
||||||
@@ -274,16 +269,16 @@ static Symbol *createNonrelocSymbol(char const *symName, bool numeric)
|
|||||||
Symbol *sym = sym_FindExactSymbol(symName);
|
Symbol *sym = sym_FindExactSymbol(symName);
|
||||||
|
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
sym = createsymbol(symName);
|
sym = &createsymbol(symName);
|
||||||
} else if (sym->isDefined()) {
|
} else if (sym->isDefined()) {
|
||||||
error("'%s' already defined at ", symName);
|
error("'%s' already defined at ", symName);
|
||||||
dumpFilename(sym);
|
dumpFilename(*sym);
|
||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
return nullptr; // Don't allow overriding the symbol, that'd be bad!
|
return nullptr; // Don't allow overriding the symbol, that'd be bad!
|
||||||
} else if (!numeric) {
|
} else if (!numeric) {
|
||||||
// The symbol has already been referenced, but it's not allowed
|
// The symbol has already been referenced, but it's not allowed
|
||||||
error("'%s' already referenced at ", symName);
|
error("'%s' already referenced at ", symName);
|
||||||
dumpFilename(sym);
|
dumpFilename(*sym);
|
||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
return nullptr; // Don't allow overriding the symbol, that'd be bad!
|
return nullptr; // Don't allow overriding the symbol, that'd be bad!
|
||||||
}
|
}
|
||||||
@@ -314,7 +309,7 @@ Symbol *sym_RedefEqu(char const *symName, int32_t value)
|
|||||||
|
|
||||||
if (sym->isDefined() && sym->type != SYM_EQU) {
|
if (sym->isDefined() && sym->type != SYM_EQU) {
|
||||||
error("'%s' already defined as non-EQU at ", symName);
|
error("'%s' already defined as non-EQU at ", symName);
|
||||||
dumpFilename(sym);
|
dumpFilename(*sym);
|
||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} else if (sym->isBuiltin) {
|
} else if (sym->isBuiltin) {
|
||||||
@@ -322,7 +317,7 @@ Symbol *sym_RedefEqu(char const *symName, int32_t value)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSymbolFilename(sym);
|
updateSymbolFilename(*sym);
|
||||||
sym->type = SYM_EQU;
|
sym->type = SYM_EQU;
|
||||||
sym->value = value;
|
sym->value = value;
|
||||||
|
|
||||||
@@ -348,7 +343,7 @@ Symbol *sym_AddString(char const *symName, char const *value)
|
|||||||
if (!sym)
|
if (!sym)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
assignStringSymbol(sym, value);
|
assignStringSymbol(*sym, value);
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,7 +359,7 @@ Symbol *sym_RedefString(char const *symName, char const *value)
|
|||||||
error("'%s' already defined as non-EQUS at ", symName);
|
error("'%s' already defined as non-EQUS at ", symName);
|
||||||
else
|
else
|
||||||
error("'%s' already referenced at ", symName);
|
error("'%s' already referenced at ", symName);
|
||||||
dumpFilename(sym);
|
dumpFilename(*sym);
|
||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} else if (sym->isBuiltin) {
|
} else if (sym->isBuiltin) {
|
||||||
@@ -372,10 +367,10 @@ Symbol *sym_RedefString(char const *symName, char const *value)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSymbolFilename(sym);
|
updateSymbolFilename(*sym);
|
||||||
// FIXME: this leaks the previous `sym->equs`, but this can't delete it because the
|
// FIXME: this leaks the previous `sym->equs`, but this can't delete it because the
|
||||||
// expansion may be redefining itself.
|
// expansion may be redefining itself.
|
||||||
assignStringSymbol(sym, value);
|
assignStringSymbol(*sym, value);
|
||||||
|
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
@@ -386,15 +381,15 @@ Symbol *sym_AddVar(char const *symName, int32_t value)
|
|||||||
Symbol *sym = sym_FindExactSymbol(symName);
|
Symbol *sym = sym_FindExactSymbol(symName);
|
||||||
|
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
sym = createsymbol(symName);
|
sym = &createsymbol(symName);
|
||||||
} else if (sym->isDefined() && sym->type != SYM_VAR) {
|
} else if (sym->isDefined() && sym->type != SYM_VAR) {
|
||||||
error("'%s' already defined as %s at ",
|
error("'%s' already defined as %s at ",
|
||||||
symName, sym->type == SYM_LABEL ? "label" : "constant");
|
symName, sym->type == SYM_LABEL ? "label" : "constant");
|
||||||
dumpFilename(sym);
|
dumpFilename(*sym);
|
||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
return sym;
|
return sym;
|
||||||
} else {
|
} else {
|
||||||
updateSymbolFilename(sym);
|
updateSymbolFilename(*sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
sym->type = SYM_VAR;
|
sym->type = SYM_VAR;
|
||||||
@@ -414,14 +409,14 @@ static Symbol *addLabel(char const *symName)
|
|||||||
Symbol *sym = sym_FindExactSymbol(symName);
|
Symbol *sym = sym_FindExactSymbol(symName);
|
||||||
|
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
sym = createsymbol(symName);
|
sym = &createsymbol(symName);
|
||||||
} else if (sym->isDefined()) {
|
} else if (sym->isDefined()) {
|
||||||
error("'%s' already defined at ", symName);
|
error("'%s' already defined at ", symName);
|
||||||
dumpFilename(sym);
|
dumpFilename(*sym);
|
||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} else {
|
} else {
|
||||||
updateSymbolFilename(sym);
|
updateSymbolFilename(*sym);
|
||||||
}
|
}
|
||||||
// If the symbol already exists as a ref, just "take over" it
|
// If the symbol already exists as a ref, just "take over" it
|
||||||
sym->type = SYM_LABEL;
|
sym->type = SYM_LABEL;
|
||||||
@@ -550,7 +545,7 @@ Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char const *body, s
|
|||||||
if (!sym->macro)
|
if (!sym->macro)
|
||||||
fatalerror("No memory for macro: %s\n", strerror(errno));
|
fatalerror("No memory for macro: %s\n", strerror(errno));
|
||||||
|
|
||||||
setSymbolFilename(sym); // TODO: is this really necessary?
|
setSymbolFilename(*sym); // TODO: is this really necessary?
|
||||||
// The symbol is created at the line after the `endm`,
|
// The symbol is created at the line after the `endm`,
|
||||||
// override this with the actual definition line
|
// override this with the actual definition line
|
||||||
sym->fileLine = defLineNo;
|
sym->fileLine = defLineNo;
|
||||||
@@ -574,7 +569,7 @@ Symbol *sym_Ref(char const *symName)
|
|||||||
symName = fullname;
|
symName = fullname;
|
||||||
}
|
}
|
||||||
|
|
||||||
sym = createsymbol(symName);
|
sym = &createsymbol(symName);
|
||||||
sym->type = SYM_REF;
|
sym->type = SYM_REF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -589,7 +584,7 @@ void sym_SetExportAll(bool set)
|
|||||||
|
|
||||||
static Symbol *createBuiltinSymbol(char const *symName)
|
static Symbol *createBuiltinSymbol(char const *symName)
|
||||||
{
|
{
|
||||||
Symbol *sym = createsymbol(symName);
|
Symbol *sym = &createsymbol(symName);
|
||||||
|
|
||||||
sym->isBuiltin = true;
|
sym->isBuiltin = true;
|
||||||
sym->hasCallback = true;
|
sym->hasCallback = true;
|
||||||
@@ -602,7 +597,6 @@ static Symbol *createBuiltinSymbol(char const *symName)
|
|||||||
// Initialize the symboltable
|
// Initialize the symboltable
|
||||||
void sym_Init(time_t now)
|
void sym_Init(time_t now)
|
||||||
{
|
{
|
||||||
|
|
||||||
PCSymbol = createBuiltinSymbol("@");
|
PCSymbol = createBuiltinSymbol("@");
|
||||||
PCSymbol->type = SYM_LABEL;
|
PCSymbol->type = SYM_LABEL;
|
||||||
PCSymbol->numCallback = CallbackPC;
|
PCSymbol->numCallback = CallbackPC;
|
||||||
|
|||||||
Reference in New Issue
Block a user