mirror of
https://github.com/lefticus/6502-cpp.git
synced 2024-12-22 01:30:03 +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
|
// 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 = "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
|
// 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));
|
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
|
// 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);
|
instructions.emplace_back(mos6502::OpCode::txa);
|
||||||
// if low order is not negative, we know it's 0 or not 0
|
// 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));
|
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
|
// 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::lsr);
|
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::Label, set_flag_label);
|
||||||
instructions.emplace_back(ASMLine::Type::Directive, "; END remove if next is lda, bcc, bcs");
|
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)
|
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)) {
|
while (optimize(new_instructions)) {
|
||||||
// do it however many times it takes
|
// do it however many times it takes
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user