mirror of
https://github.com/ksherlock/x65.git
synced 2025-01-16 08:33:28 +00:00
Object file now protects local labels
- XDEF declares labels as global - Each incobj file keeps its own protected set of labels for link-time evalulations
This commit is contained in:
parent
12cfe830f9
commit
071d64de80
333
x65.cpp
333
x65.cpp
@ -456,7 +456,6 @@ public:
|
|||||||
_capacity = 0;
|
_capacity = 0;
|
||||||
_count = 0;
|
_count = 0;
|
||||||
}
|
}
|
||||||
~pairArray() { clear(); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// relocs are cheaper than full expressions and work with
|
// relocs are cheaper than full expressions and work with
|
||||||
@ -553,7 +552,6 @@ typedef struct Section {
|
|||||||
// Symbol list entry (in order of parsing)
|
// Symbol list entry (in order of parsing)
|
||||||
struct MapSymbol {
|
struct MapSymbol {
|
||||||
strref name; // string name
|
strref name; // string name
|
||||||
// short section; // -1 if resolved, otherwise section index
|
|
||||||
short value;
|
short value;
|
||||||
bool local; // local variables
|
bool local; // local variables
|
||||||
bool resolved;
|
bool resolved;
|
||||||
@ -583,10 +581,11 @@ typedef struct {
|
|||||||
LET_BRANCH, // calculate a branch offset and store at this address
|
LET_BRANCH, // calculate a branch offset and store at this address
|
||||||
LET_BYTE, // calculate a byte and store at this address
|
LET_BYTE, // calculate a byte and store at this address
|
||||||
};
|
};
|
||||||
int target; // offset into output buffer
|
int target; // offset into output buffer
|
||||||
int address; // current pc
|
int address; // current pc
|
||||||
int scope; // scope pc
|
int scope; // scope pc
|
||||||
int section; // which section to apply to.
|
int section; // which section to apply to.
|
||||||
|
int file_ref; // -1 if current or xdef'd otherwise index of file for label
|
||||||
strref label; // valid if this is not a target but another label
|
strref label; // valid if this is not a target but another label
|
||||||
strref expression;
|
strref expression;
|
||||||
strref source_file;
|
strref source_file;
|
||||||
@ -635,6 +634,22 @@ typedef struct {
|
|||||||
unsigned short size;
|
unsigned short size;
|
||||||
} LabelStruct;
|
} LabelStruct;
|
||||||
|
|
||||||
|
// object file labels that are not xdef'd end up here
|
||||||
|
struct ExtLabels {
|
||||||
|
pairArray<unsigned int, Label> labels;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EvalContext {
|
||||||
|
int pc; // current address at point of eval
|
||||||
|
int scope_pc; // current scope open at point of eval
|
||||||
|
int scope_end_pc; // late scope closure after eval
|
||||||
|
int relative_section; // return can be relative to this section
|
||||||
|
int file_ref; // can access private label from this file or -1
|
||||||
|
EvalContext(int _pc, int _scope, int _close, int _sect) :
|
||||||
|
pc(_pc), scope_pc(_scope), scope_end_pc(_close), relative_section(_sect),
|
||||||
|
file_ref(-1) {}
|
||||||
|
};
|
||||||
|
|
||||||
// Source context is current file (include file, etc.) or current macro.
|
// Source context is current file (include file, etc.) or current macro.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
strref source_name; // source file name (error output)
|
strref source_name; // source file name (error output)
|
||||||
@ -679,6 +694,8 @@ public:
|
|||||||
pairArray<unsigned int, Macro> macros;
|
pairArray<unsigned int, Macro> macros;
|
||||||
pairArray<unsigned int, LabelPool> labelPools;
|
pairArray<unsigned int, LabelPool> labelPools;
|
||||||
pairArray<unsigned int, LabelStruct> labelStructs;
|
pairArray<unsigned int, LabelStruct> labelStructs;
|
||||||
|
// labels matching xdef names will be marked as external
|
||||||
|
pairArray<unsigned int, strref> xdefs;
|
||||||
|
|
||||||
std::vector<LateEval> lateEval;
|
std::vector<LateEval> lateEval;
|
||||||
std::vector<LocalLabelRecord> localLabels;
|
std::vector<LocalLabelRecord> localLabels;
|
||||||
@ -686,6 +703,7 @@ public:
|
|||||||
std::vector<MemberOffset> structMembers; // labelStructs refer to sets of structMembers
|
std::vector<MemberOffset> structMembers; // labelStructs refer to sets of structMembers
|
||||||
std::vector<strref> includePaths;
|
std::vector<strref> includePaths;
|
||||||
std::vector<Section> allSections;
|
std::vector<Section> allSections;
|
||||||
|
std::vector<ExtLabels> externals; // external labels organized by object file
|
||||||
MapSymbolArray map;
|
MapSymbolArray map;
|
||||||
|
|
||||||
// context for macros / include files
|
// context for macros / include files
|
||||||
@ -755,16 +773,17 @@ public:
|
|||||||
StatusCode BuildEnum(strref name, strref declaration);
|
StatusCode BuildEnum(strref name, strref declaration);
|
||||||
|
|
||||||
// Calculate a value based on an expression.
|
// Calculate a value based on an expression.
|
||||||
EvalOperator RPNToken_Merlin(strref &expression, int pc, int scope_pc,
|
EvalOperator RPNToken_Merlin(strref &expression, const struct EvalContext &etx,
|
||||||
int scope_end_pc, EvalOperator prev_op, short §ion, int &value);
|
EvalOperator prev_op, short §ion, int &value);
|
||||||
EvalOperator RPNToken(strref &expression, int pc, int scope_pc,
|
EvalOperator RPNToken(strref &expression, const struct EvalContext &etx,
|
||||||
int scope_end_pc, EvalOperator prev_op, short §ion, int &value);
|
EvalOperator prev_op, short §ion, int &value);
|
||||||
StatusCode EvalExpression(strref expression, int pc, int scope_pc,
|
StatusCode EvalExpression(strref expression, const struct EvalContext &etx, int &result);
|
||||||
int scope_end_pc, int relative_section, int &result);
|
|
||||||
|
|
||||||
// Access labels
|
// Access labels
|
||||||
Label* GetLabel(strref label);
|
Label* GetLabel(strref label);
|
||||||
|
Label* GetLabel(strref label, int file_ref);
|
||||||
Label* AddLabel(unsigned int hash);
|
Label* AddLabel(unsigned int hash);
|
||||||
|
bool MatchXDEF(strref label);
|
||||||
StatusCode AssignLabel(strref label, strref line, bool make_constant = false);
|
StatusCode AssignLabel(strref label, strref line, bool make_constant = false);
|
||||||
StatusCode AddressLabel(strref label);
|
StatusCode AddressLabel(strref label);
|
||||||
void LabelAdded(Label *pLabel, bool local=false);
|
void LabelAdded(Label *pLabel, bool local=false);
|
||||||
@ -824,17 +843,18 @@ public:
|
|||||||
|
|
||||||
// Clean up work allocations
|
// Clean up work allocations
|
||||||
void Asm::Cleanup() {
|
void Asm::Cleanup() {
|
||||||
for (std::vector<char*>::iterator i = loadedData.begin(); i!=loadedData.end(); ++i) {
|
for (std::vector<char*>::iterator i = loadedData.begin(); i!=loadedData.end(); ++i)
|
||||||
char *data = *i;
|
free(*i);
|
||||||
free(data);
|
|
||||||
}
|
|
||||||
map.clear();
|
map.clear();
|
||||||
labelPools.clear();
|
labelPools.clear();
|
||||||
loadedData.clear();
|
loadedData.clear();
|
||||||
labels.clear();
|
labels.clear();
|
||||||
macros.clear();
|
macros.clear();
|
||||||
allSections.clear();
|
allSections.clear();
|
||||||
SetSection(strref("default"));//, 0x10001);
|
for (std::vector<ExtLabels>::iterator exti = externals.begin(); exti !=externals.end(); ++exti)
|
||||||
|
exti->labels.clear();
|
||||||
|
externals.clear();
|
||||||
|
SetSection(strref("default")); // this section is relocatable but is assigned address $1000 if exporting without directives
|
||||||
current_section = &allSections[0];
|
current_section = &allSections[0];
|
||||||
syntax = SYNTAX_SANE;
|
syntax = SYNTAX_SANE;
|
||||||
scope_depth = 0;
|
scope_depth = 0;
|
||||||
@ -1282,13 +1302,15 @@ StatusCode Asm::BuildEnum(strref name, strref declaration)
|
|||||||
pEnum->size = 0; // enums are 0 sized
|
pEnum->size = 0; // enums are 0 sized
|
||||||
int value = 0;
|
int value = 0;
|
||||||
|
|
||||||
|
struct EvalContext etx(CurrSection().GetPC(),
|
||||||
|
scope_address[scope_depth], -1, -1);
|
||||||
|
|
||||||
while (strref line = declaration.line()) {
|
while (strref line = declaration.line()) {
|
||||||
line = line.before_or_full(',');
|
line = line.before_or_full(',');
|
||||||
line.trim_whitespace();
|
line.trim_whitespace();
|
||||||
strref name = line.split_token_trim('=');
|
strref name = line.split_token_trim('=');
|
||||||
if (line) {
|
if (line) {
|
||||||
StatusCode error = EvalExpression(line, CurrSection().GetPC(),
|
StatusCode error = EvalExpression(line, etx, value);
|
||||||
scope_address[scope_depth], -1, -1, value);
|
|
||||||
if (error == STATUS_NOT_READY)
|
if (error == STATUS_NOT_READY)
|
||||||
return ERROR_ENUM_CANT_BE_ASSEMBLED;
|
return ERROR_ENUM_CANT_BE_ASSEMBLED;
|
||||||
else if (error != STATUS_OK)
|
else if (error != STATUS_OK)
|
||||||
@ -1428,7 +1450,7 @@ StatusCode Asm::EvalStruct(strref name, int &value)
|
|||||||
|
|
||||||
|
|
||||||
// Get a single token from a merlin expression
|
// Get a single token from a merlin expression
|
||||||
EvalOperator Asm::RPNToken_Merlin(strref &expression, int pc, int scope_pc, int scope_end_pc, EvalOperator prev_op, short §ion, int &value)
|
EvalOperator Asm::RPNToken_Merlin(strref &expression, const struct EvalContext &etx, EvalOperator prev_op, short §ion, int &value)
|
||||||
{
|
{
|
||||||
char c = expression.get_first();
|
char c = expression.get_first();
|
||||||
switch (c) {
|
switch (c) {
|
||||||
@ -1439,7 +1461,7 @@ EvalOperator Asm::RPNToken_Merlin(strref &expression, int pc, int scope_pc, int
|
|||||||
++expression;
|
++expression;
|
||||||
if (expression[0] == '*') return EVOP_STP; // double asterisks indicates comment
|
if (expression[0] == '*') return EVOP_STP; // double asterisks indicates comment
|
||||||
else if (prev_op==EVOP_VAL || prev_op==EVOP_RPR) return EVOP_MUL;
|
else if (prev_op==EVOP_VAL || prev_op==EVOP_RPR) return EVOP_MUL;
|
||||||
value = pc; section = CurrSection().IsRelativeSection() ? SectionId() : -1; return EVOP_VAL;
|
value = etx.pc; section = CurrSection().IsRelativeSection() ? SectionId() : -1; return EVOP_VAL;
|
||||||
case '/': ++expression; return EVOP_DIV;
|
case '/': ++expression; return EVOP_DIV;
|
||||||
case '>': if (expression.get_len() >= 2 && expression[1] == '>') { expression += 2; return EVOP_SHR; }
|
case '>': if (expression.get_len() >= 2 && expression[1] == '>') { expression += 2; return EVOP_SHR; }
|
||||||
++expression; return EVOP_HIB;
|
++expression; return EVOP_HIB;
|
||||||
@ -1448,8 +1470,8 @@ EvalOperator Asm::RPNToken_Merlin(strref &expression, int pc, int scope_pc, int
|
|||||||
case '%': // % means both binary and scope closure, disambiguate!
|
case '%': // % means both binary and scope closure, disambiguate!
|
||||||
if (expression[1]=='0' || expression[1]=='1') {
|
if (expression[1]=='0' || expression[1]=='1') {
|
||||||
++expression; value = expression.abinarytoui_skip(); return EVOP_VAL; }
|
++expression; value = expression.abinarytoui_skip(); return EVOP_VAL; }
|
||||||
if (scope_end_pc<0) return EVOP_NRY;
|
if (etx.scope_end_pc<0) return EVOP_NRY;
|
||||||
++expression; value = scope_end_pc; section = CurrSection().IsRelativeSection() ? SectionId() : -1; return EVOP_VAL;
|
++expression; value = etx.scope_end_pc; section = CurrSection().IsRelativeSection() ? SectionId() : -1; return EVOP_VAL;
|
||||||
case '|':
|
case '|':
|
||||||
case '.': ++expression; return EVOP_OR; // MERLIN: . is or, | is not used
|
case '.': ++expression; return EVOP_OR; // MERLIN: . is or, | is not used
|
||||||
case '^': ++expression; return EVOP_EOR;
|
case '^': ++expression; return EVOP_EOR;
|
||||||
@ -1463,8 +1485,8 @@ EvalOperator Asm::RPNToken_Merlin(strref &expression, int pc, int scope_pc, int
|
|||||||
default: { // MERLIN: ! is eor
|
default: { // MERLIN: ! is eor
|
||||||
if (c == '!' && (prev_op == EVOP_VAL || prev_op == EVOP_RPR)) { ++expression; return EVOP_EOR; }
|
if (c == '!' && (prev_op == EVOP_VAL || prev_op == EVOP_RPR)) { ++expression; return EVOP_EOR; }
|
||||||
else if (c == '!' && !(expression + 1).len_label()) {
|
else if (c == '!' && !(expression + 1).len_label()) {
|
||||||
if (scope_pc < 0) return EVOP_NRY; // ! by itself is current scope, !+label char is a local label
|
if (etx.scope_pc < 0) return EVOP_NRY; // ! by itself is current scope, !+label char is a local label
|
||||||
++expression; value = scope_pc; section = CurrSection().IsRelativeSection() ? SectionId() : -1; return EVOP_VAL;
|
++expression; value = etx.scope_pc; section = CurrSection().IsRelativeSection() ? SectionId() : -1; return EVOP_VAL;
|
||||||
} else if (strref::is_number(c)) {
|
} else if (strref::is_number(c)) {
|
||||||
if (prev_op == EVOP_VAL) return EVOP_STP; // value followed by value doesn't make sense, stop
|
if (prev_op == EVOP_VAL) return EVOP_STP; // value followed by value doesn't make sense, stop
|
||||||
value = expression.atoi_skip(); return EVOP_VAL;
|
value = expression.atoi_skip(); return EVOP_VAL;
|
||||||
@ -1473,7 +1495,7 @@ EvalOperator Asm::RPNToken_Merlin(strref &expression, int pc, int scope_pc, int
|
|||||||
char e0 = expression[0];
|
char e0 = expression[0];
|
||||||
int start_pos = (e0==']' || e0==':' || e0=='!' || e0=='.') ? 1 : 0;
|
int start_pos = (e0==']' || e0==':' || e0=='!' || e0=='.') ? 1 : 0;
|
||||||
strref label = expression.split_range_trim(label_end_char_range_merlin, start_pos);
|
strref label = expression.split_range_trim(label_end_char_range_merlin, start_pos);
|
||||||
Label *pLabel = GetLabel(label);
|
Label *pLabel = pLabel = GetLabel(label, etx.file_ref);
|
||||||
if (!pLabel) {
|
if (!pLabel) {
|
||||||
StatusCode ret = EvalStruct(label, value);
|
StatusCode ret = EvalStruct(label, value);
|
||||||
if (ret == STATUS_OK) return EVOP_VAL;
|
if (ret == STATUS_OK) return EVOP_VAL;
|
||||||
@ -1490,7 +1512,7 @@ EvalOperator Asm::RPNToken_Merlin(strref &expression, int pc, int scope_pc, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get a single token from most non-apple II assemblers
|
// Get a single token from most non-apple II assemblers
|
||||||
EvalOperator Asm::RPNToken(strref &expression, int pc, int scope_pc, int scope_end_pc, EvalOperator prev_op, short §ion, int &value)
|
EvalOperator Asm::RPNToken(strref &expression, const struct EvalContext &etx, EvalOperator prev_op, short §ion, int &value)
|
||||||
{
|
{
|
||||||
char c = expression.get_first();
|
char c = expression.get_first();
|
||||||
switch (c) {
|
switch (c) {
|
||||||
@ -1501,7 +1523,7 @@ EvalOperator Asm::RPNToken(strref &expression, int pc, int scope_pc, int scope_e
|
|||||||
++expression;
|
++expression;
|
||||||
if (expression[0] == '*') return EVOP_STP; // double asterisks indicates comment
|
if (expression[0] == '*') return EVOP_STP; // double asterisks indicates comment
|
||||||
else if (prev_op == EVOP_VAL || prev_op == EVOP_RPR) return EVOP_MUL;
|
else if (prev_op == EVOP_VAL || prev_op == EVOP_RPR) return EVOP_MUL;
|
||||||
value = pc; section = CurrSection().IsRelativeSection() ? SectionId() : -1; return EVOP_VAL;
|
value = etx.pc; section = CurrSection().IsRelativeSection() ? SectionId() : -1; return EVOP_VAL;
|
||||||
case '/': ++expression; return EVOP_DIV;
|
case '/': ++expression; return EVOP_DIV;
|
||||||
case '>': if (expression.get_len() >= 2 && expression[1] == '>') { expression += 2; return EVOP_SHR; }
|
case '>': if (expression.get_len() >= 2 && expression[1] == '>') { expression += 2; return EVOP_SHR; }
|
||||||
++expression; return EVOP_HIB;
|
++expression; return EVOP_HIB;
|
||||||
@ -1509,8 +1531,8 @@ EvalOperator Asm::RPNToken(strref &expression, int pc, int scope_pc, int scope_e
|
|||||||
++expression; return EVOP_LOB;
|
++expression; return EVOP_LOB;
|
||||||
case '%': // % means both binary and scope closure, disambiguate!
|
case '%': // % means both binary and scope closure, disambiguate!
|
||||||
if (expression[1] == '0' || expression[1] == '1') { ++expression; value = expression.abinarytoui_skip(); return EVOP_VAL; }
|
if (expression[1] == '0' || expression[1] == '1') { ++expression; value = expression.abinarytoui_skip(); return EVOP_VAL; }
|
||||||
if (scope_end_pc<0) return EVOP_NRY;
|
if (etx.scope_end_pc<0) return EVOP_NRY;
|
||||||
++expression; value = scope_end_pc; section = CurrSection().IsRelativeSection() ? SectionId() : -1; return EVOP_VAL;
|
++expression; value = etx.scope_end_pc; section = CurrSection().IsRelativeSection() ? SectionId() : -1; return EVOP_VAL;
|
||||||
case '|': ++expression; return EVOP_OR;
|
case '|': ++expression; return EVOP_OR;
|
||||||
case '^': ++expression; return EVOP_EOR;
|
case '^': ++expression; return EVOP_EOR;
|
||||||
case '&': ++expression; return EVOP_AND;
|
case '&': ++expression; return EVOP_AND;
|
||||||
@ -1521,8 +1543,8 @@ EvalOperator Asm::RPNToken(strref &expression, int pc, int scope_pc, int scope_e
|
|||||||
case '\'': return EVOP_STP;
|
case '\'': return EVOP_STP;
|
||||||
default: { // ! by itself is current scope, !+label char is a local label
|
default: { // ! by itself is current scope, !+label char is a local label
|
||||||
if (c == '!' && !(expression + 1).len_label()) {
|
if (c == '!' && !(expression + 1).len_label()) {
|
||||||
if (scope_pc < 0) return EVOP_NRY;
|
if (etx.scope_pc < 0) return EVOP_NRY;
|
||||||
++expression; value = scope_pc; section = CurrSection().IsRelativeSection() ? SectionId() : -1; return EVOP_VAL;
|
++expression; value = etx.scope_pc; section = CurrSection().IsRelativeSection() ? SectionId() : -1; return EVOP_VAL;
|
||||||
} else if (strref::is_number(c)) {
|
} else if (strref::is_number(c)) {
|
||||||
if (prev_op == EVOP_VAL) return EVOP_STP; // value followed by value doesn't make sense, stop
|
if (prev_op == EVOP_VAL) return EVOP_STP; // value followed by value doesn't make sense, stop
|
||||||
value = expression.atoi_skip(); return EVOP_VAL;
|
value = expression.atoi_skip(); return EVOP_VAL;
|
||||||
@ -1531,7 +1553,7 @@ EvalOperator Asm::RPNToken(strref &expression, int pc, int scope_pc, int scope_e
|
|||||||
char e0 = expression[0];
|
char e0 = expression[0];
|
||||||
int start_pos = (e0 == ':' || e0 == '!' || e0 == '.') ? 1 : 0;
|
int start_pos = (e0 == ':' || e0 == '!' || e0 == '.') ? 1 : 0;
|
||||||
strref label = expression.split_range_trim(label_end_char_range, start_pos);
|
strref label = expression.split_range_trim(label_end_char_range, start_pos);
|
||||||
Label *pLabel = GetLabel(label);
|
Label *pLabel = pLabel = GetLabel(label, etx.file_ref);
|
||||||
if (!pLabel) {
|
if (!pLabel) {
|
||||||
StatusCode ret = EvalStruct(label, value);
|
StatusCode ret = EvalStruct(label, value);
|
||||||
if (ret == STATUS_OK) return EVOP_VAL;
|
if (ret == STATUS_OK) return EVOP_VAL;
|
||||||
@ -1561,7 +1583,7 @@ EvalOperator Asm::RPNToken(strref &expression, int pc, int scope_pc, int scope_e
|
|||||||
// Max number of unresolved sections to evaluate in a single expression
|
// Max number of unresolved sections to evaluate in a single expression
|
||||||
#define MAX_EVAL_SECTIONS 4
|
#define MAX_EVAL_SECTIONS 4
|
||||||
|
|
||||||
StatusCode Asm::EvalExpression(strref expression, int pc, int scope_pc, int scope_end_pc, int relative_section, int &result)
|
StatusCode Asm::EvalExpression(strref expression, const struct EvalContext &etx, int &result)
|
||||||
{
|
{
|
||||||
int numValues = 0;
|
int numValues = 0;
|
||||||
int numOps = 0;
|
int numOps = 0;
|
||||||
@ -1582,9 +1604,9 @@ StatusCode Asm::EvalExpression(strref expression, int pc, int scope_pc, int scop
|
|||||||
short section = -1, index_section = -1;
|
short section = -1, index_section = -1;
|
||||||
EvalOperator op = EVOP_NONE;
|
EvalOperator op = EVOP_NONE;
|
||||||
if (syntax == SYNTAX_MERLIN)
|
if (syntax == SYNTAX_MERLIN)
|
||||||
op = RPNToken_Merlin(expression, pc, scope_pc, scope_end_pc, prev_op, section, value);
|
op = RPNToken_Merlin(expression, etx, prev_op, section, value);
|
||||||
else
|
else
|
||||||
op = RPNToken(expression, pc, scope_pc, scope_end_pc, prev_op, section, value);
|
op = RPNToken(expression, etx, prev_op, section, value);
|
||||||
if (op == EVOP_ERR)
|
if (op == EVOP_ERR)
|
||||||
return ERROR_UNEXPECTED_CHARACTER_IN_EXPRESSION;
|
return ERROR_UNEXPECTED_CHARACTER_IN_EXPRESSION;
|
||||||
else if (op == EVOP_NRY)
|
else if (op == EVOP_NRY)
|
||||||
@ -1723,9 +1745,9 @@ StatusCode Asm::EvalExpression(strref expression, int pc, int scope_pc, int scop
|
|||||||
if (section_counts[i][0]) {
|
if (section_counts[i][0]) {
|
||||||
if (section_counts[i][0]!=1 || section_index>=0)
|
if (section_counts[i][0]!=1 || section_index>=0)
|
||||||
return STATUS_NOT_READY;
|
return STATUS_NOT_READY;
|
||||||
else if (relative_section==section_ids[i])
|
else if (etx.relative_section==section_ids[i])
|
||||||
curr_relative = true;
|
curr_relative = true;
|
||||||
else if (relative_section>=0)
|
else if (etx.relative_section>=0)
|
||||||
return STATUS_NOT_READY;
|
return STATUS_NOT_READY;
|
||||||
section_index = i;
|
section_index = i;
|
||||||
}
|
}
|
||||||
@ -1752,6 +1774,7 @@ void Asm::AddLateEval(int target, int pc, int scope_pc, strref expression, strre
|
|||||||
le.scope = scope_pc;
|
le.scope = scope_pc;
|
||||||
le.target = target;
|
le.target = target;
|
||||||
le.section = (int)(&CurrSection() - &allSections[0]);
|
le.section = (int)(&CurrSection() - &allSections[0]);
|
||||||
|
le.file_ref = -1; // current or xdef'd
|
||||||
le.label.clear();
|
le.label.clear();
|
||||||
le.expression = expression;
|
le.expression = expression;
|
||||||
le.source_file = source_file;
|
le.source_file = source_file;
|
||||||
@ -1767,6 +1790,7 @@ void Asm::AddLateEval(strref label, int pc, int scope_pc, strref expression, Lat
|
|||||||
le.scope = scope_pc;
|
le.scope = scope_pc;
|
||||||
le.target = 0;
|
le.target = 0;
|
||||||
le.label = label;
|
le.label = label;
|
||||||
|
le.file_ref = -1; // current or xdef'd
|
||||||
le.expression = expression;
|
le.expression = expression;
|
||||||
le.source_file.clear();
|
le.source_file.clear();
|
||||||
le.type = type;
|
le.type = type;
|
||||||
@ -1808,8 +1832,10 @@ StatusCode Asm::CheckLateEval(strref added_label, int scope_end)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (check) {
|
if (check) {
|
||||||
StatusCode ret = EvalExpression(i->expression, i->address, i->scope, scope_end,
|
struct EvalContext etx(i->address, i->scope, scope_end,
|
||||||
i->type==LateEval::LET_BRANCH ? SectionId() : -1, value);
|
i->type == LateEval::LET_BRANCH ? SectionId() : -1);
|
||||||
|
etx.file_ref = i->file_ref;
|
||||||
|
StatusCode ret = EvalExpression(i->expression, etx, value);
|
||||||
if (ret == STATUS_OK || ret==STATUS_RELATIVE_SECTION) {
|
if (ret == STATUS_OK || ret==STATUS_RELATIVE_SECTION) {
|
||||||
// Check if target section merged with another section
|
// Check if target section merged with another section
|
||||||
int trg = i->target;
|
int trg = i->target;
|
||||||
@ -1858,7 +1884,7 @@ StatusCode Asm::CheckLateEval(strref added_label, int scope_end)
|
|||||||
allSections[sec].SetWord(trg, value);
|
allSections[sec].SetWord(trg, value);
|
||||||
break;
|
break;
|
||||||
case LateEval::LET_LABEL: {
|
case LateEval::LET_LABEL: {
|
||||||
Label *label = GetLabel(i->label);
|
Label *label = GetLabel(i->label, i->file_ref);
|
||||||
if (!label)
|
if (!label)
|
||||||
return ERROR_LABEL_MISPLACED_INTERNAL;
|
return ERROR_LABEL_MISPLACED_INTERNAL;
|
||||||
label->value = value;
|
label->value = value;
|
||||||
@ -1909,6 +1935,22 @@ Label *Asm::GetLabel(strref label)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get a protected label record from a file if it exists
|
||||||
|
Label *Asm::GetLabel(strref label, int file_ref)
|
||||||
|
{
|
||||||
|
if (file_ref>=0 && file_ref<(int)externals.size()) {
|
||||||
|
ExtLabels &labs = externals[file_ref];
|
||||||
|
unsigned int label_hash = label.fnv1a();
|
||||||
|
unsigned int index = FindLabelIndex(label_hash, labs.labels.getKeys(), labs.labels.count());
|
||||||
|
while (index < labs.labels.count() && label_hash == labs.labels.getKey(index)) {
|
||||||
|
if (label.same_str(labs.labels.getValue(index).label_name))
|
||||||
|
return labs.labels.getValues() + index;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return GetLabel(label);
|
||||||
|
}
|
||||||
|
|
||||||
// If exporting labels, append this label to the list
|
// If exporting labels, append this label to the list
|
||||||
void Asm::LabelAdded(Label *pLabel, bool local)
|
void Asm::LabelAdded(Label *pLabel, bool local)
|
||||||
{
|
{
|
||||||
@ -2017,12 +2059,13 @@ StatusCode Asm::AddLabelPool(strref name, strref args)
|
|||||||
int ranges = 0;
|
int ranges = 0;
|
||||||
int num32 = 0;
|
int num32 = 0;
|
||||||
unsigned short aRng[256];
|
unsigned short aRng[256];
|
||||||
|
struct EvalContext etx(CurrSection().GetPC(), scope_address[scope_depth], -1, -1);
|
||||||
while (strref arg = args.split_token_trim(',')) {
|
while (strref arg = args.split_token_trim(',')) {
|
||||||
strref start = arg[0]=='(' ? arg.scoped_block_skip() : arg.split_token_trim('-');
|
strref start = arg[0]=='(' ? arg.scoped_block_skip() : arg.split_token_trim('-');
|
||||||
int addr0 = 0, addr1 = 0;
|
int addr0 = 0, addr1 = 0;
|
||||||
if (STATUS_OK != EvalExpression(start, CurrSection().GetPC(), scope_address[scope_depth], -1, -1, addr0))
|
if (STATUS_OK != EvalExpression(start, etx, addr0))
|
||||||
return ERROR_POOL_RANGE_EXPRESSION_EVAL;
|
return ERROR_POOL_RANGE_EXPRESSION_EVAL;
|
||||||
if (STATUS_OK != EvalExpression(arg, CurrSection().GetPC(), scope_address[scope_depth], -1, -1, addr1))
|
if (STATUS_OK != EvalExpression(arg, etx, addr1))
|
||||||
return ERROR_POOL_RANGE_EXPRESSION_EVAL;
|
return ERROR_POOL_RANGE_EXPRESSION_EVAL;
|
||||||
if (addr1<=addr0 || addr0<0)
|
if (addr1<=addr0 || addr0<0)
|
||||||
return ERROR_POOL_RANGE_EXPRESSION_EVAL;
|
return ERROR_POOL_RANGE_EXPRESSION_EVAL;
|
||||||
@ -2151,12 +2194,26 @@ StatusCode LabelPool::Release(unsigned int addr) {
|
|||||||
return STATUS_OK;
|
return STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if a label is marked as an xdef
|
||||||
|
bool Asm::MatchXDEF(strref label)
|
||||||
|
{
|
||||||
|
unsigned int hash = label.fnv1a();
|
||||||
|
unsigned int pos = FindLabelIndex(hash, xdefs.getKeys(), xdefs.count());
|
||||||
|
while (pos < xdefs.count() && xdefs.getKey(pos) == hash) {
|
||||||
|
if (label.same_str_case(xdefs.getValue(pos)))
|
||||||
|
return true;
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// assignment of label (<label> = <expression>)
|
// assignment of label (<label> = <expression>)
|
||||||
StatusCode Asm::AssignLabel(strref label, strref line, bool make_constant)
|
StatusCode Asm::AssignLabel(strref label, strref line, bool make_constant)
|
||||||
{
|
{
|
||||||
line.trim_whitespace();
|
line.trim_whitespace();
|
||||||
int val = 0;
|
int val = 0;
|
||||||
StatusCode status = EvalExpression(line, CurrSection().GetPC(), scope_address[scope_depth], -1, -1, val);
|
StatusCode status = EvalExpression(line, struct EvalContext(
|
||||||
|
CurrSection().GetPC(), scope_address[scope_depth], -1, -1), val);
|
||||||
if (status != STATUS_NOT_READY && status != STATUS_OK)
|
if (status != STATUS_NOT_READY && status != STATUS_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
@ -2175,7 +2232,7 @@ StatusCode Asm::AssignLabel(strref label, strref line, bool make_constant)
|
|||||||
pLabel->mapIndex = -1;
|
pLabel->mapIndex = -1;
|
||||||
pLabel->pc_relative = false;
|
pLabel->pc_relative = false;
|
||||||
pLabel->constant = make_constant;
|
pLabel->constant = make_constant;
|
||||||
pLabel->external = false;
|
pLabel->external = MatchXDEF(label);
|
||||||
|
|
||||||
bool local = label[0]=='.' || label[0]=='@' || label[0]=='!' || label[0]==':' || label.get_last()=='$';
|
bool local = label[0]=='.' || label[0]=='@' || label[0]=='!' || label[0]==':' || label.get_last()=='$';
|
||||||
if (!pLabel->evaluated)
|
if (!pLabel->evaluated)
|
||||||
@ -2207,7 +2264,7 @@ StatusCode Asm::AddressLabel(strref label)
|
|||||||
pLabel->value = CurrSection().GetPC();
|
pLabel->value = CurrSection().GetPC();
|
||||||
pLabel->evaluated = true;
|
pLabel->evaluated = true;
|
||||||
pLabel->pc_relative = true;
|
pLabel->pc_relative = true;
|
||||||
pLabel->external = false;
|
pLabel->external = MatchXDEF(label);
|
||||||
pLabel->constant = constLabel;
|
pLabel->constant = constLabel;
|
||||||
bool local = label[0]=='.' || label[0]=='@' || label[0]=='!' || label[0]==':' || label.get_last()=='$';
|
bool local = label[0]=='.' || label[0]=='@' || label[0]=='!' || label[0]==':' || label.get_last()=='$';
|
||||||
LabelAdded(pLabel, local);
|
LabelAdded(pLabel, local);
|
||||||
@ -2332,7 +2389,8 @@ void Asm::ConditionalElse() {
|
|||||||
StatusCode Asm::EvalStatement(strref line, bool &result)
|
StatusCode Asm::EvalStatement(strref line, bool &result)
|
||||||
{
|
{
|
||||||
int equ = line.find('=');
|
int equ = line.find('=');
|
||||||
if (equ >=0) {
|
struct EvalContext etx(CurrSection().GetPC(), scope_address[scope_depth], -1, -1);
|
||||||
|
if (equ >= 0) {
|
||||||
// (EXP) == (EXP)
|
// (EXP) == (EXP)
|
||||||
strref left = line.get_clipped(equ);
|
strref left = line.get_clipped(equ);
|
||||||
bool equal = left.get_last()!='!';
|
bool equal = left.get_last()!='!';
|
||||||
@ -2342,9 +2400,9 @@ StatusCode Asm::EvalStatement(strref line, bool &result)
|
|||||||
++right;
|
++right;
|
||||||
right.trim_whitespace();
|
right.trim_whitespace();
|
||||||
int value_left, value_right;
|
int value_left, value_right;
|
||||||
if (STATUS_OK != EvalExpression(left, CurrSection().GetPC(), scope_address[scope_depth], -1, -1, value_left))
|
if (STATUS_OK != EvalExpression(left, etx, value_left))
|
||||||
return ERROR_CONDITION_COULD_NOT_BE_RESOLVED;
|
return ERROR_CONDITION_COULD_NOT_BE_RESOLVED;
|
||||||
if (STATUS_OK != EvalExpression(right, CurrSection().GetPC(), scope_address[scope_depth], -1, -1, value_right))
|
if (STATUS_OK != EvalExpression(right, etx, value_right))
|
||||||
return ERROR_CONDITION_COULD_NOT_BE_RESOLVED;
|
return ERROR_CONDITION_COULD_NOT_BE_RESOLVED;
|
||||||
result = (value_left==value_right && equal) || (value_left!=value_right && !equal);
|
result = (value_left==value_right && equal) || (value_left!=value_right && !equal);
|
||||||
} else {
|
} else {
|
||||||
@ -2352,7 +2410,7 @@ StatusCode Asm::EvalStatement(strref line, bool &result)
|
|||||||
if (invert)
|
if (invert)
|
||||||
++line;
|
++line;
|
||||||
int value;
|
int value;
|
||||||
if (STATUS_OK != EvalExpression(line, CurrSection().GetPC(), scope_address[scope_depth], -1, -1, value))
|
if (STATUS_OK != EvalExpression(line, etx, value))
|
||||||
return ERROR_CONDITION_COULD_NOT_BE_RESOLVED;
|
return ERROR_CONDITION_COULD_NOT_BE_RESOLVED;
|
||||||
result = (value!=0 && !invert) || (value==0 && invert);
|
result = (value!=0 && !invert) || (value==0 && invert);
|
||||||
}
|
}
|
||||||
@ -2466,6 +2524,7 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
|
|||||||
if (dir!=AD_IF && dir!=AD_IFDEF && dir!=AD_ELSE && dir!=AD_ELIF && dir!=AD_ELSE && dir!=AD_ENDIF)
|
if (dir!=AD_IF && dir!=AD_IFDEF && dir!=AD_ELSE && dir!=AD_ELIF && dir!=AD_ELSE && dir!=AD_ENDIF)
|
||||||
return STATUS_OK;
|
return STATUS_OK;
|
||||||
}
|
}
|
||||||
|
struct EvalContext etx(CurrSection().GetPC(), scope_address[scope_depth], -1, -1);
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
case AD_ORG: { // org / pc: current address of code
|
case AD_ORG: { // org / pc: current address of code
|
||||||
int addr;
|
int addr;
|
||||||
@ -2474,7 +2533,7 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
|
|||||||
else if(keyword_equ.is_prefix_word(line)) // optional '=' or equ
|
else if(keyword_equ.is_prefix_word(line)) // optional '=' or equ
|
||||||
line.next_word_ws();
|
line.next_word_ws();
|
||||||
line.skip_whitespace();
|
line.skip_whitespace();
|
||||||
if ((error = EvalExpression(line, CurrSection().GetPC(), scope_address[scope_depth], -1, -1, addr))) {
|
if ((error = EvalExpression(line, etx, addr))) {
|
||||||
error = error == STATUS_NOT_READY ? ERROR_TARGET_ADDRESS_MUST_EVALUATE_IMMEDIATELY : error;
|
error = error == STATUS_NOT_READY ? ERROR_TARGET_ADDRESS_MUST_EVALUATE_IMMEDIATELY : error;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2493,7 +2552,7 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
|
|||||||
int addr;
|
int addr;
|
||||||
if (line[0]=='=' || keyword_equ.is_prefix_word(line))
|
if (line[0]=='=' || keyword_equ.is_prefix_word(line))
|
||||||
line.next_word_ws();
|
line.next_word_ws();
|
||||||
if ((error = EvalExpression(line, CurrSection().GetPC(), scope_address[scope_depth], -1, -1, addr))) {
|
if ((error = EvalExpression(line, etx, addr))) {
|
||||||
error = error == STATUS_NOT_READY ? ERROR_TARGET_ADDRESS_MUST_EVALUATE_IMMEDIATELY : error;
|
error = error == STATUS_NOT_READY ? ERROR_TARGET_ADDRESS_MUST_EVALUATE_IMMEDIATELY : error;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2520,16 +2579,34 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AD_XDEF:
|
case AD_XDEF: {
|
||||||
// this will store a string that when matched with a label will make that label external
|
// this stores a string that when matched with a label will make that label external
|
||||||
|
line.skip_whitespace();
|
||||||
|
strref xdef = line.split_range(syntax == SYNTAX_MERLIN ? label_end_char_range_merlin : label_end_char_range);
|
||||||
|
if (xdef) {
|
||||||
|
char f = xdef.get_first();
|
||||||
|
char e = xdef.get_last();
|
||||||
|
if (f != '.' && f != '!' && f != '@' && e != '$') {
|
||||||
|
unsigned int hash = xdef.fnv1a();
|
||||||
|
unsigned int pos = FindLabelIndex(hash, xdefs.getKeys(), xdefs.count());
|
||||||
|
while (pos < xdefs.count() && xdefs.getKey(pos) == hash) {
|
||||||
|
if (xdefs.getValue(pos).same_str_case(xdef))
|
||||||
|
return STATUS_OK;
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
xdefs.insert(pos, hash);
|
||||||
|
xdefs.getValues()[pos] = xdef;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case AD_ALIGN: // align: align address to multiple of value, fill space with 0
|
case AD_ALIGN: // align: align address to multiple of value, fill space with 0
|
||||||
if (line) {
|
if (line) {
|
||||||
if (line[0]=='=' || keyword_equ.is_prefix_word(line))
|
if (line[0]=='=' || keyword_equ.is_prefix_word(line))
|
||||||
line.next_word_ws();
|
line.next_word_ws();
|
||||||
int value;
|
int value;
|
||||||
int status = EvalExpression(line, CurrSection().GetPC(), scope_address[scope_depth], -1, -1, value);
|
int status = EvalExpression(line, etx, value);
|
||||||
if (status == STATUS_NOT_READY)
|
if (status == STATUS_NOT_READY)
|
||||||
error = ERROR_ALIGN_MUST_EVALUATE_IMMEDIATELY;
|
error = ERROR_ALIGN_MUST_EVALUATE_IMMEDIATELY;
|
||||||
else if (status == STATUS_OK && value>0) {
|
else if (status == STATUS_OK && value>0) {
|
||||||
@ -2543,8 +2620,7 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
|
|||||||
int value = 0;
|
int value = 0;
|
||||||
strref description = line.find(':')>=0 ? line.split_token_trim(':') : strref();
|
strref description = line.find(':')>=0 ? line.split_token_trim(':') : strref();
|
||||||
line.trim_whitespace();
|
line.trim_whitespace();
|
||||||
if (line && EvalExpression(line, CurrSection().GetPC(),
|
if (line && EvalExpression(line, etx, value) == STATUS_OK) {
|
||||||
scope_address[scope_depth], -1, -1, value) == STATUS_OK) {
|
|
||||||
if (description) {
|
if (description) {
|
||||||
printf("EVAL(%d): " STRREF_FMT ": \"" STRREF_FMT "\" = $%x\n",
|
printf("EVAL(%d): " STRREF_FMT ": \"" STRREF_FMT "\" = $%x\n",
|
||||||
contextStack.curr().source_file.count_lines(description)+1, STRREF_ARG(description), STRREF_ARG(line), value);
|
contextStack.curr().source_file.count_lines(description)+1, STRREF_ARG(description), STRREF_ARG(line), value);
|
||||||
@ -2564,7 +2640,7 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
|
|||||||
case AD_BYTES: // bytes: add bytes by comma separated values/expressions
|
case AD_BYTES: // bytes: add bytes by comma separated values/expressions
|
||||||
while (strref exp = line.split_token_trim(',')) {
|
while (strref exp = line.split_token_trim(',')) {
|
||||||
int value;
|
int value;
|
||||||
error = EvalExpression(exp, CurrSection().GetPC(), scope_address[scope_depth], -1, -1, value);
|
error = EvalExpression(exp, etx, value);
|
||||||
if (error>STATUS_NOT_READY)
|
if (error>STATUS_NOT_READY)
|
||||||
break;
|
break;
|
||||||
else if (error==STATUS_NOT_READY)
|
else if (error==STATUS_NOT_READY)
|
||||||
@ -2579,7 +2655,7 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
|
|||||||
while (strref exp_w = line.split_token_trim(',')) {
|
while (strref exp_w = line.split_token_trim(',')) {
|
||||||
int value = 0;
|
int value = 0;
|
||||||
if (!CurrSection().IsDummySection()) {
|
if (!CurrSection().IsDummySection()) {
|
||||||
error = EvalExpression(exp_w, CurrSection().GetPC(), scope_address[scope_depth], -1, -1, value);
|
error = EvalExpression(exp_w, etx, value);
|
||||||
if (error>STATUS_NOT_READY)
|
if (error>STATUS_NOT_READY)
|
||||||
break;
|
break;
|
||||||
else if (error==STATUS_NOT_READY)
|
else if (error==STATUS_NOT_READY)
|
||||||
@ -2607,7 +2683,7 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
|
|||||||
while (strref exp_dc = line.split_token_trim(',')) {
|
while (strref exp_dc = line.split_token_trim(',')) {
|
||||||
int value = 0;
|
int value = 0;
|
||||||
if (!CurrSection().IsDummySection()) {
|
if (!CurrSection().IsDummySection()) {
|
||||||
error = EvalExpression(exp_dc, CurrSection().GetPC(), scope_address[scope_depth], -1, -1, value);
|
error = EvalExpression(exp_dc, etx, value);
|
||||||
if (error > STATUS_NOT_READY)
|
if (error > STATUS_NOT_READY)
|
||||||
break;
|
break;
|
||||||
else if (error == STATUS_NOT_READY)
|
else if (error == STATUS_NOT_READY)
|
||||||
@ -2852,8 +2928,7 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
|
|||||||
read_source.skip_whitespace();
|
read_source.skip_whitespace();
|
||||||
expression.trim_whitespace();
|
expression.trim_whitespace();
|
||||||
int count;
|
int count;
|
||||||
if (STATUS_OK != EvalExpression(expression, CurrSection().GetPC(),
|
if (STATUS_OK != EvalExpression(expression, etx, count)) {
|
||||||
scope_address[scope_depth], -1, -1, count)) {
|
|
||||||
error = ERROR_REPT_COUNT_EXPRESSION;
|
error = ERROR_REPT_COUNT_EXPRESSION;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2870,12 +2945,10 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
|
|||||||
line.clear();
|
line.clear();
|
||||||
break;
|
break;
|
||||||
case AD_DUMMY:
|
case AD_DUMMY:
|
||||||
// dummySection = true;
|
|
||||||
line.trim_whitespace();
|
line.trim_whitespace();
|
||||||
if (line) {
|
if (line) {
|
||||||
int reorg;
|
int reorg;
|
||||||
if (STATUS_OK == EvalExpression(line, CurrSection().GetPC(),
|
if (STATUS_OK == EvalExpression(line, etx, reorg)) {
|
||||||
scope_address[scope_depth], -1, -1, reorg)) {
|
|
||||||
DummySection(reorg);
|
DummySection(reorg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2885,12 +2958,10 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
|
|||||||
case AD_DUMMY_END:
|
case AD_DUMMY_END:
|
||||||
while (CurrSection().IsDummySection())
|
while (CurrSection().IsDummySection())
|
||||||
EndSection();
|
EndSection();
|
||||||
// dummySection = false;
|
|
||||||
break;
|
break;
|
||||||
case AD_DS: {
|
case AD_DS: {
|
||||||
int value;
|
int value;
|
||||||
if (STATUS_OK != EvalExpression(line, CurrSection().GetPC(),
|
if (STATUS_OK != EvalExpression(line, etx, value))
|
||||||
scope_address[scope_depth], -1, -1, value))
|
|
||||||
error = ERROR_DS_MUST_EVALUATE_IMMEDIATELY;
|
error = ERROR_DS_MUST_EVALUATE_IMMEDIATELY;
|
||||||
else {
|
else {
|
||||||
if (value > 0) {
|
if (value > 0) {
|
||||||
@ -3030,9 +3101,9 @@ StatusCode Asm::AddOpcode(strref line, int group, int index, strref source_file)
|
|||||||
Reloc::Type target_section_type = Reloc::NONE;
|
Reloc::Type target_section_type = Reloc::NONE;
|
||||||
bool evalLater = false;
|
bool evalLater = false;
|
||||||
if (expression) {
|
if (expression) {
|
||||||
error = EvalExpression(expression, CurrSection().GetPC(),
|
error = EvalExpression(expression, struct EvalContext(CurrSection().GetPC(),
|
||||||
scope_address[scope_depth], -1,
|
scope_address[scope_depth], -1,
|
||||||
(group==OPG_BRANCH ? SectionId() : -1), value);
|
group==OPG_BRANCH ? SectionId() : -1), value);
|
||||||
if (error == STATUS_NOT_READY) {
|
if (error == STATUS_NOT_READY) {
|
||||||
evalLater = true;
|
evalLater = true;
|
||||||
error = STATUS_OK;
|
error = STATUS_OK;
|
||||||
@ -3473,10 +3544,10 @@ struct ObjFileReloc {
|
|||||||
|
|
||||||
struct ObjFileLabel {
|
struct ObjFileLabel {
|
||||||
enum LabelFlags {
|
enum LabelFlags {
|
||||||
OFL_XDEF, // External
|
OFL_EVAL = (1<<15), // Evaluated (may still be relative)
|
||||||
OFL_EVAL, // Evaluated (may still be relative)
|
OFL_ADDR = (1<<14), // Address or Assign
|
||||||
OFL_ADDR, // Address or Assign
|
OFL_CNST = (1<<13), // Constant
|
||||||
OFL_CNST // Constant
|
OFL_XDEF = OFL_CNST-1 // External (index into file array)
|
||||||
};
|
};
|
||||||
struct ObjFileStr name;
|
struct ObjFileStr name;
|
||||||
int value;
|
int value;
|
||||||
@ -3549,6 +3620,10 @@ StatusCode Asm::WriteObjectFile(strref filename)
|
|||||||
hdr.map_symbols = (short)map.size();
|
hdr.map_symbols = (short)map.size();
|
||||||
hdr.stringdata = 0;
|
hdr.stringdata = 0;
|
||||||
|
|
||||||
|
// include space for external protected labels
|
||||||
|
for (std::vector<ExtLabels>::iterator el = externals.begin(); el != externals.end(); ++el)
|
||||||
|
hdr.labels += el->labels.count();
|
||||||
|
|
||||||
char *stringPool = nullptr;
|
char *stringPool = nullptr;
|
||||||
unsigned int stringPoolCap = 0;
|
unsigned int stringPoolCap = 0;
|
||||||
pairArray<unsigned int, int> stringArray;
|
pairArray<unsigned int, int> stringArray;
|
||||||
@ -3592,10 +3667,29 @@ StatusCode Asm::WriteObjectFile(strref filename)
|
|||||||
l.section = lo.section;
|
l.section = lo.section;
|
||||||
l.mapIndex = lo.mapIndex;
|
l.mapIndex = lo.mapIndex;
|
||||||
l.flags =
|
l.flags =
|
||||||
(lo.constant ? (1 << ObjFileLabel::OFL_CNST) : 0) |
|
(lo.constant ? ObjFileLabel::OFL_CNST : 0) |
|
||||||
(lo.pc_relative ? (1 << ObjFileLabel::OFL_ADDR) : 0) |
|
(lo.pc_relative ? ObjFileLabel::OFL_ADDR : 0) |
|
||||||
(lo.evaluated ? (1 << ObjFileLabel::OFL_EVAL) : 0) |
|
(lo.evaluated ? ObjFileLabel::OFL_EVAL : 0) |
|
||||||
(lo.external ? (1 << ObjFileLabel::OFL_XDEF) : 0);
|
(lo.external ? ObjFileLabel::OFL_XDEF : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// protected labels included from other object files
|
||||||
|
int file_index = 1;
|
||||||
|
for (std::vector<ExtLabels>::iterator el = externals.begin(); el != externals.end(); ++el) {
|
||||||
|
for (unsigned int li = 0; li < el->labels.count(); ++li) {
|
||||||
|
Label &lo = el->labels.getValue(li);
|
||||||
|
struct ObjFileLabel &l = aLabels[labs++];
|
||||||
|
l.name.offs = _AddStrPool(lo.label_name, &stringArray, &stringPool, hdr.stringdata, stringPoolCap);
|
||||||
|
l.value = lo.value;
|
||||||
|
l.section = lo.section;
|
||||||
|
l.mapIndex = lo.mapIndex;
|
||||||
|
l.flags =
|
||||||
|
(lo.constant ? ObjFileLabel::OFL_CNST : 0) |
|
||||||
|
(lo.pc_relative ? ObjFileLabel::OFL_ADDR : 0) |
|
||||||
|
(lo.evaluated ? ObjFileLabel::OFL_EVAL : 0) |
|
||||||
|
file_index;
|
||||||
|
}
|
||||||
|
file_index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// write out late evals
|
// write out late evals
|
||||||
@ -3657,6 +3751,7 @@ StatusCode Asm::WriteObjectFile(strref filename)
|
|||||||
StatusCode Asm::ReadObjectFile(strref filename)
|
StatusCode Asm::ReadObjectFile(strref filename)
|
||||||
{
|
{
|
||||||
size_t size;
|
size_t size;
|
||||||
|
int file_index = (int)externals.size();
|
||||||
if (char *data = LoadBinary(filename, size)) {
|
if (char *data = LoadBinary(filename, size)) {
|
||||||
struct ObjFileHeader &hdr = *(struct ObjFileHeader*)data;
|
struct ObjFileHeader &hdr = *(struct ObjFileHeader*)data;
|
||||||
size_t sum = sizeof(hdr) + hdr.sections*sizeof(struct ObjFileSection) +
|
size_t sum = sizeof(hdr) + hdr.sections*sizeof(struct ObjFileSection) +
|
||||||
@ -3719,40 +3814,6 @@ StatusCode Asm::ReadObjectFile(strref filename)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int li = 0; li < hdr.labels; li++) {
|
|
||||||
struct ObjFileLabel &l = aLabels[li];
|
|
||||||
strref name = l.name.offs >= 0 ? strref(str_pool + l.name.offs) : strref();
|
|
||||||
Label *lbl = GetLabel(name);
|
|
||||||
if (!lbl) {
|
|
||||||
lbl = AddLabel(name.fnv1a());
|
|
||||||
short f = l.flags;
|
|
||||||
lbl->label_name = name;
|
|
||||||
lbl->pool_name.clear();
|
|
||||||
lbl->value = l.value;
|
|
||||||
lbl->evaluated = !!(f&(1 << ObjFileLabel::OFL_EVAL));
|
|
||||||
lbl->constant = !!(f&(1 << ObjFileLabel::OFL_CNST));
|
|
||||||
lbl->pc_relative = !!(f&(1 << ObjFileLabel::OFL_ADDR));
|
|
||||||
lbl->external = !!(f&(1 << ObjFileLabel::OFL_XDEF));
|
|
||||||
lbl->section = l.section >= 0 ? aSctRmp[l.section] : l.section;
|
|
||||||
lbl->mapIndex = l.mapIndex + (int)map.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int li = 0; li < hdr.late_evals; ++li) {
|
|
||||||
struct ObjFileLateEval &le = aLateEval[li];
|
|
||||||
strref name = le.label.offs >= 0 ? strref(str_pool + le.label.offs) : strref();
|
|
||||||
Label *pLabel = GetLabel(name);
|
|
||||||
if (pLabel) {
|
|
||||||
if (pLabel->evaluated) {
|
|
||||||
AddLateEval(name, le.address, le.scope, strref(str_pool + le.expression.offs), (LateEval::Type)le.type);
|
|
||||||
lateEval[lateEval.size() - 1].section = le.section >= 0 ? aSctRmp[le.section] : le.section;
|
|
||||||
lateEval[lateEval.size() - 1].source_file = le.source_file.offs >= 0 ? strref(str_pool + le.source_file.offs) : strref();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
AddLateEval(le.target, le.address, le.scope, strref(str_pool + le.expression.offs), strref(str_pool + le.source_file.offs), (LateEval::Type)le.type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int mi = 0; mi < hdr.map_symbols; mi++) {
|
for (int mi = 0; mi < hdr.map_symbols; mi++) {
|
||||||
struct ObjFileMapSymbol &m = aMapSyms[mi];
|
struct ObjFileMapSymbol &m = aMapSyms[mi];
|
||||||
if (map.size() == map.capacity())
|
if (map.size() == map.capacity())
|
||||||
@ -3765,6 +3826,60 @@ StatusCode Asm::ReadObjectFile(strref filename)
|
|||||||
map.push_back(sym);
|
map.push_back(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int li = 0; li < hdr.labels; li++) {
|
||||||
|
struct ObjFileLabel &l = aLabels[li];
|
||||||
|
strref name = l.name.offs >= 0 ? strref(str_pool + l.name.offs) : strref();
|
||||||
|
Label *lbl = GetLabel(name);
|
||||||
|
if (!lbl) {
|
||||||
|
short f = l.flags;
|
||||||
|
int external = f & ObjFileLabel::OFL_XDEF;
|
||||||
|
if (external == ObjFileLabel::OFL_XDEF)
|
||||||
|
lbl = AddLabel(name.fnv1a()); // insert shared label
|
||||||
|
else { // insert protected label
|
||||||
|
while ((file_index + external) >= (int)externals.size()) {
|
||||||
|
if (externals.size() == externals.capacity())
|
||||||
|
externals.reserve(externals.size() + 32);
|
||||||
|
externals.push_back(ExtLabels());
|
||||||
|
}
|
||||||
|
unsigned int hash = name.fnv1a();
|
||||||
|
unsigned int index = FindLabelIndex(hash, externals[file_index].labels.getKeys(), externals[file_index].labels.count());
|
||||||
|
externals[file_index].labels.insert(index, hash);
|
||||||
|
lbl = externals[file_index].labels.getValues() + index;
|
||||||
|
}
|
||||||
|
lbl->label_name = name;
|
||||||
|
lbl->pool_name.clear();
|
||||||
|
lbl->value = l.value;
|
||||||
|
lbl->evaluated = !!(f & ObjFileLabel::OFL_EVAL);
|
||||||
|
lbl->constant = !!(f & ObjFileLabel::OFL_CNST);
|
||||||
|
lbl->pc_relative = !!(f & ObjFileLabel::OFL_ADDR);
|
||||||
|
lbl->external = external == ObjFileLabel::OFL_XDEF;
|
||||||
|
lbl->section = l.section >= 0 ? aSctRmp[l.section] : l.section;
|
||||||
|
lbl->mapIndex = l.mapIndex + (int)map.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_index==(int)externals.size())
|
||||||
|
file_index = -1; // no protected labels => don't track as separate file
|
||||||
|
|
||||||
|
for (int li = 0; li < hdr.late_evals; ++li) {
|
||||||
|
struct ObjFileLateEval &le = aLateEval[li];
|
||||||
|
strref name = le.label.offs >= 0 ? strref(str_pool + le.label.offs) : strref();
|
||||||
|
Label *pLabel = GetLabel(name);
|
||||||
|
if (pLabel) {
|
||||||
|
if (pLabel->evaluated) {
|
||||||
|
AddLateEval(name, le.address, le.scope, strref(str_pool + le.expression.offs), (LateEval::Type)le.type);
|
||||||
|
LateEval &last = lateEval[lateEval.size()-1];
|
||||||
|
last.section = le.section >= 0 ? aSctRmp[le.section] : le.section;
|
||||||
|
last.source_file = le.source_file.offs >= 0 ? strref(str_pool + le.source_file.offs) : strref();
|
||||||
|
last.file_ref = file_index;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AddLateEval(le.target, le.address, le.scope, strref(str_pool + le.expression.offs), strref(str_pool + le.source_file.offs), (LateEval::Type)le.type);
|
||||||
|
LateEval &last = lateEval[lateEval.size()-1];
|
||||||
|
last.file_ref = file_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
free(aSctRmp);
|
free(aSctRmp);
|
||||||
|
|
||||||
// restore previous section
|
// restore previous section
|
||||||
|
Loading…
x
Reference in New Issue
Block a user