1
0
mirror of https://github.com/lefticus/6502-cpp.git synced 2024-06-09 20:29:28 +00:00

Better stack handling. We now require -mtiny-stack from GCC

This commit is contained in:
Jason Turner 2021-05-08 22:58:55 -06:00
parent baf9c092ea
commit a4edf7194e
5 changed files with 49 additions and 13 deletions

View File

@ -1 +1 @@
avr-gcc $1 -Wall -Wextra -c -o- -S -O3 -I ~/avr-libstdcpp/include/ -std=c++20 | tee $1.asm | ./avr-to-6502 | tee $1.asm && xa -O PETSCREEN -M $1.prg avr-gcc $1 -Wall -Wextra -mtiny-stack -c -o- -S -O3 -I ~/avr-libstdcpp/include/ -std=c++20 | tee $1.asm | ./avr-to-6502 | tee $1.asm && xa -O PETSCREEN -M $1.prg

View File

@ -34,6 +34,7 @@ struct mos6502 : ASMLine
jsr, jsr,
lda, lda,
ldx,
ldy, ldy,
lsr, lsr,
@ -51,11 +52,14 @@ struct mos6502 : ASMLine
sbc, sbc,
sec, sec,
sta, sta,
stx,
sty, sty,
tax, tax,
tay, tay,
tsx,
txa, txa,
txs,
tya, tya,
}; };
@ -82,6 +86,7 @@ struct mos6502 : ASMLine
case OpCode::jmp: case OpCode::jmp:
case OpCode::jsr: case OpCode::jsr:
case OpCode::lda: case OpCode::lda:
case OpCode::ldx:
case OpCode::ldy: case OpCode::ldy:
case OpCode::lsr: case OpCode::lsr:
case OpCode::ORA: case OpCode::ORA:
@ -96,9 +101,12 @@ struct mos6502 : ASMLine
case OpCode::sec: case OpCode::sec:
case OpCode::sta: case OpCode::sta:
case OpCode::sty: case OpCode::sty:
case OpCode::stx:
case OpCode::tax: case OpCode::tax:
case OpCode::tay: case OpCode::tay:
case OpCode::tsx:
case OpCode::txa: case OpCode::txa:
case OpCode::txs:
case OpCode::tya: case OpCode::tya:
case OpCode::unknown: case OpCode::unknown:
@ -130,6 +138,7 @@ struct mos6502 : ASMLine
case OpCode::jmp: case OpCode::jmp:
case OpCode::jsr: case OpCode::jsr:
case OpCode::lda: case OpCode::lda:
case OpCode::ldx:
case OpCode::ldy: case OpCode::ldy:
case OpCode::lsr: case OpCode::lsr:
case OpCode::ORA: case OpCode::ORA:
@ -143,10 +152,13 @@ struct mos6502 : ASMLine
case OpCode::sbc: case OpCode::sbc:
case OpCode::sec: case OpCode::sec:
case OpCode::sta: case OpCode::sta:
case OpCode::stx:
case OpCode::sty: case OpCode::sty:
case OpCode::tax: case OpCode::tax:
case OpCode::tay: case OpCode::tay:
case OpCode::tsx:
case OpCode::txa: case OpCode::txa:
case OpCode::txs:
case OpCode::tya: case OpCode::tya:
case OpCode::unknown: case OpCode::unknown:
break; break;
@ -176,15 +188,19 @@ struct mos6502 : ASMLine
case OpCode::lda: return "lda"; case OpCode::lda: return "lda";
case OpCode::asl: return "asl"; case OpCode::asl: return "asl";
case OpCode::rol: return "rol"; case OpCode::rol: return "rol";
case OpCode::ldx: return "ldx";
case OpCode::ldy: return "ldy"; case OpCode::ldy: return "ldy";
case OpCode::tay: return "tay"; case OpCode::tay: return "tay";
case OpCode::tya: return "tya"; case OpCode::tya: return "tya";
case OpCode::tax: return "tax"; case OpCode::tax: return "tax";
case OpCode::tsx: return "tsx";
case OpCode::txa: return "txa"; case OpCode::txa: return "txa";
case OpCode::txs: return "txs";
case OpCode::cpy: return "cpy"; case OpCode::cpy: return "cpy";
case OpCode::eor: return "eor"; case OpCode::eor: return "eor";
case OpCode::sta: return "sta"; case OpCode::sta: return "sta";
case OpCode::sty: return "sty"; case OpCode::sty: return "sty";
case OpCode::stx: return "stx";
case OpCode::pha: return "pha"; case OpCode::pha: return "pha";
case OpCode::pla: return "pla"; case OpCode::pla: return "pla";
case OpCode::php: return "php"; case OpCode::php: return "php";

View File

@ -103,6 +103,10 @@ bool optimize(std::vector<mos6502> &instructions)
} }
} }
// todo: fix this ldy redundant move, right now it doesn't
// take into account if Y has been used
/*
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::ldy && instructions[op].op.type == Operand::Type::literal) { if (instructions[op].opcode == mos6502::OpCode::ldy && instructions[op].op.type == Operand::Type::literal) {
auto op2 = op + 1; auto op2 = op + 1;
@ -116,7 +120,9 @@ bool optimize(std::vector<mos6502> &instructions)
++op2; ++op2;
} }
} }
} }
*/
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

View File

@ -100,9 +100,6 @@ struct C64 : Personality
return Operand(Operand::Type::literal, "$5f"); return Operand(Operand::Type::literal, "$5f");
case 31: case 31:
return Operand(Operand::Type::literal, "$60"); return Operand(Operand::Type::literal, "$60");
case 32:
// 32 is the "Stack Pointer", because I decided so, I mean, it makes sense
return Operand(Operand::Type::literal, std::string{stack_low_address()});
} }
throw std::runtime_error("Unhandled register number: " + std::to_string(reg_num)); throw std::runtime_error("Unhandled register number: " + std::to_string(reg_num));
} }

View File

@ -116,6 +116,8 @@ struct AVR : ASMLine
mov, mov,
out,
pop, pop,
push, push,
@ -185,6 +187,7 @@ struct AVR : ASMLine
if (o == "brsh") { return OpCode::brsh; } if (o == "brsh") { return OpCode::brsh; }
if (o == "breq") { return OpCode::breq; } if (o == "breq") { return OpCode::breq; }
if (o == "in") { return OpCode::in; } if (o == "in") { return OpCode::in; }
if (o == "out") { return OpCode::out; }
} }
} }
throw std::runtime_error(fmt::format("Unknown opcode: {}", o)); throw std::runtime_error(fmt::format("Unknown opcode: {}", o));
@ -249,7 +252,7 @@ void fixup_16_bit_N_Z_flags(std::vector<mos6502> &instructions)
{ {
// need to get both Z and N set appropriately // need to get both Z and N set appropriately
// assuming A contains higher order byte and Y contains lower order byte // assuming A contains higher order byte and X contains lower order byte
instructions.emplace_back(ASMLine::Type::Directive, "; BEGIN remove if next is lda"); instructions.emplace_back(ASMLine::Type::Directive, "; BEGIN remove if next is lda");
instructions.emplace_back(ASMLine::Type::Directive, "; set CPU flags assuming A holds the higher order byte already"); instructions.emplace_back(ASMLine::Type::Directive, "; set CPU flags assuming A holds the higher order byte already");
std::string set_flag_label = "flags_set_after_16_bit_op_" + std::to_string(instructions.size()); std::string set_flag_label = "flags_set_after_16_bit_op_" + std::to_string(instructions.size());
@ -269,29 +272,29 @@ void fixup_16_bit_N_Z_flags(std::vector<mos6502> &instructions)
void add_16_bit(const Personality &personality, std::vector<mos6502> &instructions, int reg, const std::uint16_t value) void add_16_bit(const Personality &personality, 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::clc); instructions.emplace_back(mos6502::OpCode::clc);
instructions.emplace_back(mos6502::OpCode::lda, personality.get_register(reg)); instructions.emplace_back(mos6502::OpCode::lda, personality.get_register(reg));
instructions.emplace_back(mos6502::OpCode::adc, Operand(Operand::Type::literal, "#" + std::to_string((value & 0xFFu)))); instructions.emplace_back(mos6502::OpCode::adc, Operand(Operand::Type::literal, "#" + std::to_string((value & 0xFFu))));
instructions.emplace_back(mos6502::OpCode::sta, personality.get_register(reg)); instructions.emplace_back(mos6502::OpCode::sta, personality.get_register(reg));
instructions.emplace_back(mos6502::OpCode::tax);
instructions.emplace_back(mos6502::OpCode::lda, personality.get_register(reg + 1)); instructions.emplace_back(mos6502::OpCode::lda, personality.get_register(reg + 1));
instructions.emplace_back(mos6502::OpCode::adc, Operand(Operand::Type::literal, "#" + std::to_string((value >> 8u) & 0xFFu))); instructions.emplace_back(mos6502::OpCode::adc, Operand(Operand::Type::literal, "#" + std::to_string((value >> 8u) & 0xFFu)));
instructions.emplace_back(mos6502::OpCode::sta, personality.get_register(reg + 1)); instructions.emplace_back(mos6502::OpCode::sta, personality.get_register(reg + 1));
instructions.emplace_back(mos6502::OpCode::tax);
fixup_16_bit_N_Z_flags(instructions); fixup_16_bit_N_Z_flags(instructions);
} }
void subtract_16_bit(const Personality &personality, std::vector<mos6502> &instructions, int reg, const std::uint16_t value) void subtract_16_bit(const Personality &personality, 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::sec); instructions.emplace_back(mos6502::OpCode::sec);
instructions.emplace_back(mos6502::OpCode::lda, personality.get_register(reg)); instructions.emplace_back(mos6502::OpCode::lda, personality.get_register(reg));
instructions.emplace_back(mos6502::OpCode::sbc, Operand(Operand::Type::literal, "#" + std::to_string((value & 0xFFu)))); instructions.emplace_back(mos6502::OpCode::sbc, Operand(Operand::Type::literal, "#" + std::to_string((value & 0xFFu))));
instructions.emplace_back(mos6502::OpCode::sta, personality.get_register(reg)); instructions.emplace_back(mos6502::OpCode::sta, personality.get_register(reg));
instructions.emplace_back(mos6502::OpCode::tax);
instructions.emplace_back(mos6502::OpCode::lda, personality.get_register(reg + 1)); instructions.emplace_back(mos6502::OpCode::lda, personality.get_register(reg + 1));
instructions.emplace_back(mos6502::OpCode::sbc, Operand(Operand::Type::literal, "#" + std::to_string((value >> 8u) & 0xFFu))); instructions.emplace_back(mos6502::OpCode::sbc, Operand(Operand::Type::literal, "#" + std::to_string((value >> 8u) & 0xFFu)));
instructions.emplace_back(mos6502::OpCode::sta, personality.get_register(reg + 1)); instructions.emplace_back(mos6502::OpCode::sta, personality.get_register(reg + 1));
instructions.emplace_back(mos6502::OpCode::tax);
fixup_16_bit_N_Z_flags(instructions); fixup_16_bit_N_Z_flags(instructions);
} }
@ -626,16 +629,30 @@ void translate_instruction(const Personality &personality, std::vector<mos6502>
return; return;
} }
} }
case AVR::OpCode::out: {
if (o1.value == "__SP_L__") {
instructions.emplace_back(mos6502::OpCode::ldx, personality.get_register(o2_reg_num));
instructions.emplace_back(mos6502::OpCode::txs);
return;
}
if (o1.value == "__SP_H__") {
// officially nothing to do - we cannot change the high byte of the SP on 6502
return;
}
throw std::runtime_error("Could not translate unknown 'out' instruction");
}
case AVR::OpCode::in: { case AVR::OpCode::in: {
if (o2.value == "__SP_L__") { if (o2.value == "__SP_L__") {
instructions.emplace_back(mos6502::OpCode::lda, Operand(Operand::Type::literal, std::string{ personality.stack_low_address() })); instructions.emplace_back(mos6502::OpCode::tsx);
instructions.emplace_back(mos6502::OpCode::sta, personality.get_register(o1_reg_num)); instructions.emplace_back(mos6502::OpCode::stx, personality.get_register(o1_reg_num));
return; return;
} }
if (o2.value == "__SP_H__") { if (o2.value == "__SP_H__") {
instructions.emplace_back(mos6502::OpCode::lda, Operand(Operand::Type::literal, std::string{ personality.stack_high_address() })); instructions.emplace_back(mos6502::OpCode::lda, Operand(Operand::Type::literal, "$01"));
instructions.emplace_back(mos6502::OpCode::sta, personality.get_register(o1_reg_num)); instructions.emplace_back(mos6502::OpCode::sta, personality.get_register(o1_reg_num));
return; return;
} }