1
0
mirror of https://github.com/lefticus/6502-cpp.git synced 2025-07-12 11:23:52 +00:00

Apply some clang-format action

This commit is contained in:
Jason Turner
2021-05-04 23:31:39 -06:00
parent 14b3f4192e
commit 1547abccab
2 changed files with 1033 additions and 938 deletions

98
.clang-format Normal file
View File

@ -0,0 +1,98 @@
AccessModifierOffset: -2
AlignAfterOpenBracket: DontAlign
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: false
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterClass: true
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: true
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyNamespace: true
SplitEmptyRecord: true
BreakAfterJavaFieldAnnotations: true
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: true
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakConstructorInitializersBeforeComma: false
BreakStringLiterals: true
ColumnLimit: 0
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 2
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: true
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeCategories:
- Priority: 2
Regex: ^"(llvm|llvm-c|clang|clang-c)/
- Priority: 3
Regex: ^(<|"(gtest|gmock|isl|json)/)
- Priority: 1
Regex: .*
IncludeIsMainRegex: (Test)?$
IndentCaseLabels: false
IndentWidth: 2
IndentWrappedFunctionNames: true
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
Language: Cpp
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 2
NamespaceIndentation: Inner
ObjCBlockIndentWidth: 7
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: false
PointerAlignment: Right
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 0
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: true
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 8
UseTab: Never

View File

@ -10,8 +10,7 @@
struct ASMLine struct ASMLine
{ {
enum class Type enum class Type {
{
Label, Label,
Instruction, Instruction,
Directive Directive
@ -41,8 +40,7 @@ std::string strip_lo_hi(const std::string &s)
std::string fixup_8bit_literal(const std::string &s) std::string fixup_8bit_literal(const std::string &s)
{ {
if (s[0] == '$') if (s[0] == '$') {
{
return "#" + std::to_string(static_cast<uint8_t>(parse_8bit_literal(s))); return "#" + std::to_string(static_cast<uint8_t>(parse_8bit_literal(s)));
} }
@ -64,13 +62,11 @@ std::string fixup_8bit_literal(const std::string &s)
} }
return s; return s;
} }
struct Operand struct Operand
{ {
enum class Type enum class Type {
{
empty, empty,
literal, literal,
reg /*ister*/ reg /*ister*/
@ -82,7 +78,8 @@ struct Operand
Operand() = default; Operand() = default;
bool operator==(const Operand &other) const { bool operator==(const Operand &other) const
{
return type == other.type && reg_num == other.reg_num && value == other.value; return type == other.type && reg_num == other.reg_num && value == other.value;
} }
@ -102,8 +99,7 @@ struct Operand
struct mos6502 : ASMLine struct mos6502 : ASMLine
{ {
enum class OpCode enum class OpCode {
{
unknown, unknown,
lda, lda,
asl, asl,
@ -142,7 +138,8 @@ struct mos6502 : ASMLine
bcs bcs
}; };
static bool get_is_branch(const OpCode o) { static bool get_is_branch(const OpCode o)
{
switch (o) { switch (o) {
case OpCode::beq: case OpCode::beq:
case OpCode::bne: case OpCode::bne:
@ -186,7 +183,8 @@ struct mos6502 : ASMLine
return false; return false;
} }
static bool get_is_comparison(const OpCode o) { static bool get_is_comparison(const OpCode o)
{
switch (o) { switch (o) {
case OpCode::cmp: case OpCode::cmp:
case OpCode::cpy: case OpCode::cpy:
@ -329,8 +327,7 @@ struct mos6502 : ASMLine
case ASMLine::Type::Label: case ASMLine::Type::Label:
return text;// + ':'; return text;// + ':';
case ASMLine::Type::Directive: case ASMLine::Type::Directive:
case ASMLine::Type::Instruction: case ASMLine::Type::Instruction: {
{
const std::string line = '\t' + text + ' ' + op.value; const std::string line = '\t' + text + ' ' + op.value;
return line + std::string(static_cast<size_t>(std::max(15 - static_cast<int>(line.size()), 1)), ' ') + "; " + comment; return line + std::string(static_cast<size_t>(std::max(15 - static_cast<int>(line.size()), 1)), ' ') + "; " + comment;
} }
@ -348,8 +345,7 @@ struct mos6502 : ASMLine
struct i386 : ASMLine struct i386 : ASMLine
{ {
enum class OpCode enum class OpCode {
{
unknown, unknown,
movzbl, movzbl,
movzwl, movzwl,
@ -388,27 +384,46 @@ struct i386 : ASMLine
call call
}; };
static Operand get_register(const int reg_num, const int offset = 0) { static Operand get_register(const int reg_num, const int offset = 0)
{
switch (reg_num) { switch (reg_num) {
// http://sta.c64.org/cbm64mem.html // http://sta.c64.org/cbm64mem.html
case 0x00: return Operand(Operand::Type::literal, "$03"); // unused, fp->int routine pointer case 0x00:
case 0x01: return Operand(Operand::Type::literal, "$04"); return Operand(Operand::Type::literal, "$03");// unused, fp->int routine pointer
case 0x02: return Operand(Operand::Type::literal, "$05"); // unused, int->fp routine pointer case 0x01:
case 0x03: return Operand(Operand::Type::literal, "$06"); return Operand(Operand::Type::literal, "$04");
case 0x04: return Operand(Operand::Type::literal, "$fb"); // unused case 0x02:
case 0x05: return Operand(Operand::Type::literal, "$fc"); // unused return Operand(Operand::Type::literal, "$05");// unused, int->fp routine pointer
case 0x06: return Operand(Operand::Type::literal, "$fd"); // unused case 0x03:
case 0x07: return Operand(Operand::Type::literal, "$fe"); // unused return Operand(Operand::Type::literal, "$06");
case 0x08: return Operand(Operand::Type::literal, "$22"); // unused case 0x04:
case 0x09: return Operand(Operand::Type::literal, "$23"); // unused return Operand(Operand::Type::literal, "$fb");// unused
case 0x0A: return Operand(Operand::Type::literal, "$39"); // Current BASIC line number case 0x05:
case 0x0B: return Operand(Operand::Type::literal, "$3a"); // Current BASIC line number return Operand(Operand::Type::literal, "$fc");// unused
case 0x10: return get_register(0x00 + offset); case 0x06:
case 0x11: return get_register(0x02 + offset); return Operand(Operand::Type::literal, "$fd");// unused
case 0x12: return get_register(0x04 + offset); case 0x07:
case 0x13: return get_register(0x06 + offset); return Operand(Operand::Type::literal, "$fe");// unused
case 0x14: return get_register(0x08 + offset); case 0x08:
case 0x15: return get_register(0x0A + offset); return Operand(Operand::Type::literal, "$22");// unused
case 0x09:
return Operand(Operand::Type::literal, "$23");// unused
case 0x0A:
return Operand(Operand::Type::literal, "$39");// Current BASIC line number
case 0x0B:
return Operand(Operand::Type::literal, "$3a");// Current BASIC line number
case 0x10:
return get_register(0x00 + offset);
case 0x11:
return get_register(0x02 + offset);
case 0x12:
return get_register(0x04 + offset);
case 0x13:
return get_register(0x06 + offset);
case 0x14:
return get_register(0x08 + offset);
case 0x15:
return get_register(0x0A + offset);
}; };
throw std::runtime_error("Unhandled register number: " + std::to_string(reg_num)); throw std::runtime_error("Unhandled register number: " + std::to_string(reg_num));
} }
@ -416,14 +431,12 @@ static Operand get_register(const int reg_num, const int offset = 0) {
static OpCode parse_opcode(Type t, const std::string &o) static OpCode parse_opcode(Type t, const std::string &o)
{ {
switch(t) switch (t) {
{
case Type::Label: case Type::Label:
return OpCode::unknown; return OpCode::unknown;
case Type::Directive: case Type::Directive:
return OpCode::unknown; return OpCode::unknown;
case Type::Instruction: case Type::Instruction: {
{
if (o == "movzwl") return OpCode::movzwl; if (o == "movzwl") return OpCode::movzwl;
if (o == "movzbl") return OpCode::movzbl; if (o == "movzbl") return OpCode::movzbl;
if (o == "shrb") return OpCode::shrb; if (o == "shrb") return OpCode::shrb;
@ -526,11 +539,9 @@ static Operand get_register(const int reg_num, const int offset = 0) {
}; };
struct AVR : ASMLine struct AVR : ASMLine
{ {
enum class OpCode enum class OpCode {
{
unknown, unknown,
ldi, ldi,
sts, sts,
@ -566,14 +577,12 @@ struct AVR : ASMLine
static OpCode parse_opcode(Type t, const std::string &o) static OpCode parse_opcode(Type t, const std::string &o)
{ {
switch(t) switch (t) {
{
case Type::Label: case Type::Label:
return OpCode::unknown; return OpCode::unknown;
case Type::Directive: case Type::Directive:
return OpCode::unknown; return OpCode::unknown;
case Type::Instruction: case Type::Instruction: {
{
if (o == "ldi") return OpCode::ldi; if (o == "ldi") return OpCode::ldi;
if (o == "sts") return OpCode::sts; if (o == "sts") return OpCode::sts;
if (o == "ret") return OpCode::ret; if (o == "ret") return OpCode::ret;
@ -603,7 +612,6 @@ struct AVR : ASMLine
if (o == "cpse") return OpCode::cpse; if (o == "cpse") return OpCode::cpse;
if (o == "cpi") return OpCode::cpi; if (o == "cpi") return OpCode::cpi;
if (o == "brlo") return OpCode::brlo; if (o == "brlo") return OpCode::brlo;
} }
} }
throw std::runtime_error("Unknown opcode: " + o); throw std::runtime_error("Unknown opcode: " + o);
@ -622,48 +630,81 @@ struct AVR : ASMLine
if (reg_name == 'Z') { if (reg_name == 'Z') {
return 30; return 30;
} }
} }
static Operand get_register(const char reg_name, const int byte = 0) { static Operand get_register(const char reg_name, const int byte = 0)
{
return get_register(get_register_number(reg_name), byte); return get_register(get_register_number(reg_name), byte);
} }
static Operand get_register(const int reg_num, [[maybe_unused]] const int offset = 0) { static Operand get_register(const int reg_num, [[maybe_unused]] const int offset = 0)
{
switch (reg_num) { switch (reg_num) {
// http://sta.c64.org/cbm64mem.html // http://sta.c64.org/cbm64mem.html
case 0: return Operand(Operand::Type::literal, "$a7"); // bit buffer for rs232 case 0:
case 1: return Operand(Operand::Type::literal, "$a8"); // counter for rs232 return Operand(Operand::Type::literal, "$a7");// bit buffer for rs232
case 2: return Operand(Operand::Type::literal, "$05"); // unused, int->fp routine pointer case 1:
case 3: return Operand(Operand::Type::literal, "$06"); return Operand(Operand::Type::literal, "$a8");// counter for rs232
case 4: return Operand(Operand::Type::literal, "$fb"); // unused case 2:
case 5: return Operand(Operand::Type::literal, "$fc"); // unused return Operand(Operand::Type::literal, "$05");// unused, int->fp routine pointer
case 6: return Operand(Operand::Type::literal, "$fd"); // unused case 3:
case 7: return Operand(Operand::Type::literal, "$fe"); // unused return Operand(Operand::Type::literal, "$06");
case 8: return Operand(Operand::Type::literal, "$22"); // unused case 4:
case 9: return Operand(Operand::Type::literal, "$23"); // unused return Operand(Operand::Type::literal, "$fb");// unused
case 10: return Operand(Operand::Type::literal, "$39"); // Current BASIC line number case 5:
case 11: return Operand(Operand::Type::literal, "$3a"); // Current BASIC line number return Operand(Operand::Type::literal, "$fc");// unused
case 12: return Operand(Operand::Type::literal, "$61"); // arithmetic register #1 case 6:
case 13: return Operand(Operand::Type::literal, "$62"); return Operand(Operand::Type::literal, "$fd");// unused
case 14: return Operand(Operand::Type::literal, "$63"); case 7:
case 15: return Operand(Operand::Type::literal, "$64"); return Operand(Operand::Type::literal, "$fe");// unused
case 16: return Operand(Operand::Type::literal, "$65"); case 8:
case 17: return Operand(Operand::Type::literal, "$69"); // arithmetic register #2 return Operand(Operand::Type::literal, "$22");// unused
case 18: return Operand(Operand::Type::literal, "$6a"); case 9:
case 19: return Operand(Operand::Type::literal, "$6b"); return Operand(Operand::Type::literal, "$23");// unused
case 20: return Operand(Operand::Type::literal, "$6c"); case 10:
case 21: return Operand(Operand::Type::literal, "$6d"); return Operand(Operand::Type::literal, "$39");// Current BASIC line number
case 22: return Operand(Operand::Type::literal, "$57"); // arithmetic register #3 case 11:
case 23: return Operand(Operand::Type::literal, "$58"); return Operand(Operand::Type::literal, "$3a");// Current BASIC line number
case 24: return Operand(Operand::Type::literal, "$59"); case 12:
case 25: return Operand(Operand::Type::literal, "$5a"); return Operand(Operand::Type::literal, "$61");// arithmetic register #1
case 26: return Operand(Operand::Type::literal, "$5b"); case 13:
case 27: return Operand(Operand::Type::literal, "$5c"); // arithmetic register #4 return Operand(Operand::Type::literal, "$62");
case 28: return Operand(Operand::Type::literal, "$5d"); case 14:
case 29: return Operand(Operand::Type::literal, "$5e"); return Operand(Operand::Type::literal, "$63");
case 30: return Operand(Operand::Type::literal, "$5f"); case 15:
case 31: return Operand(Operand::Type::literal, "$60"); 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)); throw std::runtime_error("Unhandled register number: " + std::to_string(reg_num));
} }
@ -698,8 +739,7 @@ static Operand get_register(const int reg_num, [[maybe_unused]] const int offset
void indirect_load(std::vector<mos6502> &instructions, const std::string &from_address_low_byte, const std::string &to_address) void indirect_load(std::vector<mos6502> &instructions, const std::string &from_address_low_byte, const std::string &to_address)
{ {
instructions.emplace_back(mos6502::OpCode::ldy, Operand(Operand::Type::literal, "#0")); instructions.emplace_back(mos6502::OpCode::ldy, Operand(Operand::Type::literal, "#0"));
instructions.emplace_back(mos6502::OpCode::lda, Operand(Operand::Type::literal, instructions.emplace_back(mos6502::OpCode::lda, Operand(Operand::Type::literal, "(" + from_address_low_byte + "), Y"));
"(" + from_address_low_byte + "), Y"));
instructions.emplace_back(mos6502::OpCode::sta, Operand(Operand::Type::literal, to_address)); instructions.emplace_back(mos6502::OpCode::sta, Operand(Operand::Type::literal, to_address));
} }
@ -707,8 +747,7 @@ void indirect_store(std::vector<mos6502> &instructions, const std::string &from_
{ {
instructions.emplace_back(mos6502::OpCode::lda, Operand(Operand::Type::literal, from_address)); instructions.emplace_back(mos6502::OpCode::lda, Operand(Operand::Type::literal, from_address));
instructions.emplace_back(mos6502::OpCode::ldy, Operand(Operand::Type::literal, "#0")); instructions.emplace_back(mos6502::OpCode::ldy, Operand(Operand::Type::literal, "#0"));
instructions.emplace_back(mos6502::OpCode::sta, Operand(Operand::Type::literal, instructions.emplace_back(mos6502::OpCode::sta, Operand(Operand::Type::literal, "(" + to_address_low_byte + "), Y"));
"(" + to_address_low_byte + "), Y") );
} }
void fixup_16_bit_N_Z_flags(std::vector<mos6502> &instructions) void fixup_16_bit_N_Z_flags(std::vector<mos6502> &instructions)
@ -733,7 +772,8 @@ void fixup_16_bit_N_Z_flags(std::vector<mos6502> &instructions)
} }
void subtract_16_bit(std::vector<mos6502> &instructions, int reg, const std::uint16_t value) { void subtract_16_bit(std::vector<mos6502> &instructions, int reg, const std::uint16_t value)
{
//instructions.emplace_back(mos6502::OpCode::sta, Operand(Operand::Type::literal, address_low_byte)); //instructions.emplace_back(mos6502::OpCode::sta, Operand(Operand::Type::literal, address_low_byte));
instructions.emplace_back(mos6502::OpCode::sec); instructions.emplace_back(mos6502::OpCode::sec);
instructions.emplace_back(mos6502::OpCode::lda, AVR::get_register(reg)); instructions.emplace_back(mos6502::OpCode::lda, AVR::get_register(reg));
@ -746,7 +786,8 @@ void subtract_16_bit(std::vector<mos6502> &instructions, int reg, const std::ui
fixup_16_bit_N_Z_flags(instructions); fixup_16_bit_N_Z_flags(instructions);
} }
void increment_16_bit(std::vector<mos6502> & instructions, int reg) { void increment_16_bit(std::vector<mos6502> &instructions, int reg)
{
//instructions.emplace_back(mos6502::OpCode::sta, Operand(Operand::Type::literal, address_low_byte)); //instructions.emplace_back(mos6502::OpCode::sta, Operand(Operand::Type::literal, address_low_byte));
instructions.emplace_back(mos6502::OpCode::lda, AVR::get_register(reg)); instructions.emplace_back(mos6502::OpCode::lda, AVR::get_register(reg));
instructions.emplace_back(mos6502::OpCode::clc); instructions.emplace_back(mos6502::OpCode::clc);
@ -772,8 +813,7 @@ void translate_instruction(std::vector<mos6502> &instructions, const AVR::OpCode
const auto o1_reg_num = translate_register_number(o1); const auto o1_reg_num = translate_register_number(o1);
const auto o2_reg_num = translate_register_number(o2); const auto o2_reg_num = translate_register_number(o2);
switch(op) switch (op) {
{
case AVR::OpCode::dec: case AVR::OpCode::dec:
instructions.emplace_back(mos6502::OpCode::dec, AVR::get_register(o1_reg_num)); instructions.emplace_back(mos6502::OpCode::dec, AVR::get_register(o1_reg_num));
return; return;
@ -801,8 +841,7 @@ void translate_instruction(std::vector<mos6502> &instructions, const AVR::OpCode
case AVR::OpCode::rcall: case AVR::OpCode::rcall:
instructions.emplace_back(mos6502::OpCode::jsr, o1); instructions.emplace_back(mos6502::OpCode::jsr, o1);
return; return;
case AVR::OpCode::ld: case AVR::OpCode::ld: {
{
if (o2.value == "Z" || o2.value == "X" || o2.value == "Y") { if (o2.value == "Z" || o2.value == "X" || o2.value == "Y") {
indirect_load(instructions, AVR::get_register(o2.value[0]).value, AVR::get_register(o1_reg_num).value); indirect_load(instructions, AVR::get_register(o2.value[0]).value, AVR::get_register(o1_reg_num).value);
return; return;
@ -814,8 +853,7 @@ void translate_instruction(std::vector<mos6502> &instructions, const AVR::OpCode
} }
throw std::runtime_error("Unhandled ld to non-Z"); throw std::runtime_error("Unhandled ld to non-Z");
} }
case AVR::OpCode::sbci: case AVR::OpCode::sbci: {
{
// we want to utilize the carry flag, however it was set previously // we want to utilize the carry flag, however it was set previously
// (it's really a borrow flag on the 6502) // (it's really a borrow flag on the 6502)
instructions.emplace_back(mos6502::OpCode::lda, AVR::get_register(o1_reg_num)); instructions.emplace_back(mos6502::OpCode::lda, AVR::get_register(o1_reg_num));
@ -824,8 +862,7 @@ void translate_instruction(std::vector<mos6502> &instructions, const AVR::OpCode
fixup_16_bit_N_Z_flags(instructions); fixup_16_bit_N_Z_flags(instructions);
return; return;
} }
case AVR::OpCode::subi: case AVR::OpCode::subi: {
{
// to do: deal with Carry bit (and other flags) nonsense from AVR // to do: deal with Carry bit (and other flags) nonsense from AVR
// if |x| < |y| -> x-y +carry // if |x| < |y| -> x-y +carry
// for these special cases with -(1) and -(-(1)) // for these special cases with -(1) and -(-(1))
@ -984,8 +1021,7 @@ void translate_instruction(std::vector<mos6502> &instructions, const AVR::OpCode
void translate_instruction(std::vector<mos6502> &instructions, const i386::OpCode op, const Operand &o1, const Operand &o2) void translate_instruction(std::vector<mos6502> &instructions, const i386::OpCode op, const Operand &o1, const Operand &o2)
{ {
switch(op) switch (op) {
{
case i386::OpCode::ret: case i386::OpCode::ret:
instructions.emplace_back(mos6502::OpCode::rts); instructions.emplace_back(mos6502::OpCode::rts);
break; break;
@ -1259,21 +1295,17 @@ void translate_instruction(std::vector<mos6502> &instructions, const i386::OpCod
default: default:
throw std::runtime_error("Cannot translate unhandled instruction"); throw std::runtime_error("Cannot translate unhandled instruction");
}
} }
} enum class LogLevel {
enum class LogLevel
{
Warning, Warning,
Error Error
}; };
std::string to_string(const LogLevel ll) std::string to_string(const LogLevel ll)
{ {
switch (ll) switch (ll) {
{
case LogLevel::Warning: case LogLevel::Warning:
return "warning"; return "warning";
case LogLevel::Error: case LogLevel::Error:
@ -1298,8 +1330,7 @@ template<typename FromArch>
void to_mos6502(const FromArch &i, std::vector<mos6502> &instructions) void to_mos6502(const FromArch &i, std::vector<mos6502> &instructions)
{ {
try { try {
switch(i.type) switch (i.type) {
{
case ASMLine::Type::Label: case ASMLine::Type::Label:
if (i.text == "0") { if (i.text == "0") {
instructions.emplace_back(i.type, "-memcpy_0"); instructions.emplace_back(i.type, "-memcpy_0");
@ -1314,8 +1345,7 @@ void to_mos6502(const FromArch &i, std::vector<mos6502> &instructions)
const auto count = atoi(i.text.data() + 6); const auto count = atoi(i.text.data() + 6);
std::string zeros; std::string zeros;
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i) {
{
if ((i % 20) == 0) { if ((i % 20) == 0) {
if (!zeros.empty()) { if (!zeros.empty()) {
instructions.emplace_back(ASMLine::Type::Directive, zeros); instructions.emplace_back(ASMLine::Type::Directive, zeros);
@ -1349,11 +1379,9 @@ void to_mos6502(const FromArch &i, std::vector<mos6502> &instructions)
if (text[0] == '\t') { if (text[0] == '\t') {
text.erase(0, 1); text.erase(0, 1);
} }
for_each(std::next(instructions.begin(), head), instructions.end(), for_each(std::next(instructions.begin(), head), instructions.end(), [text](auto &ins) {
[ text ](auto &ins){
ins.comment = text; ins.comment = text;
} });
);
return; return;
} }
} catch (const std::exception &e) { } catch (const std::exception &e) {
@ -1374,11 +1402,9 @@ bool optimize(std::vector<mos6502> &instructions)
return i; return i;
}; };
for (size_t op = 0; op < instructions.size() - 1; ++op) for (size_t op = 0; op < instructions.size() - 1; ++op) {
{
// look for a transfer of Y -> A immediately followed by A -> Y // look for a transfer of Y -> A immediately followed by A -> Y
if (instructions[op].opcode == mos6502::OpCode::tya) if (instructions[op].opcode == mos6502::OpCode::tya) {
{
next_instruction(op); next_instruction(op);
if (instructions[op].opcode == mos6502::OpCode::tay) { if (instructions[op].opcode == mos6502::OpCode::tay) {
instructions[op] = mos6502(ASMLine::Type::Directive, instructions[op] = mos6502(ASMLine::Type::Directive,
@ -1388,15 +1414,12 @@ bool optimize(std::vector<mos6502> &instructions)
} }
} }
for (size_t op = 0; op < instructions.size() - 1; ++op) for (size_t op = 0; op < instructions.size() - 1; ++op) {
{
// look for a store A -> loc immediately followed by loc -> A // look for a store A -> loc immediately followed by loc -> A
if (instructions[op].opcode == mos6502::OpCode::sta) if (instructions[op].opcode == mos6502::OpCode::sta) {
{
const auto next = next_instruction(op); const auto next = next_instruction(op);
if (instructions[next].opcode == mos6502::OpCode::lda if (instructions[next].opcode == mos6502::OpCode::lda
&& instructions[next].op == instructions[op].op) && instructions[next].op == instructions[op].op) {
{
instructions[next] = mos6502(ASMLine::Type::Directive, instructions[next] = mos6502(ASMLine::Type::Directive,
"; removed redundant lda: " + instructions[next].to_string()); "; removed redundant lda: " + instructions[next].to_string());
return true; return true;
@ -1410,8 +1433,7 @@ bool optimize(std::vector<mos6502> &instructions)
while (op2 < instructions.size() && (instructions[op2].type != ASMLine::Type::Label)) { while (op2 < instructions.size() && (instructions[op2].type != ASMLine::Type::Label)) {
// while inside this label // while inside this label
if (instructions[op2].opcode == mos6502::OpCode::ldy && instructions[op2].op.value == if (instructions[op2].opcode == mos6502::OpCode::ldy && instructions[op2].op.value == instructions[op].op.value) {
instructions[op].op.value) {
instructions[op2] = mos6502(ASMLine::Type::Directive, "; removed redundant ldy: " + instructions[op2].to_string()); instructions[op2] = mos6502(ASMLine::Type::Directive, "; removed redundant ldy: " + instructions[op2].to_string());
return true; return true;
} }
@ -1420,26 +1442,21 @@ bool optimize(std::vector<mos6502> &instructions)
} }
} }
for (size_t op = 0; op < instructions.size() - 1; ++op) for (size_t op = 0; op < instructions.size() - 1; ++op) {
{
if (instructions[op].opcode == mos6502::OpCode::lda if (instructions[op].opcode == mos6502::OpCode::lda
&& instructions[op].op.type == Operand::Type::literal) && instructions[op].op.type == Operand::Type::literal) {
{
const auto operand = instructions[op].op; const auto operand = instructions[op].op;
auto op2 = op + 1; auto op2 = op + 1;
// look for multiple stores of the same value // look for multiple stores of the same value
while (op2 < instructions.size() && (instructions[op2].opcode == mos6502::OpCode::sta while (op2 < instructions.size() && (instructions[op2].opcode == mos6502::OpCode::sta || instructions[op2].type == ASMLine::Type::Directive)) {
|| instructions[op2].type == ASMLine::Type::Directive)) {
++op2; ++op2;
} }
if (instructions[op2].opcode == mos6502::OpCode::lda if (instructions[op2].opcode == mos6502::OpCode::lda
&& operand == instructions[op2].op) && operand == instructions[op2].op) {
{
instructions[op2] = mos6502(ASMLine::Type::Directive, instructions[op2] = mos6502(ASMLine::Type::Directive,
"; removed redundant lda: " + instructions[op2].to_string()); "; removed redundant lda: " + instructions[op2].to_string());
return true; return true;
} }
} }
} }
@ -1449,17 +1466,14 @@ bool optimize(std::vector<mos6502> &instructions)
bool fix_long_branches(std::vector<mos6502> &instructions, int &branch_patch_count) bool fix_long_branches(std::vector<mos6502> &instructions, int &branch_patch_count)
{ {
std::map<std::string, size_t> labels; std::map<std::string, size_t> labels;
for (size_t op = 0; op < instructions.size(); ++op) for (size_t op = 0; op < instructions.size(); ++op) {
{
if (instructions[op].type == ASMLine::Type::Label) { if (instructions[op].type == ASMLine::Type::Label) {
labels[instructions[op].text] = op; labels[instructions[op].text] = op;
} }
} }
for (size_t op = 0; op < instructions.size(); ++op) 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) {
if (instructions[op].is_branch && std::abs(static_cast<int>(labels[instructions[op].op.value]) - static_cast<int>(op)) * 3 > 255)
{
++branch_patch_count; ++branch_patch_count;
const auto going_to = instructions[op].op.value; const auto going_to = instructions[op].op.value;
const auto new_pos = "patch_" + std::to_string(branch_patch_count); const auto new_pos = "patch_" + std::to_string(branch_patch_count);
@ -1494,14 +1508,12 @@ bool fix_overwritten_flags(std::vector<mos6502> &instructions)
return false; return false;
} }
for (size_t op = 0; op < instructions.size(); ++op) for (size_t op = 0; op < instructions.size(); ++op) {
{
if (instructions[op].is_comparison) { if (instructions[op].is_comparison) {
auto op2 = op + 1; auto op2 = op + 1;
while (op2 < instructions.size() while (op2 < instructions.size()
&& !instructions[op2].is_comparison && !instructions[op2].is_comparison
&& !instructions[op2].is_branch) && !instructions[op2].is_branch) {
{
++op2; ++op2;
} }
@ -1520,7 +1532,6 @@ bool fix_overwritten_flags(std::vector<mos6502> &instructions)
return true; return true;
} }
} }
} }
} }
@ -1528,19 +1539,21 @@ bool fix_overwritten_flags(std::vector<mos6502> &instructions)
return false; return false;
} }
void setup_target_cpu_state([[maybe_unused]] const std::vector<AVR> &instructions, std::vector<mos6502> &new_instructions) { void setup_target_cpu_state([[maybe_unused]] const std::vector<AVR> &instructions, std::vector<mos6502> &new_instructions)
{
// set __zero_reg__ (reg 1 on AVR) to 0 // set __zero_reg__ (reg 1 on AVR) to 0
new_instructions.emplace_back(mos6502::OpCode::lda, Operand(Operand::Type::literal, "#$00")); new_instructions.emplace_back(mos6502::OpCode::lda, Operand(Operand::Type::literal, "#$00"));
new_instructions.emplace_back(mos6502::OpCode::sta, AVR::get_register(1)); new_instructions.emplace_back(mos6502::OpCode::sta, AVR::get_register(1));
} }
void void setup_target_cpu_state([[maybe_unused]] const std::vector<i386> &instructions, [[maybe_unused]] std::vector<mos6502> &new_instructions)
setup_target_cpu_state([[maybe_unused]] const std::vector<i386> &instructions, [[maybe_unused]] std::vector<mos6502> &new_instructions) { {
} }
template<typename Arch> template<typename Arch>
void run(std::istream &input) { void run(std::istream &input)
{
std::regex Comment(R"(\s*\#.*)"); std::regex Comment(R"(\s*\#.*)");
std::regex Label(R"(^\s*(\S+):.*)"); std::regex Label(R"(^\s*(\S+):.*)");
std::regex Directive(R"(^\s*(\..+))"); std::regex Directive(R"(^\s*(\..+))");
@ -1551,17 +1564,14 @@ void run(std::istream &input) {
int lineno = 0; int lineno = 0;
std::vector<Arch> instructions; std::vector<Arch> instructions;
while (input.good()) while (input.good()) {
{
std::string line; std::string line;
getline(input, line); getline(input, line);
try { try {
std::smatch match; std::smatch match;
if (std::regex_match(line, match, Label)) if (std::regex_match(line, match, Label)) {
{
instructions.emplace_back(lineno, line, ASMLine::Type::Label, match[1]); instructions.emplace_back(lineno, line, ASMLine::Type::Label, match[1]);
} else if (std::regex_match(line, match, Comment)) { } else if (std::regex_match(line, match, Comment)) {
// don't care about comments // don't care about comments
@ -1584,8 +1594,7 @@ void run(std::istream &input) {
std::set<std::string> labels; std::set<std::string> labels;
for (const auto &i : instructions) for (const auto &i : instructions) {
{
if (i.type == ASMLine::Type::Label) { if (i.type == ASMLine::Type::Label) {
labels.insert(i.text); labels.insert(i.text);
} }
@ -1593,10 +1602,8 @@ void run(std::istream &input) {
std::set<std::string> used_labels{ "main" }; std::set<std::string> used_labels{ "main" };
for (const auto &i : instructions) for (const auto &i : instructions) {
{ if (i.type == ASMLine::Type::Instruction) {
if (i.type == ASMLine::Type::Instruction)
{
const auto check_label = [&](const auto &value) { const auto check_label = [&](const auto &value) {
if (labels.count(value) != 0) { if (labels.count(value) != 0) {
@ -1629,10 +1636,8 @@ void run(std::istream &input) {
std::clog << "Label: '" << l.first << "': '" << l.second << "'\n"; std::clog << "Label: '" << l.first << "': '" << l.second << "'\n";
} }
for (auto &i : instructions) for (auto &i : instructions) {
{ if (i.type == ASMLine::Type::Label) {
if (i.type == ASMLine::Type::Label)
{
std::clog << "Looking up Label: '" << i.text << "'\n"; std::clog << "Looking up Label: '" << i.text << "'\n";
if (i.text == "0") { if (i.text == "0") {
i.text = "-memcpy_0"; i.text = "-memcpy_0";
@ -1641,8 +1646,7 @@ void run(std::istream &input) {
} }
} }
if (i.operand2.value.starts_with("lo8(") || i.operand2.value.starts_with("hi8(")) if (i.operand2.value.starts_with("lo8(") || i.operand2.value.starts_with("hi8(")) {
{
const auto potential_label = strip_lo_hi(i.operand2.value); const auto potential_label = strip_lo_hi(i.operand2.value);
const auto itr1 = new_labels.find(potential_label); const auto itr1 = new_labels.find(potential_label);
if (itr1 != new_labels.end()) { if (itr1 != new_labels.end()) {
@ -1671,8 +1675,7 @@ void run(std::istream &input) {
bool skip_next_instruction = false; bool skip_next_instruction = false;
std::string next_label_name; std::string next_label_name;
for (const auto &i : instructions) for (const auto &i : instructions) {
{
to_mos6502(i, new_instructions); to_mos6502(i, new_instructions);
// intentionally copy so we don't invalidate the reference // intentionally copy so we don't invalidate the reference
@ -1684,33 +1687,28 @@ void run(std::istream &input) {
skip_next_instruction = false; skip_next_instruction = false;
} }
if (last_instruction.type == ASMLine::Type::Directive && last_instruction.text.starts_with("skip_next_instruction")) if (last_instruction.type == ASMLine::Type::Directive && last_instruction.text.starts_with("skip_next_instruction")) {
{
skip_next_instruction = true; skip_next_instruction = true;
next_label_name = last_instruction.text; next_label_name = last_instruction.text;
new_instructions.erase(std::next(new_instructions.begin(), static_cast<std::ptrdiff_t>(last_instruction_loc))); new_instructions.erase(std::next(new_instructions.begin(), static_cast<std::ptrdiff_t>(last_instruction_loc)));
} }
} }
while (fix_overwritten_flags(new_instructions)) while (fix_overwritten_flags(new_instructions)) {
{
// do it however many times it takes // do it however many times it takes
} }
while (optimize(new_instructions)) while (optimize(new_instructions)) {
{
// do it however many times it takes // do it however many times it takes
} }
int branch_patch_count = 0; int branch_patch_count = 0;
while (fix_long_branches(new_instructions, branch_patch_count)) while (fix_long_branches(new_instructions, branch_patch_count)) {
{
// do it however many times it takes // do it however many times it takes
} }
for (const auto i : new_instructions) for (const auto i : new_instructions) {
{
std::cout << i.to_string() << '\n'; std::cout << i.to_string() << '\n';
} }
} }
@ -1744,4 +1742,3 @@ int main([[maybe_unused]] const int argc, const char *argv[])
run<i386>(input); run<i386>(input);
} }
} }