mirror of
https://github.com/open-goal/jak-project.git
synced 2024-12-01 02:10:46 +00:00
add abs
This commit is contained in:
parent
4b90634e93
commit
f70ae6dad3
@ -723,6 +723,11 @@ BranchDelay get_branch_delay(Instruction& i, int idx) {
|
||||
b.source = make_reg(i.get_src(0).get_reg(), idx);
|
||||
b.source2 = make_reg(i.get_src(1).get_reg(), idx);
|
||||
return b;
|
||||
} else if (is_gpr_3(i, InstructionKind::DSUBU, {}, make_gpr(Reg::R0), {})) {
|
||||
BranchDelay b(BranchDelay::NEGATE);
|
||||
b.destination = make_reg(i.get_dst(0).get_reg(), idx);
|
||||
b.source = make_reg(i.get_src(1).get_reg(), idx);
|
||||
return b;
|
||||
}
|
||||
BranchDelay b(BranchDelay::UNKNOWN);
|
||||
return b;
|
||||
@ -819,6 +824,16 @@ std::shared_ptr<IR> try_bgezl(Instruction& instr, Instruction& next_instr, int i
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<IR> try_bltzl(Instruction& instr, Instruction& next_instr, int idx) {
|
||||
if (instr.kind == InstructionKind::BLTZL) {
|
||||
return std::make_shared<IR_Branch>(
|
||||
Condition(Condition::LESS_THAN_ZERO, make_reg(instr.get_src(0).get_reg(), idx), nullptr,
|
||||
nullptr),
|
||||
instr.get_src(1).get_label(), get_branch_delay(next_instr, idx), true);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<IR> try_daddiu(Instruction& i0, Instruction& i1, int idx) {
|
||||
if (i0.kind == InstructionKind::DADDIU && i1.kind == InstructionKind::MOVN &&
|
||||
i0.get_src(0).get_reg() == make_gpr(Reg::S7)) {
|
||||
@ -1279,6 +1294,9 @@ void add_basic_ops_to_block(Function* func, const BasicBlock& block, LinkedObjec
|
||||
case InstructionKind::BGEZL:
|
||||
result = try_bgezl(i, next, instr);
|
||||
break;
|
||||
case InstructionKind::BLTZL:
|
||||
result = try_bltzl(i, next, instr);
|
||||
break;
|
||||
case InstructionKind::BEQL:
|
||||
result = try_beql(i, next, instr);
|
||||
break;
|
||||
|
@ -133,25 +133,6 @@ void clean_up_cond_with_else(std::shared_ptr<IR>* ir, LinkedObjectFile& file) {
|
||||
}
|
||||
}
|
||||
|
||||
bool try_clean_up_sc_as_and(const std::shared_ptr<IR_ShortCircuit>& ir) {
|
||||
for (size_t i = 0; i < ir->entries.size(); i++) {
|
||||
auto& e = ir->entries.at(i);
|
||||
if (i < ir->entries.size() - 1) {
|
||||
// check we load the delay slot with false
|
||||
auto branch = get_condition_branch(&e.condition);
|
||||
assert(branch.first);
|
||||
}
|
||||
}
|
||||
// ir->kind = IR_ShortCircuit::AND;
|
||||
// return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void clean_up_sc(std::shared_ptr<IR_ShortCircuit> ir) {
|
||||
assert(ir->entries.size() > 1);
|
||||
// try_clean_up_sc_as_and(ir);
|
||||
}
|
||||
|
||||
/*!
|
||||
* A GOAL comparison which produces a boolean is recognized as a cond-no-else by the CFG analysis.
|
||||
* But it should not be decompiled as a branching statement.
|
||||
@ -251,6 +232,9 @@ void clean_up_cond_no_else(std::shared_ptr<IR>* ir, LinkedObjectFile& file) {
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Match for a (set! reg (math reg reg)) form
|
||||
*/
|
||||
bool is_int_math_3(IR* ir,
|
||||
MatchParam<IR_IntMath2::Kind> kind,
|
||||
MatchParam<Register> dst,
|
||||
@ -298,6 +282,62 @@ bool is_int_math_3(IR* ir,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_same_reg(IR* a, IR* b) {
|
||||
auto ar = dynamic_cast<IR_Register*>(a);
|
||||
auto br = dynamic_cast<IR_Register*>(b);
|
||||
return ar && br && ar->reg == br->reg;
|
||||
}
|
||||
|
||||
std::shared_ptr<IR> try_sc_as_abs(Function& f, LinkedObjectFile& file, ShortCircuit* vtx) {
|
||||
if (vtx->entries.size() != 1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto b0 = dynamic_cast<BlockVtx*>(vtx->entries.at(0));
|
||||
if (!b0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// todo, seems possible to be a single op instead of a begin here.
|
||||
auto b0_ptr = cfg_to_ir(f, file, b0);
|
||||
auto b0_ir = dynamic_cast<IR_Begin*>(b0_ptr.get());
|
||||
|
||||
auto branch = dynamic_cast<IR_Branch*>(b0_ir->forms.back().get());
|
||||
if (!branch) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// check the branch instruction
|
||||
if (!branch->likely || branch->condition.kind != Condition::LESS_THAN_ZERO ||
|
||||
branch->branch_delay.kind != BranchDelay::NEGATE) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto input = branch->condition.src0;
|
||||
auto output = branch->branch_delay.destination;
|
||||
|
||||
assert(is_same_reg(input.get(), branch->branch_delay.source.get()));
|
||||
|
||||
if (b0_ir->forms.size() == 1) {
|
||||
// this is probably fine but happens to not occur in anything we try yet.
|
||||
assert(false);
|
||||
} else {
|
||||
// remove the branch
|
||||
b0_ir->forms.pop_back();
|
||||
// add the ash
|
||||
b0_ir->forms.push_back(std::make_shared<IR_Set>(
|
||||
IR_Set::REG_64, output, std::make_shared<IR_IntMath1>(IR_IntMath1::ABS, input)));
|
||||
return b0_ptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Attempt to convert a short circuit expression into an arithmetic shift.
|
||||
* GOAL's shift function accepts positive/negative numbers to determine the direction
|
||||
* of the shift.
|
||||
*/
|
||||
std::shared_ptr<IR> try_sc_as_ash(Function& f, LinkedObjectFile& file, ShortCircuit* vtx) {
|
||||
if (vtx->entries.size() != 2) {
|
||||
return nullptr;
|
||||
@ -310,6 +350,7 @@ std::shared_ptr<IR> try_sc_as_ash(Function& f, LinkedObjectFile& file, ShortCirc
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// todo, seems possible to be a single op instead of a begin...
|
||||
auto b0_ptr = cfg_to_ir(f, file, b0);
|
||||
auto b0_ir = dynamic_cast<IR_Begin*>(b0_ptr.get());
|
||||
|
||||
@ -644,8 +685,12 @@ std::shared_ptr<IR> cfg_to_ir(Function& f, LinkedObjectFile& file, CfgVtx* vtx)
|
||||
if (as_ash) {
|
||||
return as_ash;
|
||||
}
|
||||
// now try as a normal and/or
|
||||
|
||||
auto as_abs = try_sc_as_abs(f, file, svtx);
|
||||
if (as_abs) {
|
||||
return as_abs;
|
||||
}
|
||||
// now try as a normal and/or
|
||||
std::vector<IR_ShortCircuit::Entry> entries;
|
||||
for (auto& x : svtx->entries) {
|
||||
IR_ShortCircuit::Entry e;
|
||||
@ -653,7 +698,7 @@ std::shared_ptr<IR> cfg_to_ir(Function& f, LinkedObjectFile& file, CfgVtx* vtx)
|
||||
entries.push_back(e);
|
||||
}
|
||||
auto result = std::make_shared<IR_ShortCircuit>(entries);
|
||||
// clean_up_sc(result);
|
||||
// todo clean these into real and/or.
|
||||
return result;
|
||||
} else if (dynamic_cast<CondNoElse*>(vtx)) {
|
||||
auto* cvtx = dynamic_cast<CondNoElse*>(vtx);
|
||||
|
@ -270,6 +270,9 @@ std::shared_ptr<Form> IR_IntMath1::to_form(const LinkedObjectFile& file) const {
|
||||
case NOT:
|
||||
math_operator = "lognot";
|
||||
break;
|
||||
case ABS:
|
||||
math_operator = "abs.si";
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
@ -340,6 +343,9 @@ std::shared_ptr<Form> BranchDelay::to_form(const LinkedObjectFile& file) const {
|
||||
case DSLLV:
|
||||
return buildList(toForm("set!"), destination->to_form(file),
|
||||
buildList("shl", source->to_form(file), source2->to_form(file)));
|
||||
case NEGATE:
|
||||
return buildList(toForm("set!"), destination->to_form(file),
|
||||
buildList("-", source->to_form(file)));
|
||||
case UNKNOWN:
|
||||
return buildList("unknown-branch-delay");
|
||||
default:
|
||||
@ -389,6 +395,7 @@ int Condition::num_args() const {
|
||||
case TRUTHY:
|
||||
case GREATER_THAN_ZERO_SIGNED:
|
||||
case GEQ_ZERO_SIGNED:
|
||||
case LESS_THAN_ZERO:
|
||||
return 1;
|
||||
case ALWAYS:
|
||||
return 0;
|
||||
@ -474,6 +481,9 @@ std::shared_ptr<Form> Condition::to_form(const LinkedObjectFile& file) const {
|
||||
case GEQ_ZERO_SIGNED:
|
||||
condtion_operator = ">=0.si";
|
||||
break;
|
||||
case LESS_THAN_ZERO:
|
||||
condtion_operator = "<0.si";
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ class IR_IntMath2 : public IR {
|
||||
|
||||
class IR_IntMath1 : public IR {
|
||||
public:
|
||||
enum Kind { NOT } kind;
|
||||
enum Kind { NOT, ABS } kind;
|
||||
IR_IntMath1(Kind _kind, std::shared_ptr<IR> _arg) : kind(_kind), arg(std::move(_arg)) {}
|
||||
std::shared_ptr<IR> arg;
|
||||
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
|
||||
@ -178,6 +178,7 @@ struct BranchDelay {
|
||||
SET_BINTEGER,
|
||||
SET_PAIR,
|
||||
DSLLV,
|
||||
NEGATE,
|
||||
UNKNOWN
|
||||
} kind;
|
||||
std::shared_ptr<IR> destination = nullptr, source = nullptr, source2 = nullptr;
|
||||
@ -195,6 +196,7 @@ struct Condition {
|
||||
LEQ_SIGNED,
|
||||
GEQ_SIGNED,
|
||||
GREATER_THAN_ZERO_SIGNED,
|
||||
LESS_THAN_ZERO,
|
||||
GEQ_ZERO_SIGNED,
|
||||
LESS_THAN_UNSIGNED,
|
||||
GREATER_THAN_UNSIGNED,
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
"asm_functions_by_name":[
|
||||
// gcommon
|
||||
"abs", "min", "max", "(method 2 vec4s)", "quad-copy!", "(method 3 vec4s)", "breakpoint-range-set!",
|
||||
"min", "max", "(method 2 vec4s)", "quad-copy!", "(method 3 vec4s)", "breakpoint-range-set!",
|
||||
|
||||
// pskernel
|
||||
"resend-exception", "kernel-set-interrupt-vector", "kernel-set-exception-vector", "return-from-exception",
|
||||
@ -42,12 +42,16 @@
|
||||
// this one fails due to false compaction where an else case has only a not expression in it.
|
||||
"master-is-hopeful-better?",
|
||||
|
||||
// temp remove me
|
||||
// fails for unknown reason
|
||||
"target-falling-anim-trans",
|
||||
|
||||
// these are all valid, but use short circuiting branches in strange ways. There's probably a few compiler uses that we're not
|
||||
"(method 21 actor-link-info)","(method 20 actor-link-info)","(method 28 collide-shape-prim-mesh)", "(method 35 collide-shape)",
|
||||
"debug-menu-item-var-render", "(method 14 level)","add-blue-motion","anim-tester-add-newobj","(method 27 orb-cache-top)",
|
||||
|
||||
// real asm
|
||||
"cspace<-parented-transformq-joint!", "blerc-a-fragment", "render-boundary-tri", "render-boundary-quad",
|
||||
"(method 19 collide-shape-prim-sphere)","vector-segment-distance-point!", "exp",
|
||||
"(method 19 collide-shape-prim-sphere)","vector-segment-distance-point!", "exp", "(method 11 collide-mesh-cache)",
|
||||
|
||||
"(method 11 cpu-thread)", "atan0", "sincos!", "sincos-rad!", "disasm-dma-list", "vblank-handler", "vif1-handler",
|
||||
"vif1-handler-debug", "entity-actor-count", "decompress-frame-data-pair-to-accumulator",
|
||||
|
Loading…
Reference in New Issue
Block a user