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:
98
.clang-format
Normal file
98
.clang-format
Normal 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
|
||||||
|
|
355
src/main.cpp
355
src/main.cpp
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user