Support 128-bit variables (#336)

* wip 128 bit support

* add a few more files to offline test
This commit is contained in:
water111
2021-03-25 16:02:48 -04:00
committed by GitHub
parent 99683c0dac
commit 7fac11ddf5
29 changed files with 509 additions and 213 deletions
+2 -3
View File
@@ -339,9 +339,8 @@ bool TypeSystem::try_reverse_lookup_inline_array(const FieldReverseLookupInput&
}
// otherwise access within the element
if (elt_idx != 0) {
path->push_back(token);
}
path->push_back(token);
FieldReverseLookupInput next_input;
next_input.deref = input.deref;
next_input.stride = 0;
+9 -2
View File
@@ -5,6 +5,7 @@
#include "third-party/fmt/core.h"
namespace decompiler {
class DecompWarnings {
public:
DecompWarnings() = default;
@@ -39,7 +40,8 @@ class DecompWarnings {
warning(Warning::Kind::INFO, str, std::forward<Args>(args)...);
}
bool has_warnings() const { return !m_warnings.empty(); }
bool has_warnings() const { return !m_warnings.empty() || m_used_lq_sq; }
void warn_sq_lq() { m_used_lq_sq = true; }
std::string get_warning_text(bool as_comment) const {
std::string result;
@@ -49,6 +51,9 @@ class DecompWarnings {
}
result += w.print();
}
if (m_used_lq_sq) {
result += ";; Used lq/sq\n";
}
return result;
}
@@ -95,4 +100,6 @@ class DecompWarnings {
}
std::vector<Warning> m_warnings;
};
bool m_used_lq_sq = false;
};
} // namespace decompiler
+6
View File
@@ -989,6 +989,9 @@ goos::Object StoreOp::to_form(const std::vector<DecompilerLabel>& labels, const
case 8:
store_name = "s.d!";
break;
case 16:
store_name = "s.q!";
break;
default:
assert(false);
}
@@ -1056,6 +1059,9 @@ goos::Object LoadVarOp::to_form(const std::vector<DecompilerLabel>& labels, cons
case 8:
forms.push_back(pretty_print::build_list("l.d", m_src.to_form(labels, env)));
break;
case 16:
forms.push_back(pretty_print::build_list("l.q", m_src.to_form(labels, env)));
break;
default:
assert(false);
}
+6
View File
@@ -324,6 +324,9 @@ FormElement* StoreOp::get_as_form(FormPool& pool, const Env& env) const {
case 8:
cast_type = "int64";
break;
case 16:
cast_type = "int128";
break;
default:
assert(false);
}
@@ -486,6 +489,9 @@ FormElement* LoadVarOp::get_as_form(FormPool& pool, const Env& env) const {
case 8:
cast_type = "int64";
break;
case 16:
cast_type = "int128";
break;
default:
assert(false);
}
+4
View File
@@ -699,6 +699,8 @@ TP_Type LoadVarOp::get_src_type(const TypeState& input,
case 4:
case 8:
return TP_Type::make_from_ts(TypeSpec("uint"));
case 16:
return TP_Type::make_from_ts(TypeSpec("uint128"));
default:
break;
}
@@ -710,6 +712,8 @@ TP_Type LoadVarOp::get_src_type(const TypeState& input,
case 4:
case 8:
return TP_Type::make_from_ts(TypeSpec("int"));
case 16:
return TP_Type::make_from_ts(TypeSpec("int128"));
default:
break;
}
+1 -1
View File
@@ -254,7 +254,7 @@ void ObjectFileDB::ir2_atomic_op_pass() {
func.ir2.atomic_ops_attempted = true;
attempted++;
try {
auto ops = convert_function_to_atomic_ops(func, data.linked_data.labels);
auto ops = convert_function_to_atomic_ops(func, data.linked_data.labels, func.warnings);
func.ir2.atomic_ops = std::make_shared<FunctionAtomicOps>(std::move(ops));
func.ir2.atomic_ops_succeeded = true;
func.ir2.env.set_end_var(func.ir2.atomic_ops->end_op().return_var());
+15 -3
View File
@@ -5,6 +5,7 @@
#include "decompiler/Function/Function.h"
#include "decompiler/Disasm/InstructionMatching.h"
#include "decompiler/util/TP_Type.h"
#include "decompiler/Function/Warnings.h"
namespace decompiler {
@@ -716,6 +717,8 @@ std::unique_ptr<AtomicOp> convert_1(const Instruction& i0, int idx) {
return convert_lw_1(i0, idx);
case InstructionKind::LD:
return make_standard_load(i0, idx, 8, LoadVarOp::Kind::UNSIGNED);
case InstructionKind::LQ:
return make_standard_load(i0, idx, 16, LoadVarOp::Kind::UNSIGNED);
case InstructionKind::DSLL:
return make_2reg_1imm_op(i0, SimpleExpression::Kind::LEFT_SHIFT, idx);
case InstructionKind::DSLL32:
@@ -778,6 +781,8 @@ std::unique_ptr<AtomicOp> convert_1(const Instruction& i0, int idx) {
return convert_sw_1(i0, idx);
case InstructionKind::SD:
return convert_sd_1(i0, idx);
case InstructionKind::SQ:
return make_standard_store(i0, idx, 16, false);
case InstructionKind::SWC1:
return make_standard_store(i0, idx, 4, true);
case InstructionKind::CVTWS: // float to int
@@ -1378,7 +1383,8 @@ int convert_block_to_atomic_ops(int begin_idx,
std::vector<Instruction>::const_iterator begin,
std::vector<Instruction>::const_iterator end,
const std::vector<DecompilerLabel>& labels,
FunctionAtomicOps* container) {
FunctionAtomicOps* container,
DecompWarnings& warnings) {
container->block_id_to_first_atomic_op.push_back(container->ops.size());
for (auto& instr = begin; instr < end;) {
// how many instructions can we look at, at most?
@@ -1391,6 +1397,10 @@ int convert_block_to_atomic_ops(int begin_idx,
bool converted = false;
std::unique_ptr<AtomicOp> op;
if (instr[0].kind == InstructionKind::SQ || instr[0].kind == InstructionKind::LQ) {
warnings.warn_sq_lq();
}
if (n_instr >= 5) {
// try 5 instructions
op = convert_5(instr[0], instr[1], instr[2], instr[3], instr[4], op_idx);
@@ -1469,7 +1479,8 @@ int convert_block_to_atomic_ops(int begin_idx,
}
FunctionAtomicOps convert_function_to_atomic_ops(const Function& func,
const std::vector<DecompilerLabel>& labels) {
const std::vector<DecompilerLabel>& labels,
DecompWarnings& warnings) {
FunctionAtomicOps result;
int last_op = 0;
@@ -1479,7 +1490,8 @@ FunctionAtomicOps convert_function_to_atomic_ops(const Function& func,
if (block.end_word > block.start_word) {
auto begin = func.instructions.begin() + block.start_word;
auto end = func.instructions.begin() + block.end_word;
last_op = convert_block_to_atomic_ops(block.start_word, begin, end, labels, &result);
last_op =
convert_block_to_atomic_ops(block.start_word, begin, end, labels, &result, warnings);
if (i == int(func.basic_blocks.size()) - 1) {
// we're the last block. insert the function end op.
result.ops.push_back(std::make_unique<FunctionEndOp>(int(result.ops.size())));
+5 -2
View File
@@ -6,6 +6,7 @@ namespace decompiler {
class Function;
struct BasicBlock;
class LinkedObjectFile;
class DecompWarnings;
/*!
* A collection of Atomic Ops in a function
@@ -45,11 +46,13 @@ int convert_block_to_atomic_ops(int begin_idx,
std::vector<Instruction>::const_iterator begin,
std::vector<Instruction>::const_iterator end,
const std::vector<DecompilerLabel>& labels,
FunctionAtomicOps* container);
FunctionAtomicOps* container,
DecompWarnings& warnings);
/*!
* Convert an entire function to AtomicOps
*/
FunctionAtomicOps convert_function_to_atomic_ops(const Function& func,
const std::vector<DecompilerLabel>& labels);
const std::vector<DecompilerLabel>& labels,
DecompWarnings& warnings);
} // namespace decompiler
+7 -4
View File
@@ -1238,7 +1238,7 @@
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
(deftype quaternion (structure)
((data float 4 :offset-assert 0)
((data float 4 :do-not-decompile :offset-assert 0)
(x float :offset 0)
(y float :offset 4)
(z float :offset 8)
@@ -1251,6 +1251,8 @@
:flag-assert #x900000010
)
(define-extern *unity-quaternion* quaternion)
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; EULER-H ;;;;;;;;;;;;;;;;;;;;;;
@@ -1264,6 +1266,9 @@
:flag-assert #x900000010
)
(define-extern EulNext (array int32))
(define-extern EulSafe (array int32))
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; TRANSFORM-H ;;;;;;;;;;;;;;;;;;;;;;
@@ -32495,11 +32500,9 @@
;;(define-extern matrix3 object) ;; unknown type
;;(define-extern matrix object) ;; unknown type
;;(define-extern *unity-quaternion* object) ;; unknown type
;;(define-extern quaternion object) ;; unknown type
;;(define-extern euler-angles object) ;; unknown type
;;(define-extern EulNext object) ;; unknown type
;;(define-extern EulSafe object) ;; unknown type
;;(define-extern transform object) ;; unknown type
;;(define-extern trs object) ;; unknown type
;;(define-extern border-plane object) ;; unknown type
@@ -38,6 +38,13 @@
["L26", "vector", true]
],
"quaternion-h": [["L1", "quaternion", true]],
"euler-h": [
["L3", "_auto_", true],
["L2", "_auto_", true]
],
"trigonometry": [
["L143", "float", true],
["L144", "float", true],
@@ -165,7 +165,7 @@
},
"qmem-copy->!":{
"args":["dst", "src", "size"],
"vars":{"v0-0":"result", "v1-1":"qwc", "a0-1":"src-ptr", "a1-1":"dst-ptr", "a2-3":"value"}
"vars":{"v0-0":"result", "v1-1":"qwc", "a1-1":"src-ptr", "a0-1":"dst-ptr", "a2-3":"value"}
},
"mem-set32!":{
"args":["dst", "size", "value"],
+12 -17
View File
@@ -40,21 +40,16 @@
:flag-assert #x900000020
)
(defun matrix-copy! ((dst matrix) (src matrix))
"Copy src to dst."
(rlet ((r0 :class vf)
(r1 :class vf)
(r2 :class vf)
(r3 :class vf)
)
(.lvf r0 (&-> src quad 0))
(.lvf r1 (&-> src quad 1))
(.lvf r2 (&-> src quad 2))
(.lvf r3 (&-> src quad 3))
(.svf (&-> dst quad 0) r0)
(.svf (&-> dst quad 1) r1)
(.svf (&-> dst quad 2) r2)
(.svf (&-> dst quad 3) r3)
)
dst
(defun matrix-copy! ((arg0 matrix) (arg1 matrix))
(let ((v1-0 (-> arg1 vector 0 quad))
(a2-0 (-> arg1 vector 1 quad))
(a3-0 (-> arg1 vector 2 quad))
(a1-1 (-> arg1 vector 3 quad))
)
(set! (-> arg0 vector 0 quad) v1-0)
(set! (-> arg0 vector 1 quad) a2-0)
(set! (-> arg0 vector 2 quad) a3-0)
(set! (-> arg0 vector 3 quad) a1-1)
)
arg0
)
+1 -1
View File
@@ -6,7 +6,7 @@
;; dgos: GAME, ENGINE
(deftype quaternion (structure)
((data float 4 :offset-assert 0)
((data float 4 :do-not-decompile :offset-assert 0)
(x float :offset 0)
(y float :offset 4)
(z float :offset 8)
+24 -2
View File
@@ -32,13 +32,26 @@ RegVal* Val::to_fpr(Env* fe) {
}
}
/*!
* Fallback to_xmm128 if a more optimized one is not provided.
*/
RegVal* Val::to_xmm128(Env* fe) {
auto rv = to_reg(fe);
if (rv->ireg().reg_class == RegClass::INT_128 || rv->ireg().reg_class == RegClass::VECTOR_FLOAT) {
return rv;
} else {
auto re = fe->make_ireg(coerce_to_reg_type(m_ts), RegClass::INT_128);
fe->emit(std::make_unique<IR_RegSet>(re, rv));
return re;
}
}
RegVal* RegVal::to_reg(Env* fe) {
(void)fe;
return this;
}
RegVal* RegVal::to_gpr(Env* fe) {
(void)fe;
if (m_ireg.reg_class == RegClass::GPR_64) {
return this;
} else {
@@ -49,7 +62,6 @@ RegVal* RegVal::to_gpr(Env* fe) {
}
RegVal* RegVal::to_fpr(Env* fe) {
(void)fe;
if (m_ireg.reg_class == RegClass::FLOAT) {
return this;
} else {
@@ -59,6 +71,16 @@ RegVal* RegVal::to_fpr(Env* fe) {
}
}
RegVal* RegVal::to_xmm128(Env* fe) {
if (m_ireg.reg_class == RegClass::INT_128 || m_ireg.reg_class == RegClass::VECTOR_FLOAT) {
return this;
} else {
auto re = fe->make_ireg(coerce_to_reg_type(m_ts), RegClass::INT_128);
fe->emit(std::make_unique<IR_RegSet>(re, this));
return re;
}
}
void RegVal::set_rlet_constraint(emitter::Register reg) {
m_rlet_constraint = reg;
}
+9 -1
View File
@@ -41,6 +41,7 @@ class Val {
}
virtual RegVal* to_gpr(Env* fe);
virtual RegVal* to_fpr(Env* fe);
virtual RegVal* to_xmm128(Env* fe);
const TypeSpec& type() const { return m_ts; }
void set_type(TypeSpec ts) { m_ts = std::move(ts); }
@@ -75,6 +76,7 @@ class RegVal : public Val {
RegVal* to_reg(Env* fe) override;
RegVal* to_gpr(Env* fe) override;
RegVal* to_fpr(Env* fe) override;
RegVal* to_xmm128(Env* fe) override;
void set_rlet_constraint(emitter::Register reg);
const std::optional<emitter::Register>& rlet_constraint() const;
@@ -182,7 +184,13 @@ class StackVarAddrVal : public Val {
class MemoryOffsetConstantVal : public Val {
public:
MemoryOffsetConstantVal(TypeSpec ts, Val* _base, s64 _offset)
: Val(std::move(ts)), base(_base), offset(_offset) {}
: Val(std::move(ts)), base(_base), offset(_offset) {
auto base_as_offset = dynamic_cast<MemoryOffsetConstantVal*>(base);
if (base_as_offset) {
offset += base_as_offset->offset;
base = base_as_offset->base;
}
}
std::string print() const override {
return "(" + base->print() + " + " + std::to_string(offset) + ")";
}
+8
View File
@@ -161,6 +161,14 @@ Val* Compiler::do_set(const goos::Object& form, Val* dest, RegVal* src_in_reg, V
typecheck_reg_type_allow_false(form, dest_type, src, "set! memory");
}
// we want to allow setting a 128-bit field from a 64-bit variable.
if (as_mem_deref->info.size == 16) {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto src_128 = fe->make_ireg(src_in_reg->type(), RegClass::INT_128);
env->emit_ir<IR_RegSet>(src_128, src_in_reg);
src_in_reg = src_128;
}
// setting somewhere in memory
auto base = as_mem_deref->base;
auto base_as_mco = dynamic_cast<MemoryOffsetConstantVal*>(base);
+2 -1
View File
@@ -146,7 +146,8 @@ std::unique_ptr<FormRegressionTest::TestData> FormRegressionTest::make_function(
fmt::print("CFG:\n{}\n", test->func.cfg->to_dot());
}
auto ops = convert_function_to_atomic_ops(test->func, program.labels);
DecompWarnings warnings;
auto ops = convert_function_to_atomic_ops(test->func, program.labels, warnings);
test->func.ir2.atomic_ops = std::make_shared<FunctionAtomicOps>(std::move(ops));
test->func.ir2.atomic_ops_succeeded = true;
test->func.ir2.env.set_end_var(test->func.ir2.atomic_ops->end_op().return_var());
+43
View File
@@ -0,0 +1,43 @@
;;-*-Lisp-*-
(in-package goal)
;; definition for symbol EulSafe, type (array int32)
(define
EulSafe
(the-as (array int32) (new 'static 'boxed-array int32 4 0 1 2 0))
)
;; definition for symbol EulNext, type (array int32)
(define
EulNext
(the-as (array int32) (new 'static 'boxed-array int32 4 1 2 0 1))
)
;; definition of type euler-angles
(deftype euler-angles (vector)
()
:method-count-assert 9
:size-assert #x10
:flag-assert #x900000010
)
;; definition for method 3 of type euler-angles
;; Used lq/sq
(defmethod inspect euler-angles ((obj euler-angles))
(format #t "[~8x] ~A~%" obj 'euler-angles)
(format #t "~Tdata[4] @ #x~X~%" (-> obj data))
(format #t "~Tx: ~f~%" (-> obj data 0))
(format #t "~Ty: ~f~%" (-> obj data 1))
(format #t "~Tz: ~f~%" (-> obj data 2))
(format #t "~Tw: ~f~%" (-> obj data 3))
(format #t "~Tquad: ~D~%" (-> obj quad))
obj
)
;; failed to figure out what this is:
(let ((v0-1 0))
)
;; failed to figure out what this is:
(none)
+25 -39
View File
@@ -626,9 +626,8 @@
)
;; definition for method 2 of type array
;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ]
;; Used lq/sq
(defmethod print array ((obj array))
(local-vars (a2-8 int))
(format #t "#(")
(if (type-type? (-> obj content-type) integer)
(let ((content-type-sym (-> obj content-type symbol)))
@@ -717,19 +716,11 @@
(cond
((or (= content-type-sym 'uint128) (= content-type-sym 'int128))
(dotimes (s5-8 (-> obj length))
(let ((t9-10 format)
(a0-21 #t)
(a1-11 (if (zero? s5-8)
"#x~X"
" #x~X"
)
)
)
(let
((v1-42 (+ (shl s5-8 4) (the-as int (the-as (array uint128) obj)))))
(TODO.LQ a2-8 v1-42 :offset 12)
)
(t9-10 a0-21 a1-11 a2-8)
(format #t (if (zero? s5-8)
"#x~X"
" #x~X"
)
(-> (the-as (array uint128) obj) s5-8)
)
)
)
@@ -771,9 +762,8 @@
)
;; definition for method 3 of type array
;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ]
;; Used lq/sq
(defmethod inspect array ((obj array))
(local-vars (a3-10 int))
(format #t "[~8x] ~A~%" obj (-> obj type))
(format #t "~Tallocated-length: ~D~%" (-> obj allocated-length))
(format #t "~Tlength: ~D~%" (-> obj length))
@@ -826,15 +816,11 @@
(cond
((or (= content-type-sym 'int128) (= content-type-sym 'uint128))
(dotimes (s5-8 (-> obj length))
(let ((t9-14 format)
(a0-25 #t)
(a1-15 "~T [~D] #x~X~%")
(a2-13 s5-8)
)
(let ((v1-42 (+ (shl s5-8 4) (the-as int obj))))
(TODO.LQ a3-10 v1-42 :offset 12)
)
(t9-14 a0-25 a1-15 a2-13 a3-10)
(format
#t
"~T [~D] #x~X~%"
s5-8
(-> (the-as (pointer uint128) (+ (shl s5-8 4) (the-as int obj))))
)
)
)
@@ -900,16 +886,16 @@
)
;; definition for function qmem-copy<-!
;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ]
;; WARN: Inline assembly instruction marked with TODO - [TODO.SQ]
;; Used lq/sq
(defun qmem-copy<-! ((dst pointer) (src pointer) (size int))
(local-vars (value int))
(let ((result dst))
(let ((qwc (sar (+ size 15) 4)))
(while (nonzero? qwc)
(+! qwc -1)
(TODO.LQ value src)
(TODO.SQ value dst)
(set!
(-> (the-as (pointer uint128) dst))
(-> (the-as (pointer uint128) src))
)
(&+! dst 16)
(&+! src 16)
)
@@ -919,21 +905,21 @@
)
;; definition for function qmem-copy->!
;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ]
;; WARN: Inline assembly instruction marked with TODO - [TODO.SQ]
;; Used lq/sq
(defun qmem-copy->! ((dst pointer) (src pointer) (size int))
(local-vars (value int))
(let ((result dst))
(let* ((qwc (sar (+ size 15) 4))
(src-ptr (&+ dst (shl qwc 4)))
(dst-ptr (&+ src (shl qwc 4)))
(dst-ptr (&+ dst (shl qwc 4)))
(src-ptr (&+ src (shl qwc 4)))
)
(while (nonzero? qwc)
(+! qwc -1)
(&+! src-ptr -16)
(&+! dst-ptr -16)
(TODO.LQ value dst-ptr)
(TODO.SQ value src-ptr)
(&+! src-ptr -16)
(set!
(-> (the-as (pointer uint128) dst-ptr))
(-> (the-as (pointer uint128) src-ptr))
)
)
)
result
@@ -0,0 +1,62 @@
;;-*-Lisp-*-
(in-package goal)
;; definition of type curve
(deftype curve (structure)
((cverts uint32 :offset-assert 0)
(num-cverts int32 :offset-assert 4)
(knots uint32 :offset-assert 8)
(num-knots int32 :offset-assert 12)
(length float :offset-assert 16)
)
:method-count-assert 9
:size-assert #x14
:flag-assert #x900000014
)
;; definition for method 3 of type curve
(defmethod inspect curve ((obj curve))
(format #t "[~8x] ~A~%" obj 'curve)
(format #t "~Tcverts: #x~X~%" (-> obj cverts))
(format #t "~Tnum-cverts: ~D~%" (-> obj num-cverts))
(format #t "~Tknots: #x~X~%" (-> obj knots))
(format #t "~Tnum-knots: ~D~%" (-> obj num-knots))
(format #t "~Tlength: ~f~%" (-> obj length))
obj
)
;; definition of type border-plane
(deftype border-plane (basic)
((name basic :offset-assert 4)
(action basic :offset-assert 8)
(slot int8 :offset-assert 12)
(trans vector :inline :offset-assert 16)
(normal vector :inline :offset-assert 32)
)
:method-count-assert 11
:size-assert #x30
:flag-assert #xb00000030
(:methods
(dummy-9 () none 9)
(dummy-10 () none 10)
)
)
;; definition for method 3 of type border-plane
(defmethod inspect border-plane ((obj border-plane))
(format #t "[~8x] ~A~%" obj (-> obj type))
(format #t "~Tname: ~A~%" (-> obj name))
(format #t "~Taction: ~A~%" (-> obj action))
(format #t "~Tslot: ~D~%" (-> obj slot))
(format #t "~Ttrans: ~`vector`P~%" (-> obj trans))
(format #t "~Tnormal: ~`vector`P~%" (-> obj normal))
obj
)
;; failed to figure out what this is:
(let ((v0-2 0))
)
;; failed to figure out what this is:
(none)
+85
View File
@@ -0,0 +1,85 @@
;;-*-Lisp-*-
(in-package goal)
;; definition of type matrix
(deftype matrix (structure)
((data float 16 :offset-assert 0)
(vector vector 4 :inline :offset 0)
(quad uint128 4 :offset 0)
)
:method-count-assert 10
:size-assert #x40
:flag-assert #xa00000040
(:methods
(dummy-9 () none 9)
)
)
;; definition for method 3 of type matrix
(defmethod inspect matrix ((obj matrix))
(format #t "[~8x] ~A~%" obj 'matrix)
(format #t "~Tdata[16] @ #x~X~%" (-> obj data))
(format #t "~Tvector[4] @ #x~X~%" (-> obj data))
(format #t "~Tquad[4] @ #x~X~%" (-> obj data))
obj
)
;; definition of type matrix3
(deftype matrix3 (structure)
((data float 12 :offset-assert 0)
(vector vector 3 :inline :offset 0)
(quad uint128 3 :offset 0)
)
:method-count-assert 9
:size-assert #x30
:flag-assert #x900000030
)
;; definition for method 3 of type matrix3
(defmethod inspect matrix3 ((obj matrix3))
(format #t "[~8x] ~A~%" obj 'matrix3)
(format #t "~Tdata[12] @ #x~X~%" (-> obj data))
(format #t "~Tvector[3] @ #x~X~%" (-> obj data))
(format #t "~Tquad[3] @ #x~X~%" (-> obj data))
obj
)
;; definition of type matrix4h
(deftype matrix4h (structure)
((data int16 16 :offset-assert 0)
(vector4h vector4h 4 :inline :offset 0)
(long int64 4 :offset 0)
)
:method-count-assert 9
:size-assert #x20
:flag-assert #x900000020
)
;; definition for method 3 of type matrix4h
(defmethod inspect matrix4h ((obj matrix4h))
(format #t "[~8x] ~A~%" obj 'matrix4h)
(format #t "~Tdata[16] @ #x~X~%" (-> obj data))
(format #t "~Tvector4h[4] @ #x~X~%" (-> obj data))
(format #t "~Tlong[4] @ #x~X~%" (-> obj data))
obj
)
;; definition for function matrix-copy!
;; Used lq/sq
(defun matrix-copy! ((arg0 matrix) (arg1 matrix))
(let ((v1-0 (-> arg1 vector 0 quad))
(a2-0 (-> arg1 vector 1 quad))
(a3-0 (-> arg1 vector 2 quad))
(a1-1 (-> arg1 vector 3 quad))
)
(set! (-> arg0 vector 0 quad) v1-0)
(set! (-> arg0 vector 1 quad) a2-0)
(set! (-> arg0 vector 2 quad) a3-0)
(set! (-> arg0 vector 3 quad) a1-1)
)
arg0
)
;; failed to figure out what this is:
(none)
@@ -0,0 +1,41 @@
;;-*-Lisp-*-
(in-package goal)
;; definition of type quaternion
(deftype quaternion (structure)
((data float 4 :offset-assert 0)
(x float :offset 0)
(y float :offset 4)
(z float :offset 8)
(w float :offset 12)
(vec vector :inline :offset 0)
(quad uint128 :offset 0)
)
:method-count-assert 9
:size-assert #x10
:flag-assert #x900000010
)
;; definition for method 3 of type quaternion
;; Used lq/sq
(defmethod inspect quaternion ((obj quaternion))
(format #t "[~8x] ~A~%" obj 'quaternion)
(format #t "~Tdata[4] @ #x~X~%" (-> obj data))
(format #t "~Tx: ~f~%" (-> obj data 0))
(format #t "~Ty: ~f~%" (-> obj data 1))
(format #t "~Tz: ~f~%" (-> obj data 2))
(format #t "~Tw: ~f~%" (-> obj data 3))
(format #t "~Tvec: #<vector @ #x~X>~%" (-> obj data))
(format #t "~Tquad: ~D~%" (-> obj vec quad))
obj
)
;; definition for symbol *unity-quaternion*, type quaternion
(define *unity-quaternion* (new 'static 'quaternion :w 1.0))
;; failed to figure out what this is:
(let ((v0-1 0))
)
;; failed to figure out what this is:
(none)
@@ -0,0 +1,50 @@
;;-*-Lisp-*-
(in-package goal)
;; definition of type transform
(deftype transform (structure)
((trans vector :inline :offset-assert 0)
(rot vector :inline :offset-assert 16)
(scale vector :inline :offset-assert 32)
)
:method-count-assert 9
:size-assert #x30
:flag-assert #x900000030
)
;; definition for method 3 of type transform
(defmethod inspect transform ((obj transform))
(format #t "[~8x] ~A~%" obj 'transform)
(format #t "~Ttrans: ~`vector`P~%" (-> obj trans))
(format #t "~Trot: ~`vector`P~%" (-> obj rot))
(format #t "~Tscale: ~`vector`P~%" (-> obj scale))
obj
)
;; definition of type trs
(deftype trs (basic)
((trans vector :inline :offset-assert 16)
(rot vector :inline :offset-assert 32)
(scale vector :inline :offset-assert 48)
)
:method-count-assert 9
:size-assert #x40
:flag-assert #x900000040
)
;; definition for method 3 of type trs
(defmethod inspect trs ((obj trs))
(format #t "[~8x] ~A~%" obj (-> obj type))
(format #t "~Ttrans: ~`vector`P~%" (-> obj trans))
(format #t "~Trot: ~`vector`P~%" (-> obj rot))
(format #t "~Tscale: ~`vector`P~%" (-> obj scale))
obj
)
;; failed to figure out what this is:
(let ((v0-2 0))
)
;; failed to figure out what this is:
(none)
@@ -0,0 +1,10 @@
;;-*-Lisp-*-
(in-package goal)
;; failed to figure out what this is:
(let ((v0-0 0))
)
;; failed to figure out what this is:
(none)
+20 -80
View File
@@ -282,9 +282,8 @@
)
;; definition for method 3 of type vector4w
;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ]
;; Used lq/sq
(defmethod inspect vector4w ((obj vector4w))
(local-vars (a2-7 int))
(format #t "[~8x] ~A~%" obj 'vector4w)
(format #t "~Tdata[4] @ #x~X~%" (-> obj data))
(format #t "~Tx: ~D~%" (-> obj data 0))
@@ -292,13 +291,7 @@
(format #t "~Tz: ~D~%" (-> obj data 2))
(format #t "~Tw: ~D~%" (-> obj data 3))
(format #t "~Tdword[2] @ #x~X~%" (-> obj data))
(let ((t9-7 format)
(a0-8 #t)
(a1-7 "~Tquad: ~D~%")
)
(TODO.LQ a2-7 obj)
(t9-7 a0-8 a1-7 a2-7)
)
(format #t "~Tquad: ~D~%" (-> obj quad))
obj
)
@@ -414,18 +407,11 @@
)
;; definition for method 3 of type vector8h
;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ]
;; Used lq/sq
(defmethod inspect vector8h ((obj vector8h))
(local-vars (a2-2 int))
(format #t "[~8x] ~A~%" obj 'vector8h)
(format #t "~Tdata[8] @ #x~X~%" (-> obj data))
(let ((t9-2 format)
(a0-3 #t)
(a1-2 "~Tquad: ~D~%")
)
(TODO.LQ a2-2 obj)
(t9-2 a0-3 a1-2 a2-2)
)
(format #t "~Tquad: ~D~%" (-> obj quad))
obj
)
@@ -440,18 +426,11 @@
)
;; definition for method 3 of type vector16b
;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ]
;; Used lq/sq
(defmethod inspect vector16b ((obj vector16b))
(local-vars (a2-2 int))
(format #t "[~8x] ~A~%" obj 'vector16b)
(format #t "~Tdata[8] @ #x~X~%" (-> obj data))
(let ((t9-2 format)
(a0-3 #t)
(a1-2 "~Tquad: ~D~%")
)
(TODO.LQ a2-2 obj)
(t9-2 a0-3 a1-2 a2-2)
)
(format #t "~Tquad: ~D~%" (-> obj quad))
obj
)
@@ -471,22 +450,15 @@
;; definition for method 3 of type vector
;; INFO: this function exists in multiple non-identical object files
;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ]
;; Used lq/sq
(defmethod inspect vector ((obj vector))
(local-vars (a2-6 int))
(format #t "[~8x] ~A~%" obj 'vector)
(format #t "~Tdata[4] @ #x~X~%" (-> obj data))
(format #t "~Tx: ~f~%" (-> obj data 0))
(format #t "~Ty: ~f~%" (-> obj data 1))
(format #t "~Tz: ~f~%" (-> obj data 2))
(format #t "~Tw: ~f~%" (-> obj data 3))
(let ((t9-6 format)
(a0-7 #t)
(a1-6 "~Tquad: ~D~%")
)
(TODO.LQ a2-6 obj)
(t9-6 a0-7 a1-6 a2-6)
)
(format #t "~Tquad: ~D~%" (-> obj quad))
obj
)
@@ -590,22 +562,15 @@
)
;; definition for method 3 of type rgbaf
;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ]
;; Used lq/sq
(defmethod inspect rgbaf ((obj rgbaf))
(local-vars (a2-6 int))
(format #t "[~8x] ~A~%" obj 'rgbaf)
(format #t "~Tdata[4] @ #x~X~%" (-> obj data))
(format #t "~Tx: ~f~%" (-> obj data 0))
(format #t "~Ty: ~f~%" (-> obj data 1))
(format #t "~Tz: ~f~%" (-> obj data 2))
(format #t "~Tw: ~f~%" (-> obj data 3))
(let ((t9-6 format)
(a0-7 #t)
(a1-6 "~Tquad: ~D~%")
)
(TODO.LQ a2-6 obj)
(t9-6 a0-7 a1-6 a2-6)
)
(format #t "~Tquad: ~D~%" (-> obj quad))
(format #t "~Tr: ~f~%" (-> obj data 0))
(format #t "~Tg: ~f~%" (-> obj data 1))
(format #t "~Tb: ~f~%" (-> obj data 2))
@@ -626,22 +591,15 @@
)
;; definition for method 3 of type plane
;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ]
;; Used lq/sq
(defmethod inspect plane ((obj plane))
(local-vars (a2-6 int))
(format #t "[~8x] ~A~%" obj 'plane)
(format #t "~Tdata[4] @ #x~X~%" (-> obj data))
(format #t "~Tx: ~f~%" (-> obj data 0))
(format #t "~Ty: ~f~%" (-> obj data 1))
(format #t "~Tz: ~f~%" (-> obj data 2))
(format #t "~Tw: ~f~%" (-> obj data 3))
(let ((t9-6 format)
(a0-7 #t)
(a1-6 "~Tquad: ~D~%")
)
(TODO.LQ a2-6 obj)
(t9-6 a0-7 a1-6 a2-6)
)
(format #t "~Tquad: ~D~%" (-> obj quad))
(format #t "~Ta: ~f~%" (-> obj data 0))
(format #t "~Tb: ~f~%" (-> obj data 1))
(format #t "~Tc: ~f~%" (-> obj data 2))
@@ -659,22 +617,15 @@
)
;; definition for method 3 of type sphere
;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ]
;; Used lq/sq
(defmethod inspect sphere ((obj sphere))
(local-vars (a2-6 int))
(format #t "[~8x] ~A~%" obj 'sphere)
(format #t "~Tdata[4] @ #x~X~%" (-> obj data))
(format #t "~Tx: ~f~%" (-> obj data 0))
(format #t "~Ty: ~f~%" (-> obj data 1))
(format #t "~Tz: ~f~%" (-> obj data 2))
(format #t "~Tw: ~f~%" (-> obj data 3))
(let ((t9-6 format)
(a0-7 #t)
(a1-6 "~Tquad: ~D~%")
)
(TODO.LQ a2-6 obj)
(t9-6 a0-7 a1-6 a2-6)
)
(format #t "~Tquad: ~D~%" (-> obj quad))
(format #t "~Tr: ~f~%" (-> obj data 3))
obj
)
@@ -834,22 +785,15 @@
)
;; definition for method 3 of type qword
;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ]
;; Used lq/sq
(defmethod inspect qword ((obj qword))
(local-vars (a2-6 int))
(format #t "[~8x] ~A~%" obj 'qword)
(format #t "~Tdata[4] @ #x~X~%" (-> obj data))
(format #t "~Tbyte[16] @ #x~X~%" (-> obj data))
(format #t "~Thword[8] @ #x~X~%" (-> obj data))
(format #t "~Tword[4] @ #x~X~%" (-> obj data))
(format #t "~Tdword[2] @ #x~X~%" (-> obj data))
(let ((t9-6 format)
(a0-7 #t)
(a1-6 "~Tquad: ~D~%")
)
(TODO.LQ a2-6 obj)
(t9-6 a0-7 a1-6 a2-6)
)
(format #t "~Tquad: ~D~%" (-> obj quad))
(format #t "~Tvector: #<vector @ #x~X>~%" (-> obj data))
(format #t "~Tvector4w: #<vector4w @ #x~X>~%" (-> obj data))
obj
@@ -999,10 +943,9 @@
)
;; definition for function vector-zero!
;; WARN: Inline assembly instruction marked with TODO - [TODO.SQ]
;; Used lq/sq
(defun vector-zero! ((arg0 vector))
(local-vars (r0-0 none))
(TODO.SQ r0-0 arg0)
(set! (-> arg0 quad) (the-as uint128 0))
arg0
)
@@ -1016,12 +959,9 @@
)
;; definition for function vector-copy!
;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ]
;; WARN: Inline assembly instruction marked with TODO - [TODO.SQ]
;; Used lq/sq
(defun vector-copy! ((arg0 vector) (arg1 vector))
(local-vars (v1-0 int))
(TODO.LQ v1-0 arg1)
(TODO.SQ v1-0 arg0)
(set! (-> arg0 quad) (-> arg1 quad))
arg0
)
+6 -3
View File
@@ -1,10 +1,11 @@
#include <regex>
#include "gtest/gtest.h"
#include "decompiler/IR2/AtomicOp.h"
#include "decompiler/analysis/atomic_op_builder.h"
#include "decompiler/Disasm/InstructionParser.h"
#include "third-party/fmt/core.h"
#include "third-party/fmt/format.h"
#include <regex>
#include "decompiler/Function/Warnings.h"
using namespace decompiler;
@@ -42,8 +43,9 @@ void test_case(std::string assembly_lines,
FunctionAtomicOps container;
// treat the entire program as a single basic block, and convert!
DecompWarnings warnings;
convert_block_to_atomic_ops(0, prg.instructions.begin(), prg.instructions.end(), prg.labels,
&container);
&container, warnings);
// count operations
EXPECT_EQ(container.ops.size(), output_lines.size());
@@ -126,8 +128,9 @@ TEST(DecompilerAtomicOpBuilder, RegUseDuplication) {
ParsedProgram prg = parser.parse_program(assembly);
EXPECT_EQ(prg.print(), assembly);
FunctionAtomicOps container;
DecompWarnings warnings;
convert_block_to_atomic_ops(0, prg.instructions.begin(), prg.instructions.end(), prg.labels,
&container);
&container, warnings);
ASSERT_EQ(1, container.ops.size());
auto& op = container.ops.at(0);
for (const auto& reg_group : {op->read_regs(), op->write_regs(), op->clobber_regs()}) {
+4 -2
View File
@@ -2618,8 +2618,10 @@ TEST_F(FormRegressionTest, QMemCpy) {
" (+! v1-1 -1)\n"
" (&+! a0-1 -16)\n"
" (&+! a1-1 -16)\n"
" (.lq a2-3 0 a1-1)\n"
" (.sq a2-3 0 a0-1)\n"
" (set!\n"
" (-> (the-as (pointer uint128) a0-1))\n"
" (-> (the-as (pointer uint128) a1-1))\n"
" )\n"
" )\n"
" )\n"
" v0-0\n"
@@ -627,18 +627,15 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
" (else\n"
" (cond\n"
" ((or (= v1-1 (quote uint128)) (= v1-1 (quote int128)))\n"
" (dotimes\n"
" (s5-8 (-> arg0 length))\n"
" (let\n"
" ((t9-10 format) (a0-21 #t) (a1-11 (if (zero? s5-8) \"#x~X\" \" #x~X\")))\n"
" (let\n"
" ((v1-42 (+ (shl s5-8 4) (the-as int (the-as (array uint128) arg0)))))\n"
" (.lq a2-8 12 v1-42)\n"
" )\n"
" (t9-10 a0-21 a1-11 a2-8)\n"
" (dotimes (s5-8 (-> arg0 length))\n"
" (format #t (if (zero? s5-8)\n"
" \"#x~X\"\n"
" \" #x~X\"\n"
" )\n"
" (-> (the-as (array uint128) arg0) s5-8)\n"
" )\n"
" )\n"
" )\n"
" )"
" (else\n"
" (dotimes\n"
" (s5-9 (-> arg0 length))\n"
@@ -1223,18 +1220,15 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
" (else\n"
" (cond\n"
" ((or (= v1-1 (quote int128)) (= v1-1 (quote uint128)))\n"
" (dotimes\n"
" (s5-8 (-> arg0 length))\n"
" (let\n"
" ((t9-14 format) (a0-25 #t) (a1-15 \"~T [~D] #x~X~%\") (a2-13 s5-8))\n"
" (let\n"
" ((v1-42 (+ (shl s5-8 4) (the-as int (the-as (array uint128) arg0)))))\n"
" (.lq a3-10 12 v1-42)\n"
" )\n"
" (t9-14 a0-25 a1-15 a2-13 a3-10)\n"
" (dotimes (s5-8 (-> arg0 length))\n"
" (format\n"
" #t\n"
" \"~T [~D] #x~X~%\"\n"
" s5-8\n"
" (-> (the-as (array uint128) arg0) s5-8)\n"
" )\n"
" )\n"
" )\n"
" )"
" (else\n"
" (dotimes\n"
" (s5-9 (-> arg0 length))\n"
+30 -31
View File
@@ -10,25 +10,35 @@
namespace {
// the object files to test
const std::unordered_set<std::string> g_object_files_to_decompile = {"gcommon",
"gstring-h",
"gkernel-h",
"gkernel",
/*"pskernel",*/ "gstring",
"dgo-h",
"gstate",
"types-h",
"vu1-macros",
"math",
"vector-h",
"bounding-box-h",
/* gap */ "bounding-box"};
const std::unordered_set<std::string> g_object_files_to_decompile = {
"gcommon", "gstring-h", "gkernel-h", "gkernel",
/*"pskernel",*/ "gstring", "dgo-h", "gstate", "types-h", "vu1-macros", "math", "vector-h",
"bounding-box-h", "matrix-h", "quaternion-h", "euler-h", "transform-h", "geometry-h",
"trigonometry-h",
/* gap */
"bounding-box"};
// the object files to check against a reference in test/decompiler/reference
const std::vector<std::string> g_object_files_to_check_against_reference = {
"gcommon", // NOTE: this file needs work, but adding it for now just to test the framework.
"gstring-h", "gkernel-h", "gkernel", "gstring", "dgo-h", "gstate",
"types-h", "vu1-macros", "math", "vector-h", "bounding-box-h", /* gap */ "bounding-box"};
"gstring-h",
"gkernel-h",
"gkernel",
"gstring",
"dgo-h",
"gstate",
"types-h",
"vu1-macros",
"math",
"vector-h",
"bounding-box-h",
"matrix-h",
"quaternion-h",
"euler-h",
"transform-h",
"geometry-h",
"trigonometry-h",
/* gap */ "bounding-box"};
// the functions we expect the decompiler to skip
const std::unordered_set<std::string> expected_skip_in_decompiler = {
@@ -64,10 +74,8 @@ const std::unordered_set<std::string> skip_in_compiling = {
"abs", "ash", "min", "max", "lognor",
// weird PS2 specific debug registers:
"breakpoint-range-set!",
// these require 128-bit integers. We want these eventually, but disabling for now to focus
// on more important issues.
"(method 3 vec4s)", "(method 2 vec4s)", "qmem-copy<-!", "qmem-copy->!", "(method 2 array)",
"(method 3 array)",
// int128 fancy stuff.
"(method 3 vec4s)", "(method 2 vec4s)",
// does weird stuff with the type system.
"print", "printl", "inspect",
// inline assembly
@@ -89,18 +97,9 @@ const std::unordered_set<std::string> skip_in_compiling = {
"log2", // weird tricky int-as-float stuff
/// VECTOR-H
"(method 3 vector4w)", // print quad
"(method 3 vector8h)", // print quad
"(method 3 vector16b)", // print quad
"(method 3 vector)", // print quad
"(method 3 rgbaf)", // print quad
"(method 3 plane)", // print quad
"(method 3 sphere)", // print quad
"(method 3 qword)", // print quad
"vector-zero!", // i128
"vector-copy!", // i128
"vector-dot", // fpu acc
"vector4-dot", // fpu acc
"(method 3 vector)", // this function appears twice, which confuses the compiler.
"vector-dot", // fpu acc
"vector4-dot", // fpu acc
};
// default location for the data. It can be changed with a command line argument.