macro_interpreter: Implement AddWithCarry and SubtractWithBorrow.

- Used by Undertale.
This commit is contained in:
bunnei 2018-11-21 14:32:21 -05:00
parent bb175ab430
commit 033b46253e
2 changed files with 25 additions and 8 deletions

View file

@ -35,6 +35,7 @@ void MacroInterpreter::Reset() {
// The next parameter index starts at 1, because $r1 already has the value of the first // The next parameter index starts at 1, because $r1 already has the value of the first
// parameter. // parameter.
next_parameter_index = 1; next_parameter_index = 1;
carry_flag = false;
} }
bool MacroInterpreter::Step(u32 offset, bool is_delay_slot) { bool MacroInterpreter::Step(u32 offset, bool is_delay_slot) {
@ -135,14 +136,28 @@ MacroInterpreter::Opcode MacroInterpreter::GetOpcode(u32 offset) const {
return {macro_memory[offset + pc / sizeof(u32)]}; return {macro_memory[offset + pc / sizeof(u32)]};
} }
u32 MacroInterpreter::GetALUResult(ALUOperation operation, u32 src_a, u32 src_b) const { u32 MacroInterpreter::GetALUResult(ALUOperation operation, u32 src_a, u32 src_b) {
switch (operation) { switch (operation) {
case ALUOperation::Add: case ALUOperation::Add: {
return src_a + src_b; const u64 result{static_cast<u64>(src_a) + src_b};
// TODO(Subv): Implement AddWithCarry carry_flag = result > 0xffffffff;
case ALUOperation::Subtract: return static_cast<u32>(result);
return src_a - src_b; }
// TODO(Subv): Implement SubtractWithBorrow case ALUOperation::AddWithCarry: {
const u64 result{static_cast<u64>(src_a) + src_b + (carry_flag ? 1ULL : 0ULL)};
carry_flag = result > 0xffffffff;
return static_cast<u32>(result);
}
case ALUOperation::Subtract: {
const u64 result{static_cast<u64>(src_a) - src_b};
carry_flag = result < 0x100000000;
return static_cast<u32>(result);
}
case ALUOperation::SubtractWithBorrow: {
const u64 result{static_cast<u64>(src_a) - src_b - (carry_flag ? 0ULL : 1ULL)};
carry_flag = result < 0x100000000;
return static_cast<u32>(result);
}
case ALUOperation::Xor: case ALUOperation::Xor:
return src_a ^ src_b; return src_a ^ src_b;
case ALUOperation::Or: case ALUOperation::Or:

View file

@ -117,7 +117,7 @@ private:
bool Step(u32 offset, bool is_delay_slot); bool Step(u32 offset, bool is_delay_slot);
/// Calculates the result of an ALU operation. src_a OP src_b; /// Calculates the result of an ALU operation. src_a OP src_b;
u32 GetALUResult(ALUOperation operation, u32 src_a, u32 src_b) const; u32 GetALUResult(ALUOperation operation, u32 src_a, u32 src_b);
/// Performs the result operation on the input result and stores it in the specified register /// Performs the result operation on the input result and stores it in the specified register
/// (if necessary). /// (if necessary).
@ -165,5 +165,7 @@ private:
std::vector<u32> parameters; std::vector<u32> parameters;
/// Index of the next parameter that will be fetched by the 'parm' instruction. /// Index of the next parameter that will be fetched by the 'parm' instruction.
u32 next_parameter_index = 0; u32 next_parameter_index = 0;
bool carry_flag{};
}; };
} // namespace Tegra } // namespace Tegra