1
0
mirror of https://github.com/lefticus/6502-cpp.git synced 2024-12-30 07:31:38 +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,
lda,
ldx,
ldy,
lsr,
@ -51,11 +52,14 @@ struct mos6502 : ASMLine
sbc,
sec,
sta,
stx,
sty,
tax,
tay,
tsx,
txa,
txs,
tya,
};
@ -82,6 +86,7 @@ struct mos6502 : ASMLine
case OpCode::jmp:
case OpCode::jsr:
case OpCode::lda:
case OpCode::ldx:
case OpCode::ldy:
case OpCode::lsr:
case OpCode::ORA:
@ -96,9 +101,12 @@ struct mos6502 : ASMLine
case OpCode::sec:
case OpCode::sta:
case OpCode::sty:
case OpCode::stx:
case OpCode::tax:
case OpCode::tay:
case OpCode::tsx:
case OpCode::txa:
case OpCode::txs:
case OpCode::tya:
case OpCode::unknown:
@ -130,6 +138,7 @@ struct mos6502 : ASMLine
case OpCode::jmp:
case OpCode::jsr:
case OpCode::lda:
case OpCode::ldx:
case OpCode::ldy:
case OpCode::lsr:
case OpCode::ORA:
@ -143,10 +152,13 @@ struct mos6502 : ASMLine
case OpCode::sbc:
case OpCode::sec:
case OpCode::sta:
case OpCode::stx:
case OpCode::sty:
case OpCode::tax:
case OpCode::tay:
case OpCode::tsx:
case OpCode::txa:
case OpCode::txs:
case OpCode::tya:
case OpCode::unknown:
break;
@ -176,15 +188,19 @@ struct mos6502 : ASMLine
case OpCode::lda: return "lda";
case OpCode::asl: return "asl";
case OpCode::rol: return "rol";
case OpCode::ldx: return "ldx";
case OpCode::ldy: return "ldy";
case OpCode::tay: return "tay";
case OpCode::tya: return "tya";
case OpCode::tax: return "tax";
case OpCode::tsx: return "tsx";
case OpCode::txa: return "txa";
case OpCode::txs: return "txs";
case OpCode::cpy: return "cpy";
case OpCode::eor: return "eor";
case OpCode::sta: return "sta";
case OpCode::sty: return "sty";
case OpCode::stx: return "stx";
case OpCode::pha: return "pha";
case OpCode::pla: return "pla";
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) {
if (instructions[op].opcode == mos6502::OpCode::ldy && instructions[op].op.type == Operand::Type::literal) {
auto op2 = op + 1;
@ -116,7 +120,9 @@ bool optimize(std::vector<mos6502> &instructions)
++op2;
}
}
}
}
*/
for (size_t op = 0; op < instructions.size() - 1; ++op) {
if (instructions[op].opcode == mos6502::OpCode::lda

View File

@ -100,9 +100,6 @@ struct C64 : Personality
return Operand(Operand::Type::literal, "$5f");
case 31:
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));
}

View File

@ -116,6 +116,8 @@ struct AVR : ASMLine
mov,
out,
pop,
push,
@ -185,6 +187,7 @@ struct AVR : ASMLine
if (o == "brsh") { return OpCode::brsh; }
if (o == "breq") { return OpCode::breq; }
if (o == "in") { return OpCode::in; }
if (o == "out") { return OpCode::out; }
}
}
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
// 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, "; 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());
@ -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)
{
//instructions.emplace_back(mos6502::OpCode::sta, Operand(Operand::Type::literal, address_low_byte));
instructions.emplace_back(mos6502::OpCode::clc);
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::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::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::tax);
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)
{
//instructions.emplace_back(mos6502::OpCode::sta, Operand(Operand::Type::literal, address_low_byte));
instructions.emplace_back(mos6502::OpCode::sec);
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::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::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::tax);
fixup_16_bit_N_Z_flags(instructions);
}
@ -626,16 +629,30 @@ void translate_instruction(const Personality &personality, std::vector<mos6502>
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: {
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::sta, personality.get_register(o1_reg_num));
instructions.emplace_back(mos6502::OpCode::tsx);
instructions.emplace_back(mos6502::OpCode::stx, personality.get_register(o1_reg_num));
return;
}
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));
return;
}