From fa122356ec1342d86c9d6394537d3d8433af77ea Mon Sep 17 00:00:00 2001 From: water111 <48171810+water111@users.noreply.github.com> Date: Fri, 23 Apr 2021 20:29:15 -0400 Subject: [PATCH] [Decompiler] Fixes for dma-disasm (#377) * small tweaks * fix up some more dma stuff --- common/type_system/defenum.cpp | 23 ++- decompiler/Function/Function.cpp | 19 +- decompiler/IR2/AtomicOpForm.cpp | 10 +- decompiler/IR2/AtomicOpTypeAnalysis.cpp | 3 + decompiler/IR2/FormExpressionAnalysis.cpp | 58 +++++- decompiler/IR2/bitfields.cpp | 21 ++ decompiler/IR2/bitfields.h | 6 + decompiler/ObjectFile/ObjectFileDB_IR2.cpp | 2 +- decompiler/analysis/final_output.cpp | 30 ++- decompiler/config/all-types.gc | 97 +++++++-- decompiler/config/jak1_ntsc_black_label.jsonc | 3 - .../jak1_ntsc_black_label/type_casts.jsonc | 8 + decompiler/util/TP_Type.cpp | 2 +- decompiler/util/TP_Type.h | 3 +- decompiler/util/data_decompile.cpp | 78 +++++-- decompiler/util/data_decompile.h | 1 + doc/changelog.md | 5 +- goal_src/engine/dma/dma-disasm.gc | 190 +----------------- goal_src/engine/dma/dma-h.gc | 115 +++++++---- .../reference/all_forward_declarations.gc | 62 ++++++ .../reference/bounding-box-h_REF.gc | 2 - test/decompiler/reference/bounding-box_REF.gc | 2 - test/decompiler/reference/dgo-h_REF.gc | 2 - test/decompiler/reference/dma-bucket_REF.gc | 3 +- test/decompiler/reference/dma-buffer_REF.gc | 4 +- test/decompiler/reference/dma-h_REF.gc | 24 +-- test/decompiler/reference/dma_REF.gc | 3 +- test/decompiler/reference/euler-h_REF.gc | 3 +- test/decompiler/reference/euler_REF.gc | 3 +- test/decompiler/reference/gcommon_REF.gc | 2 - test/decompiler/reference/geometry-h_REF.gc | 2 - test/decompiler/reference/gkernel-h_REF.gc | 3 +- test/decompiler/reference/gkernel_REF.gc | 2 - test/decompiler/reference/gsound-h_REF.gc | 3 +- test/decompiler/reference/gstate_REF.gc | 2 - test/decompiler/reference/gstring-h_REF.gc | 2 - test/decompiler/reference/gstring_REF.gc | 3 +- test/decompiler/reference/math_REF.gc | 3 - test/decompiler/reference/matrix-h_REF.gc | 2 - test/decompiler/reference/matrix_REF.gc | 3 +- test/decompiler/reference/quaternion-h_REF.gc | 2 - test/decompiler/reference/quaternion_REF.gc | 6 - test/decompiler/reference/sync-info-h_REF.gc | 6 - test/decompiler/reference/sync-info_REF.gc | 7 - test/decompiler/reference/timer-h_REF.gc | 7 - test/decompiler/reference/timer_REF.gc | 3 - test/decompiler/reference/transform-h_REF.gc | 3 - test/decompiler/reference/transform_REF.gc | 5 - .../reference/trigonometry-h_REF.gc | 4 - test/decompiler/reference/types-h_REF.gc | 3 - test/decompiler/reference/vector-h_REF.gc | 3 - test/decompiler/reference/video-h_REF.gc | 7 - test/decompiler/reference/vif-h_REF.gc | 3 - test/decompiler/reference/vu1-macros_REF.gc | 3 - test/decompiler/reference/vu1-user-h_REF.gc | 6 - test/decompiler/test_DataParser.cpp | 21 +- test/decompiler/test_FormExpressionBuild2.cpp | 2 +- 57 files changed, 467 insertions(+), 433 deletions(-) diff --git a/common/type_system/defenum.cpp b/common/type_system/defenum.cpp index 287d4eefe..5ac732744 100644 --- a/common/type_system/defenum.cpp +++ b/common/type_system/defenum.cpp @@ -89,7 +89,6 @@ EnumType* parse_defenum(const goos::Object& defenum, TypeSystem* ts) { iter = cdr(iter); auto option_value = car(iter); iter = cdr(iter); - current = car(iter); if (option_name == ":type") { base_type = parse_typespec(ts, option_value); @@ -102,10 +101,28 @@ EnumType* parse_defenum(const goos::Object& defenum, TypeSystem* ts) { fmt::print("Invalid option {} to :bitfield option.\n", option_value.print()); throw std::runtime_error("invalid bitfield option"); } + } else if (option_name == ":copy-entries") { + auto other_info = ts->try_enum_lookup(parse_typespec(ts, option_value)); + if (!other_info) { + throw std::runtime_error(fmt::format( + "Cannot copy entries from {}, it is not a valid enum type", option_value.print())); + } + for (auto& e : other_info->entries()) { + if (entries.find(e.first) != entries.end()) { + throw std::runtime_error(fmt::format("Entry {} appears multiple times.", e.first)); + } + entries[e.first] = e.second; + } } else { fmt::print("Unknown option {} for defenum.\n", option_name); throw std::runtime_error("unknown option for defenum"); } + + if (iter->is_pair()) { + current = car(iter); + } else { + break; + } } auto type = ts->lookup_type(base_type); @@ -128,6 +145,10 @@ EnumType* parse_defenum(const goos::Object& defenum, TypeSystem* ts) { fmt::print("Got too many items in defenum {} entry {}\n", name, entry_name); } + if (entries.find(entry_name) != entries.end()) { + throw std::runtime_error(fmt::format("Entry {} appears multiple times.", entry_name)); + } + entries[entry_name] = entry_val; iter = cdr(iter); } diff --git a/decompiler/Function/Function.cpp b/decompiler/Function/Function.cpp index 66038c6b1..8bdb114e2 100644 --- a/decompiler/Function/Function.cpp +++ b/decompiler/Function/Function.cpp @@ -137,25 +137,14 @@ void Function::analyze_prologue(const LinkedObjectFile& file) { while (is_no_link_gpr_store(instructions.at(gpr_idx), 16, {}, {}, make_gpr(Reg::SP))) { auto store_reg = instructions.at(gpr_idx).get_src(0).get_reg(); - // sometimes stack memory is zeroed immediately after gpr backups, and this fools the previous - // check. - if (store_reg == make_gpr(Reg::R0)) { - lg::warn("Function {} has stack zeroing, manually check prologue!", - guessed_name.to_string()); - warnings.general_warning("Stack zeroing, check prologue!"); + // sometimes stack memory is zeroed or a register is spilled immediately after gpr backups, + // and this fools the previous check. + if (store_reg == make_gpr(Reg::R0) || store_reg == make_gpr(Reg::A0)) { + warnings.general_warning("Check prologue - tricky store of {}", store_reg.to_string()); expect_nothing_after_gprs = true; break; } - // this also happens a few times per game. this a0/r0 check seems to be all that's needed to - // avoid false positives here! - if (store_reg == make_gpr(Reg::A0)) { - suspected_asm = true; - lg::warn("Function {} stores a0 on the stack, flagging as asm!", guessed_name.to_string()); - warnings.general_warning("Flagged as asm due to storing a0 on stack"); - return; - } - n_gpr_backups++; gpr_idx++; } diff --git a/decompiler/IR2/AtomicOpForm.cpp b/decompiler/IR2/AtomicOpForm.cpp index 4f66afebe..d28799ab5 100644 --- a/decompiler/IR2/AtomicOpForm.cpp +++ b/decompiler/IR2/AtomicOpForm.cpp @@ -484,6 +484,12 @@ Form* LoadVarOp::get_load_src(FormPool& pool, const Env& env) const { rd_in.deref = dk; rd_in.base_type = input_type.get_obj_plus_const_mult_typespec(); rd_in.stride = input_type.get_multiplier(); + // this is a bit of a hack to prevent something like arr_of_bytes[val * 4] getting stuck + // with the stride of 4 bytes but load size of 1 byte. I _believe_ it only applies when + // the load size is 1. + if (rd_in.base_type == env.dts->ts.make_pointer_typespec("uint8") && rd_in.stride != 0) { + rd_in.stride = 1; + } rd_in.offset = ro.offset; auto rd = env.dts->ts.reverse_field_lookup(rd_in); @@ -496,8 +502,8 @@ Form* LoadVarOp::get_load_src(FormPool& pool, const Env& env) const { // we pass along the register offset because code generation seems to be a bit // different in different cases. - return pool.alloc_single_element_form( - nullptr, ro.var, tokens, input_type.get_multiplier(), ro.offset); + return pool.alloc_single_element_form(nullptr, ro.var, tokens, + rd_in.stride, ro.offset); } } diff --git a/decompiler/IR2/AtomicOpTypeAnalysis.cpp b/decompiler/IR2/AtomicOpTypeAnalysis.cpp index 2a5040c9d..91ef38002 100644 --- a/decompiler/IR2/AtomicOpTypeAnalysis.cpp +++ b/decompiler/IR2/AtomicOpTypeAnalysis.cpp @@ -419,6 +419,9 @@ TP_Type SimpleExpression::get_type_int2(const TypeState& input, if ((m_kind == Kind::ADD || m_kind == Kind::SUB) && arg0_type.typespec().base_type() == "pointer" && tc(dts, TypeSpec("integer"), arg1_type)) { + if (m_kind == Kind::ADD && !m_args[1].is_int()) { + return TP_Type::make_object_plus_product(arg0_type.typespec(), 1); + } // plain pointer plus integer = plain pointer return TP_Type::make_from_ts(arg0_type.typespec()); } diff --git a/decompiler/IR2/FormExpressionAnalysis.cpp b/decompiler/IR2/FormExpressionAnalysis.cpp index 56e344df7..308bd194e 100644 --- a/decompiler/IR2/FormExpressionAnalysis.cpp +++ b/decompiler/IR2/FormExpressionAnalysis.cpp @@ -217,8 +217,12 @@ Form* cast_form(Form* in, const TypeSpec& new_type, FormPool& pool, const Env& e } auto enum_info = dynamic_cast(type_info); - if (enum_info && enum_info->is_bitfield()) { - return cast_to_bitfield_enum(enum_info, new_type, pool, env, in); + if (enum_info) { + if (enum_info->is_bitfield()) { + return cast_to_bitfield_enum(enum_info, new_type, pool, env, in); + } else { + return cast_to_int_enum(enum_info, new_type, pool, env, in); + } } return pool.alloc_single_element_form(nullptr, new_type, in); @@ -2326,10 +2330,10 @@ FormElement* ConditionElement::make_nonzero_check_generic(const Env& env, } } -FormElement* ConditionElement::make_equal_check_generic(const Env&, +FormElement* ConditionElement::make_equal_check_generic(const Env& env, FormPool& pool, const std::vector& source_forms, - const std::vector&) { + const std::vector& source_types) { assert(source_forms.size() == 2); // (= thing '()) auto ref = source_forms.at(1); @@ -2339,8 +2343,18 @@ FormElement* ConditionElement::make_equal_check_generic(const Env&, return pool.alloc_element(GenericOperator::make_fixed(FixedOperatorKind::NULLP), source_forms.at(0)); } else { - return pool.alloc_element(GenericOperator::make_fixed(FixedOperatorKind::EQ), - source_forms); + auto int_val = get_goal_integer_constant(source_forms.at(1), env); + auto src0_as_enum = env.dts->ts.try_enum_lookup(source_types.at(0)); + if (src0_as_enum && int_val) { + // if comparing an enum against a constant integer, rewrite the enum. + auto forms_with_cast = source_forms; + forms_with_cast.at(1) = cast_form(source_forms.at(1), source_types.at(0), pool, env); + return pool.alloc_element(GenericOperator::make_fixed(FixedOperatorKind::EQ), + forms_with_cast); + } else { + return pool.alloc_element(GenericOperator::make_fixed(FixedOperatorKind::EQ), + source_forms); + } } } @@ -2812,7 +2826,37 @@ void ArrayFieldAccess::update_with_val(Form* new_val, if (m_constant_offset == 0) { if (m_expected_stride == 1) { - throw std::runtime_error("One case, not yet implemented (no offset)"); + auto base_matcher = + Matcher::match_or({Matcher::cast("int", Matcher::any(0)), + Matcher::cast("uint", Matcher::any(0)), Matcher::any(0)}); + auto offset_matcher = + Matcher::match_or({Matcher::cast("int", Matcher::any(1)), + Matcher::cast("uint", Matcher::any(1)), Matcher::any(1)}); + + // (&+ data-ptr ) + auto matcher = Matcher::match_or( + {Matcher::fixed_op(FixedOperatorKind::ADDITION, {base_matcher, offset_matcher}), + Matcher::fixed_op(FixedOperatorKind::ADDITION_PTR, {base_matcher, offset_matcher})}); + + auto match_result = match(matcher, new_val); + if (!match_result.matched) { + throw std::runtime_error( + fmt::format("Failed to match array stride 1 load {}", new_val->to_string(env))); + } + auto idx = match_result.maps.forms.at(1); + auto base = match_result.maps.forms.at(0); + assert(idx && base); + + std::vector tokens = m_deref_tokens; + for (auto& x : tokens) { + if (x.kind() == DerefToken::Kind::EXPRESSION_PLACEHOLDER) { + x = DerefToken::make_int_expr(idx); + } + } + // tokens.push_back(DerefToken::make_int_expr(idx)); + + auto deref = pool.alloc_element(base, false, tokens); + result->push_back(deref); } else if (is_power_of_two(m_expected_stride, &power_of_two)) { // reg0 is base // reg1 is idx diff --git a/decompiler/IR2/bitfields.cpp b/decompiler/IR2/bitfields.cpp index 19f11cd65..1174caa4d 100644 --- a/decompiler/IR2/bitfields.cpp +++ b/decompiler/IR2/bitfields.cpp @@ -478,6 +478,7 @@ Form* cast_to_bitfield_enum(const EnumType* type_info, FormPool& pool, const Env& env, Form* in) { + assert(type_info->is_bitfield()); auto integer = get_goal_integer_constant(strip_int_or_uint_cast(in), env); if (integer) { auto elts = @@ -495,4 +496,24 @@ Form* cast_to_bitfield_enum(const EnumType* type_info, } } +Form* cast_to_int_enum(const EnumType* type_info, + const TypeSpec& typespec, + FormPool& pool, + const Env& env, + Form* in) { + assert(!type_info->is_bitfield()); + auto integer = get_goal_integer_constant(strip_int_or_uint_cast(in), env); + if (integer) { + auto entry = + decompile_int_enum_from_int(TypeSpec(type_info->get_name()), env.dts->ts, *integer); + auto oper = GenericOperator::make_function( + pool.alloc_single_element_form(nullptr, type_info->get_name())); + return pool.alloc_single_element_form( + nullptr, oper, pool.alloc_single_element_form(nullptr, entry)); + } else { + // all failed, just return whatever. + return pool.alloc_single_element_form(nullptr, typespec, in); + } +} + } // namespace decompiler \ No newline at end of file diff --git a/decompiler/IR2/bitfields.h b/decompiler/IR2/bitfields.h index f8331e4f6..7b9c4abb7 100644 --- a/decompiler/IR2/bitfields.h +++ b/decompiler/IR2/bitfields.h @@ -144,5 +144,11 @@ Form* cast_to_bitfield_enum(const EnumType* type_info, const Env& env, Form* in); +Form* cast_to_int_enum(const EnumType* type_info, + const TypeSpec& typespec, + FormPool& pool, + const Env& env, + Form* in); + std::optional get_goal_integer_constant(Form* in, const Env&); } // namespace decompiler diff --git a/decompiler/ObjectFile/ObjectFileDB_IR2.cpp b/decompiler/ObjectFile/ObjectFileDB_IR2.cpp index 3a339db1a..77c05f63b 100644 --- a/decompiler/ObjectFile/ObjectFileDB_IR2.cpp +++ b/decompiler/ObjectFile/ObjectFileDB_IR2.cpp @@ -42,7 +42,7 @@ void ObjectFileDB::analyze_functions_ir2(const std::string& output_dir) { ir2_register_usage_pass(); lg::info("Variable analysis..."); ir2_variable_pass(); - lg::info("Initial structuring.."); + lg::info("Initial structuring..."); ir2_cfg_build_pass(); if (get_config().analyze_expressions) { lg::info("Storing temporary form result..."); diff --git a/decompiler/analysis/final_output.cpp b/decompiler/analysis/final_output.cpp index d755346bb..5ae638202 100644 --- a/decompiler/analysis/final_output.cpp +++ b/decompiler/analysis/final_output.cpp @@ -163,7 +163,31 @@ std::string write_from_top_level(const Function& top_level, return ";; ERROR: top level has no register use analysis. Cannot decompile.\n\n"; } + std::vector forms = top_form->elts(); + assert(!forms.empty()); + + // remove a (none) from the end, if it exists. + auto back_as_generic_op = dynamic_cast(forms.back()); + if (back_as_generic_op && back_as_generic_op->op().is_fixed(FixedOperatorKind::NONE)) { + forms.pop_back(); + } + std::string result; + // look for the whole thing being in a (when *debug-segment* ....) + bool in_debug_only_file = false; + if (forms.size() == 1) { + auto as_cne = dynamic_cast(forms.at(0)); + if (as_cne && as_cne->entries.size() == 1) { + auto& entry = as_cne->entries.at(0); + // a bit gross... + if (entry.condition->to_string(env) == "*debug-segment*") { + forms = entry.body->elts(); + result += ";; this file is debug only\n"; + result += "(when *debug-segment*\n"; + in_debug_only_file = true; + } + } + } // (set! identity L312) constexpr int func_name = 1; @@ -195,7 +219,7 @@ std::string write_from_top_level(const Function& top_level, // (set! sym-val ) auto define_symbol_matcher = Matcher::set(Matcher::any_symbol(0), Matcher::any(1)); - for (auto& x : top_form->elts()) { + for (auto& x : forms) { bool something_matched = false; Form f; f.elts().push_back(x); @@ -291,6 +315,10 @@ std::string write_from_top_level(const Function& top_level, } } + if (in_debug_only_file) { + result += ")\n"; + } + return result; } } // namespace decompiler \ No newline at end of file diff --git a/decompiler/config/all-types.gc b/decompiler/config/all-types.gc index 1be1d1c9a..16862c76d 100644 --- a/decompiler/config/all-types.gc +++ b/decompiler/config/all-types.gc @@ -2365,14 +2365,27 @@ :flag-assert #x900000014 ) +(defenum dma-tag-id + :bitfield #f + :type uint8 + (refe 0) ;; addr=ADDR, ends after this transfer + (cnt 1) ;; addr=after tag, next-tag=after data + (next 2) ;; addr=after tag, next-tag=ADDR + (ref 3) ;; addr=ADDR, next-tag=after tag + (refs 4) ;; ref, but stall controled + (call 5) ;; + (ret 6) ;; + (end 7) ;; next, but ends. + ) + ; ;; dma-h (deftype dma-tag (uint64) - ((qwc uint16 :offset 0) ;; quadword count - (pce uint8 :offset 26 :size 2) ;; priority (source mode) - (id uint8 :offset 28 :size 3) ;; ID (what the tag means) - (irq uint8 :offset 31 :size 1) ;; interrupt at the end? - (addr uint32 :offset 32 :size 31) ;; address (31 bits) - (spr uint8 :offset 63 :size 1) ;; spr or not flag. + ((qwc uint16 :offset 0) ;; quadword count + (pce uint8 :offset 26 :size 2) ;; priority (source mode) + (id dma-tag-id :offset 28 :size 3) ;; ID (what the tag means) + (irq uint8 :offset 31 :size 1) ;; interrupt at the end? + (addr uint32 :offset 32 :size 31) ;; address (31 bits) + (spr uint8 :offset 63 :size 1) ;; spr or not flag. ) :method-count-assert 9 :size-assert #x8 @@ -2391,13 +2404,61 @@ :flag-assert #x900000010 ) +;; all these have mask (only applies to unpacks) and interrupt not set. +(defenum vif-cmd + :bitfield #f + :type uint8 + (nop 0) ;; no-op, can still have irq set. + (stcycl 1) ;; set write recycle register + (offset 2) ;; set offset register + (base 3) ;; set base register + (itop 4) ;; set data pointer register (itops) + (stmod 5) ;; set mode register + (mskpath3 6) ;; set path 3 mask + (mark 7) ;; set mark register + (flushe 16) ;; wait for end of microprogram + (flush 17) ;; wait for end of microprogram and transfer (path1/path2) + (flusha 19) ;; wait for end of microprogram and transfer (path1/path2/path3) + (mscal 20) ;; activate microprogram (call) + (mscalf 21) ;; flushe and activate (call) + (mscnt 23) ;; activate microprogram (continue) + (stmask 32) ;; set MASK register. + (strow 48) ;; set filling data + (stcol 49) ;; set filling data + (mpg 74) ;; transfer microprogram + (direct 80) ;; straight to GIF. + (directhl 81) + (unpack-s-32 96) + (unpack-s-16 97) + (unpack-s-8 98) + ;; 99 is invllid + (unpack-v2-32 100) + (unpack-v2-16 101) + (unpack-v2-8 102) + ;; 103 is invalid + (unpack-v3-32 104) + (unpack-v3-16 105) + (unpack-v3-8 106) + ;; 107 is invalid + (unpack-v4-32 108) + (unpack-v4-16 109) + (unpack-v4-8 110) + (unpack-v4-5 111) + ) + +(defenum vif-cmd-32 + :bitfield #f + :type uint32 + :copy-entries vif-cmd + ) + ;; dma-h (deftype vif-tag (uint32) - ((imm uint16 :offset 0 :size 16) - (num uint8 :offset 16 :size 8) - (cmd uint8 :offset 24 :size 7) - (irq uint8 :offset 31 :size 1) - (msk uint8 :offset 28 :size 1) + ((imm uint16 :offset 0 :size 16) + (num uint8 :offset 16 :size 8) + (cmd vif-cmd :offset 24 :size 7) + (irq uint8 :offset 31 :size 1) + (msk uint8 :offset 28 :size 1) ) :method-count-assert 9 :size-assert #x4 @@ -2698,10 +2759,10 @@ (deftype vif-disasm-element (structure) - ((mask uint32 :offset-assert 0) - (tag uint32 :offset-assert 4) - (val uint32 :offset-assert 8) - (print uint32 :offset-assert 12) + ((mask uint32 :offset-assert 0) + (tag vif-cmd-32 :offset-assert 4) + (val uint32 :offset-assert 8) + (print uint32 :offset-assert 12) (string1 string :offset-assert 16) (string2 string :offset-assert 20) ) @@ -2712,10 +2773,10 @@ (define-extern *vif-disasm-table* (array vif-disasm-element)) ;; unknown type ;;(define-extern disasm-vif-tag (function (pointer uint32) int symbol int symbol)) -(define-extern disasm-dma-tag (function uint symbol int)) -(define-extern disasm-vif-details (function symbol (pointer uint8) int int symbol)) +(define-extern disasm-dma-tag (function dma-tag symbol int)) +(define-extern disasm-vif-details (function symbol (pointer uint8) vif-cmd int symbol)) (define-extern vif-disasm-element type) -;;(define-extern *dma-disasm* object) ;; unknown type +(define-extern *dma-disasm* symbol) (define-extern disasm-dma-list function) ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~; diff --git a/decompiler/config/jak1_ntsc_black_label.jsonc b/decompiler/config/jak1_ntsc_black_label.jsonc index 403ab1a98..cc4465bab 100644 --- a/decompiler/config/jak1_ntsc_black_label.jsonc +++ b/decompiler/config/jak1_ntsc_black_label.jsonc @@ -157,9 +157,6 @@ "symlink2", // F: asm branching "dma-sync-hang", - // dma-disasm (BUG) - "disasm-dma-list", - // display "vblank-handler", // F: weird asm for interrupt handler "vif1-handler", // F: weird asm for interrupt handler diff --git a/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc b/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc index 859b84b46..6d32caede 100644 --- a/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc @@ -173,6 +173,14 @@ [3, "a0", "dma-bucket"] ], + "disasm-vif-details": [ + [[62, 94], "s3", "(pointer uint32)"], + [[98, 130], "s3", "(pointer uint16)"], + [[134, 164], "s3", "(pointer uint32)"], + [[168, 198], "s3", "(pointer uint16)"], + [[202, 225], "s3", "(pointer uint16)"] + ], + // LEVEL "lookup-level-info": [ [3, "a1", "symbol"], diff --git a/decompiler/util/TP_Type.cpp b/decompiler/util/TP_Type.cpp index 2c63b2a0b..e6f60fcfb 100644 --- a/decompiler/util/TP_Type.cpp +++ b/decompiler/util/TP_Type.cpp @@ -131,7 +131,7 @@ TypeSpec TP_Type::typespec() const { return m_ts; case Kind::OBJECT_PLUS_PRODUCT_WITH_CONSTANT: if (m_ts.base_type() == "pointer") { - return TypeSpec("pointer"); + return m_ts; } // this can be part of an array access, so we don't really know the type. // probably not a good idea to try to do anything with this as a typespec diff --git a/decompiler/util/TP_Type.h b/decompiler/util/TP_Type.h index 4c8f66cb7..0e89f1513 100644 --- a/decompiler/util/TP_Type.h +++ b/decompiler/util/TP_Type.h @@ -59,10 +59,11 @@ class TP_Type { case Kind::NON_VIRTUAL_METHOD: return false; case Kind::UNINITIALIZED: - case Kind::OBJECT_PLUS_PRODUCT_WITH_CONSTANT: case Kind::OBJECT_NEW_METHOD: case Kind::DYNAMIC_METHOD_ACCESS: return true; + case Kind::OBJECT_PLUS_PRODUCT_WITH_CONSTANT: + return m_ts.base_type() != "pointer"; case Kind::INVALID: default: assert(false); diff --git a/decompiler/util/data_decompile.cpp b/decompiler/util/data_decompile.cpp index 9bb1c6f00..fb83e4abb 100644 --- a/decompiler/util/data_decompile.cpp +++ b/decompiler/util/data_decompile.cpp @@ -526,21 +526,55 @@ goos::Object decompile_structure(const TypeSpec& type, return pretty_print::build_list(result_def); } +namespace { +goos::Object bitfield_defs_print(const TypeSpec& type, + const std::vector& defs) { + std::vector result; + result.push_back(pretty_print::to_symbol(fmt::format("new 'static '{}", type.print()))); + for (auto& def : defs) { + if (def.is_signed) { + result.push_back( + pretty_print::to_symbol(fmt::format(":{} {}", def.field_name, (s64)def.value))); + } else { + result.push_back( + pretty_print::to_symbol(fmt::format(":{} #x{:x}", def.field_name, def.value))); + } + } + return pretty_print::build_list(result); +} + +} // namespace + goos::Object decompile_value(const TypeSpec& type, const std::vector& bytes, const TypeSystem& ts) { - auto bitfield_enum = ts.try_enum_lookup(type); - if (bitfield_enum) { - assert((int)bytes.size() == bitfield_enum->get_load_size()); + auto as_enum = ts.try_enum_lookup(type); + if (as_enum) { + assert((int)bytes.size() == as_enum->get_load_size()); assert(bytes.size() <= 8); u64 value = 0; memcpy(&value, bytes.data(), bytes.size()); - auto defs = decompile_bitfield_enum_from_int(type, ts, value); - std::vector result_def = {pretty_print::to_symbol(type.print())}; - for (auto& x : defs) { - result_def.push_back(pretty_print::to_symbol(x)); + if (as_enum->is_bitfield()) { + auto defs = decompile_bitfield_enum_from_int(type, ts, value); + std::vector result_def = {pretty_print::to_symbol(type.print())}; + for (auto& x : defs) { + result_def.push_back(pretty_print::to_symbol(x)); + } + return pretty_print::build_list(result_def); + } else { + auto def = decompile_int_enum_from_int(type, ts, value); + return pretty_print::build_list(type.print(), def); } - return pretty_print::build_list(result_def); + } + + auto as_bitfield = dynamic_cast(ts.lookup_type(type)); + if (as_bitfield) { + assert((int)bytes.size() == as_bitfield->get_load_size()); + assert(bytes.size() <= 8); + u64 value = 0; + memcpy(&value, bytes.data(), bytes.size()); + auto defs = decompile_bitfield_from_int(type, ts, value); + return bitfield_defs_print(type, defs); } // try as common integer types: @@ -802,20 +836,7 @@ goos::Object decompile_bitfield(const TypeSpec& type, // read as u64 u64 value = *(u64*)(elt_bytes.data()); auto defs = decompile_bitfield_from_int(type, ts, value); - - std::vector result; - result.push_back(pretty_print::to_symbol(fmt::format("new 'static '{}", type.print()))); - for (auto& def : defs) { - if (def.is_signed) { - result.push_back( - pretty_print::to_symbol(fmt::format(":{} {}", def.field_name, (s64)def.value))); - } else { - result.push_back( - pretty_print::to_symbol(fmt::format(":{} #x{:x}", def.field_name, def.value))); - } - } - - return pretty_print::build_list(result); + return bitfield_defs_print(type, defs); } std::vector decompile_bitfield_from_int(const TypeSpec& type, @@ -894,4 +915,17 @@ std::vector decompile_bitfield_enum_from_int(const TypeSpec& type, return result; } +std::string decompile_int_enum_from_int(const TypeSpec& type, const TypeSystem& ts, u64 value) { + auto type_info = ts.try_enum_lookup(type.base_type()); + assert(type_info); + assert(!type_info->is_bitfield()); + for (auto& field : type_info->entries()) { + if ((u64)field.second == value) { + return field.first; + } + } + throw std::runtime_error( + fmt::format("Failed to decompile integer enum. Value {} wasn't found in enum {}", value, + type_info->get_name())); +} } // namespace decompiler \ No newline at end of file diff --git a/decompiler/util/data_decompile.h b/decompiler/util/data_decompile.h index ad2f66cad..21708ab4a 100644 --- a/decompiler/util/data_decompile.h +++ b/decompiler/util/data_decompile.h @@ -79,5 +79,6 @@ std::vector decompile_bitfield_from_int(const TypeSpec& typ std::vector decompile_bitfield_enum_from_int(const TypeSpec& type, const TypeSystem& ts, u64 value); +std::string decompile_int_enum_from_int(const TypeSpec& type, const TypeSystem& ts, u64 value); } // namespace decompiler diff --git a/doc/changelog.md b/doc/changelog.md index 50b88d27a..8df114ef2 100644 --- a/doc/changelog.md +++ b/doc/changelog.md @@ -136,4 +136,7 @@ - Fixed a bug where creating a stack array of 0 sized caused a compiler assertion. It is now a normal compiler error. - Fixed a bug where the repl history was not loaded on compiler start - Branch target addresses in the disassembly generated by `md`, `asm-file` with `:disassemble` and `(declare (print-asm))` are now correct -- Fixed a segfault when the `goal-library.gc` contains an `(exit)` \ No newline at end of file +- Fixed a segfault when the `goal-library.gc` contains an `(exit)` +- `defenum` now creates real types. Boxed arrays of enums and bitfields correctly have runtime type of the parent integer. +- Added a `:copy-entries ` to copy entries from a previous bitfield. +- Adding a duplicate entry to an enum now generates a compiler error. diff --git a/goal_src/engine/dma/dma-disasm.gc b/goal_src/engine/dma/dma-disasm.gc index b10a280e4..4b0110225 100644 --- a/goal_src/engine/dma/dma-disasm.gc +++ b/goal_src/engine/dma/dma-disasm.gc @@ -6,12 +6,12 @@ ;; dgos: GAME, ENGINE (deftype vif-disasm-element (structure) - ((mask uint32 :offset-assert 0) - (tag uint32 :offset-assert 4) - (val uint32 :offset-assert 8) - (print uint32 :offset-assert 12) - (string1 string :offset-assert 16) - (string2 string :offset-assert 20) + ((mask uint32 :offset-assert 0) + (tag vif-cmd-32 :offset-assert 4) + (val uint32 :offset-assert 8) + (print uint32 :offset-assert 12) + (string1 string :offset-assert 16) + (string2 string :offset-assert 20) ) :method-count-assert 9 :size-assert #x18 @@ -55,182 +55,4 @@ (new 'static 'vif-disasm-element :mask #x6f :tag #x6f :val #x2 :print #x7 :string1 "unpack-v4-5") (new 'static 'vif-disasm-element :print #x8))) -(defun disasm-vif-details ((stream symbol) (data (pointer uint8)) (kind int) (count int)) - (local-vars - (v1-21 uint) - (v1-26 uint) - (a3-7 int) - (i int) - (s2-1 int) - (s2-2 int) - (s2-3 int) - (s2-4 int) - (s2-5 int) - (s2-6 int) - (data-ptr (pointer uint8)) - (s3-1 (pointer uint8)) - (s3-2 (pointer uint8)) - (s3-3 (pointer uint8)) - (s3-4 (pointer uint8)) - (s3-5 (pointer uint8)) - (s3-6 (pointer uint8)) - (count2 int) - ) - (set! count2 count) - (cond - ((= kind 110) - (set! data-ptr (&-> data 4)) - (set! i 0) - (while (< i count2) - (format stream " #x~X: #x~2X #x~2X #x~2X #x~2X~%" - (+ (+ (shl i 2) 4) (the-as int data)) - (-> (the-as (pointer uint8) (&+ data-ptr (shl i 2)))) - (-> (the-as (pointer uint8) (&+ data-ptr (+ (shl i 2) 1)))) - (-> (the-as (pointer uint8) (&+ data-ptr (+ (shl i 2) 2)))) - (-> (the-as (pointer uint8) (&+ data-ptr (+ (shl i 2) 3)))) - ) - (+! i 1) - ) - ) - ((= kind 98) - (set! s3-1 (&-> data 4)) - (set! s2-1 0) - (while (< s2-1 count2) - (format stream " #x~X: #x~2x~%" (+ (+ s2-1 4) (the-as int data)) count) - (set! v1-21 (-> (the-as (pointer uint8) (&+ s3-1 (* 3 s2-1))))) - (set! v1-26 (-> (the-as (pointer uint8) (&+ s3-1 (+ (* 3 s2-1) 1))))) - (+! s2-1 1) - ) - ) - ((= kind 108) - (set! s3-2 (&-> data 4)) - (set! s2-2 0) - (while (< s2-2 count2) - (format stream " #x~X: #x~8x #x~8x #x~8x #x~8x~%" - (+ (+ (shl s2-2 4) 4) (the-as int data)) - (-> (the-as (pointer uint32) (&+ s3-2 (shl (shl s2-2 2) 2)))) - (-> (the-as (pointer uint32) (&+ s3-2 (shl (+ (shl s2-2 2) 1) 2)))) - (-> (the-as (pointer uint32) (&+ s3-2 (shl (+ (shl s2-2 2) 2) 2)))) - (-> (the-as (pointer uint32) (&+ s3-2 (shl (+ (shl s2-2 2) 3) 2)))) - ) - (+! s2-2 1) - ) - ) - ((= kind 109) - (set! s3-3 (&-> data 4)) - (set! s2-3 0) - (while - (< s2-3 count2) - (format stream " #x~X: #x~4x #x~4x #x~4x #x~4x~%" - (+ (+ (shl s2-3 3) 4) (the-as int data)) - (-> (the-as (pointer uint16) (&+ s3-3 (shl (shl s2-3 2) 1)))) - (-> (the-as (pointer uint16) (&+ s3-3 (shl (+ (shl s2-3 2) 1) 1)))) - (-> (the-as (pointer uint16) (&+ s3-3 (shl (+ (shl s2-3 2) 2) 1)))) - (-> (the-as (pointer uint16) (&+ s3-3 (shl (+ (shl s2-3 2) 3) 1)))) - ) - (+! s2-3 1) - ) - ) - ((= kind 104) - (set! s3-4 (&-> data 4)) - (set! s2-4 0) - (while - (< s2-4 count2) - (format stream - " #x~X: #x~8x #x~8x #x~8x~%" - (+ (+ (* 12 s2-4) 4) (the-as int data)) - (-> (the-as (pointer uint32) (&+ s3-4 (* 12 s2-4)))) - (-> (the-as (pointer uint32) (&+ s3-4 (shl (+ (* 3 s2-4) 1) 2)))) - (-> (the-as (pointer uint32) (&+ s3-4 (shl (+ (* 3 s2-4) 2) 2)))) - ) - (+! s2-4 1) - ) - ) - ((= kind 105) - (set! s3-5 (&-> data 4)) - (set! s2-5 0) - (while - (< s2-5 count2) - (format stream - " #x~X: #x~4x #x~4x #x~4x~%" - (+ (+ (* 6 s2-5) 4) (the-as int data)) - (-> (the-as (pointer uint16) (&+ s3-5 (* 6 s2-5)))) - (-> (the-as (pointer uint16) (&+ s3-5 (shl (+ (* 3 s2-5) 1) 1)))) - (-> (the-as (pointer uint16) (&+ s3-5 (shl (+ (* 3 s2-5) 2) 1)))) - ) - (+! s2-5 1) - ) - ) - ((= kind 101) - (set! s3-6 (&-> data 4)) - (set! s2-6 0) - (while - (< s2-6 count2) - (format stream " #x~X: #x~4x #x~4x~%" - (+ (+ (shl s2-6 2) 4) (the-as int data)) - (-> (the-as (pointer uint16) (&+ s3-6 (* 6 s2-6)))) - (-> (the-as (pointer uint16) (&+ s3-6 (shl (+ (* 3 s2-6) 1) 1)))) - ) - (+! s2-6 1) - ) - ) - (else - (set! a3-7 kind) - (format stream - " #x~X: Data format #b~b not yet supported, add it for yourself!~%" - (&-> data 4) - a3-7 - ) - ) - ) - #f - ) -(defun disasm-dma-tag ((arg0 uint) (arg1 symbol)) - "Print out a dma-tag" - (local-vars - (v1-1 uint) - (v1-15 int) - ) - (format arg1 "(dma-tag ") - - ;; this is a case used by value, which it doesn't like because the temp v1-1 can't be folded into a single - ;; expression. In reality, the game does the following line _after_ the format symbol is loaded, - ;; but this makes no difference and OpenGOAL doesn't have case, so we have to make do with this. - (set! v1-1 (shr (shl arg0 33) 61)) - (format arg1 "~s" - (cond - ((= v1-1 7) "end") - ((= v1-1 6) "ret") - ((= v1-1 5) "call") - ((= v1-1 4) "refs") - ((= v1-1 3) "ref") - ((= v1-1 2) "next") - ((= v1-1 1) "cnt") - ((zero? v1-1) "refe") - (else "*unknown*") - ) - ) - - ;; only print address if nonzero - (if (> (shr (shl arg0 1) 33) 0) - (format arg1 " :addr #x~8x" (shr (shl arg0 1) 33)) - ) - - ;; only print qwc if nonzero - (if (> (shr (shl arg0 48) 48) 0) - (format arg1 " :qwc ~d" (shr (shl arg0 48) 48)) - ) - ;; only print spr if set - (if (> (shr arg0 63) 0) - (format arg1 " :spr ~d" (shr arg0 63))) - ;;(.srl v1-15 arg0 31) - (set! v1-15 (logand #xffffffff (shr arg0 31))) - (when (> (the-as uint v1-15) 0) - (format arg1 " :irq ~d" (logand #xffffffff (shr arg0 31))) - ) - (if (> (shr (shl arg0 36) 62) 0) - (format arg1 " :pce ~d" (shr (shl arg0 36) 62)) - ) - (the-as int (format arg1 ")~%")) - ) diff --git a/goal_src/engine/dma/dma-h.gc b/goal_src/engine/dma/dma-h.gc index 3055a0e3f..42c159281 100644 --- a/goal_src/engine/dma/dma-h.gc +++ b/goal_src/engine/dma/dma-h.gc @@ -169,34 +169,36 @@ :flag-assert #x900000008 ) + +(defenum dma-tag-id + :bitfield #f + :type uint8 + (refe 0) ;; addr=ADDR, ends after this transfer + (cnt 1) ;; addr=after tag, next-tag=after data + (next 2) ;; addr=after tag, next-tag=ADDR + (ref 3) ;; addr=ADDR, next-tag=after tag + (refs 4) ;; ref, but stall controled + (call 5) ;; + (ret 6) ;; + (end 7) ;; next, but ends. + ) + ;; In source chain mode, the DMA controller reads "DMAtag"s to determine addresses ;; sizes, and the next thing to transfer. ;; A tag is 8 bytes. (deftype dma-tag (uint64) - ((qwc uint16 :offset 0) ;; quadword count - (pce uint8 :offset 26 :size 2) ;; priority (source mode) - (id uint8 :offset 28 :size 3) ;; ID (what the tag means) - (irq uint8 :offset 31 :size 1) ;; interrupt at the end? - (addr uint32 :offset 32 :size 31) ;; address (31 bits) - (spr uint8 :offset 63 :size 1) ;; spr or not flag. + ((qwc uint16 :offset 0) ;; quadword count + (pce uint8 :offset 26 :size 2) ;; priority (source mode) + (id dma-tag-id :offset 28 :size 3) ;; ID (what the tag means) + (irq uint8 :offset 31 :size 1) ;; interrupt at the end? + (addr uint32 :offset 32 :size 31) ;; address (31 bits) + (spr uint8 :offset 63 :size 1) ;; spr or not flag. ) :method-count-assert 9 :size-assert #x8 :flag-assert #x900000008 ) -(defenum dma-tag-id - :bitfield #f - (refe 0) ;; addr=ADDR, ends after this transfer - (cnt 1) ;; addr=after tag, next-tag=after data - (next 2) ;; addr=after tag, next-tag=ADDR - (ref 3) ;; addr=ADDR, next-tag=after tag - (refs 4) ;; ref, but stall controled - (call 5) ;; - (ret 6) ;; - (end 7) ;; next, but ends. - ) - ;; A DMA bucket is a way of organizing data within a dma buffer. ;; The buckets themselves live inside in the dma buffer. ;; the addr field of their tag should point to the next bucket. @@ -252,38 +254,63 @@ ) +;; all these have mask (only applies to unpacks) and interrupt not set. (defenum vif-cmd :bitfield #f - (nop 0) ;; no-op, can still have irq set. - (stcycl 1) ;; set write recycle register - (offset 2) ;; set offset register - (base 3) ;; set base register - (itop 4) ;; set data pointer register (itops) - (stmod 5) ;; set mode register - (mskpath3 6) ;; set path 3 mask - (mark 7) ;; set mark register - (flushe 16) ;; wait for end of microprogram - (flush 17) ;; wait for end of microprogram and transfer (path1/path2) - (flusha 19) ;; wait for end of microprogram and transfer (path1/path2/path3) - (mscal 20) ;; activate microprogram (call) - (mscalf 21) ;; flushe and activate (call) - (mscnt 23) ;; activate microprogram (continue) - (stmask 32) ;; set MASK register. - (strow 48) ;; set filling data - (strow 49) ;; set filling data - (mpg 74) ;; transfer microprogram - ;; there's more... + :type uint8 + (nop 0) ;; no-op, can still have irq set. + (stcycl 1) ;; set write recycle register + (offset 2) ;; set offset register + (base 3) ;; set base register + (itop 4) ;; set data pointer register (itops) + (stmod 5) ;; set mode register + (mskpath3 6) ;; set path 3 mask + (mark 7) ;; set mark register + (flushe 16) ;; wait for end of microprogram + (flush 17) ;; wait for end of microprogram and transfer (path1/path2) + (flusha 19) ;; wait for end of microprogram and transfer (path1/path2/path3) + (mscal 20) ;; activate microprogram (call) + (mscalf 21) ;; flushe and activate (call) + (mscnt 23) ;; activate microprogram (continue) + (stmask 32) ;; set MASK register. + (strow 48) ;; set filling data + (stcol 49) ;; set filling data + (mpg 74) ;; transfer microprogram + (direct 80) ;; straight to GIF. + (directhl 81) + (unpack-s-32 96) + (unpack-s-16 97) + (unpack-s-8 98) + ;; 99 is invllid + (unpack-v2-32 100) + (unpack-v2-16 101) + (unpack-v2-8 102) + ;; 103 is invalid + (unpack-v3-32 104) + (unpack-v3-16 105) + (unpack-v3-8 106) + ;; 107 is invalid + (unpack-v4-32 108) + (unpack-v4-16 109) + (unpack-v4-8 110) + (unpack-v4-5 111) + ) + +;; this makes a copy of the above type, but uses a uint32. +(defenum vif-cmd-32 + :bitfield #f + :type uint32 + :copy-entries vif-cmd ) - ;; The VIF also has tags to control it. -;; Different VIF commands (called VIFcode) have different tag layouts. +;; Different VIF commands (called VIFcode) have different tag layouts.;; dma-h (deftype vif-tag (uint32) - ((imm uint16 :offset 0 :size 16) - (num uint8 :offset 16 :size 8) - (cmd uint8 :offset 24 :size 7) - (irq uint8 :offset 31 :size 1) - (msk uint8 :offset 28 :size 1) + ((imm uint16 :offset 0 :size 16) + (num uint8 :offset 16 :size 8) + (cmd vif-cmd :offset 24 :size 7) + (irq uint8 :offset 31 :size 1) + (msk uint8 :offset 28 :size 1) ) :method-count-assert 9 :size-assert #x4 diff --git a/test/decompiler/reference/all_forward_declarations.gc b/test/decompiler/reference/all_forward_declarations.gc index 1bf2b7026..b35b4a08f 100644 --- a/test/decompiler/reference/all_forward_declarations.gc +++ b/test/decompiler/reference/all_forward_declarations.gc @@ -129,8 +129,70 @@ (busclk/256 2) (hblank 3) ) + +;; dma (declare-type dma-buffer basic) +(defenum vif-cmd + :bitfield #f + :type uint8 + (nop 0) ;; no-op, can still have irq set. + (stcycl 1) ;; set write recycle register + (offset 2) ;; set offset register + (base 3) ;; set base register + (itop 4) ;; set data pointer register (itops) + (stmod 5) ;; set mode register + (mskpath3 6) ;; set path 3 mask + (mark 7) ;; set mark register + (flushe 16) ;; wait for end of microprogram + (flush 17) ;; wait for end of microprogram and transfer (path1/path2) + (flusha 19) ;; wait for end of microprogram and transfer (path1/path2/path3) + (mscal 20) ;; activate microprogram (call) + (mscalf 21) ;; flushe and activate (call) + (mscnt 23) ;; activate microprogram (continue) + (stmask 32) ;; set MASK register. + (strow 48) ;; set filling data + (stcol 49) ;; set filling data + (mpg 74) ;; transfer microprogram + (direct 80) ;; straight to GIF. + (directhl 81) + (unpack-s-32 96) + (unpack-s-16 97) + (unpack-s-8 98) + ;; 99 is invllid + (unpack-v2-32 100) + (unpack-v2-16 101) + (unpack-v2-8 102) + ;; 103 is invalid + (unpack-v3-32 104) + (unpack-v3-16 105) + (unpack-v3-8 106) + ;; 107 is invalid + (unpack-v4-32 108) + (unpack-v4-16 109) + (unpack-v4-8 110) + (unpack-v4-5 111) + ) + +(defenum vif-cmd-32 + :bitfield #f + :type uint32 + :copy-entries vif-cmd + ) + +(defenum dma-tag-id + :bitfield #f + :type uint8 + (refe 0) ;; addr=ADDR, ends after this transfer + (cnt 1) ;; addr=after tag, next-tag=after data + (next 2) ;; addr=after tag, next-tag=ADDR + (ref 3) ;; addr=ADDR, next-tag=after tag + (refs 4) ;; ref, but stall controled + (call 5) ;; + (ret 6) ;; + (end 7) ;; next, but ends. + ) + ;; display-h (deftype display-env (structure) ((pmode uint64 :offset-assert 0) diff --git a/test/decompiler/reference/bounding-box-h_REF.gc b/test/decompiler/reference/bounding-box-h_REF.gc index 2943d83c9..eaa728951 100644 --- a/test/decompiler/reference/bounding-box-h_REF.gc +++ b/test/decompiler/reference/bounding-box-h_REF.gc @@ -68,5 +68,3 @@ (let ((v0-3 0)) ) -;; failed to figure out what this is: -(none) \ No newline at end of file diff --git a/test/decompiler/reference/bounding-box_REF.gc b/test/decompiler/reference/bounding-box_REF.gc index 9a068122a..14be2171c 100644 --- a/test/decompiler/reference/bounding-box_REF.gc +++ b/test/decompiler/reference/bounding-box_REF.gc @@ -142,5 +142,3 @@ ;; definition for method 9 of type bounding-box ;; ERROR: function was not converted to expressions. Cannot decompile. -;; failed to figure out what this is: -(none) diff --git a/test/decompiler/reference/dgo-h_REF.gc b/test/decompiler/reference/dgo-h_REF.gc index 555432fe1..f934cc0d3 100644 --- a/test/decompiler/reference/dgo-h_REF.gc +++ b/test/decompiler/reference/dgo-h_REF.gc @@ -45,5 +45,3 @@ (let ((v0-2 0)) ) -;; failed to figure out what this is: -(none) diff --git a/test/decompiler/reference/dma-bucket_REF.gc b/test/decompiler/reference/dma-bucket_REF.gc index 27c5bfc06..5e34a6cb4 100644 --- a/test/decompiler/reference/dma-bucket_REF.gc +++ b/test/decompiler/reference/dma-bucket_REF.gc @@ -55,6 +55,5 @@ (let ((v0-0 0)) ) -;; failed to figure out what this is: -(none) + diff --git a/test/decompiler/reference/dma-buffer_REF.gc b/test/decompiler/reference/dma-buffer_REF.gc index 93471ed01..42bdf3183 100644 --- a/test/decompiler/reference/dma-buffer_REF.gc +++ b/test/decompiler/reference/dma-buffer_REF.gc @@ -138,7 +138,7 @@ (defun dma-buffer-add-vu-function ((dma-buf dma-buffer) (vu-func vu-function) (arg2 int)) - (let ((func-ptr (the-as pointer (&-> vu-func data 4))) + (let ((func-ptr (&-> vu-func data 4)) (qlen (-> vu-func qlength)) (origin (-> vu-func origin)) ) @@ -204,8 +204,6 @@ (none) ) -;; failed to figure out what this is: -(none) diff --git a/test/decompiler/reference/dma-h_REF.gc b/test/decompiler/reference/dma-h_REF.gc index b17f22e05..8eb50c147 100644 --- a/test/decompiler/reference/dma-h_REF.gc +++ b/test/decompiler/reference/dma-h_REF.gc @@ -207,12 +207,12 @@ ;; definition of type dma-tag (deftype dma-tag (uint64) - ((qwc uint16 :offset 0 :size 16) - (pce uint8 :offset 26 :size 2) - (id uint8 :offset 28 :size 3) - (irq uint8 :offset 31 :size 1) - (addr uint32 :offset 32 :size 31) - (spr uint8 :offset 63 :size 1) + ((qwc uint16 :offset 0 :size 16) + (pce uint8 :offset 26 :size 2) + (id dma-tag-id :offset 28 :size 3) + (irq uint8 :offset 31 :size 1) + (addr uint32 :offset 32 :size 31) + (spr uint8 :offset 63 :size 1) ) :method-count-assert 9 :size-assert #x8 @@ -300,11 +300,11 @@ ;; definition of type vif-tag (deftype vif-tag (uint32) - ((imm uint16 :offset 0 :size 16) - (num uint8 :offset 16 :size 8) - (cmd uint8 :offset 24 :size 7) - (irq uint8 :offset 31 :size 1) - (msk uint8 :offset 28 :size 1) + ((imm uint16 :offset 0 :size 16) + (num uint8 :offset 16 :size 8) + (cmd vif-cmd :offset 24 :size 7) + (irq uint8 :offset 31 :size 1) + (msk uint8 :offset 28 :size 1) ) :method-count-assert 9 :size-assert #x4 @@ -334,8 +334,6 @@ ;; definition for function dma-count-until-done ;; ERROR: function was not converted to expressions. Cannot decompile. -;; failed to figure out what this is: -(none) diff --git a/test/decompiler/reference/dma_REF.gc b/test/decompiler/reference/dma_REF.gc index af57597f4..889665c4b 100644 --- a/test/decompiler/reference/dma_REF.gc +++ b/test/decompiler/reference/dma_REF.gc @@ -411,8 +411,7 @@ ;; failed to figure out what this is: (dma-initialize) -;; failed to figure out what this is: -(none) + diff --git a/test/decompiler/reference/euler-h_REF.gc b/test/decompiler/reference/euler-h_REF.gc index 8f11ef2dc..984ddaa54 100644 --- a/test/decompiler/reference/euler-h_REF.gc +++ b/test/decompiler/reference/euler-h_REF.gc @@ -38,6 +38,5 @@ (let ((v0-1 0)) ) -;; failed to figure out what this is: -(none) + diff --git a/test/decompiler/reference/euler_REF.gc b/test/decompiler/reference/euler_REF.gc index bc6279198..47f2c2209 100644 --- a/test/decompiler/reference/euler_REF.gc +++ b/test/decompiler/reference/euler_REF.gc @@ -508,8 +508,7 @@ arg0 ) -;; failed to figure out what this is: -(none) + diff --git a/test/decompiler/reference/gcommon_REF.gc b/test/decompiler/reference/gcommon_REF.gc index 883ce8dbb..f8227dd73 100644 --- a/test/decompiler/reference/gcommon_REF.gc +++ b/test/decompiler/reference/gcommon_REF.gc @@ -1292,5 +1292,3 @@ (let ((v0-3 0)) ) -;; failed to figure out what this is: -(none) \ No newline at end of file diff --git a/test/decompiler/reference/geometry-h_REF.gc b/test/decompiler/reference/geometry-h_REF.gc index 714741fff..a2cdcf9b8 100644 --- a/test/decompiler/reference/geometry-h_REF.gc +++ b/test/decompiler/reference/geometry-h_REF.gc @@ -57,6 +57,4 @@ (let ((v0-2 0)) ) -;; failed to figure out what this is: -(none) diff --git a/test/decompiler/reference/gkernel-h_REF.gc b/test/decompiler/reference/gkernel-h_REF.gc index ff274c3a7..ec5e7d329 100644 --- a/test/decompiler/reference/gkernel-h_REF.gc +++ b/test/decompiler/reference/gkernel-h_REF.gc @@ -371,5 +371,4 @@ (let ((v0-11 0)) ) -;; failed to figure out what this is: -(none) + diff --git a/test/decompiler/reference/gkernel_REF.gc b/test/decompiler/reference/gkernel_REF.gc index d3167b399..f52cea62a 100644 --- a/test/decompiler/reference/gkernel_REF.gc +++ b/test/decompiler/reference/gkernel_REF.gc @@ -2005,5 +2005,3 @@ (gp-5 a0-63 *active-pool*) ) -;; failed to figure out what this is: -(none) \ No newline at end of file diff --git a/test/decompiler/reference/gsound-h_REF.gc b/test/decompiler/reference/gsound-h_REF.gc index 21328036d..7001e2994 100644 --- a/test/decompiler/reference/gsound-h_REF.gc +++ b/test/decompiler/reference/gsound-h_REF.gc @@ -788,8 +788,7 @@ (let ((v0-34 0)) ) -;; failed to figure out what this is: -(none) + diff --git a/test/decompiler/reference/gstate_REF.gc b/test/decompiler/reference/gstate_REF.gc index 6102722c4..8ce8d8407 100644 --- a/test/decompiler/reference/gstate_REF.gc +++ b/test/decompiler/reference/gstate_REF.gc @@ -175,5 +175,3 @@ (the-as symbol #f) ) -;; failed to figure out what this is: -(none) diff --git a/test/decompiler/reference/gstring-h_REF.gc b/test/decompiler/reference/gstring-h_REF.gc index 1b5fa192d..b1454163e 100644 --- a/test/decompiler/reference/gstring-h_REF.gc +++ b/test/decompiler/reference/gstring-h_REF.gc @@ -5,5 +5,3 @@ (let ((v0-0 0)) ) -;; failed to figure out what this is: -(none) \ No newline at end of file diff --git a/test/decompiler/reference/gstring_REF.gc b/test/decompiler/reference/gstring_REF.gc index 283910e74..9c4cc5fdc 100644 --- a/test/decompiler/reference/gstring_REF.gc +++ b/test/decompiler/reference/gstring_REF.gc @@ -707,5 +707,4 @@ ;; definition for symbol *temp-string*, type string (define *temp-string* (new 'global 'string 256 (the-as string #f))) -;; failed to figure out what this is: -(none) + diff --git a/test/decompiler/reference/math_REF.gc b/test/decompiler/reference/math_REF.gc index bb6dfe026..f0aa1d08b 100644 --- a/test/decompiler/reference/math_REF.gc +++ b/test/decompiler/reference/math_REF.gc @@ -230,6 +230,3 @@ (let ((v0-6 0)) ) -;; failed to figure out what this is: -(none) - diff --git a/test/decompiler/reference/matrix-h_REF.gc b/test/decompiler/reference/matrix-h_REF.gc index e60857a55..2b21c8105 100644 --- a/test/decompiler/reference/matrix-h_REF.gc +++ b/test/decompiler/reference/matrix-h_REF.gc @@ -82,6 +82,4 @@ arg0 ) -;; failed to figure out what this is: -(none) diff --git a/test/decompiler/reference/matrix_REF.gc b/test/decompiler/reference/matrix_REF.gc index 317776e91..f5a18b1fa 100644 --- a/test/decompiler/reference/matrix_REF.gc +++ b/test/decompiler/reference/matrix_REF.gc @@ -1691,5 +1691,4 @@ ;; definition for method 9 of type matrix ;; ERROR: function was not converted to expressions. Cannot decompile. -;; failed to figure out what this is: -(none) + diff --git a/test/decompiler/reference/quaternion-h_REF.gc b/test/decompiler/reference/quaternion-h_REF.gc index 636779e7d..691b732cc 100644 --- a/test/decompiler/reference/quaternion-h_REF.gc +++ b/test/decompiler/reference/quaternion-h_REF.gc @@ -38,5 +38,3 @@ (let ((v0-1 0)) ) -;; failed to figure out what this is: -(none) diff --git a/test/decompiler/reference/quaternion_REF.gc b/test/decompiler/reference/quaternion_REF.gc index c794890bb..000f5928b 100644 --- a/test/decompiler/reference/quaternion_REF.gc +++ b/test/decompiler/reference/quaternion_REF.gc @@ -1171,9 +1171,3 @@ ) ) -;; failed to figure out what this is: -(none) - - - - diff --git a/test/decompiler/reference/sync-info-h_REF.gc b/test/decompiler/reference/sync-info-h_REF.gc index bff5db5bb..f715e335c 100644 --- a/test/decompiler/reference/sync-info-h_REF.gc +++ b/test/decompiler/reference/sync-info-h_REF.gc @@ -234,9 +234,3 @@ (let ((v0-8 0)) ) -;; failed to figure out what this is: -(none) - - - - diff --git a/test/decompiler/reference/sync-info_REF.gc b/test/decompiler/reference/sync-info_REF.gc index a7f4a0ca6..8efd37970 100644 --- a/test/decompiler/reference/sync-info_REF.gc +++ b/test/decompiler/reference/sync-info_REF.gc @@ -711,10 +711,3 @@ (-> obj value) ) ) - -;; failed to figure out what this is: -(none) - - - - diff --git a/test/decompiler/reference/timer-h_REF.gc b/test/decompiler/reference/timer-h_REF.gc index 9e88ef07a..292dd305e 100644 --- a/test/decompiler/reference/timer-h_REF.gc +++ b/test/decompiler/reference/timer-h_REF.gc @@ -163,10 +163,3 @@ ;; failed to figure out what this is: (let ((v0-7 0)) ) - -;; failed to figure out what this is: -(none) - - - - diff --git a/test/decompiler/reference/timer_REF.gc b/test/decompiler/reference/timer_REF.gc index 83b43b618..9a7e81967 100644 --- a/test/decompiler/reference/timer_REF.gc +++ b/test/decompiler/reference/timer_REF.gc @@ -174,6 +174,3 @@ ) ) -;; failed to figure out what this is: -(none) - diff --git a/test/decompiler/reference/transform-h_REF.gc b/test/decompiler/reference/transform-h_REF.gc index fca6f31f2..b8d5fe6f7 100644 --- a/test/decompiler/reference/transform-h_REF.gc +++ b/test/decompiler/reference/transform-h_REF.gc @@ -48,6 +48,3 @@ (let ((v0-2 0)) ) -;; failed to figure out what this is: -(none) - diff --git a/test/decompiler/reference/transform_REF.gc b/test/decompiler/reference/transform_REF.gc index 32503515e..be8757d87 100644 --- a/test/decompiler/reference/transform_REF.gc +++ b/test/decompiler/reference/transform_REF.gc @@ -108,9 +108,4 @@ (transform-matrix-calc! (the-as transform (-> tf trans)) dst-mat) ) -;; failed to figure out what this is: -(none) - - - diff --git a/test/decompiler/reference/trigonometry-h_REF.gc b/test/decompiler/reference/trigonometry-h_REF.gc index e412f7e2e..d92736d4c 100644 --- a/test/decompiler/reference/trigonometry-h_REF.gc +++ b/test/decompiler/reference/trigonometry-h_REF.gc @@ -4,7 +4,3 @@ ;; failed to figure out what this is: (let ((v0-0 0)) ) - -;; failed to figure out what this is: -(none) - diff --git a/test/decompiler/reference/types-h_REF.gc b/test/decompiler/reference/types-h_REF.gc index 16d8d2b74..69b8d1392 100644 --- a/test/decompiler/reference/types-h_REF.gc +++ b/test/decompiler/reference/types-h_REF.gc @@ -20,6 +20,3 @@ ;; failed to figure out what this is: (let ((v0-2 0)) ) - -;; failed to figure out what this is: -(none) diff --git a/test/decompiler/reference/vector-h_REF.gc b/test/decompiler/reference/vector-h_REF.gc index e21dab5e9..f3e10b4fc 100644 --- a/test/decompiler/reference/vector-h_REF.gc +++ b/test/decompiler/reference/vector-h_REF.gc @@ -964,6 +964,3 @@ ;; definition for symbol *zero-vector*, type vector (define *zero-vector* (new 'static 'vector)) -;; failed to figure out what this is: -(none) - diff --git a/test/decompiler/reference/video-h_REF.gc b/test/decompiler/reference/video-h_REF.gc index a14541f34..3e9883168 100644 --- a/test/decompiler/reference/video-h_REF.gc +++ b/test/decompiler/reference/video-h_REF.gc @@ -75,10 +75,3 @@ ;; failed to figure out what this is: (let ((v0-1 0)) ) - -;; failed to figure out what this is: -(none) - - - - diff --git a/test/decompiler/reference/vif-h_REF.gc b/test/decompiler/reference/vif-h_REF.gc index 0cfbc4bda..dea1c3ca4 100644 --- a/test/decompiler/reference/vif-h_REF.gc +++ b/test/decompiler/reference/vif-h_REF.gc @@ -122,7 +122,4 @@ (let ((v0-4 0)) ) -;; failed to figure out what this is: -(none) - diff --git a/test/decompiler/reference/vu1-macros_REF.gc b/test/decompiler/reference/vu1-macros_REF.gc index ded789d55..d92736d4c 100644 --- a/test/decompiler/reference/vu1-macros_REF.gc +++ b/test/decompiler/reference/vu1-macros_REF.gc @@ -4,6 +4,3 @@ ;; failed to figure out what this is: (let ((v0-0 0)) ) - -;; failed to figure out what this is: -(none) diff --git a/test/decompiler/reference/vu1-user-h_REF.gc b/test/decompiler/reference/vu1-user-h_REF.gc index 7e3690556..b4b756090 100644 --- a/test/decompiler/reference/vu1-user-h_REF.gc +++ b/test/decompiler/reference/vu1-user-h_REF.gc @@ -113,9 +113,3 @@ (let ((v0-4 0)) ) -;; failed to figure out what this is: -(none) - - - - diff --git a/test/decompiler/test_DataParser.cpp b/test/decompiler/test_DataParser.cpp index 1a34191b4..4f9db5ecd 100644 --- a/test/decompiler/test_DataParser.cpp +++ b/test/decompiler/test_DataParser.cpp @@ -148,9 +148,9 @@ TEST_F(DataDecompTest, SimpleStructure) { auto parsed = parse_data(input); auto decomp = decompile_at_label(TypeSpec("vif-disasm-element"), parsed.label("L217"), parsed.labels, {parsed.words}, dts->ts); - check_forms_equal( - decomp.print(), - "(new 'static 'vif-disasm-element :mask #x7f :tag #x1 :print #x2 :string1 \"stcycl\")"); + check_forms_equal(decomp.print(), + "(new 'static 'vif-disasm-element :mask #x7f :tag (vif-cmd-32 stcycl) :print " + "#x2 :string1 \"stcycl\")"); } TEST_F(DataDecompTest, VifDisasmArray) { @@ -209,13 +209,14 @@ TEST_F(DataDecompTest, VifDisasmArray) { auto parsed = parse_data(input); auto decomp = decompile_at_label_guess_type(parsed.label("L148"), parsed.labels, {parsed.words}, dts->ts); - check_forms_equal( - decomp.print(), - "(new 'static 'boxed-array vif-disasm-element 3\n" - " (new 'static 'vif-disasm-element :mask #x7f :string1 \"nop\")\n" - " (new 'static 'vif-disasm-element :mask #x7f :tag #x1 :print #x2 :string1 \"stcycl\")\n" - " (new 'static 'vif-disasm-element :mask #x7f :tag #x2 :print #x1 :string1 \"offset\" " - " :string2 \"offset\"))"); + check_forms_equal(decomp.print(), + "(new 'static 'boxed-array vif-disasm-element 3\n" + " (new 'static 'vif-disasm-element :mask #x7f :string1 \"nop\")\n" + " (new 'static 'vif-disasm-element :mask #x7f :tag (vif-cmd-32 stcycl) :print " + "#x2 :string1 \"stcycl\")\n" + " (new 'static 'vif-disasm-element :mask #x7f :tag (vif-cmd-32 offset) :print " + "#x1 :string1 \"offset\" " + " :string2 \"offset\"))"); } TEST_F(DataDecompTest, ContinuePoint) { diff --git a/test/decompiler/test_FormExpressionBuild2.cpp b/test/decompiler/test_FormExpressionBuild2.cpp index f816ebc89..83dd1fbfc 100644 --- a/test/decompiler/test_FormExpressionBuild2.cpp +++ b/test/decompiler/test_FormExpressionBuild2.cpp @@ -952,7 +952,7 @@ TEST_F(FormRegressionTest, DmaBufferAddVuFunction) { std::string type = "(function dma-buffer vu-function int symbol)"; std::string expected = "(begin\n" - " (let ((v1-0 (the-as pointer (&-> arg1 data 4)))\n" + " (let ((v1-0 (&-> arg1 data 4))\n" " (a3-0 (-> arg1 qlength))\n" " (a1-1 (-> arg1 origin))\n" " )\n"