mirror of
https://github.com/open-goal/jak-project
synced 2026-05-23 15:02:01 -04:00
142961a747
* decomp: Add texture-upload to ref tests * maybe 50% done? * 5 functions to go! * decomp: stuck in `navigate` * work-around fp issue * some cleanup and label casts * working on supporting asm instructions -- this is currently WRONG * support ASM operations * fixes for asm op support * decomp: finish the vast majority of `navigate` * format * update test though i think this suggests a regression! * decomp: cleanup some more of navigate * decomp: finish `rolling-lightning-mole` * revert `r0` handling for `pcpyud` and `pextuw` * update ref tests * lint * fix a failing test * help * navigate mostly works now, with some potential bugs * remove my debugging logs * update ref tests * review feedback cleanup * these are all likely fine * can't get the crab to chase me anymore * the crab is back
95 lines
3.6 KiB
C++
95 lines
3.6 KiB
C++
#include "inline_asm_rewrite.h"
|
|
#include "common/goos/PrettyPrinter.h"
|
|
#include "decompiler/Function/Function.h"
|
|
#include "decompiler/IR2/Form.h"
|
|
#include "decompiler/IR2/FormStack.h"
|
|
#include "decompiler/IR2/OpenGoalMapping.h"
|
|
#include "decompiler/ObjectFile/LinkedObjectFile.h"
|
|
#include "decompiler/analysis/reg_usage.h"
|
|
#include "decompiler/util/DecompilerTypeSystem.h"
|
|
|
|
namespace decompiler {
|
|
|
|
bool rewrite_inline_asm_instructions(Form* top_level_form,
|
|
FormPool& pool,
|
|
Function& f,
|
|
const DecompilerTypeSystem&) {
|
|
assert(top_level_form);
|
|
|
|
try {
|
|
RegSet vf_regs;
|
|
// Iterate through all TLFs
|
|
top_level_form->apply_form([&](Form* form) {
|
|
std::vector<FormElement*> new_entries;
|
|
for (auto& entry : form->elts()) {
|
|
// All vector instructions are inline assembly, so we only care to re-write assembly
|
|
// operations
|
|
AsmOpElement* elem = dynamic_cast<AsmOpElement*>(entry);
|
|
if (!elem) {
|
|
auto as_load_store = dynamic_cast<VectorFloatLoadStoreElement*>(entry);
|
|
if (as_load_store) {
|
|
as_load_store->collect_vf_regs(vf_regs);
|
|
}
|
|
new_entries.push_back(entry);
|
|
continue;
|
|
}
|
|
|
|
// We then convert the normal AsmOpElement to a more tailor-made FormElement that has
|
|
// OpenGOAL considerations Not _all_ assembly instructors are vector
|
|
OpenGOALAsm asmOp = OpenGOALAsm(elem->op()->instruction());
|
|
if (!asmOp.valid) {
|
|
// If its an invalid or unsupported exception, skip it
|
|
/*lg::warn("[ASM Re-Write] - Unsupported inline assembly instruction kind - [{}]",
|
|
asmOp.instr.kind);*/
|
|
f.warnings.general_warning("Unsupported inline assembly instruction kind - [{}]",
|
|
asmOp.m_instr.to_string(f.ir2.env.file->labels));
|
|
new_entries.push_back(entry);
|
|
continue;
|
|
} else if (asmOp.todo) {
|
|
// If its an invalid or unsupported exception, skip it
|
|
/*lg::warn("[ASM Re-Write] - Inline assembly instruction marked with TODO - [{}]",
|
|
asmOp.full_function_name());*/
|
|
f.warnings.general_warning("Inline assembly instruction marked with TODO - [{}]",
|
|
asmOp.full_function_name());
|
|
}
|
|
|
|
// If we've made it this far, it's an AsmOperation that is also a supported vector
|
|
// instruction by OpenGOAL All we have to do is convert it to the correct `FormElement` that
|
|
// will write the form so it works for OpenGOAL
|
|
|
|
OpenGoalAsmOpElement* newElem = pool.alloc_element<OpenGoalAsmOpElement>(elem->op());
|
|
newElem->collect_vf_regs(vf_regs);
|
|
|
|
new_entries.push_back(newElem);
|
|
}
|
|
|
|
assert(!new_entries.empty());
|
|
form->clear();
|
|
for (auto x : new_entries) {
|
|
form->push_back(x);
|
|
}
|
|
});
|
|
|
|
// If we have to wrap the entire function in an 'rlet'
|
|
if (!vf_regs.empty()) {
|
|
Form* body = pool.alloc_empty_form();
|
|
for (auto& entry : top_level_form->elts()) {
|
|
body->push_back(entry);
|
|
}
|
|
|
|
RLetElement* rlet = pool.alloc_element<RLetElement>(body, vf_regs);
|
|
top_level_form->clear();
|
|
top_level_form->push_back(rlet);
|
|
}
|
|
} catch (std::exception& e) {
|
|
std::string warning =
|
|
fmt::format("ASM instruction re-writing failed in {}: {}", f.name(), e.what());
|
|
lg::warn(warning);
|
|
f.warnings.general_warning(";; {}", warning);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
} // namespace decompiler
|