mirror of
https://github.com/lefticus/6502-cpp.git
synced 2024-10-15 00:24:24 +00:00
Fix handling of 16 bit C,N,Z flags
This commit is contained in:
parent
a6f012878e
commit
4cbdae3ffe
@ -259,7 +259,7 @@ void fixup_16_bit_N_Z_flags(std::vector<mos6502> &instructions)
|
||||
// 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());
|
||||
std::string set_flag_label = "fixup_16_bit_op_flags" + std::to_string(instructions.size());
|
||||
// if high order is negative, we know it's not 0 and it is negative
|
||||
instructions.emplace_back(mos6502::OpCode::bmi, Operand(Operand::Type::literal, set_flag_label));
|
||||
// if it's not 0, then branch down, we know the result is not 0 and not negative
|
||||
@ -268,8 +268,8 @@ void fixup_16_bit_N_Z_flags(std::vector<mos6502> &instructions)
|
||||
instructions.emplace_back(mos6502::OpCode::txa);
|
||||
// if low order is not negative, we know it's 0 or not 0
|
||||
instructions.emplace_back(mos6502::OpCode::bpl, Operand(Operand::Type::literal, set_flag_label));
|
||||
// if low order byte is negative, shift right by one bit, then we'll get the proper Z/N flags
|
||||
instructions.emplace_back(mos6502::OpCode::lsr);
|
||||
// if low order byte is negative, just load 1, this will properly set the Z flag and leave C correct
|
||||
instructions.emplace_back(mos6502::OpCode::lda, Operand(Operand::Type::literal, "#1"));
|
||||
instructions.emplace_back(ASMLine::Type::Label, set_flag_label);
|
||||
instructions.emplace_back(ASMLine::Type::Directive, "; END remove if next is lda, bcc, bcs");
|
||||
}
|
||||
@ -810,43 +810,7 @@ bool fix_long_branches(std::vector<mos6502> &instructions, int &branch_patch_cou
|
||||
}
|
||||
|
||||
|
||||
bool fix_overwritten_flags(std::vector<mos6502> &instructions)
|
||||
{
|
||||
// return false;
|
||||
if (instructions.size() < 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t op = 0; op < instructions.size(); ++op) {
|
||||
if (instructions[op].is_comparison) {
|
||||
auto op2 = op + 1;
|
||||
while (op2 < instructions.size()
|
||||
&& !instructions[op2].is_comparison
|
||||
&& !instructions[op2].is_branch) {
|
||||
++op2;
|
||||
}
|
||||
|
||||
if (op2 < instructions.size()
|
||||
&& (op2 - op) > 1
|
||||
&& instructions[op2 - 1].opcode != mos6502::OpCode::plp) {
|
||||
if (instructions[op2].is_comparison) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (instructions[op2].is_branch) {
|
||||
// insert a pull of processor status before the branch
|
||||
instructions.insert(std::next(std::begin(instructions), static_cast<std::ptrdiff_t>(op2)), mos6502(mos6502::OpCode::plp));
|
||||
// insert a push of processor status after the comparison
|
||||
instructions.insert(std::next(std::begin(instructions), static_cast<std::ptrdiff_t>(op + 1)), mos6502(mos6502::OpCode::php));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void run(const Personality &personality, std::istream &input)
|
||||
{
|
||||
@ -1008,13 +972,6 @@ void run(const Personality &personality, std::istream &input)
|
||||
}
|
||||
}
|
||||
|
||||
// it seems that with the move to AVR for the base, this
|
||||
// fixup no longer makes sense, but I'm not going to remove it just yet
|
||||
// until we have more complex C++ examples working
|
||||
// while (fix_overwritten_flags(new_instructions)) {
|
||||
// do it however many times it takes
|
||||
// }
|
||||
|
||||
while (optimize(new_instructions)) {
|
||||
// do it however many times it takes
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user