From 30d1e1d6c99f37d2d5c61d4f82e651124896b81b Mon Sep 17 00:00:00 2001 From: water111 <48171810+water111@users.noreply.github.com> Date: Sat, 21 Aug 2021 10:20:55 -0400 Subject: [PATCH] [decompiler] maybe fix symbol decompile issue (#776) * maybe fix symbol decompile issue * try again on a label * allow int to float on seconds --- decompiler/IR2/AtomicOpForm.cpp | 16 ++++++++++++++++ decompiler/IR2/FormExpressionAnalysis.cpp | 2 +- decompiler/util/data_decompile.cpp | 15 +++++++++------ .../decompiler/reference/engine/ps2/timer_REF.gc | 2 +- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/decompiler/IR2/AtomicOpForm.cpp b/decompiler/IR2/AtomicOpForm.cpp index 48a402346c..d7d1fbb80b 100644 --- a/decompiler/IR2/AtomicOpForm.cpp +++ b/decompiler/IR2/AtomicOpForm.cpp @@ -549,6 +549,22 @@ FormElement* make_label_load(int label_idx, } } + if (load_kind != LoadVarOp::Kind::FLOAT && load_size == 8) { + if ((int)env.file->words_by_seg.at(label.target_segment).size() > (label.offset / 4) + 1) { + assert((label.offset % 8) == 0); + auto word0 = env.file->words_by_seg.at(label.target_segment).at(label.offset / 4); + auto word1 = env.file->words_by_seg.at(label.target_segment).at(1 + (label.offset / 4)); + assert(word0.kind == LinkedWord::PLAIN_DATA); + assert(word1.kind == LinkedWord::PLAIN_DATA); + u64 value; + memcpy(&value, &word0.data, 4); + memcpy(((u8*)&value) + 4, &word1.data, 4); + return pool.alloc_element(TypeSpec("uint"), + pool.alloc_single_element_form( + nullptr, SimpleAtom::make_int_constant(value))); + } + } + return nullptr; } diff --git a/decompiler/IR2/FormExpressionAnalysis.cpp b/decompiler/IR2/FormExpressionAnalysis.cpp index c76c1ef0a0..ad92abebc2 100644 --- a/decompiler/IR2/FormExpressionAnalysis.cpp +++ b/decompiler/IR2/FormExpressionAnalysis.cpp @@ -1800,7 +1800,7 @@ void SimpleExpressionElement::update_from_stack_int_to_float(const Env& env, auto fpr_convert_matcher = Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::GPR_TO_FPR), {Matcher::any(0)}); auto type = env.get_types_before_op(var.idx()).get(var.reg()).typespec(); - if (type == TypeSpec("int") || type == TypeSpec("uint")) { + if (type == TypeSpec("int") || type == TypeSpec("uint") || type == TypeSpec("seconds")) { auto mr = match(fpr_convert_matcher, arg); if (mr.matched) { arg = mr.maps.forms.at(0); diff --git a/decompiler/util/data_decompile.cpp b/decompiler/util/data_decompile.cpp index 21ac31535c..e405658e92 100644 --- a/decompiler/util/data_decompile.cpp +++ b/decompiler/util/data_decompile.cpp @@ -588,12 +588,6 @@ goos::Object decompile_structure(const TypeSpec& type, continue; } - // OK - READ THE FIELD: - for (int i = field_start; i < field_end; i++) { - // even if our field was partially zero, we mark those zero bytes as "has data". - field_status_per_byte.at(i) = HAS_DATA_READ; - } - // first, let's see if it's a value or reference auto field_type_info = ts.lookup_type(field.type()); if (!field_type_info->is_reference()) { @@ -627,6 +621,9 @@ goos::Object decompile_structure(const TypeSpec& type, field.name(), sp_field_init_spec_decompile(obj_words, labels, label.target_segment, field_start, ts, field, words, file)); } else { + if (obj_words.at(field_start / 4).kind != LinkedWord::PLAIN_DATA) { + continue; + } std::vector bytes_out; for (int byte_idx = field_start; byte_idx < field_end; byte_idx++) { bytes_out.push_back(obj_words.at(byte_idx / 4).get_byte(byte_idx % 4)); @@ -758,6 +755,12 @@ goos::Object decompile_structure(const TypeSpec& type, } } } + + // OK - READ THE FIELD: + for (int i = field_start; i < field_end; i++) { + // even if our field was partially zero, we mark those zero bytes as "has data". + field_status_per_byte.at(i) = HAS_DATA_READ; + } } for (size_t i = 0; i < field_status_per_byte.size(); i++) { diff --git a/test/decompiler/reference/engine/ps2/timer_REF.gc b/test/decompiler/reference/engine/ps2/timer_REF.gc index 542c9f4019..b13183bf60 100644 --- a/test/decompiler/reference/engine/ps2/timer_REF.gc +++ b/test/decompiler/reference/engine/ps2/timer_REF.gc @@ -31,7 +31,7 @@ ;; WARN: Unsupported inline assembly instruction kind - [sync.p] (defun disable-irq () (local-vars (v0-0 int)) - (let ((v1-0 (l.d L21))) + (let ((v1-0 (the-as uint #xfffffffe))) (.mfc0 v0-0 Status) (let ((v0-1 (logand v0-0 v1-0))) (.mtc0 Status v0-1)