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:
parent
baf9c092ea
commit
a4edf7194e
@ -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
|
||||
|
@ -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";
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user