Export and import of object files

First pass implementation of object files - all imported labels are
currently global.
This commit is contained in:
Carl-Henrik Skårstedt 2015-10-13 19:38:13 -07:00
parent 6962a98419
commit ca604ad81c
4 changed files with 492 additions and 89 deletions

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
# Asm6502 - Sublime Text Package [Sublime Text 3](http://www.sublimetext.com/3) is a great text editor that supports custom languages and build scripts, Asm6502.sublime-package is a single file collection of config files that enable Asm6502 language syntax, Asm6502 Build and an Asm6502 color theme that's got some c64 colors in it as well. Updates * 2015-10-06 Fixed some naming, added a bunch more directives as recognized keywords including a bunch for MERLIN / LISA assemblers. Copy Asm6502.sublime-package from this folder to: Windows: ``` %USERPROFILE%\AppData\Roaming\Sublime Text 3\Installed Packages\ ``` OSX: ``` ~/Library/Application Support/Sublime Text 3/Installed Packages/ ``` Compile a 64 or 32 bit release build of Asm6502 and put it into c:\c64\asm6502\asm6502.exe Download the Vice C64 Emulator into c:\vice or c:\c64\vice Within Sublime Text set the Build System to Asm6502 with a 6502 .s or .asm source file loaded and press Ctrl+B to build, or Ctrl+6 to build and launch Vice with the built prg file. With sincere apologies to the author of the Sublime Text package for Kick Assembler without which I would have spent countless hours to figure this out, check out the kick assembler Sublime package here: http://goatpower.org/projects-releases/sublime-package-kick-assembler-c64/ Feel free to modify this package as desired. To open up the individual files add a '.zip' extension to Asm6502.sublime-package and unzip it and paste the files to ``` ``` # Asm6502 - Sublime Text Package [Sublime Text 3](http://www.sublimetext.com/3) is a great text editor that supports custom languages and build scripts, x65.sublime-package is a single file collection of config files that enable Asm6502 language syntax, Asm6502 Build and an Asm6502 color theme that's got some c64 colors in it as well. Updates * 2015-10-06 Fixed some naming, added a bunch more directives as recognized keywords including a bunch for MERLIN / LISA assemblers. Copy x65.sublime-package from this folder to: Windows: ``` %USERPROFILE%\AppData\Roaming\Sublime Text 3\Installed Packages\ ``` OSX: ``` ~/Library/Application Support/Sublime Text 3/Installed Packages/ ``` Compile a 64 or 32 bit release build of Asm6502 and put it into c:\c64\asm6502\asm6502.exe Download the Vice C64 Emulator into c:\vice or c:\c64\vice Within Sublime Text set the Build System to x65 with a 6502 .s or .asm source file loaded and press Ctrl+B to build, or Ctrl+6 to build and launch Vice with the built prg file. With sincere apologies to the author of the Sublime Text package for Kick Assembler without which I would have spent countless hours to figure this out, check out the kick assembler Sublime package here: http://goatpower.org/projects-releases/sublime-package-kick-assembler-c64/ Feel free to modify this package as desired, or just unzip it if sublime doesn't recogize the package. To open up the individual files add a '.zip' extension to Asm6502.sublime-package and unzip it and paste the files to ``` * 2015-10-06 Fixed some naming, added a bunch more directives as recognized keywords including a bunch for MERLIN / LISA assemblers. ```

Binary file not shown.

577
x65.cpp
View File

@ -1,5 +1,5 @@
// //
// asm6502.cpp // x65.cpp
// //
// //
// Created by Carl-Henrik Skårstedt on 9/23/15. // Created by Carl-Henrik Skårstedt on 9/23/15.
@ -27,7 +27,7 @@
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// //
// Details, source and documentation at https://github.com/Sakrac/Asm6502. // Details, source and documentation at https://github.com/Sakrac/x65.
// //
// "struse.h" can be found at https://github.com/Sakrac/struse, only the header file is required. // "struse.h" can be found at https://github.com/Sakrac/struse, only the header file is required.
// //
@ -97,6 +97,7 @@ enum StatusCode {
ERROR_REPT_COUNT_EXPRESSION, ERROR_REPT_COUNT_EXPRESSION,
ERROR_HEX_WITH_ODD_NIBBLE_COUNT, ERROR_HEX_WITH_ODD_NIBBLE_COUNT,
ERROR_DS_MUST_EVALUATE_IMMEDIATELY, ERROR_DS_MUST_EVALUATE_IMMEDIATELY,
ERROR_NOT_AN_X65_OBJECT_FILE,
ERROR_STOP_PROCESSING_ON_HIGHER, // errors greater than this will stop execution ERROR_STOP_PROCESSING_ON_HIGHER, // errors greater than this will stop execution
@ -152,6 +153,7 @@ const char *aStatusStrings[STATUSCODE_COUNT] = {
"rept count expression could not be evaluated", "rept count expression could not be evaluated",
"hex must be followed by an even number of hex numbers", "hex must be followed by an even number of hex numbers",
"DS directive failed to evaluate immediately", "DS directive failed to evaluate immediately",
"File is not a valid x65 object file",
"Errors after this point will stop execution", "Errors after this point will stop execution",
@ -179,6 +181,8 @@ enum AssemblerDirective {
AD_LOAD, // LOAD: If applicable, instruct to load at this address AD_LOAD, // LOAD: If applicable, instruct to load at this address
AD_SECTION, // SECTION: Enable code that will be assigned a start address during a link step AD_SECTION, // SECTION: Enable code that will be assigned a start address during a link step
AD_LINK, // LINK: Put sections with this name at this address (must be ORG / fixed address section) AD_LINK, // LINK: Put sections with this name at this address (must be ORG / fixed address section)
AD_XDEF, // XDEF: Externally declare a label
AD_INCOBJ, // INCOBJ: Read in an object file saved from a previous build
AD_ALIGN, // ALIGN: Add to address to make it evenly divisible by this AD_ALIGN, // ALIGN: Add to address to make it evenly divisible by this
AD_MACRO, // MACRO: Create a macro AD_MACRO, // MACRO: Create a macro
AD_EVAL, // EVAL: Print expression to stdout during assemble AD_EVAL, // EVAL: Print expression to stdout during assemble
@ -340,7 +344,7 @@ static const strref c_comment("//");
static const strref word_char_range("!0-9a-zA-Z_@$!#"); static const strref word_char_range("!0-9a-zA-Z_@$!#");
static const strref label_end_char_range("!0-9a-zA-Z_@$!."); static const strref label_end_char_range("!0-9a-zA-Z_@$!.");
static const strref label_end_char_range_merlin("!0-9a-zA-Z_@$!]:?"); static const strref label_end_char_range_merlin("!0-9a-zA-Z_@$!]:?");
static const strref filename_end_char_range("!0-9a-zA-Z_!@#$%&()/\\-"); static const strref filename_end_char_range("!0-9a-zA-Z_!@#$%&()/\\-.");
static const strref keyword_equ("equ"); static const strref keyword_equ("equ");
static const strref str_label("label"); static const strref str_label("label");
static const strref str_const("const"); static const strref str_const("const");
@ -513,7 +517,7 @@ typedef struct Section {
void Cleanup() { if (output) free(output); reset(); } void Cleanup() { if (output) free(output); reset(); }
bool empty() const { return merged_offset<0 && curr==output; } bool empty() const { return merged_offset<0 && curr==output; }
size_t DataOffset() const { return curr - output; } int DataOffset() const { return int(curr - output); }
size_t size() const { return curr - output; } size_t size() const { return curr - output; }
const unsigned char *get() { return output; } const unsigned char *get() { return output; }
@ -547,9 +551,10 @@ 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 section; // -1 if resolved, otherwise section index
short value; short value;
bool local; // local variables bool local; // local variables
bool resolved;
}; };
typedef std::vector<struct MapSymbol> MapSymbolArray; typedef std::vector<struct MapSymbol> MapSymbolArray;
@ -564,6 +569,7 @@ public:
bool evaluated; // a value may not yet be evaluated bool evaluated; // a value may not yet be evaluated
bool pc_relative; // this is an inline label describing a point in the code bool pc_relative; // this is an inline label describing a point in the code
bool constant; // the value of this label can not change bool constant; // the value of this label can not change
bool external; // this label is globally accessible
} Label; } Label;
// If an expression can't be evaluated immediately, this is required // If an expression can't be evaluated immediately, this is required
@ -575,7 +581,7 @@ 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
}; };
size_t 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.
@ -709,7 +715,7 @@ public:
bool errorEncountered; bool errorEncountered;
// Convert source to binary // Convert source to binary
void Assemble(strref source, strref filename); void Assemble(strref source, strref filename, bool obj_target);
// Clean up memory allocations, reset assembler state // Clean up memory allocations, reset assembler state
void Cleanup(); void Cleanup();
@ -721,6 +727,7 @@ public:
void SetSection(strref name, int address); // fixed address section void SetSection(strref name, int address); // fixed address section
void SetSection(strref name); // relative address section void SetSection(strref name); // relative address section
StatusCode LinkSections(strref name); // link relative address sections with this name here StatusCode LinkSections(strref name); // link relative address sections with this name here
void LinkLabelsToAddress(int section_id, int section_address);
void DummySection(int address); void DummySection(int address);
void DummySection(); void DummySection();
void EndSection(); void EndSection();
@ -731,6 +738,10 @@ public:
void AddWord(int w) { CurrSection().AddWord(w); } void AddWord(int w) { CurrSection().AddWord(w); }
void AddBin(unsigned const char *p, int size) { CurrSection().AddBin(p, size); } void AddBin(unsigned const char *p, int size) { CurrSection().AddBin(p, size); }
// Object file handling
StatusCode WriteObjectFile(strref filename);
StatusCode ReadObjectFile(strref filename);
// Macro management // Macro management
StatusCode AddMacro(strref macro, strref source_name, strref source_file, strref &left); StatusCode AddMacro(strref macro, strref source_name, strref source_file, strref &left);
StatusCode BuildMacro(Macro &m, strref arg_list); StatusCode BuildMacro(Macro &m, strref arg_list);
@ -767,7 +778,7 @@ public:
void FlushLabelPools(int scope_exit); void FlushLabelPools(int scope_exit);
// Late expression evaluation // Late expression evaluation
void AddLateEval(int pc, int scope_pc, strref expression, void AddLateEval(int target, int pc, int scope_pc, strref expression,
strref source_file, LateEval::Type type); strref source_file, LateEval::Type type);
void AddLateEval(strref label, int pc, int scope_pc, void AddLateEval(strref label, int pc, int scope_pc,
strref expression, LateEval::Type type); strref expression, LateEval::Type type);
@ -884,6 +895,9 @@ char* Asm::LoadBinary(strref filename, size_t &size) {
if (file.get_last()!='/' && file.get_last()!='\\') if (file.get_last()!='/' && file.get_last()!='\\')
file.append('/'); file.append('/');
file.append(filename); file.append(filename);
#ifdef WIN32
file.replace('/', '\\');
#endif
++i; ++i;
} }
size = 0; size = 0;
@ -971,6 +985,26 @@ Section& Asm::ExportSection() {
return CurrSection(); return CurrSection();
} }
// Apply labels assigned to addresses in a relative section a fixed address
void Asm::LinkLabelsToAddress(int section_id, int section_address)
{
Label *pLabels = labels.getValues();
int numLabels = labels.count();
for (int l = 0; l < numLabels; l++) {
if (pLabels->section == section_id) {
pLabels->value += section_address;
pLabels->section = -1;
if (pLabels->mapIndex>=0 && pLabels->mapIndex<(int)map.size()) {
struct MapSymbol &msym = map[pLabels->mapIndex];
msym.value = pLabels->value;
msym.resolved = true;
}
CheckLateEval(pLabels->label_name);
}
++pLabels;
}
}
StatusCode Asm::LinkSections(strref name) { StatusCode Asm::LinkSections(strref name) {
if (CurrSection().IsRelativeSection()) if (CurrSection().IsRelativeSection())
return ERROR_LINKER_MUST_BE_IN_FIXED_ADDRESS_SECTION; return ERROR_LINKER_MUST_BE_IN_FIXED_ADDRESS_SECTION;
@ -1004,16 +1038,7 @@ StatusCode Asm::LinkSections(strref name) {
s.merged_offset = (int)(section_out - CurrSection().output); s.merged_offset = (int)(section_out - CurrSection().output);
// All labels in this section can now be assigned // All labels in this section can now be assigned
Label *pLabels = labels.getValues(); LinkLabelsToAddress(section_id, section_address);
int numLabels = labels.count();
for (int l = 0; l < numLabels; l++) {
if (pLabels->section == section_id) {
pLabels->value += section_address;
pLabels->section = -1;
CheckLateEval(pLabels->label_name);
}
++pLabels;
}
// go through relocs in all sections to see if any targets this section // go through relocs in all sections to see if any targets this section
// relocate section to address! // relocate section to address!
@ -1099,6 +1124,9 @@ void Section::AddReloc(int base, int offset, int section, Reloc::Type type)
pRelocs = new relocList; pRelocs = new relocList;
if (pRelocs->size() == pRelocs->capacity()) if (pRelocs->size() == pRelocs->capacity())
pRelocs->reserve(pRelocs->size() + 32); pRelocs->reserve(pRelocs->size() + 32);
printf("Add reloc base = $0x%04x offs=$0x%04x section=$0x%04x type = %d\n", base, offset, section, type);
pRelocs->push_back(Reloc(base, offset, section, type)); pRelocs->push_back(Reloc(base, offset, section, type));
} }
@ -1694,18 +1722,18 @@ StatusCode Asm::EvalExpression(strref expression, int pc, int scope_pc, int scop
// if an expression could not be evaluated, add it along with // if an expression could not be evaluated, add it along with
// the action to perform if it can be evaluated later. // the action to perform if it can be evaluated later.
void Asm::AddLateEval(int pc, int scope_pc, strref expression, strref source_file, LateEval::Type type) void Asm::AddLateEval(int target, int pc, int scope_pc, strref expression, strref source_file, LateEval::Type type)
{ {
LateEval le; LateEval le;
le.address = pc; le.address = pc;
le.scope = scope_pc; le.scope = scope_pc;
le.target = CurrSection().DataOffset(); le.target = target;
le.section = (int)(&CurrSection() - &allSections[0]); le.section = (int)(&CurrSection() - &allSections[0]);
le.label.clear(); le.label.clear();
le.expression = expression; le.expression = expression;
le.source_file = source_file; le.source_file = source_file;
le.type = type; le.type = type;
lateEval.push_back(le); lateEval.push_back(le);
} }
@ -1761,7 +1789,7 @@ StatusCode Asm::CheckLateEval(strref added_label, int scope_end)
i->type==LateEval::LET_BRANCH ? SectionId() : -1, value); i->type==LateEval::LET_BRANCH ? SectionId() : -1, 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
size_t trg = i->target; int trg = i->target;
int sec = i->section; int sec = i->section;
if (i->type != LateEval::LET_LABEL) { if (i->type != LateEval::LET_LABEL) {
if (allSections[sec].IsMergedSection()) { if (allSections[sec].IsMergedSection()) {
@ -1782,7 +1810,7 @@ StatusCode Asm::CheckLateEval(strref added_label, int scope_end)
if (i->section<0) if (i->section<0)
resolved = false; resolved = false;
else { else {
allSections[i->section].AddReloc(lastEvalValue, i->address, lastEvalSection, allSections[sec].AddReloc(lastEvalValue, trg, lastEvalSection,
lastEvalPart==Reloc::HI_BYTE ? Reloc::HI_BYTE : Reloc::LO_BYTE); lastEvalPart==Reloc::HI_BYTE ? Reloc::HI_BYTE : Reloc::LO_BYTE);
value = 0; value = 0;
} }
@ -1794,7 +1822,7 @@ StatusCode Asm::CheckLateEval(strref added_label, int scope_end)
if (i->section<0) if (i->section<0)
resolved = false; resolved = false;
else { else {
allSections[i->section].AddReloc(lastEvalValue, i->address, lastEvalSection, lastEvalPart); allSections[sec].AddReloc(lastEvalValue, trg, lastEvalSection, lastEvalPart);
value = 0; value = 0;
} }
} }
@ -1839,7 +1867,7 @@ StatusCode Asm::CheckLateEval(strref added_label, int scope_end)
// Get a labelc record if it exists // Get a label record if it exists
Label *Asm::GetLabel(strref label) Label *Asm::GetLabel(strref label)
{ {
unsigned int label_hash = label.fnv1a(); unsigned int label_hash = label.fnv1a();
@ -1860,10 +1888,10 @@ void Asm::LabelAdded(Label *pLabel, bool local)
map.reserve(map.size() + 256); map.reserve(map.size() + 256);
MapSymbol sym; MapSymbol sym;
sym.name = pLabel->label_name; sym.name = pLabel->label_name;
sym.section = pLabel->section; sym.resolved = pLabel->section < 0;
sym.value = pLabel->value; sym.value = pLabel->value;
sym.local = local; sym.local = local;
if (sym.section>=0) if (!sym.resolved)
pLabel->mapIndex = (int)map.size(); pLabel->mapIndex = (int)map.size();
else else
pLabel->mapIndex = -1; pLabel->mapIndex = -1;
@ -2022,6 +2050,7 @@ StatusCode Asm::AssignPoolLabel(LabelPool &pool, strref label)
pLabel->value = addr; pLabel->value = addr;
pLabel->pc_relative = true; pLabel->pc_relative = true;
pLabel->constant = true; pLabel->constant = true;
pLabel->external = false;
MarkLabelLocal(label, true); MarkLabelLocal(label, true);
return error; return error;
@ -2117,7 +2146,8 @@ 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;
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)
AddLateEval(label, CurrSection().GetPC(), scope_address[scope_depth], line, LateEval::LET_LABEL); AddLateEval(label, CurrSection().GetPC(), scope_address[scope_depth], line, LateEval::LET_LABEL);
@ -2148,6 +2178,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->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);
@ -2340,8 +2371,10 @@ DirectiveName aDirectiveNames[] {
{ "ORG", AD_ORG }, { "ORG", AD_ORG },
{ "LOAD", AD_LOAD }, { "LOAD", AD_LOAD },
{ "SECTION", AD_SECTION }, { "SECTION", AD_SECTION },
// { "SEG", AD_SECTION }, // DASM version of SECTION { "SEG", AD_SECTION }, // DASM version of SECTION
{ "LINK", AD_LINK }, { "LINK", AD_LINK },
{ "XDEF", AD_XDEF },
{ "INCOBJ", AD_INCOBJ },
{ "ALIGN", AD_ALIGN }, { "ALIGN", AD_ALIGN },
{ "MACRO", AD_MACRO }, { "MACRO", AD_MACRO },
{ "EVAL", AD_EVAL }, { "EVAL", AD_EVAL },
@ -2422,6 +2455,7 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
CurrSection().load_address = addr; CurrSection().load_address = addr;
CurrSection().address = addr; CurrSection().address = addr;
CurrSection().address_assigned = true; CurrSection().address_assigned = true;
LinkLabelsToAddress(SectionId(), addr); // in case any labels were defined prior to org & data
} else } else
SetSection(strref(), addr); SetSection(strref(), addr);
break; break;
@ -2448,6 +2482,19 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
error = LinkSections(line); error = LinkSections(line);
break; break;
case AD_INCOBJ: {
strref file = line.between('"', '"');
if (!file) // MERLIN: No quotes around PUT filenames
file = line.split_range(filename_end_char_range);
size_t size = 0;
error = ReadObjectFile(file);
break;
}
case AD_XDEF:
// this will store a string that when matched with a label will make that label external
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))
@ -2492,9 +2539,9 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
if (error>STATUS_NOT_READY) if (error>STATUS_NOT_READY)
break; break;
else if (error==STATUS_NOT_READY) else if (error==STATUS_NOT_READY)
AddLateEval(CurrSection().GetPC(), scope_address[scope_depth], exp, source_file, LateEval::LET_BYTE); AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], exp, source_file, LateEval::LET_BYTE);
else if (error == STATUS_RELATIVE_SECTION) else if (error == STATUS_RELATIVE_SECTION)
CurrSection().AddReloc(lastEvalValue, CurrSection().GetPC(), lastEvalSection, CurrSection().AddReloc(lastEvalValue, CurrSection().DataOffset(), lastEvalSection,
lastEvalPart == Reloc::HI_BYTE ? Reloc::HI_BYTE : Reloc::LO_BYTE); lastEvalPart == Reloc::HI_BYTE ? Reloc::HI_BYTE : Reloc::LO_BYTE);
AddByte(value); AddByte(value);
} }
@ -2507,9 +2554,9 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
if (error>STATUS_NOT_READY) if (error>STATUS_NOT_READY)
break; break;
else if (error==STATUS_NOT_READY) else if (error==STATUS_NOT_READY)
AddLateEval(CurrSection().GetPC(), scope_address[scope_depth], exp_w, source_file, LateEval::LET_ABS_REF); AddLateEval(CurrSection().DataOffset(), CurrSection().DataOffset(), scope_address[scope_depth], exp_w, source_file, LateEval::LET_ABS_REF);
else if (error == STATUS_RELATIVE_SECTION) { else if (error == STATUS_RELATIVE_SECTION) {
CurrSection().AddReloc(lastEvalValue, CurrSection().GetPC(), lastEvalSection, lastEvalPart); CurrSection().AddReloc(lastEvalValue, CurrSection().DataOffset(), lastEvalSection, lastEvalPart);
value = 0; value = 0;
} }
} }
@ -2535,13 +2582,13 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
if (error > STATUS_NOT_READY) if (error > STATUS_NOT_READY)
break; break;
else if (error == STATUS_NOT_READY) else if (error == STATUS_NOT_READY)
AddLateEval(CurrSection().GetPC(), scope_address[scope_depth], exp_dc, source_file, words ? LateEval::LET_ABS_REF : LateEval::LET_BYTE); AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], exp_dc, source_file, words ? LateEval::LET_ABS_REF : LateEval::LET_BYTE);
else if (error == STATUS_RELATIVE_SECTION) { else if (error == STATUS_RELATIVE_SECTION) {
value = 0; value = 0;
if (words) if (words)
CurrSection().AddReloc(lastEvalValue, CurrSection().GetPC(), lastEvalSection, lastEvalPart); CurrSection().AddReloc(lastEvalValue, CurrSection().DataOffset(), lastEvalSection, lastEvalPart);
else else
CurrSection().AddReloc(lastEvalValue, CurrSection().GetPC(), lastEvalSection, CurrSection().AddReloc(lastEvalValue, CurrSection().DataOffset(), lastEvalSection,
lastEvalPart == Reloc::HI_BYTE ? Reloc::HI_BYTE : Reloc::LO_BYTE); lastEvalPart == Reloc::HI_BYTE ? Reloc::HI_BYTE : Reloc::LO_BYTE);
} }
} }
@ -3082,7 +3129,7 @@ StatusCode Asm::AddOpcode(strref line, int group, int index, strref source_file)
case CA_BRANCH: case CA_BRANCH:
AddByte(opcode); AddByte(opcode);
if (evalLater) if (evalLater)
AddLateEval(CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_BRANCH); AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_BRANCH);
else if (((int)value - (int)CurrSection().GetPC()-1) < -128 || ((int)value - (int)CurrSection().GetPC()-1) > 127) { else if (((int)value - (int)CurrSection().GetPC()-1) < -128 || ((int)value - (int)CurrSection().GetPC()-1) > 127) {
error = ERROR_BRANCH_OUT_OF_RANGE; error = ERROR_BRANCH_OUT_OF_RANGE;
break; break;
@ -3092,18 +3139,20 @@ StatusCode Asm::AddOpcode(strref line, int group, int index, strref source_file)
case CA_ONE_BYTE: case CA_ONE_BYTE:
AddByte(opcode); AddByte(opcode);
if (evalLater) if (evalLater)
AddLateEval(CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_BYTE); AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_BYTE);
else if (error == STATUS_RELATIVE_SECTION) else if (error == STATUS_RELATIVE_SECTION)
CurrSection().AddReloc(target_section_offs, CurrSection().GetPC(), target_section, CurrSection().AddReloc(target_section_offs, CurrSection().DataOffset(), target_section,
target_section_type == Reloc::HI_BYTE ? Reloc::HI_BYTE : Reloc::LO_BYTE); target_section_type == Reloc::HI_BYTE ? Reloc::HI_BYTE : Reloc::LO_BYTE);
AddByte(value); AddByte(value);
break; break;
case CA_TWO_BYTES: case CA_TWO_BYTES:
AddByte(opcode); AddByte(opcode);
if (evalLater) if (evalLater)
AddLateEval(CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_ABS_REF); AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_ABS_REF);
else if (error == STATUS_RELATIVE_SECTION) { else if (error == STATUS_RELATIVE_SECTION) {
CurrSection().AddReloc(target_section_offs, CurrSection().GetPC(), printf("Reloc two byte op: ");
CurrSection().AddReloc(target_section_offs, CurrSection().DataOffset(),
target_section, target_section_type); target_section, target_section_type);
value = 0; value = 0;
} }
@ -3309,7 +3358,7 @@ StatusCode Asm::BuildSegment(OP_ID *pInstr, int numInstructions)
} }
// create an instruction table (mnemonic hash lookup + directives) // create an instruction table (mnemonic hash lookup + directives)
void Asm::Assemble(strref source, strref filename) void Asm::Assemble(strref source, strref filename, bool obj_target)
{ {
OP_ID *pInstr = new OP_ID[256]; OP_ID *pInstr = new OP_ID[256];
int numInstructions = BuildInstructionTable(pInstr, strref(aInstr, strl_t(sizeof(aInstr)-1)), 256); int numInstructions = BuildInstructionTable(pInstr, strref(aInstr, strl_t(sizeof(aInstr)-1)), 256);
@ -3334,31 +3383,383 @@ void Asm::Assemble(strref source, strref filename)
fwrite(errorText.get(), errorText.get_len(), 1, stderr); fwrite(errorText.get(), errorText.get_len(), 1, stderr);
} }
for (std::vector<LateEval>::iterator i = lateEval.begin(); i!=lateEval.end(); ++i) { if (!obj_target) {
strown<512> errorText; for (std::vector<LateEval>::iterator i = lateEval.begin(); i!=lateEval.end(); ++i) {
int line = i->source_file.count_lines(i->expression); strown<512> errorText;
errorText.sprintf("Error (%d): ", line+1); int line = i->source_file.count_lines(i->expression);
errorText.append("Failed to evaluate label \""); errorText.sprintf("Error (%d): ", line+1);
errorText.append(i->expression); errorText.append("Failed to evaluate label \"");
if (line>=0) { errorText.append(i->expression);
errorText.append("\" : \""); if (line>=0) {
errorText.append(i->source_file.get_line(line).get_trimmed_ws()); errorText.append("\" : \"");
errorText.append(i->source_file.get_line(line).get_trimmed_ws());
}
errorText.append("\"\n");
fwrite(errorText.get(), errorText.get_len(), 1, stderr);
} }
errorText.append("\"\n");
fwrite(errorText.get(), errorText.get_len(), 1, stderr);
} }
} }
} }
//
//
// OBJECT FILE HANDLING
//
//
struct ObjFileHeader {
short id; // 'o6'
short sections;
short relocs;
short labels;
short late_evals;
short map_symbols;
unsigned int stringdata;
int bindata;
};
struct ObjFileStr {
int offs; // offset into string table
};
struct ObjFileSection {
enum SectionFlags {
OFS_DUMMY,
OFS_FIXED,
OFS_MERGED,
};
struct ObjFileStr name;
int start_address;
int output_size; // assembled binary size
short relocs;
short flags;
};
struct ObjFileReloc {
int base_value;
int section_offset;
short target_section;
short value_type; // Reloc::Type
};
struct ObjFileLabel {
enum LabelFlags {
OFL_XDEF, // External
OFL_EVAL, // Evaluated (may still be relative)
OFL_ADDR, // Address or Assign
OFL_CNST // Constant
};
struct ObjFileStr name;
int value;
int flags; // 1<<(LabelFlags)
short section; // -1 if resolved, file section # if section rel
short mapIndex; // -1 if resolved, index into map if relative
};
struct ObjFileLateEval {
struct ObjFileStr label;
struct ObjFileStr expression;
struct ObjFileStr source_file;
int address; // PC relative to section or fixed
short section; // section to target
short target; // offset into section memory
short scope; // PC start of scope
short type; // label, byte, branch, word (LateEval::Type)
};
struct ObjFileMapSymbol {
struct ObjFileStr name; // symbol name
int value;
bool local; // local labels are probably needed
bool resolved; // set if in a relative section, when resolved label eval should clear this..
};
// Simple string pool, converts strref strings to zero terminated strings and returns the offset to the string in the pool.
static int _AddStrPool(strref str, pairArray<unsigned int, int> *pLookup, char **strPool, unsigned int &strPoolSize, unsigned int &strPoolCap)
{
if (!str)
return -1; // empty string
unsigned int hash = str.fnv1a();
unsigned int index = FindLabelIndex(hash, pLookup->getKeys(), pLookup->count());
if (index<pLookup->count() && str.same_str_case(*strPool + pLookup->getValue(index)))
return pLookup->getValue(index);
if ((strPoolSize + str.get_len() + 1) > strPoolCap) {
strPoolCap += 4096;
char *strPoolGrow = (char*)malloc(strPoolCap);
if (*strPool) {
memcpy(strPoolGrow, *strPool, strPoolSize);
free(*strPool);
}
*strPool = strPoolGrow;
}
int ret = strPoolSize;
memcpy(*strPool + strPoolSize, str.get(), str.get_len());
(*strPool + strPoolSize)[str.get_len()] = 0;
strPoolSize += str.get_len()+1;
pLookup->insert(index, hash);
pLookup->getValues()[index] = ret;
return ret;
}
StatusCode Asm::WriteObjectFile(strref filename)
{
if (FILE *f = fopen(strown<512>(filename).c_str(), "wb")) {
struct ObjFileHeader hdr = { 0 };
hdr.id = 'o6';
hdr.sections = (short)allSections.size();
hdr.relocs = 0;
hdr.bindata = 0;
for (std::vector<Section>::iterator s = allSections.begin(); s!=allSections.end(); ++s) {
if (s->pRelocs)
hdr.relocs += short(s->pRelocs->size());
hdr.bindata += (int)s->size();
}
hdr.labels = labels.count();
hdr.late_evals = (short)lateEval.size();
hdr.map_symbols = (short)map.size();
hdr.stringdata = 0;
char *stringPool = nullptr;
unsigned int stringPoolCap = 0;
pairArray<unsigned int, int> stringArray;
stringArray.reserve(hdr.labels * 2 + hdr.sections + hdr.late_evals*2);
struct ObjFileSection *aSects = hdr.sections ? (struct ObjFileSection*)calloc(hdr.sections, sizeof(struct ObjFileSection)) : nullptr;
struct ObjFileReloc *aRelocs = hdr.relocs ? (struct ObjFileReloc*)calloc(hdr.relocs, sizeof(struct ObjFileReloc)) : nullptr;
struct ObjFileLabel *aLabels = hdr.labels ? (struct ObjFileLabel*)calloc(hdr.labels, sizeof(struct ObjFileLabel)) : nullptr;
struct ObjFileLateEval *aLateEvals = hdr.late_evals ? (struct ObjFileLateEval*)calloc(hdr.late_evals, sizeof(struct ObjFileLateEval)) : nullptr;
struct ObjFileMapSymbol *aMapSyms = hdr.map_symbols ? (struct ObjFileMapSymbol*)calloc(hdr.map_symbols, sizeof(struct ObjFileMapSymbol)) : nullptr;
int sect = 0, reloc = 0, labs = 0, late = 0, map_sym = 0;
// write out sections and relocs
for (std::vector<Section>::iterator si = allSections.begin(); si!=allSections.end(); ++si) {
struct ObjFileSection &s = aSects[sect++];
s.name.offs = _AddStrPool(si->name, &stringArray, &stringPool, hdr.stringdata, stringPoolCap);
s.output_size = (short)si->size();
s.relocs = si->pRelocs ? (short)(si->pRelocs->size()) : 0;
s.start_address = si->start_address;
s.flags =
(si->IsDummySection() ? (1 << ObjFileSection::OFS_DUMMY) : 0) |
(si->IsMergedSection() ? (1 << ObjFileSection::OFS_MERGED) : 0) |
(si->address_assigned ? (1 << ObjFileSection::OFS_FIXED) : 0);
if (si->pRelocs && si->pRelocs->size()) {
for (relocList::iterator ri = si->pRelocs->begin(); ri!=si->pRelocs->end(); ++ri) {
struct ObjFileReloc &r = aRelocs[reloc++];
r.base_value = ri->base_value;
r.section_offset = ri->section_offset;
r.target_section = ri->target_section;
r.value_type = ri->value_type;
}
}
}
// write out labels
for (unsigned int li = 0; li<labels.count(); li++) {
Label &lo = 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 ? (1 << ObjFileLabel::OFL_CNST) : 0) |
(lo.pc_relative ? (1 << ObjFileLabel::OFL_ADDR) : 0) |
(lo.evaluated ? (1 << ObjFileLabel::OFL_EVAL) : 0) |
(lo.external ? (1 << ObjFileLabel::OFL_XDEF) : 0);
}
// write out late evals
for (std::vector<LateEval>::iterator lei = lateEval.begin(); lei != lateEval.end(); ++lei) {
struct ObjFileLateEval &le = aLateEvals[late++];
le.label.offs = _AddStrPool(lei->label, &stringArray, &stringPool, hdr.stringdata, stringPoolCap);
le.expression.offs = _AddStrPool(lei->expression, &stringArray, &stringPool, hdr.stringdata, stringPoolCap);
le.source_file.offs = _AddStrPool(lei->source_file, &stringArray, &stringPool, hdr.stringdata, stringPoolCap);
le.section = lei->section;
le.target = (short)lei->target;
le.address = lei->address;
le.scope = lei->scope;
le.type = lei->type;
}
// write out map symbols
for (MapSymbolArray::iterator mi = map.begin(); mi != map.end(); ++mi) {
struct ObjFileMapSymbol &ms = aMapSyms[map_sym++];
ms.name.offs = _AddStrPool(mi->name, &stringArray, &stringPool, hdr.stringdata, stringPoolCap);
ms.value = mi->value;
ms.local = mi->local;
ms.resolved = mi->resolved;
}
// write out the file
fwrite(&hdr, sizeof(hdr), 1, f);
fwrite(aSects, sizeof(aSects[0]), sect, f);
fwrite(aRelocs, sizeof(aRelocs[0]), reloc, f);
fwrite(aLabels, sizeof(aLabels[0]), labs, f);
fwrite(aLateEvals, sizeof(aLateEvals[0]), late, f);
fwrite(aMapSyms, sizeof(aMapSyms[0]), map_sym, f);
fwrite(stringPool, hdr.stringdata, 1, f);
for (std::vector<Section>::iterator si = allSections.begin(); si!=allSections.end(); ++si) {
if (!si->IsDummySection() && !si->IsMergedSection() && si->size()!=0)
fwrite(si->output, si->size(), 1, f);
}
// done with I/O
fclose(f);
if (stringPool)
free(stringPool);
if (aMapSyms)
free(aMapSyms);
if (aLateEvals)
free(aLateEvals);
if (aLabels)
free(aLabels);
if (aRelocs)
free(aRelocs);
if (aSects)
free(aSects);
stringArray.clear();
}
return STATUS_OK;
}
StatusCode Asm::ReadObjectFile(strref filename)
{
size_t size;
if (char *data = LoadBinary(filename, size)) {
struct ObjFileHeader &hdr = *(struct ObjFileHeader*)data;
size_t sum = sizeof(hdr) + hdr.sections*sizeof(struct ObjFileSection) +
hdr.relocs * sizeof(struct ObjFileReloc) + hdr.labels * sizeof(struct ObjFileLabel) +
hdr.late_evals * sizeof(struct ObjFileLateEval) +
hdr.map_symbols * sizeof(struct ObjFileMapSymbol) + hdr.stringdata + hdr.bindata;
if (hdr.id == 'o6' && sum == size) {
struct ObjFileSection *aSect = (struct ObjFileSection*)(&hdr + 1);
struct ObjFileReloc *aReloc = (struct ObjFileReloc*)(aSect + hdr.sections);
struct ObjFileLabel *aLabels = (struct ObjFileLabel*)(aReloc + hdr.relocs);
struct ObjFileLateEval *aLateEval = (struct ObjFileLateEval*)(aLabels + hdr.labels);
struct ObjFileMapSymbol *aMapSyms = (struct ObjFileMapSymbol*)(aLateEval + hdr.late_evals);
const char *str_orig = (const char*)(aMapSyms + hdr.map_symbols);
const char *bin_data = str_orig + hdr.stringdata;
char *str_pool = (char*)malloc(hdr.stringdata);
memcpy(str_pool, str_orig, hdr.stringdata);
loadedData.push_back(str_pool);
int prevSection = SectionId();
short *aSctRmp = (short*)malloc(hdr.sections * sizeof(short));
// for now just append to existing assembler data
// sections
int load_section = (int)allSections.size();
int reloc_idx = 0;
for (int si = 0; si < hdr.sections; si++) {
Section *s = nullptr;
short f = aSect[si].flags;
aSctRmp[si] = (short)allSections.size();
if (f & (1 << ObjFileSection::OFS_MERGED))
continue;
if (f & (1 << ObjFileSection::OFS_DUMMY)) {
if (f&(1 << ObjFileSection::OFS_FIXED))
DummySection(aSect[si].start_address);
else
DummySection();
} else {
if (f&(1 << ObjFileSection::OFS_FIXED))
SetSection(aSect[si].name.offs>=0 ? strref(str_pool + aSect[si].name.offs) : strref(), aSect[si].start_address);
else
SetSection(aSect[si].name.offs >= 0 ? strref(str_pool + aSect[si].name.offs) : strref());
if (aSect[si].output_size) {
CurrSection().output = (unsigned char*)malloc(aSect[si].output_size+64);
memcpy(CurrSection().output, bin_data, aSect[si].output_size);
CurrSection().curr = CurrSection().output + aSect[si].output_size;
CurrSection().output_capacity = aSect[si].output_size;
bin_data += aSect[si].output_size;
}
}
}
for (int si = 0; si < hdr.sections; si++) {
for (int r = 0; r < aSect[si].relocs; r++) {
struct ObjFileReloc &rs = aReloc[reloc_idx++];
allSections[aSctRmp[si]].AddReloc(rs.base_value, rs.section_offset, aSctRmp[rs.target_section], Reloc::Type(rs.value_type));
}
}
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++) {
struct ObjFileMapSymbol &m = aMapSyms[mi];
if (map.size() == map.capacity())
map.reserve(map.size() + 256);
MapSymbol sym;
sym.name = m.name.offs>=0 ? strref(str_pool + m.name.offs) : strref();
sym.resolved = m.resolved;
sym.value = m.value;
sym.local = m.local;
map.push_back(sym);
}
free(aSctRmp);
// restore previous section
current_section = &allSections[prevSection];
} else
return ERROR_NOT_AN_X65_OBJECT_FILE;
}
return STATUS_OK;
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int return_value = 0; int return_value = 0;
bool load_header = true; bool load_header = true;
bool size_header = false; bool size_header = false;
bool info = false;
Asm assembler; Asm assembler;
const char *source_filename=nullptr, *binary_out_name=nullptr; const char *source_filename = nullptr, *obj_out_file = nullptr;
const char *binary_out_name = nullptr;
const char *sym_file=nullptr, *vs_file=nullptr; const char *sym_file=nullptr, *vs_file=nullptr;
for (int a=1; a<argc; a++) { for (int a=1; a<argc; a++) {
strref arg(argv[a]); strref arg(argv[a]);
@ -3383,8 +3784,12 @@ int main(int argc, char **argv)
} else if (arg.same_str("bin")) { } else if (arg.same_str("bin")) {
load_header = false; load_header = false;
size_header = false; size_header = false;
} else if (arg.same_str("sym") && (a + 1) < argc) } else if (arg.same_str("info"))
info = true;
else if (arg.same_str("sym") && (a + 1) < argc)
sym_file = argv[++a]; sym_file = argv[++a];
else if (arg.same_str("obj") && (a + 1) < argc)
obj_out_file = argv[++a];
else if (arg.same_str("vice") && (a + 1) < argc) else if (arg.same_str("vice") && (a + 1) < argc)
vs_file = argv[++a]; vs_file = argv[++a];
} }
@ -3395,15 +3800,14 @@ int main(int argc, char **argv)
} }
if (!source_filename) { if (!source_filename) {
puts("Usage:\nAsm6502 [options] filename.s code.prg\n" puts("Usage:\nx65 [options] filename.s code.prg\n"
" * -i<path>: Add include path\n * -D<label>[=<value>]: Define a label with an optional value (otherwise 1)\n" " * -i<path>: Add include path\n * -D<label>[=<value>]: Define a label with an optional value (otherwise 1)\n"
" * -bin: Raw binary\n * -c64: Include load address (default)\n * -a2b: Apple II Dos 3.3 Binary\n" " * -bin: Raw binary\n * -c64: Include load address (default)\n * -a2b: Apple II Dos 3.3 Binary\n"
" * -sym <file.sym>: vice/kick asm symbol file\n" " * -sym <file.sym>: vice/kick asm symbol file\n"
" * -vice <file.vs>: export a vice symbol file\nhttps://github.com/sakrac/Asm6502\n"); " * -vice <file.vs>: export a vice symbol file\nhttps://github.com/sakrac/x65\n");
return 0; return 0;
} }
// Load source // Load source
if (source_filename) { if (source_filename) {
size_t size = 0; size_t size = 0;
@ -3412,23 +3816,30 @@ int main(int argc, char **argv)
// if source_filename contains a path add that as a search path for include files // if source_filename contains a path add that as a search path for include files
assembler.AddIncludeFolder(srcname.before_last('/', '\\')); assembler.AddIncludeFolder(srcname.before_last('/', '\\'));
assembler.symbol_export = sym_file!=nullptr; assembler.symbol_export = true;// sym_file!=nullptr;
assembler.Assemble(strref(buffer, strl_t(size)), strref(argv[1])); assembler.Assemble(strref(buffer, strl_t(size)), strref(argv[1]), obj_out_file != nullptr);
if (assembler.errorEncountered) if (assembler.errorEncountered)
return_value = 1; return_value = 1;
else { else {
// export object file
if (obj_out_file)
assembler.WriteObjectFile(obj_out_file);
Section exportSec = assembler.ExportSection(); Section exportSec = assembler.ExportSection();
printf("SECTIONS SUMMARY\n================\n"); if (info) {
for (size_t i = 0; i<assembler.allSections.size(); ++i) { printf("SECTIONS SUMMARY\n================\n");
Section &s = assembler.allSections[i]; for (size_t i = 0; i < assembler.allSections.size(); ++i) {
printf("Section %d%s: \"" STRREF_FMT "\" Dummy: %s Relative: %s Start: 0x%04x End: 0x%04x\n", Section &s = assembler.allSections[i];
(int)i, (&exportSec == &s) ? " (export)" : "", STRREF_ARG(s.name), s.dummySection ? "yes" : "no", printf("Section %d%s: \"" STRREF_FMT "\" Dummy: %s Relative: %s Start: 0x%04x End: 0x%04x\n",
s.IsRelativeSection() ? "yes" : "no", s.start_address, s.address); (int)i, (&exportSec == &s) ? " (export)" : "", STRREF_ARG(s.name), s.dummySection ? "yes" : "no",
if (s.pRelocs) { s.IsRelativeSection() ? "yes" : "no", s.start_address, s.address);
for (relocList::iterator i = s.pRelocs->begin(); i != s.pRelocs->end(); ++i) if (s.pRelocs) {
printf("\tReloc value $%x at offs $%x section %d\n", i->base_value, i->section_offset, i->target_section); for (relocList::iterator i = s.pRelocs->begin(); i != s.pRelocs->end(); ++i)
printf("\tReloc value $%x at offs $%x section %d\n", i->base_value, i->section_offset, i->target_section);
}
} }
} }
@ -3456,16 +3867,12 @@ int main(int argc, char **argv)
bool wasLocal = false; bool wasLocal = false;
for (MapSymbolArray::iterator i = assembler.map.begin(); i!=assembler.map.end(); ++i) { for (MapSymbolArray::iterator i = assembler.map.begin(); i!=assembler.map.end(); ++i) {
unsigned int value = (unsigned int)i->value; unsigned int value = (unsigned int)i->value;
if (i->section>=0 && i->section<(int)assembler.allSections.size()) { if (i->resolved) {
Section &s = assembler.allSections[i->section]; fprintf(f, "%s.label " STRREF_FMT " = $%04x",
value += s.start_address; wasLocal==i->local ? "\n" : (i->local ? " {\n" : "\n}\n"),
if (s.IsMergedSection()) STRREF_ARG(i->name), value);
value += assembler.allSections[s.merged_section].start_address; wasLocal = i->local;
} }
fprintf(f, "%s.label " STRREF_FMT " = $%04x",
wasLocal==i->local ? "\n" : (i->local ? " {\n" : "\n}\n"),
STRREF_ARG(i->name), value);
wasLocal = i->local;
} }
fputs(wasLocal ? "\n}\n" : "\n", f); fputs(wasLocal ? "\n}\n" : "\n", f);
fclose(f); fclose(f);
@ -3476,15 +3883,11 @@ int main(int argc, char **argv)
if (FILE *f = fopen(vs_file, "w")) { if (FILE *f = fopen(vs_file, "w")) {
for (MapSymbolArray::iterator i = assembler.map.begin(); i!=assembler.map.end(); ++i) { for (MapSymbolArray::iterator i = assembler.map.begin(); i!=assembler.map.end(); ++i) {
unsigned int value = (unsigned int)i->value; unsigned int value = (unsigned int)i->value;
if (i->section>=0 && i->section<(int)assembler.allSections.size()) { if (i->resolved) {
Section &s = assembler.allSections[i->section]; fprintf(f, "al $%04x %s" STRREF_FMT "\n",
value += s.start_address; value, i->name[0]=='.' ? "" : ".",
if (s.IsMergedSection()) STRREF_ARG(i->name));
value += assembler.allSections[s.merged_section].start_address;
} }
fprintf(f, "al $%04x %s" STRREF_FMT "\n",
value, i->name[0]=='.' ? "" : ".",
STRREF_ARG(i->name));
} }
fclose(f); fclose(f);
} }