From e7a3db9ddaabbb208cbc7a06c61f905dcc362845 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 13 May 2021 23:35:57 -0600 Subject: [PATCH] Fix up some optimizer passes --- examples/hello_commodore.cpp | 44 +++++++ examples/test_lambda.cpp | 141 ++++++++++++++++++++ examples/test_mod.cpp | 235 ++++++++++++++++++++++++++++++++++ include/optimizer.hpp | 133 +++++++++++-------- include/personalities/c64.hpp | 113 +++++----------- include/personality.hpp | 2 - src/6502-c++.cpp | 8 +- 7 files changed, 539 insertions(+), 137 deletions(-) create mode 100644 examples/hello_commodore.cpp create mode 100644 examples/test_lambda.cpp create mode 100644 examples/test_mod.cpp diff --git a/examples/hello_commodore.cpp b/examples/hello_commodore.cpp new file mode 100644 index 0000000..7ae14fc --- /dev/null +++ b/examples/hello_commodore.cpp @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include + +enum Colors : uint8_t { WHITE = 0x01 }; + +static volatile uint8_t &memory_loc(const uint16_t loc) { + return *reinterpret_cast(loc); +} + +static void poke(const uint16_t loc, const uint8_t value) { + memory_loc(loc) = value; +} + +static std::uint8_t peek(const std::uint16_t loc) { return memory_loc(loc); } + +static void puts(uint8_t x, uint8_t y, std::string_view str) { + const auto start = 0x400 + (y * 40 + x); + + std::memcpy(const_cast(&memory_loc(start)), str.data(), + str.size()); +} + +int main() { + std::uint8_t x = 0; + std::uint8_t y = 0; + + while (true) { + puts(x, y, "hello commodore!"); + x += 3; + ++y; + if (x > 26) { + x = 0; + } + + if (y>25) { + y = 0; + } + + } +} + diff --git a/examples/test_lambda.cpp b/examples/test_lambda.cpp new file mode 100644 index 0000000..44f2080 --- /dev/null +++ b/examples/test_lambda.cpp @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include + +enum Colors : uint8_t { WHITE = 0x01 }; + +static volatile uint8_t &memory_loc(const uint16_t loc) { + return *reinterpret_cast(loc); +} + +static void poke(const uint16_t loc, const uint8_t value) { + memory_loc(loc) = value; +} + +static std::uint8_t peek(const std::uint16_t loc) { return memory_loc(loc); } + +static void decrement_border_color() { --memory_loc(0xd020); } + +static void increment_border_color() { ++memory_loc(0xd020); } + +static bool joystick_down() { + uint8_t joystick_state = peek(0xDC00); + return (joystick_state & 2) == 0; +} + +void use_data(std::array &data); + +static void puts(uint8_t x, uint8_t y, std::string_view str) { + const auto start = 0x400 + (y * 40 + x); + + std::memcpy(const_cast(&memory_loc(start)), str.data(), + str.size()); +} + + +template +struct Graphic +{ + std::array data; + + static constexpr auto width() noexcept { + return Width; + } + + static constexpr auto height() noexcept { + return Height; + } + + constexpr Graphic() = default; + + constexpr Graphic(std::array data_) noexcept : data(data_) {} + constexpr Graphic(std::initializer_list data_) noexcept { + std::copy(begin(data_), end(data_), begin(data)); + } + + constexpr auto &operator()(const std::uint8_t x, const std::uint8_t y) noexcept { + return data[y * Width + x]; + } + + constexpr const auto &operator()(const std::uint8_t x, const std::uint8_t y) const noexcept { + return data[y * Width + x]; + } +}; + +static void putc(uint8_t x, uint8_t y, uint8_t c) { + const auto start = 0x400 + (y * 40 + x); + poke(start, c); +} + +static void put_hex(uint8_t x, uint8_t y, uint8_t value) { + const auto put_nibble = [](auto x, auto y, uint8_t nibble) { + if (nibble <= 9) { + putc(x, y, nibble + 48); + } else { + putc(x, y, nibble - 9); + } + }; + + put_nibble(x + 1, y, 0xF & value); + put_nibble(x, y, 0xF & (value >> 4)); +} + +static void put_hex(uint8_t x, uint8_t y, uint16_t value) { + put_hex(x+2,y, static_cast(0xFF & value)); + put_hex(x,y, static_cast(0xFF & (value >> 8))); +} + +static void put_graphic(uint8_t x, uint8_t y, const auto &graphic) +{ + for (uint8_t cur_y = 0; cur_y < graphic.height(); ++cur_y) { + for (uint8_t cur_x = 0; cur_x < graphic.width(); ++cur_x) { + putc(cur_x + x, cur_y + y, graphic(cur_x, cur_y)); + } + } +} + +static void cls() { + for (std::uint16_t i = 0x400; i < 0x400 + 1000; ++i) { + poke(i, 32); + } +} + +struct Clock { + using milliseconds = std::chrono::duration; + + // return elapsed time since last restart + [[nodiscard]] milliseconds restart() { + // stop Timer A + poke(0xDC0E, 0b00000000); + + // last value + const auto previous_value = static_cast( + peek(0xDC04) | (static_cast(peek(0xDC05)) << 8)); + + // reset timer + poke(0xDC04, 0xFF); + poke(0xDC05, 0xFF); + + // restart timer A + poke(0xDC0E, 0b00010001); + + return milliseconds{0xFFFF - previous_value}; + } + + Clock() { [[maybe_unused]] const auto value = restart(); } +}; + +int main() { + cls(); + + auto fib = [f0 = 0u, f1 = 1u] mutable { + f0 = std::exchange(f1, f0 + f1); + return f0; + }; + + for (std::uint8_t y = 0; y < 25; ++y) { + put_hex(30, y, fib()); + } +} diff --git a/examples/test_mod.cpp b/examples/test_mod.cpp new file mode 100644 index 0000000..7f2bc54 --- /dev/null +++ b/examples/test_mod.cpp @@ -0,0 +1,235 @@ +#include +#include +#include +#include +#include + +enum Colors : uint8_t { WHITE = 0x01 }; + +static volatile uint8_t &memory_loc(const uint16_t loc) { + return *reinterpret_cast(loc); +} + +static void poke(const uint16_t loc, const uint8_t value) { + memory_loc(loc) = value; +} + +static std::uint8_t peek(const std::uint16_t loc) { return memory_loc(loc); } + +static void decrement_border_color() { --memory_loc(0xd020); } + +static void increment_border_color() { ++memory_loc(0xd020); } + +static bool joystick_down() { + uint8_t joystick_state = peek(0xDC00); + return (joystick_state & 2) == 0; +} + +unsigned int __attribute__ ((noinline)) multiply(unsigned int x, unsigned int y) { + unsigned int result = 0; + unsigned int input = x; + unsigned int add_in = y; + while (input != 0) { + if (input & 1) { + result += add_in; + } + add_in <<= 1; + input >>= 1; + } + + return result; +} + + +void use_data(std::array &data); + +static void puts(uint8_t x, uint8_t y, std::string_view str) { + const auto start = 0x400 + (y * 40 + x); + + std::memcpy(const_cast(&memory_loc(start)), str.data(), + str.size()); +} + + +template +struct Graphic +{ + std::array data; + + static constexpr auto width() noexcept { + return Width; + } + + static constexpr auto height() noexcept { + return Height; + } + + constexpr Graphic() = default; + + constexpr Graphic(std::array data_) noexcept : data(data_) {} + constexpr Graphic(std::initializer_list data_) noexcept { + std::copy(begin(data_), end(data_), begin(data)); + } + + constexpr auto &operator()(const std::uint8_t x, const std::uint8_t y) noexcept { + return data[y * Width + x]; + } + + constexpr const auto &operator()(const std::uint8_t x, const std::uint8_t y) const noexcept { + return data[y * Width + x]; + } +}; + +static void putc(uint8_t x, uint8_t y, uint8_t c) { + const auto start = 0x400 + (y * 40 + x); + poke(start, c); +} + +static void put_hex(uint8_t x, uint8_t y, uint8_t value) { + const auto put_nibble = [](auto x, auto y, uint8_t nibble) { + if (nibble <= 9) { + putc(x, y, nibble + 48); + } else { + putc(x, y, nibble - 9); + } + }; + + put_nibble(x + 1, y, 0xF & value); + put_nibble(x, y, 0xF & (value >> 4)); +} + +static void put_hex(uint8_t x, uint8_t y, uint16_t value) { + put_hex(x+2,y, static_cast(0xFF & value)); + put_hex(x,y, static_cast(0xFF & (value >> 8))); +} + +static void put_graphic(uint8_t x, uint8_t y, const auto &graphic) +{ + for (uint8_t cur_y = 0; cur_y < graphic.height(); ++cur_y) { + for (uint8_t cur_x = 0; cur_x < graphic.width(); ++cur_x) { + putc(cur_x + x, cur_y + y, graphic(cur_x, cur_y)); + } + } +} + +struct Clock { + using milliseconds = std::chrono::duration; + + // return elapsed time since last restart + [[nodiscard]] milliseconds restart() { + // stop Timer A + poke(0xDC0E, 0b00000000); + + // last value + const auto previous_value = static_cast( + peek(0xDC04) | (static_cast(peek(0xDC05)) << 8)); + + // reset timer + poke(0xDC04, 0xFF); + poke(0xDC05, 0xFF); + + // restart timer A + poke(0xDC0E, 0b00010001); + + return milliseconds{0xFFFF - previous_value}; + } + + Clock() { [[maybe_unused]] const auto value = restart(); } +}; + +int main() { + + // static constexpr std::array data{0}; + // std::memcpy(const_cast(&memory_loc(0x400)), data.data(), + // data.size()); + + static constexpr auto pic = + Graphic<5,4>{ + 78,119,77,32,32, + 101,32,32,80,32, + 101,79,101,103,32, + 76,101,76,122,88 + }; + + static constexpr auto map1 = + Graphic<4, 2>{ + 1,0,1,0, + 1,1,1,1 + }; + + static constexpr auto map2 = + Graphic<6, 3>{ + 1,0,1,0,0,0, + 1,1,1,1,0,1, + 0,0,0,1,0,0 + }; + +/* + static constexpr auto map = + Graphic<10, 2>{ + 0,1,0,1,0,0,0,1,0,0, + 1,0,0,0,0,0,1,0,0,0, + }; +*/ + // put_graphic(10,10,pic); + + + const auto draw_map = [](const auto &map) { + for (std::uint8_t y=0; y < map.height(); ++y) { + for (std::uint8_t x = 0; x < map.width(); ++x) { + if (map(x, y) == 1) { + put_graphic(x*4, y*4, pic); + } + } + } + }; + + +// draw_map(map1); + + Clock game_clock{}; + + + std::uint16_t counter = 0; + std::uint8_t y = 19; + + while (true) { + const auto us_elapsed = game_clock.restart().count(); + + draw_map(map2); + + puts(5, 17, "timing history"); + puts(21, 17, "16bit counter"); + + + put_hex(5, y, us_elapsed); + put_hex(21, y, counter); + put_hex(26, y, static_cast(multiply(counter, y))); + // put_hex(31, y, counter*10); + + + + if (y++ == 24) { + y = 19; + } + + ++counter; + increment_border_color(); + } + + /* + const auto background_color = [](Colors col) { + memory_loc(0xd021) = static_cast(col); + }; + + background_color(Colors::WHITE); + + while(true) { + if (joystick_down()) { + increment_border_color(); + } else { + decrement_border_color(); + } + } + */ +} diff --git a/include/optimizer.hpp b/include/optimizer.hpp index 249f4ea..6fce98b 100644 --- a/include/optimizer.hpp +++ b/include/optimizer.hpp @@ -2,15 +2,14 @@ #define INC_6502_CPP_OPTIMIZER_HPP #include "6502.hpp" +#include "personality.hpp" #include -bool optimize(std::vector &instructions) +bool optimize(std::vector &instructions, const Personality &personality) { - // return false; + // return false; - if (instructions.size() < 2) { - return false; - } + if (instructions.size() < 2) { return false; } const auto next_instruction = [&instructions](auto i) { do { @@ -23,16 +22,16 @@ bool optimize(std::vector &instructions) // remove unused flag-fix-up blocks // it might make sense in the future to only insert these if determined they are needed? for (size_t op = 10; op < instructions.size(); ++op) { - if (instructions[op].opcode == mos6502::OpCode::lda || instructions[op].opcode == mos6502::OpCode::bcc || instructions[op].opcode == mos6502::OpCode::bcs) { + if (instructions[op].opcode == mos6502::OpCode::lda || instructions[op].opcode == mos6502::OpCode::bcc + || instructions[op].opcode == mos6502::OpCode::bcs) { if (instructions[op - 1].text == "; END remove if next is lda, bcc, bcs" - || (instructions[op -2].text == "; END remove if next is lda, bcc, bcs" && instructions[op-1].type == ASMLine::Type::Directive)) { + || (instructions[op - 2].text == "; END remove if next is lda, bcc, bcs" + && instructions[op - 1].type == ASMLine::Type::Directive)) { for (size_t inner_op = op - 1; inner_op > 1; --inner_op) { - instructions[inner_op] = mos6502(ASMLine::Type::Directive, - "; removed unused flag fix-up: " + instructions[inner_op].to_string()); + instructions[inner_op] = + mos6502(ASMLine::Type::Directive, "; removed unused flag fix-up: " + instructions[inner_op].to_string()); - if (instructions[inner_op].text.find("; BEGIN") != std::string::npos) { - return true; - } + if (instructions[inner_op].text.find("; BEGIN") != std::string::npos) { return true; } } } } @@ -41,11 +40,11 @@ bool optimize(std::vector &instructions) // look for redundant load of lda after a tax for (size_t op = 0; op < instructions.size() - 3; ++op) { - if (instructions[op].opcode == mos6502::OpCode::sta - && instructions[op + 1].opcode == mos6502::OpCode::tax + if (instructions[op].opcode == mos6502::OpCode::sta && instructions[op + 1].opcode == mos6502::OpCode::tax && instructions[op + 2].opcode == mos6502::OpCode::lda && instructions[op].op.value == instructions[op + 2].op.value) { - instructions[op + 2] = mos6502(ASMLine::Type::Directive, "; removed redundant lda: " + instructions[op + 2].to_string()); + instructions[op + 2] = + mos6502(ASMLine::Type::Directive, "; removed redundant lda: " + instructions[op + 2].to_string()); return true; } } @@ -53,41 +52,65 @@ bool optimize(std::vector &instructions) // look for redundant stores to 0-page registers with sta for (size_t op = 0; op < instructions.size(); ++op) { // todo, make sure this is in the register map - if (instructions[op].opcode == mos6502::OpCode::sta - && instructions[op].op.value.size() == 3) { + if (instructions[op].opcode == mos6502::OpCode::sta && instructions[op].op.value.size() == 3) { for (size_t next_op = op + 1; next_op < instructions.size(); ++next_op) { - if (instructions[next_op].opcode != mos6502::OpCode::sta && instructions[next_op].op.value == instructions[op].op.value) { + if (instructions[next_op].opcode != mos6502::OpCode::sta + && instructions[next_op].op.value == instructions[op].op.value) { // we just found a use of ourselves back, abort the search, there's probably something else going on break; } - if (instructions[next_op].opcode == mos6502::OpCode::lda && instructions[next_op].op.value != instructions[op].op.value) { + if (instructions[next_op].opcode == mos6502::OpCode::lda + && instructions[next_op].op.value != instructions[op].op.value) { // someone just loaded lda with a different value, so we need to abort! break; } // abort at label - if (instructions[next_op].type == ASMLine::Type::Label) { - break; - } + if (instructions[next_op].type == ASMLine::Type::Label) { break; } if (instructions[next_op].opcode == mos6502::OpCode::sta && instructions[next_op].op.value == instructions[op].op.value) { // looks like we found a redundant store, remove the first one - instructions[op] = mos6502(ASMLine::Type::Directive, - "; removed redundant sta: " + instructions[op].to_string()); + instructions[op] = + mos6502(ASMLine::Type::Directive, "; removed redundant sta: " + instructions[op].to_string()); return true; } } } } + for (size_t op = 0; op < instructions.size() - 1; ++op) { + // look for a transfer of A -> X immediately followed by LDX + if (instructions[op].opcode == mos6502::OpCode::sta) { + const auto next_op = next_instruction(op); + if (instructions[next_op].opcode == mos6502::OpCode::ldx && instructions[op].op == instructions[next_op].op) { + auto last_comment = instructions[next_op].comment; + instructions[next_op] = mos6502(mos6502::OpCode::tax); + instructions[next_op].comment = last_comment; + return true; + } + } + } + + for (size_t op = 0; op < instructions.size() - 1; ++op) { + // look for a transfer of A -> X immediately followed by LDX + if (instructions[op].opcode == mos6502::OpCode::tax) { + const auto next_op = next_instruction(op); + if (instructions[next_op].opcode == mos6502::OpCode::ldx) { + instructions[op] = + mos6502(ASMLine::Type::Directive, "; removed redundant tax: " + instructions[op].to_string()); + return true; + } + } + } + for (size_t op = 0; op < instructions.size() - 1; ++op) { // look for a transfer of Y -> A immediately followed by A -> Y if (instructions[op].opcode == mos6502::OpCode::tya) { - next_instruction(op); - if (instructions[op].opcode == mos6502::OpCode::tay) { - instructions[op] = mos6502(ASMLine::Type::Directive, - "; removed redundant tay: " + instructions[op].to_string()); + const auto next_op = next_instruction(op); + if (instructions[next_op].opcode == mos6502::OpCode::tay) { + instructions[op] = + mos6502(ASMLine::Type::Directive, "; removed redundant tay: " + instructions[op].to_string()); return true; } } @@ -96,50 +119,60 @@ bool optimize(std::vector &instructions) for (size_t op = 0; op < instructions.size() - 1; ++op) { // look for a store A -> loc immediately followed by loc -> A if (instructions[op].opcode == mos6502::OpCode::sta) { + const auto next = next_instruction(op); - if (instructions[next].opcode == mos6502::OpCode::lda - && instructions[next].op == instructions[op].op) { - instructions[next] = mos6502(ASMLine::Type::Directive, - "; removed redundant lda: " + instructions[next].to_string()); + if (instructions[next].opcode == mos6502::OpCode::lda && instructions[next].op == instructions[op].op) { + instructions[next] = + mos6502(ASMLine::Type::Directive, "; removed redundant lda: " + instructions[next].to_string()); return true; } } } - // todo: fix this ldy redundant move, right now it doesn't - // take into account if Y has been used + for (auto &op : instructions) { + if (op.type == ASMLine::Type::Instruction && op.op.type == Operand::Type::literal + && op.op.value == personality.get_register(1).value && op.opcode != mos6502::OpCode::sta) { + // replace use of zero reg with literal 0 + op.op.value = "#0"; + } + } - /* for (size_t op = 0; op < instructions.size() - 1; ++op) { if (instructions[op].opcode == mos6502::OpCode::ldy && instructions[op].op.type == Operand::Type::literal) { auto op2 = op + 1; while (op2 < instructions.size() && (instructions[op2].type != ASMLine::Type::Label)) { // while inside this label - if (instructions[op2].opcode == mos6502::OpCode::ldy && instructions[op2].op.value == instructions[op].op.value) { - instructions[op2] = mos6502(ASMLine::Type::Directive, "; removed redundant ldy: " + instructions[op2].to_string()); - return true; + if (instructions[op2].opcode == mos6502::OpCode::ldy) { + + if (instructions[op2].op.value == instructions[op].op.value) { + instructions[op2] = + mos6502(ASMLine::Type::Directive, "; removed redundant ldy: " + instructions[op2].to_string()); + return true; + } else { + // if we ldy with any other value in this block then abort + break; + } } ++op2; } } - } - */ - + } + for (size_t op = 0; op < instructions.size() - 1; ++op) { - if (instructions[op].opcode == mos6502::OpCode::lda - && instructions[op].op.type == Operand::Type::literal) { + if (instructions[op].opcode == mos6502::OpCode::lda && instructions[op].op.type == Operand::Type::literal) { const auto operand = instructions[op].op; - auto op2 = op + 1; + auto op2 = op + 1; // look for multiple stores of the same value - while (op2 < instructions.size() && (instructions[op2].opcode == mos6502::OpCode::sta || instructions[op2].type == ASMLine::Type::Directive)) { + while ( + op2 < instructions.size() + && (instructions[op2].opcode == mos6502::OpCode::sta || instructions[op2].type == ASMLine::Type::Directive)) { ++op2; } - if (instructions[op2].opcode == mos6502::OpCode::lda - && operand == instructions[op2].op) { - instructions[op2] = mos6502(ASMLine::Type::Directive, - "; removed redundant lda: " + instructions[op2].to_string()); + if (instructions[op2].opcode == mos6502::OpCode::lda && operand == instructions[op2].op) { + instructions[op2] = + mos6502(ASMLine::Type::Directive, "; removed redundant lda: " + instructions[op2].to_string()); return true; } } @@ -148,4 +181,4 @@ bool optimize(std::vector &instructions) return false; } -#endif//INC_6502_CPP_OPTIMIZER_HPP +#endif// INC_6502_CPP_OPTIMIZER_HPP diff --git a/include/personalities/c64.hpp b/include/personalities/c64.hpp index 2863579..1aa0151 100644 --- a/include/personalities/c64.hpp +++ b/include/personalities/c64.hpp @@ -15,94 +15,47 @@ struct C64 : Personality new_instructions.emplace_back(ASMLine::Type::Directive, "* = " + std::to_string(start_address)); new_instructions.emplace_back(ASMLine::Type::Directive, "; jmp to start of program with BASIC"); new_instructions.emplace_back(ASMLine::Type::Directive, ".byt $0B,$08,$0A,$00,$9E,$32,$30,$36,$31,$00,$00,$00"); - - // load start of stack space into stack address pointers - new_instructions.emplace_back(mos6502::OpCode::lda, Operand(Operand::Type::literal, "#$FF")); - new_instructions.emplace_back(mos6502::OpCode::sta, Operand(Operand::Type::literal, std::string{stack_low_address()})); - new_instructions.emplace_back(mos6502::OpCode::lda, Operand(Operand::Type::literal, "#$CF")); - new_instructions.emplace_back(mos6502::OpCode::sta, Operand(Operand::Type::literal, std::string{ stack_high_address() })); - } - - [[nodiscard]] std::string_view stack_low_address() const override - { - return "$02"; - } - [[nodiscard]] std::string_view stack_high_address() const override - { - return "$03"; } [[nodiscard]] Operand get_register(const int reg_num) const override { switch (reg_num) { // http://sta.c64.org/cbm64mem.html - case 0: - return Operand(Operand::Type::literal, "$a7");// bit buffer for rs232 - case 1: - return Operand(Operand::Type::literal, "$a8");// counter for rs232 - case 2: - return Operand(Operand::Type::literal, "$05");// unused, int->fp routine pointer - case 3: - return Operand(Operand::Type::literal, "$06"); - case 4: - return Operand(Operand::Type::literal, "$fb");// unused - case 5: - return Operand(Operand::Type::literal, "$fc");// unused - case 6: - return Operand(Operand::Type::literal, "$fd");// unused - case 7: - return Operand(Operand::Type::literal, "$fe");// unused - case 8: - return Operand(Operand::Type::literal, "$22");// unused - case 9: - return Operand(Operand::Type::literal, "$23");// unused - case 10: - return Operand(Operand::Type::literal, "$39");// Current BASIC line number - case 11: - return Operand(Operand::Type::literal, "$3a");// Current BASIC line number - case 12: - return Operand(Operand::Type::literal, "$61");// arithmetic register #1 - case 13: - return Operand(Operand::Type::literal, "$62"); - case 14: - return Operand(Operand::Type::literal, "$63"); - case 15: - return Operand(Operand::Type::literal, "$64"); - case 16: - return Operand(Operand::Type::literal, "$65"); - case 17: - return Operand(Operand::Type::literal, "$69");// arithmetic register #2 - case 18: - return Operand(Operand::Type::literal, "$6a"); - case 19: - return Operand(Operand::Type::literal, "$6b"); - case 20: - return Operand(Operand::Type::literal, "$6c"); - case 21: - return Operand(Operand::Type::literal, "$6d"); - case 22: - return Operand(Operand::Type::literal, "$57");// arithmetic register #3 - case 23: - return Operand(Operand::Type::literal, "$58"); - case 24: - return Operand(Operand::Type::literal, "$59"); - case 25: - return Operand(Operand::Type::literal, "$5a"); - case 26: - return Operand(Operand::Type::literal, "$5b"); - case 27: - return Operand(Operand::Type::literal, "$5c");// arithmetic register #4 - case 28: - return Operand(Operand::Type::literal, "$5d"); - case 29: - return Operand(Operand::Type::literal, "$5e"); - case 30: - return Operand(Operand::Type::literal, "$5f"); - case 31: - return Operand(Operand::Type::literal, "$60"); + case 0: return Operand(Operand::Type::literal, "$a7");// bit buffer for rs232 + case 1: return Operand(Operand::Type::literal, "$a8");// counter for rs232 + case 2: return Operand(Operand::Type::literal, "$05");// unused, int->fp routine pointer + case 3: return Operand(Operand::Type::literal, "$06"); + case 4: return Operand(Operand::Type::literal, "$fb");// unused + case 5: return Operand(Operand::Type::literal, "$fc");// unused + case 6: return Operand(Operand::Type::literal, "$fd");// unused + case 7: return Operand(Operand::Type::literal, "$fe");// unused + case 8: return Operand(Operand::Type::literal, "$22");// unused + case 9: return Operand(Operand::Type::literal, "$23");// unused + case 10: return Operand(Operand::Type::literal, "$39");// Current BASIC line number + case 11: return Operand(Operand::Type::literal, "$3a");// Current BASIC line number + case 12: return Operand(Operand::Type::literal, "$61");// arithmetic register #1 + case 13: return Operand(Operand::Type::literal, "$62"); + case 14: return Operand(Operand::Type::literal, "$63"); + case 15: return Operand(Operand::Type::literal, "$64"); + case 16: return Operand(Operand::Type::literal, "$65"); + case 17: return Operand(Operand::Type::literal, "$69");// arithmetic register #2 + case 18: return Operand(Operand::Type::literal, "$6a"); + case 19: return Operand(Operand::Type::literal, "$6b"); + case 20: return Operand(Operand::Type::literal, "$6c"); + case 21: return Operand(Operand::Type::literal, "$6d"); + case 22: return Operand(Operand::Type::literal, "$57");// arithmetic register #3 + case 23: return Operand(Operand::Type::literal, "$58"); + case 24: return Operand(Operand::Type::literal, "$59"); + case 25: return Operand(Operand::Type::literal, "$5a"); + case 26: return Operand(Operand::Type::literal, "$5b"); + case 27: return Operand(Operand::Type::literal, "$5c");// arithmetic register #4 + case 28: return Operand(Operand::Type::literal, "$5d"); + case 29: return Operand(Operand::Type::literal, "$5e"); + case 30: return Operand(Operand::Type::literal, "$5f"); + case 31: return Operand(Operand::Type::literal, "$60"); } throw std::runtime_error("Unhandled register number: " + std::to_string(reg_num)); } }; -#endif//INC_6502_C_C64_HPP +#endif// INC_6502_C_C64_HPP diff --git a/include/personality.hpp b/include/personality.hpp index 2586eb7..b684002 100644 --- a/include/personality.hpp +++ b/include/personality.hpp @@ -9,8 +9,6 @@ class Personality public: virtual void insert_autostart_sequence(std::vector &new_instructions) const = 0; [[nodiscard]] virtual Operand get_register(const int reg_num) const = 0; - [[nodiscard]] virtual std::string_view stack_low_address() const = 0; - [[nodiscard]] virtual std::string_view stack_high_address() const= 0; virtual ~Personality() = default; Personality(const Personality &) = delete; diff --git a/src/6502-c++.cpp b/src/6502-c++.cpp index 7d690ad..c054c99 100644 --- a/src/6502-c++.cpp +++ b/src/6502-c++.cpp @@ -677,7 +677,7 @@ void translate_instruction(const Personality &personality, } if (o2.value == "__SP_H__") { - instructions.emplace_back(mos6502::OpCode::lda, Operand(Operand::Type::literal, "$01")); + instructions.emplace_back(mos6502::OpCode::lda, Operand(Operand::Type::literal, "#$01")); instructions.emplace_back(mos6502::OpCode::sta, personality.get_register(o1_reg_num)); return; } @@ -963,7 +963,7 @@ std::vector run(const Personality &personality, std::istream &input) } } - while (optimize(new_instructions)) { + while (optimize(new_instructions, personality)) { // do it however many times it takes } @@ -973,7 +973,6 @@ std::vector run(const Personality &personality, std::istream &input) } return new_instructions; - } enum struct Target { C64 }; @@ -1041,8 +1040,7 @@ int main(const int argc, const char **argv) for (const auto &i : new_instructions) { mos6502_output << i.to_string() << '\n'; } } - const std::string xa_command = fmt::format( - "xa -O PETSCREEN -M -o {outfile} {infile}", + const std::string xa_command = fmt::format("xa -O PETSCREEN -M -o {outfile} {infile}", fmt::arg("infile", mos6502_output_file.generic_string()), fmt::arg("outfile", program_output_file.generic_string()));