2021-03-27 15:18:59 -04:00
|
|
|
#include "gtest/gtest.h"
|
|
|
|
#include "FormRegressionTest.h"
|
|
|
|
|
|
|
|
using namespace decompiler;
|
|
|
|
|
2021-04-02 11:35:14 -04:00
|
|
|
// tests stack variables
|
2021-03-27 15:18:59 -04:00
|
|
|
TEST_F(FormRegressionTest, MatrixPMult) {
|
|
|
|
std::string func =
|
|
|
|
"sll r0, r0, 0\n"
|
|
|
|
" daddiu sp, sp, -112\n"
|
|
|
|
" sd ra, 0(sp)\n"
|
|
|
|
" sq s5, 80(sp)\n"
|
|
|
|
" sq gp, 96(sp)\n"
|
|
|
|
|
|
|
|
" or gp, a0, r0\n"
|
|
|
|
" daddiu s5, sp, 16\n"
|
|
|
|
" sq r0, 0(s5)\n"
|
|
|
|
" sq r0, 16(s5)\n"
|
|
|
|
" sq r0, 32(s5)\n"
|
|
|
|
" sq r0, 48(s5)\n"
|
|
|
|
" lw t9, matrix*!(s7)\n"
|
|
|
|
" or a0, s5, r0\n"
|
|
|
|
" jalr ra, t9\n"
|
|
|
|
" sll v0, ra, 0\n"
|
|
|
|
|
|
|
|
" lq v1, 0(s5)\n"
|
|
|
|
" sq v1, 0(gp)\n"
|
|
|
|
" lq v1, 16(s5)\n"
|
|
|
|
" sq v1, 16(gp)\n"
|
|
|
|
" lq v1, 32(s5)\n"
|
|
|
|
" sq v1, 32(gp)\n"
|
|
|
|
" lq v1, 48(s5)\n"
|
|
|
|
" sq v1, 48(gp)\n"
|
|
|
|
" or v0, gp, r0\n"
|
|
|
|
" ld ra, 0(sp)\n"
|
|
|
|
" lq gp, 96(sp)\n"
|
|
|
|
" lq s5, 80(sp)\n"
|
|
|
|
" jr ra\n"
|
|
|
|
" daddiu sp, sp, 112";
|
|
|
|
std::string type = "(function matrix matrix matrix matrix)";
|
|
|
|
std::string expected =
|
|
|
|
"(begin\n"
|
|
|
|
" (let ((s5-0 (new (quote stack) (quote matrix))))\n"
|
|
|
|
" (set! (-> s5-0 vector 0 quad) (the-as uint128 0))\n"
|
|
|
|
" (set! (-> s5-0 vector 1 quad) (the-as uint128 0))\n"
|
|
|
|
" (set! (-> s5-0 vector 2 quad) (the-as uint128 0))\n"
|
|
|
|
" (set! (-> s5-0 vector 3 quad) (the-as uint128 0))\n"
|
|
|
|
" (matrix*! s5-0 arg1 arg2)\n"
|
|
|
|
" (set! (-> arg0 vector 0 quad) (-> s5-0 vector 0 quad))\n"
|
|
|
|
" (set! (-> arg0 vector 1 quad) (-> s5-0 vector 1 quad))\n"
|
|
|
|
" (set! (-> arg0 vector 2 quad) (-> s5-0 vector 2 quad))\n"
|
|
|
|
" (set! (-> arg0 vector 3 quad) (-> s5-0 vector 3 quad))\n"
|
|
|
|
" )\n"
|
|
|
|
" arg0\n"
|
|
|
|
" )";
|
|
|
|
test_with_stack_vars(func, type, expected,
|
|
|
|
"[\n"
|
|
|
|
" [16, \"matrix\"]\n"
|
|
|
|
" ]");
|
2021-04-02 11:35:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO- this should also work without the cast, but be uglier.
|
|
|
|
TEST_F(FormRegressionTest, VectorXQuaternionWithCast) {
|
|
|
|
std::string func =
|
|
|
|
"sll r0, r0, 0\n"
|
|
|
|
|
|
|
|
" daddiu sp, sp, -112\n"
|
|
|
|
" sd ra, 0(sp)\n"
|
|
|
|
" sq s5, 80(sp)\n"
|
|
|
|
" sq gp, 96(sp)\n"
|
|
|
|
|
|
|
|
" or gp, a0, r0\n"
|
|
|
|
" daddiu s5, sp, 16\n"
|
|
|
|
" sq r0, 0(s5)\n"
|
|
|
|
" sq r0, 16(s5)\n"
|
|
|
|
" sq r0, 32(s5)\n"
|
|
|
|
" sq r0, 48(s5)\n"
|
|
|
|
" lw t9, quaternion->matrix(s7)\n"
|
|
|
|
" or a0, s5, r0\n"
|
|
|
|
" jalr ra, t9\n"
|
|
|
|
" sll v0, ra, 0\n"
|
|
|
|
|
|
|
|
" daddu v1, r0, s5\n"
|
|
|
|
" lq v1, 0(v1)\n"
|
|
|
|
|
|
|
|
" sq v1, 0(gp)\n"
|
|
|
|
" or v0, gp, r0\n"
|
|
|
|
" ld ra, 0(sp)\n"
|
|
|
|
" lq gp, 96(sp)\n"
|
|
|
|
" lq s5, 80(sp)\n"
|
|
|
|
" jr ra\n"
|
|
|
|
" daddiu sp, sp, 112";
|
|
|
|
std::string type = "(function quaternion quaternion quaternion)";
|
|
|
|
std::string expected =
|
|
|
|
"(begin\n"
|
|
|
|
" (let ((s5-0 (new (quote stack) (quote matrix))))\n"
|
|
|
|
" (set! (-> s5-0 vector 0 quad) (the-as uint128 0))\n"
|
|
|
|
" (set! (-> s5-0 vector 1 quad) (the-as uint128 0))\n"
|
|
|
|
" (set! (-> s5-0 vector 2 quad) (the-as uint128 0))\n"
|
|
|
|
" (set! (-> s5-0 vector 3 quad) (the-as uint128 0))\n"
|
|
|
|
" (quaternion->matrix s5-0 arg1)\n"
|
|
|
|
" (set! (-> arg0 vec quad) (-> (the-as (pointer uint128) (-> s5-0 data)) 0))\n"
|
|
|
|
" )\n"
|
|
|
|
" arg0\n"
|
|
|
|
" )";
|
|
|
|
test_with_stack_vars(func, type, expected,
|
|
|
|
"[\n"
|
|
|
|
" [16, \"matrix\"]\n"
|
|
|
|
" ]",
|
|
|
|
"[[10, \"v1\", \"(pointer uint128)\"]]");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(FormRegressionTest, EliminateFloatDeadSet) {
|
|
|
|
std::string func =
|
|
|
|
"sll r0, r0, 0\n"
|
|
|
|
"L32:\n"
|
|
|
|
" daddiu sp, sp, -16\n"
|
|
|
|
" sd fp, 8(sp)\n"
|
|
|
|
" or fp, t9, r0\n"
|
|
|
|
|
|
|
|
" lwu v1, 4(a0)\n"
|
|
|
|
" mtc1 f0, v1\n"
|
|
|
|
" cvt.s.w f1, f0\n"
|
|
|
|
//" lwc1 f0, L83(fp)\n"
|
|
|
|
" mtc1 f0, r0\n"
|
|
|
|
" lw a1, *display*(s7)\n"
|
|
|
|
" ld a1, 780(a1)\n"
|
|
|
|
" divu a1, v1\n"
|
|
|
|
" mfhi v1\n"
|
|
|
|
" mtc1 f2, v1\n"
|
|
|
|
" cvt.s.w f2, f2\n"
|
|
|
|
" lwc1 f3, 0(a0)\n"
|
|
|
|
" add.s f2, f2, f3\n"
|
|
|
|
" div.s f3, f2, f1\n"
|
|
|
|
" cvt.w.s f3, f3\n"
|
|
|
|
" cvt.s.w f3, f3\n"
|
|
|
|
" mul.s f3, f3, f1\n"
|
|
|
|
" sub.s f2, f2, f3\n"
|
|
|
|
" div.s f1, f2, f1\n"
|
|
|
|
" mul.s f0, f0, f1\n"
|
|
|
|
//" lwc1 f1, L84(fp)\n"
|
|
|
|
" mtc1 f1, r0\n"
|
|
|
|
//" lwc1 f2, L83(fp)\n"
|
|
|
|
" mtc1 f2, r0\n"
|
|
|
|
" lwc1 f3, 12(a0)\n"
|
|
|
|
" mul.s f2, f2, f3\n"
|
|
|
|
" sub.s f1, f1, f2\n"
|
|
|
|
//" lwc1 f2, L84(fp)\n"
|
|
|
|
" mtc1 f2, r0\n"
|
|
|
|
//" lwc1 f3, L83(fp)\n"
|
|
|
|
" mtc1 f3, r0\n"
|
|
|
|
" lwc1 f4, 8(a0)\n"
|
|
|
|
" mul.s f3, f3, f4\n"
|
|
|
|
" sub.s f2, f2, f3\n"
|
|
|
|
//" lwc1 f3, L84(fp)\n"
|
|
|
|
" mtc1 f3, r0\n"
|
|
|
|
" add.s f3, f3, f1\n"
|
|
|
|
" c.lt.s f0, f3\n"
|
|
|
|
" bc1t L33\n"
|
|
|
|
" sll r0, r0, 0\n"
|
|
|
|
|
|
|
|
" mtc1 f0, r0\n"
|
|
|
|
" mfc1 v1, f0\n"
|
|
|
|
" beq r0, r0, L36\n"
|
|
|
|
" sll r0, r0, 0\n"
|
|
|
|
|
|
|
|
"L33:\n"
|
|
|
|
//" lwc1 f3, L84(fp)\n"e
|
|
|
|
" mtc1 f3, r0\n"
|
|
|
|
" c.lt.s f3, f0\n"
|
|
|
|
" bc1f L34\n"
|
|
|
|
" sll r0, r0, 0\n"
|
|
|
|
|
|
|
|
//" lwc1 f2, L84(fp)\n"
|
|
|
|
" mtc1 f2, r0\n"
|
|
|
|
//" lwc1 f3, L82(fp)\n"
|
|
|
|
" mtc1 f3, r0\n"
|
|
|
|
" add.s f0, f3, f0\n"
|
|
|
|
" div.s f0, f0, f1\n"
|
|
|
|
" sub.s f0, f2, f0\n"
|
|
|
|
" mfc1 v1, f0\n"
|
|
|
|
" beq r0, r0, L36\n"
|
|
|
|
" sll r0, r0, 0\n"
|
|
|
|
|
|
|
|
"L34:\n"
|
|
|
|
" c.lt.s f0, f2\n"
|
|
|
|
" bc1t L35\n"
|
|
|
|
" sll r0, r0, 0\n"
|
|
|
|
|
|
|
|
//" lwc1 f0, L84(fp)\n"
|
|
|
|
" mtc1 f0, r0\n"
|
|
|
|
" mfc1 v1, f0\n"
|
|
|
|
" beq r0, r0, L36\n"
|
|
|
|
" sll r0, r0, 0\n"
|
|
|
|
|
|
|
|
"L35:\n"
|
|
|
|
" div.s f0, f0, f2\n"
|
|
|
|
" mfc1 v1, f0\n"
|
|
|
|
|
|
|
|
"L36:\n"
|
|
|
|
" mfc1 v0, f0\n"
|
|
|
|
" ld fp, 8(sp)\n"
|
|
|
|
" jr ra\n"
|
|
|
|
" daddiu sp, sp, 16";
|
|
|
|
std::string type = "(function sync-info-paused float)";
|
|
|
|
std::string expected =
|
|
|
|
"(let* ((v1-0 (-> arg0 period))\n"
|
|
|
|
" (f1-0 (the float v1-0))\n"
|
|
|
|
" (f0-1 0.0)\n"
|
|
|
|
" (f2-2\n"
|
|
|
|
" (+\n"
|
|
|
|
" (the float (mod (-> *display* base-frame-counter) v1-0))\n"
|
|
|
|
" (-> arg0 offset)\n"
|
|
|
|
" )\n"
|
|
|
|
" )\n"
|
|
|
|
" (f0-2\n"
|
|
|
|
" (* f0-1 (/ (- f2-2 (* (the float (the int (/ f2-2 f1-0))) f1-0)) f1-0))\n"
|
|
|
|
" )\n"
|
|
|
|
" (f1-3 (- 0.0 (* 0.0 (-> arg0 pause-after-in))))\n"
|
|
|
|
" (f2-7 (- 0.0 (* 0.0 (-> arg0 pause-after-out))))\n"
|
|
|
|
" )\n"
|
|
|
|
" (cond\n"
|
|
|
|
" ((>= f0-2 (+ 0.0 f1-3))\n"
|
|
|
|
" 0.0\n"
|
|
|
|
" )\n"
|
|
|
|
" ((< 0.0 f0-2)\n"
|
|
|
|
" (- 0.0 (/ (+ 0.0 f0-2) f1-3))\n"
|
|
|
|
" )\n"
|
|
|
|
" ((>= f0-2 f2-7)\n"
|
|
|
|
" 0.0\n"
|
|
|
|
" )\n"
|
|
|
|
" (else\n"
|
|
|
|
" (/ f0-2 f2-7)\n"
|
|
|
|
" )\n"
|
|
|
|
" )\n"
|
|
|
|
" )";
|
|
|
|
test_with_stack_vars(func, type, expected, "[]");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(FormRegressionTest, IterateProcessTree) {
|
|
|
|
std::string func =
|
|
|
|
"sll r0, r0, 0\n"
|
|
|
|
|
|
|
|
" daddiu sp, sp, -80\n"
|
|
|
|
" sd ra, 0(sp)\n"
|
|
|
|
" sq s3, 16(sp)\n"
|
|
|
|
" sq s4, 32(sp)\n"
|
|
|
|
" sq s5, 48(sp)\n"
|
|
|
|
" sq gp, 64(sp)\n"
|
|
|
|
|
|
|
|
" or s3, a0, r0\n"
|
|
|
|
" or gp, a1, r0\n"
|
|
|
|
" or s5, a2, r0\n"
|
|
|
|
" lwu v1, 4(s3)\n"
|
|
|
|
" andi v1, v1, 256\n"
|
|
|
|
" bnel v1, r0, L113\n"
|
|
|
|
|
|
|
|
" daddiu s4, s7, 8\n"
|
|
|
|
|
|
|
|
" or t9, gp, r0\n"
|
|
|
|
" or a0, s3, r0\n"
|
|
|
|
" jalr ra, t9\n"
|
|
|
|
" sll v0, ra, 0\n"
|
|
|
|
" or s4, v0, r0\n"
|
|
|
|
|
|
|
|
"L113:\n"
|
|
|
|
" daddiu v1, s7, dead\n"
|
|
|
|
" bne s4, v1, L114\n"
|
|
|
|
" sll r0, r0, 0\n"
|
|
|
|
|
|
|
|
" or v1, s7, r0\n"
|
|
|
|
" beq r0, r0, L117\n"
|
|
|
|
" sll r0, r0, 0\n"
|
|
|
|
|
|
|
|
"L114:\n"
|
|
|
|
" lwu v1, 16(s3)\n"
|
|
|
|
" beq r0, r0, L116\n"
|
|
|
|
" sll r0, r0, 0\n"
|
|
|
|
|
|
|
|
"L115:\n"
|
|
|
|
" lwu a0, 0(v1)\n"
|
|
|
|
" lwu s3, 12(a0)\n"
|
|
|
|
" lw t9, iterate-process-tree(s7)\n"
|
|
|
|
" lwu a0, 0(v1)\n"
|
|
|
|
" or a1, gp, r0\n"
|
|
|
|
" or a2, s5, r0\n"
|
|
|
|
" jalr ra, t9\n"
|
|
|
|
" sll v0, ra, 0\n"
|
|
|
|
|
|
|
|
" or v1, s3, r0\n"
|
|
|
|
" or a0, v1, r0\n"
|
|
|
|
|
|
|
|
"L116:\n"
|
|
|
|
" bne s7, v1, L115\n"
|
|
|
|
" sll r0, r0, 0\n"
|
|
|
|
|
|
|
|
" or v1, s7, r0\n"
|
|
|
|
|
|
|
|
"L117:\n"
|
|
|
|
" or v0, s4, r0\n"
|
|
|
|
" ld ra, 0(sp)\n"
|
|
|
|
" lq gp, 64(sp)\n"
|
|
|
|
" lq s5, 48(sp)\n"
|
|
|
|
" lq s4, 32(sp)\n"
|
|
|
|
" lq s3, 16(sp)\n"
|
|
|
|
" jr ra\n"
|
|
|
|
" daddiu sp, sp, 80";
|
|
|
|
std::string type = "(function process-tree (function object object) kernel-context object)";
|
|
|
|
std::string expected =
|
|
|
|
"(let ((s4-0 (or (nonzero? (logand (-> arg0 mask) 256)) (arg1 arg0))))\n"
|
|
|
|
" (cond\n"
|
|
|
|
" ((= s4-0 (quote dead))\n"
|
|
|
|
" )\n"
|
|
|
|
" (else\n"
|
|
|
|
" (let ((v1-4 (-> arg0 child)))\n"
|
|
|
|
" (while v1-4\n"
|
|
|
|
" (let ((s3-1 (-> v1-4 0 brother)))\n"
|
|
|
|
" (iterate-process-tree (-> v1-4 0) arg1 arg2)\n"
|
|
|
|
" (set! v1-4 s3-1)\n"
|
|
|
|
" )\n"
|
|
|
|
" )\n"
|
|
|
|
" )\n"
|
|
|
|
" )\n"
|
|
|
|
" )\n"
|
|
|
|
" s4-0\n"
|
|
|
|
" )";
|
|
|
|
test_with_stack_vars(func, type, expected, "[]");
|
2021-03-27 15:18:59 -04:00
|
|
|
}
|