mirror of
https://github.com/lefticus/6502-cpp.git
synced 2025-04-14 19:37:03 +00:00
Minor optimizer fixes
This commit is contained in:
parent
f52296a00f
commit
2536c4e2c7
@ -1,3 +1,4 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
@ -5,41 +6,38 @@
|
||||
#include <span>
|
||||
#include <string_view>
|
||||
#include <variant>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
#include "chargen.hpp"
|
||||
|
||||
enum struct Colors : std::uint8_t
|
||||
{
|
||||
enum struct Colors : std::uint8_t {
|
||||
black = 0,
|
||||
white = 1,
|
||||
red = 2,
|
||||
cyan=3,
|
||||
violet=4,
|
||||
green=5,
|
||||
blue=6,
|
||||
yellow=7,
|
||||
orange=8,
|
||||
brown=9,
|
||||
light_red=10,
|
||||
dark_grey=11,
|
||||
grey=12,
|
||||
light_green=13,
|
||||
light_blue=14,
|
||||
light_grey=15
|
||||
cyan = 3,
|
||||
violet = 4,
|
||||
green = 5,
|
||||
blue = 6,
|
||||
yellow = 7,
|
||||
orange = 8,
|
||||
brown = 9,
|
||||
light_red = 10,
|
||||
dark_grey = 11,
|
||||
grey = 12,
|
||||
light_green = 13,
|
||||
light_blue = 14,
|
||||
light_grey = 15
|
||||
};
|
||||
|
||||
constexpr char charToPETSCII(char c) noexcept {
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
return c - 'A' + 1;
|
||||
}
|
||||
constexpr char charToPETSCII(char c) noexcept
|
||||
{
|
||||
if (c >= 'A' && c <= 'Z') { return c - 'A' + 1; }
|
||||
return c;
|
||||
}
|
||||
|
||||
template<std::size_t Size>
|
||||
constexpr auto PETSCII(const char (&value)[Size]) noexcept
|
||||
template<std::size_t Size> constexpr auto PETSCII(const char (&value)[Size]) noexcept
|
||||
{
|
||||
std::array<char, Size-1> result{};
|
||||
std::array<char, Size - 1> result{};
|
||||
std::transform(std::begin(value), std::prev(std::end(value)), std::begin(result), charToPETSCII);
|
||||
return result;
|
||||
}
|
||||
@ -75,7 +73,7 @@ static bool joystick_down()
|
||||
|
||||
void use_data(std::array<char, 1024> &data);
|
||||
|
||||
static void puts(uint8_t x, uint8_t y, const auto &range, const Colors color=Colors::white)
|
||||
static void puts(uint8_t x, uint8_t y, const auto &range, const Colors color = Colors::white)
|
||||
{
|
||||
const auto offset = y * 40 + x;
|
||||
|
||||
@ -126,6 +124,12 @@ template<std::uint8_t Width, std::uint8_t Height> struct Graphic
|
||||
}
|
||||
};
|
||||
|
||||
template<std::uint8_t Width, std::uint8_t Height> struct ColoredGraphic
|
||||
{
|
||||
Graphic<Width, Height> data;
|
||||
Graphic<Width, Height> colors;
|
||||
};
|
||||
|
||||
|
||||
static constexpr auto load_charset(const std::span<const std::uint8_t, 256 * 8> &bits)
|
||||
{
|
||||
@ -236,6 +240,12 @@ static std::uint8_t loadc(uint8_t x, uint8_t y)
|
||||
return peek(start);
|
||||
}
|
||||
|
||||
static void invertc(uint8_t x, uint8_t y)
|
||||
{
|
||||
const auto start = 0x400 + (y * 40 + x);
|
||||
memory_loc(start) += 128;
|
||||
}
|
||||
|
||||
|
||||
static void put_hex(uint8_t x, uint8_t y, uint8_t value, Colors color)
|
||||
{
|
||||
@ -260,10 +270,22 @@ static void put_hex(uint8_t x, uint8_t y, uint16_t value, Colors color)
|
||||
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), Colors::white); }
|
||||
for (uint8_t cur_x = 0; cur_x < graphic.width(); ++cur_x) {
|
||||
putc(cur_x + x, cur_y + y, graphic(cur_x, cur_y), Colors::white);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void put_graphic(uint8_t x, uint8_t y, const auto &graphic) requires requires { graphic.colors(0, 0); }
|
||||
{
|
||||
for (uint8_t cur_y = 0; cur_y < graphic.data.height(); ++cur_y) {
|
||||
for (uint8_t cur_x = 0; cur_x < graphic.data.width(); ++cur_x) {
|
||||
putc(cur_x + x, cur_y + y, graphic.data(cur_x, cur_y), static_cast<Colors>(graphic.colors(cur_x, cur_y)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct Clock
|
||||
{
|
||||
using milliseconds = std::chrono::duration<std::uint16_t, std::milli>;
|
||||
@ -324,7 +346,8 @@ struct Screen
|
||||
}
|
||||
}
|
||||
|
||||
void hide(auto &s) {
|
||||
void hide(auto &s)
|
||||
{
|
||||
if (s.is_shown) {
|
||||
put_graphic(s.x, s.y, s.saved_background);
|
||||
s.is_shown = false;
|
||||
@ -345,8 +368,7 @@ struct Screen
|
||||
}
|
||||
};
|
||||
|
||||
template<std::uint8_t Width, std::uint8_t Height>
|
||||
struct Map;
|
||||
template<std::uint8_t Width, std::uint8_t Height> struct Map;
|
||||
|
||||
struct GameState
|
||||
{
|
||||
@ -363,16 +385,24 @@ struct GameState
|
||||
|
||||
Map<10, 5> const *current_map = nullptr;
|
||||
|
||||
constexpr void set_current_map(const Map<10, 5> &new_map) {
|
||||
constexpr void set_current_map(const Map<10, 5> &new_map)
|
||||
{
|
||||
current_map = &new_map;
|
||||
redraw = true;
|
||||
}
|
||||
|
||||
constexpr void execute_actions(const auto &character) noexcept
|
||||
constexpr void execute_actions(std::uint8_t new_x, std::uint8_t new_y, const auto &character) noexcept
|
||||
{
|
||||
if (new_x + character.width() > 40) { new_x = x; }
|
||||
|
||||
if (new_y + character.height() > 20) { new_y = y; }
|
||||
|
||||
x = new_x;
|
||||
y = new_y;
|
||||
|
||||
if (current_map) {
|
||||
for (auto &action : current_map->actions) {
|
||||
action.execute_if_collision(x,y,character.width(), character.height(), *this);
|
||||
action.execute_if_collision(x, y, character.width(), character.height(), *this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -423,10 +453,13 @@ struct Map_Action
|
||||
using Action_Func = void (*)(GameState &);
|
||||
Action_Func action = nullptr;
|
||||
|
||||
constexpr void execute_if_collision(std::uint8_t obj_x, std::uint8_t obj_y, std::uint8_t obj_width, std::uint8_t obj_height, GameState &game) const {
|
||||
if (action == nullptr) {
|
||||
return;
|
||||
}
|
||||
constexpr void execute_if_collision(std::uint8_t obj_x,
|
||||
std::uint8_t obj_y,
|
||||
std::uint8_t obj_width,
|
||||
std::uint8_t obj_height,
|
||||
GameState &game) const
|
||||
{
|
||||
if (action == nullptr) { return; }
|
||||
|
||||
const std::uint8_t rect1_x1 = x;
|
||||
const std::uint8_t rect1_x2 = x + width;
|
||||
@ -438,26 +471,43 @@ struct Map_Action
|
||||
const std::uint8_t rect2_y1 = obj_y;
|
||||
const std::uint8_t rect2_y2 = obj_y + obj_height;
|
||||
|
||||
if (rect1_x1 < rect2_x2 && rect1_x2 > rect2_x1 &&
|
||||
rect1_y1 < rect2_y2 && rect1_y2 > rect2_y1) {
|
||||
action(game);
|
||||
}
|
||||
if (rect1_x1 < rect2_x2 && rect1_x2 > rect2_x1 && rect1_y1 < rect2_y2 && rect1_y2 > rect2_y1) { action(game); }
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<std::uint8_t Width, std::uint8_t Height>
|
||||
struct Map {
|
||||
template<std::uint8_t Width, std::uint8_t Height> struct Map
|
||||
{
|
||||
std::string_view name;
|
||||
Graphic<Width, Height> layout;
|
||||
|
||||
std::span<const Map_Action> actions;
|
||||
};
|
||||
|
||||
void draw_box(uint8_t x, uint8_t y, uint8_t width, uint8_t height, Colors color) {
|
||||
putc(x, y, 85, color);
|
||||
putc(x + width - 1, y, 73, color);
|
||||
putc(x + width - 1, y + height - 1, 75, color);
|
||||
putc(x, y + height - 1, 74, color);
|
||||
|
||||
for (uint8_t cur_x = x + 1; cur_x < x + width - 1; ++cur_x) {
|
||||
putc(cur_x, y, 67, color);
|
||||
putc(cur_x, y + height - 1, 67, color);
|
||||
}
|
||||
|
||||
for (uint8_t cur_y = y + 1; cur_y < y + height - 1; ++cur_y) {
|
||||
putc(x, cur_y, 93, color);
|
||||
putc(x + width - 1, cur_y, 93, color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
// static constexpr auto charset = load_charset(uppercase);
|
||||
|
||||
// clang-format off
|
||||
static constexpr auto inn = Graphic<6,5> {
|
||||
32,233,160,160,223,32,
|
||||
233,160,160,160,160,223,
|
||||
@ -482,12 +532,29 @@ int main()
|
||||
160,160,160,160,76,160,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
static constexpr auto town = Graphic<4, 4>{
|
||||
85, 67, 67, 73,
|
||||
93, 233, 223, 93,
|
||||
93, 160, 160, 93,
|
||||
74, 67, 67, 75 };
|
||||
*/
|
||||
|
||||
static constexpr auto town = ColoredGraphic<4, 4>{
|
||||
{
|
||||
32, 32,32, 32,
|
||||
233,223,233,223,
|
||||
224,224,224,224,
|
||||
104,104,104,104
|
||||
},
|
||||
{
|
||||
2,2,10,10,
|
||||
4,4,7,7,
|
||||
4,4,7,7,
|
||||
11,11,11,11
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static constexpr auto mountain = Graphic<4, 4>{
|
||||
32, 78, 77, 32,
|
||||
@ -495,6 +562,21 @@ int main()
|
||||
78, 77, 32, 32,
|
||||
32, 78, 77, 32 };
|
||||
|
||||
static constexpr auto colored_mountain = ColoredGraphic<4, 4>{
|
||||
{
|
||||
32, 78, 77, 32,
|
||||
32, 32, 233, 223,
|
||||
233, 223, 32, 32,
|
||||
32, 78, 77, 32 },
|
||||
{
|
||||
1, 9, 9, 1,
|
||||
1, 1, 8, 8,
|
||||
9, 9, 1, 1,
|
||||
1, 8, 8, 1
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
auto character = SimpleSprite<2, 3>{
|
||||
32, 87,
|
||||
@ -529,14 +611,14 @@ int main()
|
||||
},
|
||||
std::span<const Map_Action>(begin(overview_actions), end(overview_actions))
|
||||
};
|
||||
|
||||
// clang-format on
|
||||
|
||||
|
||||
static constexpr std::array<void (*)(std::uint8_t, std::uint8_t), 7> tile_types{
|
||||
[](std::uint8_t x, std::uint8_t y) {
|
||||
/* do nothing for 0th */
|
||||
},
|
||||
[](std::uint8_t x, std::uint8_t y) { put_graphic(x, y, mountain); },
|
||||
[](std::uint8_t x, std::uint8_t y) { put_graphic(x, y, colored_mountain); },
|
||||
[](std::uint8_t x, std::uint8_t y) {
|
||||
/* do nothing for 2 */
|
||||
},
|
||||
@ -557,24 +639,6 @@ int main()
|
||||
}
|
||||
};
|
||||
|
||||
constexpr auto draw_box = [](uint8_t x, uint8_t y, uint8_t width, uint8_t height, Colors color) {
|
||||
putc(x, y, 85, color);
|
||||
putc(x + width - 1, y, 73, color);
|
||||
putc(x + width - 1, y + height - 1, 75, color);
|
||||
putc(x, y + height - 1, 74, color);
|
||||
|
||||
for (uint8_t cur_x = x + 1; cur_x < x + width - 1; ++cur_x) {
|
||||
putc(cur_x, y, 67, color);
|
||||
putc(cur_x, y + height - 1, 67, color);
|
||||
}
|
||||
|
||||
for (uint8_t cur_y = y + 1; cur_y < y + height - 1; ++cur_y) {
|
||||
putc(x, cur_y, 93, color);
|
||||
putc(x + width - 1, cur_y, 93, color);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
GameState game;
|
||||
game.current_map = &overview_map;
|
||||
|
||||
@ -591,13 +655,132 @@ int main()
|
||||
|
||||
Screen screen;
|
||||
|
||||
auto eventHandler = overloaded{ [&](const GameState::JoyStick2StateChanged &e) {
|
||||
if (e.state.up()) { --game.y; }
|
||||
if (e.state.down()) { ++game.y; }
|
||||
if (e.state.left()) { --game.x; }
|
||||
if (e.state.right()) { ++game.x; }
|
||||
static constexpr auto menu_options =
|
||||
std::array {
|
||||
std::string_view{"info"},
|
||||
std::string_view{"test2"},
|
||||
std::string_view{"test3"},
|
||||
std::string_view{"an even longer thing"}
|
||||
};
|
||||
struct Menu {
|
||||
consteval Menu(std::span<const std::string_view> t_options)
|
||||
: options{t_options}, width{std::max_element(begin(options), end(options),
|
||||
[](std::string_view lhs, std::string_view rhs) {
|
||||
return lhs.size() < rhs.size();
|
||||
}
|
||||
)->size() + 2},
|
||||
height{options.size() + 2},
|
||||
x{(40 - width) / 2},
|
||||
y{(20 - height) / 2}
|
||||
{
|
||||
|
||||
game.execute_actions(character.graphic);
|
||||
}
|
||||
|
||||
void highlight(std::uint8_t selection) {
|
||||
const std::uint8_t cur_y = selection + 1 + y;
|
||||
for (auto cur_x = 1; cur_x < width - 1; ++cur_x) {
|
||||
invertc(x + cur_x, cur_y);
|
||||
}
|
||||
}
|
||||
|
||||
void unhighlight(std::uint8_t selection)
|
||||
{
|
||||
highlight(selection);
|
||||
}
|
||||
|
||||
void hide(GameState &game) {
|
||||
displayed = false;
|
||||
game.redraw = true;
|
||||
}
|
||||
|
||||
bool show(GameState &game, std::uint8_t &selection) {
|
||||
if (!displayed) {
|
||||
displayed = true;
|
||||
|
||||
draw_box(x, y, width, height, Colors::white);
|
||||
|
||||
for (auto cur_y = y + 1; const auto &str : options) {
|
||||
puts(x+1, cur_y++, str, Colors::grey);
|
||||
}
|
||||
|
||||
highlight(current_selection);
|
||||
}
|
||||
|
||||
if (current_selection != next_selection) {
|
||||
unhighlight(current_selection);
|
||||
highlight(next_selection);
|
||||
current_selection = next_selection;
|
||||
}
|
||||
|
||||
if (selected) {
|
||||
selected = false;
|
||||
selection = current_selection;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool process_event(const GameState::Event &e) {
|
||||
if (not displayed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (const auto *ptr = std::get_if<GameState::JoyStick2StateChanged>(&e); ptr) {
|
||||
if (ptr->state.up()) {
|
||||
next_selection = current_selection - 1;
|
||||
}
|
||||
|
||||
if (ptr->state.down()) {
|
||||
next_selection = current_selection + 1;
|
||||
}
|
||||
|
||||
if (next_selection > options.size() - 1) {
|
||||
next_selection = options.size() - 1;
|
||||
}
|
||||
|
||||
if (ptr->state.fire()) {
|
||||
selected = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::span<const std::string_view> options;
|
||||
std::uint8_t width;
|
||||
std::uint8_t height;
|
||||
std::uint8_t x;
|
||||
std::uint8_t y;
|
||||
std::uint8_t current_selection{0};
|
||||
std::uint8_t next_selection{0};
|
||||
bool selected{false};
|
||||
bool displayed{false};
|
||||
|
||||
};
|
||||
|
||||
Menu m(menu_options);
|
||||
|
||||
bool show_game_menu = false;
|
||||
|
||||
auto eventHandler = overloaded{ [&](const GameState::JoyStick2StateChanged &e) {
|
||||
auto new_x = game.x;
|
||||
auto new_y = game.y;
|
||||
|
||||
if (e.state.fire()) {
|
||||
show_game_menu = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.state.up()) { --new_y; }
|
||||
if (e.state.down()) { ++new_y; }
|
||||
if (e.state.left()) { --new_x; }
|
||||
if (e.state.right()) { ++new_x; }
|
||||
|
||||
|
||||
game.execute_actions(new_x, new_y, character.graphic);
|
||||
|
||||
screen.show(game.x, game.y, character);
|
||||
|
||||
@ -606,7 +789,12 @@ int main()
|
||||
[](const GameState::TimeElapsed &e) { put_hex(36, 0, e.us.count(), Colors::dark_grey); } };
|
||||
|
||||
while (true) {
|
||||
std::visit(eventHandler, game.next_event());
|
||||
const auto next_event = game.next_event();
|
||||
|
||||
if (not m.process_event(next_event)) {
|
||||
// if no gui elements needed the event, then we handle it
|
||||
std::visit(eventHandler, next_event);
|
||||
}
|
||||
|
||||
if (game.redraw) {
|
||||
screen.hide(character);
|
||||
@ -624,6 +812,14 @@ int main()
|
||||
screen.show(game.x, game.y, character);
|
||||
}
|
||||
|
||||
if (std::uint8_t result = 0; show_game_menu && m.show(game, result)) {
|
||||
// we had a menu item selected
|
||||
m.hide(game);
|
||||
show_game_menu = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
increment_border_color();
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ bool optimize_dead_sta(std::span<mos6502> &block, const Personality &personality
|
||||
for (auto itr = block.begin(); itr != block.end(); ++itr) {
|
||||
if (itr->opcode == mos6502::OpCode::sta && is_virtual_register_op(*itr, personality)) {
|
||||
for (auto inner = std::next(itr); inner != block.end(); ++inner) {
|
||||
if (inner->op.value.find('(') != std::string::npos) {
|
||||
if (not inner->op.value.starts_with("#<(") && inner->op.value.find('(') != std::string::npos) {
|
||||
// this is an indexed operation, which is risky to optimize a sta around on the virtual registers,
|
||||
// so we'll skip this block
|
||||
break;
|
||||
@ -260,9 +260,11 @@ bool optimize(std::vector<mos6502> &instructions, [[maybe_unused]] const Persona
|
||||
// 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 || instructions[op].opcode == mos6502::OpCode::ldy) {
|
||||
if (instructions[op - 1].text == "; END remove if next is lda, bcc, bcs, ldy"
|
||||
|| (instructions[op - 2].text == "; END remove if next is lda, bcc, bcs, ldy"
|
||||
|| instructions[op].opcode == mos6502::OpCode::bcs || instructions[op].opcode == mos6502::OpCode::ldy
|
||||
|| instructions[op].opcode == mos6502::OpCode::inc || instructions[op].opcode == mos6502::OpCode::clc
|
||||
|| instructions[op].opcode == mos6502::OpCode::sec) {
|
||||
if (instructions[op - 1].text == "; END remove if next is lda, bcc, bcs, ldy, inc, clc, sec"
|
||||
|| (instructions[op - 2].text == "; END remove if next is lda, bcc, bcs, ldy, inc, clc, sec"
|
||||
&& instructions[op - 1].type == ASMLine::Type::Directive)) {
|
||||
for (size_t inner_op = op - 1; inner_op > 1; --inner_op) {
|
||||
instructions[inner_op] =
|
||||
|
@ -210,7 +210,7 @@ struct AVR : ASMLine
|
||||
if (o == "nop") { return OpCode::nop; }
|
||||
if (o == "jmp") { return OpCode::jmp; }
|
||||
if (o == "tst") { return OpCode::tst; }
|
||||
if (o == "brge"){ return OpCode::brge; }
|
||||
if (o == "brge") { return OpCode::brge; }
|
||||
if (o == "brlt") { return OpCode::brlt; }
|
||||
if (o == "or") { return OpCode::OR; }
|
||||
}
|
||||
@ -291,7 +291,7 @@ void indirect_store(std::vector<mos6502> &instructions,
|
||||
instructions.emplace_back(ASMLine::Type::Label, n_set);
|
||||
instructions.emplace_back(mos6502::OpCode::bvs, Operand(Operand::Type::literal, s_clear));
|
||||
instructions.emplace_back(mos6502::OpCode::jmp, Operand(Operand::Type::literal, s_set));
|
||||
return {s_set, s_clear};
|
||||
return { s_set, s_clear };
|
||||
}
|
||||
|
||||
void fixup_16_bit_N_Z_flags(std::vector<mos6502> &instructions)
|
||||
@ -313,7 +313,7 @@ void fixup_16_bit_N_Z_flags(std::vector<mos6502> &instructions)
|
||||
// if low order byte is negative, just load 1, this will properly set the Z flag and leave C correct
|
||||
instructions.emplace_back(mos6502::OpCode::lda, Operand(Operand::Type::literal, "#1"));
|
||||
instructions.emplace_back(ASMLine::Type::Label, set_flag_label);
|
||||
instructions.emplace_back(ASMLine::Type::Directive, "; END remove if next is lda, bcc, bcs, ldy");
|
||||
instructions.emplace_back(ASMLine::Type::Directive, "; END remove if next is lda, bcc, bcs, ldy, inc, clc, sec");
|
||||
}
|
||||
|
||||
void add_16_bit(const Personality &personality,
|
||||
@ -617,7 +617,7 @@ void translate_instruction(const Personality &personality,
|
||||
case AVR::OpCode::cpse: {
|
||||
instructions.emplace_back(mos6502::OpCode::lda, personality.get_register(o1_reg_num));
|
||||
instructions.emplace_back(mos6502::OpCode::cmp, personality.get_register(o2_reg_num));
|
||||
std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()) + "__optimizable";
|
||||
std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size());
|
||||
instructions.emplace_back(mos6502::OpCode::beq, Operand(Operand::Type::literal, new_label_name));
|
||||
instructions.emplace_back(ASMLine::Type::Directive, new_label_name);
|
||||
return;
|
||||
@ -626,7 +626,7 @@ void translate_instruction(const Personality &personality,
|
||||
instructions.emplace_back(
|
||||
mos6502::OpCode::lda, Operand(o2.type, fixup_8bit_literal("$" + std::to_string(1 << (to_int(o2.value))))));
|
||||
instructions.emplace_back(mos6502::OpCode::bit, personality.get_register(o1_reg_num));
|
||||
std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()) + "__optimizable";
|
||||
std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size());
|
||||
instructions.emplace_back(mos6502::OpCode::beq, Operand(Operand::Type::literal, new_label_name));
|
||||
instructions.emplace_back(ASMLine::Type::Directive, new_label_name);
|
||||
return;
|
||||
@ -635,7 +635,7 @@ void translate_instruction(const Personality &personality,
|
||||
instructions.emplace_back(mos6502::OpCode::lda,
|
||||
Operand(o2.type, fixup_8bit_literal("$" + std::to_string(1 << (to_int(o2.value.c_str()))))));
|
||||
instructions.emplace_back(mos6502::OpCode::bit, personality.get_register(o1_reg_num));
|
||||
std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()) + "__optimizable";
|
||||
std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size());
|
||||
instructions.emplace_back(mos6502::OpCode::bne, Operand(Operand::Type::literal, new_label_name));
|
||||
instructions.emplace_back(ASMLine::Type::Directive, new_label_name);
|
||||
return;
|
||||
@ -646,7 +646,7 @@ void translate_instruction(const Personality &personality,
|
||||
return;
|
||||
} else if (o1.value == ".+2") {
|
||||
// assumes 6502 'borrow' for Carry flag instead of carry, so bcc instead of bcs
|
||||
std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()) + "__optimizable";
|
||||
std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size());
|
||||
instructions.emplace_back(mos6502::OpCode::bne, Operand(Operand::Type::literal, new_label_name));
|
||||
instructions.emplace_back(ASMLine::Type::Directive, new_label_name);
|
||||
return;
|
||||
@ -688,7 +688,6 @@ void translate_instruction(const Personality &personality,
|
||||
instructions.emplace_back(mos6502::OpCode::lda, Operand(Operand::Type::literal, "#$FF"));
|
||||
instructions.emplace_back(mos6502::OpCode::eor, personality.get_register(o1_reg_num));
|
||||
instructions.emplace_back(mos6502::OpCode::sta, personality.get_register(o1_reg_num));
|
||||
instructions.emplace_back(mos6502::OpCode::sec);
|
||||
return;
|
||||
}
|
||||
case AVR::OpCode::clr: {
|
||||
@ -708,7 +707,7 @@ void translate_instruction(const Personality &personality,
|
||||
|
||||
if (o1.value == ".+2") {
|
||||
// assumes 6502 'borrow' for Carry flag instead of carry, so bcc instead of bcs
|
||||
std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()) + "__optimizable";
|
||||
std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size());
|
||||
instructions.emplace_back(mos6502::OpCode::bcc, Operand(Operand::Type::literal, new_label_name));
|
||||
instructions.emplace_back(ASMLine::Type::Directive, new_label_name);
|
||||
return;
|
||||
@ -773,7 +772,7 @@ void translate_instruction(const Personality &personality,
|
||||
case AVR::OpCode::brsh: {
|
||||
if (o1.value == ".+2") {
|
||||
// assumes 6502 'borrow' for Carry flag instead of carry, so bcs instead of bcc
|
||||
std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()) + "__optimizable";
|
||||
std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size());
|
||||
instructions.emplace_back(mos6502::OpCode::bcs, Operand(Operand::Type::literal, new_label_name));
|
||||
instructions.emplace_back(ASMLine::Type::Directive, new_label_name);
|
||||
return;
|
||||
@ -816,7 +815,7 @@ void translate_instruction(const Personality &personality,
|
||||
case AVR::OpCode::breq: {
|
||||
if (o1.value == ".+2") {
|
||||
// assumes 6502 'borrow' for Carry flag instead of carry, so bcc instead of bcs
|
||||
std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size()) + "__optimizable";
|
||||
std::string new_label_name = "skip_next_instruction_" + std::to_string(instructions.size());
|
||||
instructions.emplace_back(mos6502::OpCode::beq, Operand(Operand::Type::literal, new_label_name));
|
||||
instructions.emplace_back(ASMLine::Type::Directive, new_label_name);
|
||||
return;
|
||||
@ -857,7 +856,7 @@ void to_mos6502(const Personality &personality, const AVR &from_instruction, std
|
||||
|
||||
if (const auto results = matcher(from_instruction.text); results) {
|
||||
const auto matched_gs = results.get<1>().to_string();
|
||||
instructions.emplace_back(ASMLine::Type::Directive, ".word " + std::string{strip_gs(matched_gs)});
|
||||
instructions.emplace_back(ASMLine::Type::Directive, ".word " + std::string{ strip_gs(matched_gs) });
|
||||
} else {
|
||||
instructions.emplace_back(ASMLine::Type::Directive, ".word " + from_instruction.text.substr(6));
|
||||
// spdlog::warn("Unknown .word directive '{}'", from_instruction.text);
|
||||
@ -925,7 +924,7 @@ bool fix_long_branches(std::vector<mos6502> &instructions, int &branch_patch_cou
|
||||
|
||||
for (size_t op = 0; op < instructions.size(); ++op) {
|
||||
if (instructions[op].is_branch
|
||||
&& std::abs(static_cast<int>(labels[instructions[op].op.value]) - static_cast<int>(op)) * 3 > 255) {
|
||||
&& std::abs(static_cast<int>(labels[instructions[op].op.value]) - static_cast<int>(op)) * 4 > 255) {
|
||||
++branch_patch_count;
|
||||
const auto going_to = instructions[op].op.value;
|
||||
const auto new_pos = "patch_" + std::to_string(branch_patch_count);
|
||||
@ -1051,7 +1050,7 @@ std::vector<mos6502> run(const Personality &personality, std::istream &input, co
|
||||
if (const auto results = matcher(i.text); results) {
|
||||
const auto matched_gs = results.get<1>().to_string();
|
||||
spdlog::trace("matched .word: '{}' from '{}'", matched_gs, i.text);
|
||||
check_label(std::string{strip_gs(matched_gs)});
|
||||
check_label(std::string{ strip_gs(matched_gs) });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1086,6 +1085,7 @@ std::vector<mos6502> run(const Personality &personality, std::istream &input, co
|
||||
i.text = new_labels.at(i.text);
|
||||
} catch (...) {
|
||||
spdlog::warn("Unused label: '{}', consider making function static until we remove unused functions", i.text);
|
||||
i.text = "; Label is unused: " + i.text;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1097,9 +1097,7 @@ std::vector<mos6502> run(const Personality &personality, std::istream &input, co
|
||||
const auto matched_gs = results.get<1>().to_string();
|
||||
const auto possible_label = std::string{ strip_gs(matched_gs) };
|
||||
const auto matched_label = new_labels.find(possible_label);
|
||||
if (matched_label != new_labels.end()) {
|
||||
i.text = ".word " + matched_label->second;
|
||||
}
|
||||
if (matched_label != new_labels.end()) { i.text = ".word " + matched_label->second; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1131,30 +1129,33 @@ std::vector<mos6502> run(const Personality &personality, std::istream &input, co
|
||||
new_instructions.emplace_back(mos6502::OpCode::jmp, Operand(Operand::Type::literal, "main"));
|
||||
|
||||
|
||||
int instructions_to_skip = 0;
|
||||
int instructions_to_skip = -1;
|
||||
std::string next_label_name;
|
||||
for (const auto &i : instructions) {
|
||||
to_mos6502(personality, i, new_instructions);
|
||||
|
||||
// intentionally copy so we don't invalidate the reference
|
||||
const auto last_instruction = new_instructions.back();
|
||||
const auto last_instruction_loc = new_instructions.size() - 1;
|
||||
|
||||
if (instructions_to_skip == 1) { new_instructions.emplace_back(ASMLine::Type::Label, next_label_name); }
|
||||
if (i.type == ASMLine::Type::Instruction) { --instructions_to_skip; }
|
||||
if (instructions_to_skip == 0) {
|
||||
new_instructions.emplace_back(ASMLine::Type::Label, next_label_name);
|
||||
// todo: I kind of hate this -1 as a marker
|
||||
instructions_to_skip = -1;
|
||||
}
|
||||
|
||||
--instructions_to_skip;
|
||||
|
||||
if (last_instruction.type == ASMLine::Type::Directive
|
||||
&& last_instruction.text.starts_with("skip_next_instruction")) {
|
||||
instructions_to_skip = 1;
|
||||
next_label_name = last_instruction.text;
|
||||
new_instructions.erase(std::next(new_instructions.begin(), static_cast<std::ptrdiff_t>(last_instruction_loc)));
|
||||
new_instructions.pop_back();
|
||||
}
|
||||
if (last_instruction.type == ASMLine::Type::Directive
|
||||
&& last_instruction.text.starts_with("skip_next_2_instructions")) {
|
||||
instructions_to_skip = 2;
|
||||
next_label_name = last_instruction.text;
|
||||
new_instructions.erase(std::next(new_instructions.begin(), static_cast<std::ptrdiff_t>(last_instruction_loc)));
|
||||
new_instructions.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user