Skip to content

Commit

Permalink
Allow extending sections.
Browse files Browse the repository at this point in the history
  • Loading branch information
dillof committed Jun 2, 2024
1 parent 376507f commit b15a91a
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 21 deletions.
4 changes: 4 additions & 0 deletions share/target/c64-basic.target
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ basic_start = $0801
basic_end = $7fff

.include "commodore-basic.inc"

.section reserved .extend {
address: $c000 - $cfff
}
58 changes: 39 additions & 19 deletions src/Assembler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const Token Assembler::token_data_end = Token(Token::NAME, ".data_end");
const Token Assembler::token_data_size = Token(Token::NAME, ".data_size");
const Token Assembler::token_data_start = Token(Token::NAME, ".data_start");
const Token Assembler::token_default_string_encoding = Token(Token::DIRECTIVE, "default_string_encoding");
const Token Assembler::token_extend = Token(Token::DIRECTIVE, "extend");
const Token Assembler::token_extension = Token(Token::DIRECTIVE, "extension");
const Token Assembler::token_macro = Token(Token::DIRECTIVE, "macro");
const Token Assembler::token_output = Token(Token::DIRECTIVE, "output");
Expand Down Expand Up @@ -241,39 +242,58 @@ void Assembler::parse_section() {
throw ParseException(tokenizer.current_location(), "expected newline");
}
else {
auto extend = false;
if (tokenizer.peek() == token_extend) {
tokenizer.next();
extend = true;
}
auto parse_value = ParsedValue::parse(tokenizer);
tokenizer.unget(Token{Token::NEWLINE, tokenizer.current_location()});
auto parameters = parse_value->as_dictionary();

if (section_names.contains(name)) {
throw ParseException(name, "duplicate section definition"); // TODO: attach note
if (extend != section_names.contains(name)) {
if (extend) {
throw ParseException(name, "extending non-existing section");
}
else {
throw ParseException(name, "duplicate section definition"); // TODO: attach note
}
}
section_names.insert(name);

auto type = MemoryMap::READ_WRITE;

auto type_parameter = parameters->get_optional(token_type);
if (type_parameter != nullptr) {
type = parse_type(type_parameter->as_singular_scalar()->token());
}
auto blocks = std::vector<MemoryMap::Block>();
auto segment = parameters->get_optional(token_segment_name);
if (segment) {
if (parameters->has_key(token_address_name)) {
throw ParseException(name, "segment and address are mutually exclusive");
}

if (auto address = parameters->get_optional(token_address_name)) {
blocks = parse_address((*parameters)[token_address_name].get());
}
if (auto segment = parameters->get_optional(token_segment_name)) {
auto segment_blocks = parsed_target.map.segment(segment->as_singular_scalar()->token().as_symbol());
if (segment_blocks == nullptr) {
throw ParseException(segment->as_singular_scalar()->token(), "unknown segment");
}
blocks.insert(blocks.begin(), segment_blocks->begin(), segment_blocks->end());
blocks.insert(blocks.end(), segment_blocks->begin(), segment_blocks->end());
}
else {
blocks = parse_address((*parameters)[token_address_name].get());

if (extend) {
if (parameters->has_key(token_type)) {
throw ParseException(name, "can't specify type when extending section");
}
auto it = parsed_target.map.sections.find(name.as_symbol());
if (it == parsed_target.map.sections.end()) {
throw ParseException(name, "extending non-existing section");
}
it->second.add_blocks(blocks);
}
else {
section_names.insert(name);

auto type = MemoryMap::READ_WRITE;

parsed_target.map.add_section(MemoryMap::Section(name.as_symbol(), type, std::move(blocks)));
auto type_parameter = parameters->get_optional(token_type);
if (type_parameter != nullptr) {
type = parse_type(type_parameter->as_singular_scalar()->token());
}

parsed_target.map.add_section(MemoryMap::Section(name.as_symbol(), type, std::move(blocks)));
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/Assembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class Assembler {
static const Token token_cpu;
static const Token token_default;
static const Token token_default_string_encoding;
static const Token token_extend;
static const Token token_extension;
static const Token token_macro;
static const Token token_output;
Expand Down
11 changes: 9 additions & 2 deletions src/MemoryMap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <algorithm>

#include "Exception.h"
#include "Int.h"

const std::vector<MemoryMap::Block> *MemoryMap::segment(Symbol name) const {
auto it = segments.find(name);
Expand Down Expand Up @@ -137,7 +136,15 @@ bool MemoryMap::Block::operator==(const MemoryMap::Block &other) const {


MemoryMap::Section::Section(Symbol name, MemoryMap::AccessType access, std::vector<Block> raw_blocks): name(name), access(access) {
add_blocks(std::move(raw_blocks));
}

void MemoryMap::Section::add_blocks(std::vector<Block> raw_blocks) {
raw_blocks.insert(raw_blocks.end(), blocks.begin(), blocks.end());
std::sort(raw_blocks.begin(), raw_blocks.end());

blocks.clear();
size = 0;
Block* previous = nullptr;

for (const auto& block: raw_blocks) {
Expand All @@ -150,8 +157,8 @@ MemoryMap::Section::Section(Symbol name, MemoryMap::AccessType access, std::vect
previous = &blocks.emplace_back(block);
}
}
}

}

bool MemoryMap::Section::operator<(const MemoryMap::Section &other) const {
if (size != other.size) {
Expand Down
1 change: 1 addition & 0 deletions src/MemoryMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class MemoryMap {

bool operator<(const Section& other) const;

void add_blocks(std::vector<Block> raw_blocks);
[[nodiscard]] bool empty() const {return blocks.empty();}
[[nodiscard]] uint64_t maximum_address() const {return empty() ? 0 : blocks.back().range.end();}
[[nodiscard]] uint64_t minimum_address() const {return empty() ? 0 : blocks.front().range.start;}
Expand Down

0 comments on commit b15a91a

Please sign in to comment.