about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-07-02 14:37:09 +0200
committerptitSeb <sebastien.chev@gmail.com>2021-07-02 14:37:09 +0200
commit7bb9dd18da19f7acaf32927c720403385065175d (patch)
tree93d1b0d6548cf129cabd9a0457c93d401070682e /src
parent140254f311eead840969229040c807ad3da3f177 (diff)
downloadbox64-7bb9dd18da19f7acaf32927c720403385065175d.tar.gz
box64-7bb9dd18da19f7acaf32927c720403385065175d.zip
[DYNAREC] Improved the fast native call path
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/arm64_epilog.S3
-rwxr-xr-xsrc/dynarec/arm64_next.S8
-rwxr-xr-xsrc/dynarec/arm64_prolog.S3
-rwxr-xr-xsrc/dynarec/dynarec_arm64_00.c9
-rwxr-xr-xsrc/dynarec/dynarec_arm64_helper.c35
-rwxr-xr-xsrc/dynarec/dynarec_arm64_helper.h6
-rwxr-xr-xsrc/include/regs.h1
-rwxr-xr-xsrc/libtools/signals.c17
-rw-r--r--src/wrapped/generated/wrapper.c281
9 files changed, 198 insertions, 165 deletions
diff --git a/src/dynarec/arm64_epilog.S b/src/dynarec/arm64_epilog.S
index c4dd0043..4b73803a 100755
--- a/src/dynarec/arm64_epilog.S
+++ b/src/dynarec/arm64_epilog.S
@@ -18,9 +18,6 @@ arm64_epilog:
     stp     x22, x23, [x0, (8 * 12)]
     stp     x24, x25, [x0, (8 * 14)]
     stp     x26, x27, [x0, (8 * 16)] // put back reg value in emu, including EIP (so x27 must be EIP now)
-    // and the 4 first SSE regs too
-    stp     q0, q1, [x0, (8 * 18)]
-    stp     q2, q3, [x0, (8 * 22)]
     //restore all used register
     //vpop     {d8-d15}
     ldp     x19, x20, [sp, (8 * 0)]
diff --git a/src/dynarec/arm64_next.S b/src/dynarec/arm64_next.S
index 3baae986..48aefc17 100755
--- a/src/dynarec/arm64_next.S
+++ b/src/dynarec/arm64_next.S
@@ -12,15 +12,13 @@
 arm64_next:
     // emu is r0
     // IP address is r1
-    sub     sp,  sp,  (8 * 12 + 16 * 4)
+    sub     sp,  sp,  (8 * 12)
     stp     x0,  x1,  [sp, (8 *  0)]
     stp     x10, x11, [sp, (8 *  2)]
     stp     x12, x13, [sp, (8 *  4)]
     stp     x14, x15, [sp, (8 *  6)]
     stp     x16, x17, [sp, (8 *  8)]
     str     x18, [sp, (8 * 10)]
-    stp     q0, q1, [sp, (8 * 12)]
-    stp     q2, q3, [sp, (8 * 16)]
 
     mov     x2, lr      // "from" is in lr, so put in x2
     // call the function
@@ -34,9 +32,7 @@ arm64_next:
     ldp     x14, x15, [sp, (8 *  6)]
     ldp     x16, x17, [sp, (8 *  8)]
     ldr     x18, [sp, (8 * 10)]
-    ldp     q0, q1, [sp, (8 * 12)]
-    ldp     q2, q3, [sp, (8 * 16)]
-    add     sp,  sp, (8 * 12 + 16 * 4)
+    add     sp,  sp, (8 * 12)
     // return offset is jump address
     br      x3
 
diff --git a/src/dynarec/arm64_prolog.S b/src/dynarec/arm64_prolog.S
index 5c6a92cd..21961e5b 100755
--- a/src/dynarec/arm64_prolog.S
+++ b/src/dynarec/arm64_prolog.S
@@ -31,8 +31,5 @@ arm64_prolog:
     ldp     x22, x23, [x0, (8 * 12)]
     ldp     x24, x25, [x0, (8 * 14)]
     ldp     x26, x27, [x0, (8 * 16)]
-    // grab 4 first SSE regs too
-    ldp     q0, q1, [x0, (8 * 18)]
-    ldp     q2, q3, [x0, (8 * 22)]
     //jump to function
     br       x1
diff --git a/src/dynarec/dynarec_arm64_00.c b/src/dynarec/dynarec_arm64_00.c
index 6e1c67e7..4d189ec3 100755
--- a/src/dynarec/dynarec_arm64_00.c
+++ b/src/dynarec/dynarec_arm64_00.c
@@ -1558,9 +1558,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     MESSAGE(LOG_DUMP, "Native Call to %s\n", GetNativeName(GetNativeFnc(ip)));
                     x87_forget(dyn, ninst, x3, x4, 0);
                     sse_purge07cache(dyn, ninst, x3);
-                    if(box64_log<2 && isSimpleWrapper(*(wrapper_t*)(addr))) {
+                    tmp = isSimpleWrapper(*(wrapper_t*)(addr));
+                    if(box64_log<2 && tmp) {
                         //GETIP(ip+3+8+8); // read the 0xCC
-                        call_n(dyn, ninst, *(void**)(addr+8));
+                        call_n(dyn, ninst, *(void**)(addr+8), tmp);
                         addr+=8+8;
                     } else {
                         GETIP(ip+1); // read the 0xCC
@@ -1996,9 +1997,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall-1)), dyn->insts[ninst].retn);
                     // calling a native function
                     sse_purge07cache(dyn, ninst, x3);
-                    if(box64_log<2 && dyn->insts && isSimpleWrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2))) {
+                    if(box64_log<2 && dyn->insts && (tmp=isSimpleWrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2)))) {
                         //GETIP(ip+3+8+8); // read the 0xCC
-                        call_n(dyn, ninst, *(void**)(dyn->insts[ninst].natcall+2+8));
+                        call_n(dyn, ninst, *(void**)(dyn->insts[ninst].natcall+2+8), tmp);
                         POP1(xRIP);   // pop the return address
                     } else {
                         GETIP_(dyn->insts[ninst].natcall); // read the 0xCC already
diff --git a/src/dynarec/dynarec_arm64_helper.c b/src/dynarec/dynarec_arm64_helper.c
index add6f1d1..d44277e5 100755
--- a/src/dynarec/dynarec_arm64_helper.c
+++ b/src/dynarec/dynarec_arm64_helper.c
@@ -518,7 +518,7 @@ void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int save
     SET_NODF();
 }
 
-void call_n(dynarec_arm_t* dyn, int ninst, void* fnc)
+void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w)
 {
     MAYUSE(fnc);
     STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));
@@ -527,7 +527,17 @@ void call_n(dynarec_arm_t* dyn, int ninst, void* fnc)
     // RDI, RSI, RDX, RCX, R8, R9 are used for function call
     STPx_S7_preindex(xEmu, xRBX, xSP, -16);   // ARM64 stack needs to be 16byte aligned
     STPx_S7_offset(xRSP, xRBP, xEmu, offsetof(x64emu_t, regs[_SP]));
-    STPx_S7_offset(xRSI, xRDI, xEmu, offsetof(x64emu_t, regs[_SI]));
+    // float and double args
+    if(abs(w)>1) {
+        MESSAGE(LOG_DUMP, "Getting %d XMM args\n", abs(w)-1);
+        for(int i=0; i<abs(w)-1; ++i) {
+            sse_get_reg(dyn, ninst, x7, i);
+        }
+    }
+    if(w<0) {
+        MESSAGE(LOG_DUMP, "Return in XMM0\n");
+        sse_get_reg_empty(dyn, ninst, x7, 0);
+    }
     // prepare regs for native call
     MOVx_REG(0, xRDI);
     MOVx_REG(x1, xRSI);
@@ -539,13 +549,14 @@ void call_n(dynarec_arm_t* dyn, int ninst, void* fnc)
     TABLE64(16, (uintptr_t)fnc);    // using x16 as scratch regs for call address
     BLR(16);
     // put return value in x86 regs
-    MOVx_REG(xRAX, 0);
-    MOVx_REG(xRDX, x1);
+    if(w>0) {
+        MOVx_REG(xRAX, 0);
+        MOVx_REG(xRDX, x1);
+    }
     // all done, restore all regs
     LDPx_S7_postindex(xEmu, xRBX, xSP, 16);
     #define GO(A, B) LDPx_S7_offset(x##A, x##B, xEmu, offsetof(x64emu_t, regs[_##A]))
     GO(RSP, RBP);
-    GO(RSI, RDI);
     #undef GO
 
     fpu_popcache(dyn, ninst, x3, 1);
@@ -1061,7 +1072,7 @@ static void sse_reset(dynarec_arm_t* dyn, int ninst)
     (void)ninst;
 #if STEP > 1
     for (int i=0; i<16; ++i)
-        dyn->ssecache[i] = (i<4)?i:-1;
+        dyn->ssecache[i] = -1;
 #else
     (void)dyn;
 #endif
@@ -1101,7 +1112,7 @@ void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1)
     (void) ninst; (void)s1;
 #if STEP > 1
     int old = -1;
-    for (int i=4; i<8; ++i)
+    for (int i=0; i<8; ++i)
         if(dyn->ssecache[i]!=-1) {
             if (old==-1) {
                 MESSAGE(LOG_DUMP, "\tPurge XMM0..7 Cache ------\n");
@@ -1125,7 +1136,7 @@ static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
     (void) ninst; (void)s1;
 #if STEP > 1
     int old = -1;
-    for (int i=4; i<16; ++i)
+    for (int i=0; i<16; ++i)
         if(dyn->ssecache[i]!=-1) {
             if (old==-1) {
                 MESSAGE(LOG_DUMP, "\tPurge SSE Cache ------\n");
@@ -1157,11 +1168,11 @@ static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
 }
 #endif
 
-void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1, int not03)
+void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1, int not07)
 {
     (void) ninst; (void)s1;
 #if STEP > 1
-    int start = not03?4:0;
+    int start = not07?8:0;
     // only SSE regs needs to be push back to xEmu
     int n=0;
     for (int i=start; i<16; i++)
@@ -1180,11 +1191,11 @@ void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1, int not03)
 #endif
 }
 
-void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1, int not03)
+void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1, int not07)
 {
     (void) ninst; (void)s1;
 #if STEP > 1
-    int start = not03?4:0;
+    int start = not07?8:0;
     // only SSE regs needs to be pop back from xEmu
     int n=0;
     for (int i=start; i<16; i++)
diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h
index 48bc1f1e..63986f61 100755
--- a/src/dynarec/dynarec_arm64_helper.h
+++ b/src/dynarec/dynarec_arm64_helper.h
@@ -754,7 +754,7 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst);
 void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n);
 void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits);
 void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int save_reg);
-void call_n(dynarec_arm_t* dyn, int ninst, void* fnc);
+void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w);
 void grab_segdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg, int segment);
 void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
 void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
@@ -880,8 +880,8 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
 #ifdef HAVE_TRACE
 void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
 #endif
-void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1, int not03);
-void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1, int not03);
+void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1, int not07);
+void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1, int not07);
 
 uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
diff --git a/src/include/regs.h b/src/include/regs.h
index 4eacf160..b7da3078 100755
--- a/src/include/regs.h
+++ b/src/include/regs.h
@@ -247,6 +247,7 @@ typedef union {
 } mmx87_regs_t;
 
 typedef union {
+	__uint128_t u128;
 	uint64_t q[2];
 	int64_t sq[2];
 	double d[2];
diff --git a/src/libtools/signals.c b/src/libtools/signals.c
index 0e3bf721..c374a2b3 100755
--- a/src/libtools/signals.c
+++ b/src/libtools/signals.c
@@ -707,6 +707,17 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
     void* rsp = NULL;
 #ifdef __aarch64__
     void * pc = (void*)p->uc_mcontext.pc;
+    struct fpsimd_context *fpsimd = NULL;
+    // find fpsimd struct
+    {
+        struct _aarch64_ctx * ff = (struct _aarch64_ctx*)p->uc_mcontext.__reserved;
+        while (ff->magic && !fpsimd) {
+            if(ff->magic==FPSIMD_MAGIC)
+                fpsimd = (struct fpsimd_context*)ff;
+            else
+                ff = (struct _aarch64_ctx*)((uintptr_t)ff + ff->size);
+        }
+    }
 #elif defined __x86_64__
     void * pc = (void*)p->uc_mcontext.gregs[X64_RIP];
 #elif defined __powerpc64__
@@ -747,6 +758,12 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
                 ejb->emu->regs[_R13].q[0] = p->uc_mcontext.regs[23];
                 ejb->emu->regs[_R14].q[0] = p->uc_mcontext.regs[24];
                 ejb->emu->regs[_R15].q[0] = p->uc_mcontext.regs[25];
+                if(fpsimd) {
+                    ejb->emu->xmm[0].u128 = fpsimd->vregs[0];
+                    ejb->emu->xmm[1].u128 = fpsimd->vregs[1];
+                    ejb->emu->xmm[2].u128 = fpsimd->vregs[2];
+                    ejb->emu->xmm[3].u128 = fpsimd->vregs[3];
+                }
                 ejb->emu->ip.q[0] = getX64Address(db, (uintptr_t)pc);
                 ejb->emu->eflags.x64 = p->uc_mcontext.regs[26];
                 if(addr>=db->x64_addr && addr<(db->x64_addr+db->x64_size)) {
diff --git a/src/wrapped/generated/wrapper.c b/src/wrapped/generated/wrapper.c
index 14861a6c..97c6304e 100644
--- a/src/wrapped/generated/wrapper.c
+++ b/src/wrapped/generated/wrapper.c
@@ -2643,27 +2643,27 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &vFv) return 1;
 	if (fun == &vFi) return 1;
 	if (fun == &vFu) return 1;
-	if (fun == &vFf) return 1;
-	if (fun == &vFd) return 1;
+	if (fun == &vFf) return 2;
+	if (fun == &vFd) return 2;
 	if (fun == &vFl) return 1;
 	if (fun == &vFL) return 1;
 	if (fun == &vFp) return 1;
 	if (fun == &cFv) return 1;
 	if (fun == &cFi) return 1;
 	if (fun == &cFu) return 1;
-	if (fun == &cFf) return 1;
+	if (fun == &cFf) return 2;
 	if (fun == &cFp) return 1;
 	if (fun == &wFp) return 1;
 	if (fun == &iFv) return 1;
 	if (fun == &iFw) return 1;
 	if (fun == &iFi) return 1;
 	if (fun == &iFu) return 1;
-	if (fun == &iFf) return 1;
-	if (fun == &iFd) return 1;
+	if (fun == &iFf) return 2;
+	if (fun == &iFd) return 2;
 	if (fun == &iFL) return 1;
 	if (fun == &iFp) return 1;
-	if (fun == &IFf) return 1;
-	if (fun == &IFd) return 1;
+	if (fun == &IFf) return 2;
+	if (fun == &IFd) return 2;
 	if (fun == &IFp) return 1;
 	if (fun == &CFp) return 1;
 	if (fun == &WFi) return 1;
@@ -2672,18 +2672,18 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &uFv) return 1;
 	if (fun == &uFi) return 1;
 	if (fun == &uFu) return 1;
-	if (fun == &uFd) return 1;
+	if (fun == &uFd) return 2;
 	if (fun == &uFp) return 1;
 	if (fun == &UFv) return 1;
 	if (fun == &UFp) return 1;
-	if (fun == &fFi) return 1;
-	if (fun == &fFf) return 1;
-	if (fun == &fFp) return 1;
-	if (fun == &dFv) return 1;
-	if (fun == &dFi) return 1;
-	if (fun == &dFu) return 1;
-	if (fun == &dFd) return 1;
-	if (fun == &dFp) return 1;
+	if (fun == &fFi) return -1;
+	if (fun == &fFf) return -2;
+	if (fun == &fFp) return -1;
+	if (fun == &dFv) return -1;
+	if (fun == &dFi) return -1;
+	if (fun == &dFu) return -1;
+	if (fun == &dFd) return -2;
+	if (fun == &dFp) return -1;
 	if (fun == &lFv) return 1;
 	if (fun == &lFi) return 1;
 	if (fun == &lFl) return 1;
@@ -2695,32 +2695,32 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &pFi) return 1;
 	if (fun == &pFW) return 1;
 	if (fun == &pFu) return 1;
-	if (fun == &pFd) return 1;
+	if (fun == &pFd) return 2;
 	if (fun == &pFl) return 1;
 	if (fun == &pFL) return 1;
 	if (fun == &pFp) return 1;
 	if (fun == &vFii) return 1;
 	if (fun == &vFiu) return 1;
-	if (fun == &vFif) return 1;
-	if (fun == &vFid) return 1;
+	if (fun == &vFif) return 2;
+	if (fun == &vFid) return 2;
 	if (fun == &vFip) return 1;
 	if (fun == &vFWW) return 1;
 	if (fun == &vFWp) return 1;
 	if (fun == &vFui) return 1;
 	if (fun == &vFuu) return 1;
-	if (fun == &vFuf) return 1;
-	if (fun == &vFud) return 1;
+	if (fun == &vFuf) return 2;
+	if (fun == &vFud) return 2;
 	if (fun == &vFup) return 1;
-	if (fun == &vFfi) return 1;
-	if (fun == &vFff) return 1;
-	if (fun == &vFfp) return 1;
-	if (fun == &vFdd) return 1;
+	if (fun == &vFfi) return 2;
+	if (fun == &vFff) return 3;
+	if (fun == &vFfp) return 2;
+	if (fun == &vFdd) return 3;
 	if (fun == &vFlp) return 1;
 	if (fun == &vFLp) return 1;
 	if (fun == &vFpi) return 1;
 	if (fun == &vFpu) return 1;
-	if (fun == &vFpf) return 1;
-	if (fun == &vFpd) return 1;
+	if (fun == &vFpf) return 2;
+	if (fun == &vFpd) return 2;
 	if (fun == &vFpl) return 1;
 	if (fun == &vFpL) return 1;
 	if (fun == &vFpp) return 1;
@@ -2746,8 +2746,8 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &iFpC) return 1;
 	if (fun == &iFpu) return 1;
 	if (fun == &iFpU) return 1;
-	if (fun == &iFpf) return 1;
-	if (fun == &iFpd) return 1;
+	if (fun == &iFpf) return 2;
+	if (fun == &iFpd) return 2;
 	if (fun == &iFpl) return 1;
 	if (fun == &iFpL) return 1;
 	if (fun == &iFpp) return 1;
@@ -2770,18 +2770,18 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &UFii) return 1;
 	if (fun == &UFUp) return 1;
 	if (fun == &UFpp) return 1;
-	if (fun == &fFif) return 1;
-	if (fun == &fFfi) return 1;
-	if (fun == &fFff) return 1;
-	if (fun == &fFfp) return 1;
-	if (fun == &fFpp) return 1;
-	if (fun == &dFid) return 1;
-	if (fun == &dFdi) return 1;
-	if (fun == &dFdd) return 1;
-	if (fun == &dFdp) return 1;
-	if (fun == &dFLL) return 1;
-	if (fun == &dFpi) return 1;
-	if (fun == &dFpp) return 1;
+	if (fun == &fFif) return -2;
+	if (fun == &fFfi) return -2;
+	if (fun == &fFff) return -3;
+	if (fun == &fFfp) return -2;
+	if (fun == &fFpp) return -1;
+	if (fun == &dFid) return -2;
+	if (fun == &dFdi) return -2;
+	if (fun == &dFdd) return -3;
+	if (fun == &dFdp) return -2;
+	if (fun == &dFLL) return -1;
+	if (fun == &dFpi) return -1;
+	if (fun == &dFpp) return -1;
 	if (fun == &lFll) return 1;
 	if (fun == &lFpi) return 1;
 	if (fun == &lFpp) return 1;
@@ -2798,7 +2798,7 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &pFui) return 1;
 	if (fun == &pFuu) return 1;
 	if (fun == &pFup) return 1;
-	if (fun == &pFdd) return 1;
+	if (fun == &pFdd) return 3;
 	if (fun == &pFlp) return 1;
 	if (fun == &pFLL) return 1;
 	if (fun == &pFpi) return 1;
@@ -2812,47 +2812,47 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &vFiui) return 1;
 	if (fun == &vFiuu) return 1;
 	if (fun == &vFiup) return 1;
-	if (fun == &vFiff) return 1;
-	if (fun == &vFidd) return 1;
+	if (fun == &vFiff) return 3;
+	if (fun == &vFidd) return 3;
 	if (fun == &vFipi) return 1;
 	if (fun == &vFipu) return 1;
 	if (fun == &vFipp) return 1;
 	if (fun == &vFuii) return 1;
 	if (fun == &vFuiI) return 1;
 	if (fun == &vFuiu) return 1;
-	if (fun == &vFuif) return 1;
-	if (fun == &vFuid) return 1;
+	if (fun == &vFuif) return 2;
+	if (fun == &vFuid) return 2;
 	if (fun == &vFuip) return 1;
 	if (fun == &vFuui) return 1;
 	if (fun == &vFuuu) return 1;
-	if (fun == &vFuuf) return 1;
-	if (fun == &vFuud) return 1;
+	if (fun == &vFuuf) return 2;
+	if (fun == &vFuud) return 2;
 	if (fun == &vFuup) return 1;
-	if (fun == &vFuff) return 1;
-	if (fun == &vFudd) return 1;
+	if (fun == &vFuff) return 3;
+	if (fun == &vFudd) return 3;
 	if (fun == &vFull) return 1;
 	if (fun == &vFupu) return 1;
-	if (fun == &vFfff) return 1;
-	if (fun == &vFfpp) return 1;
-	if (fun == &vFddd) return 1;
-	if (fun == &vFdpp) return 1;
+	if (fun == &vFfff) return 4;
+	if (fun == &vFfpp) return 2;
+	if (fun == &vFddd) return 4;
+	if (fun == &vFdpp) return 2;
 	if (fun == &vFLpp) return 1;
 	if (fun == &vFpii) return 1;
 	if (fun == &vFpiu) return 1;
-	if (fun == &vFpif) return 1;
-	if (fun == &vFpid) return 1;
+	if (fun == &vFpif) return 2;
+	if (fun == &vFpid) return 2;
 	if (fun == &vFpip) return 1;
 	if (fun == &vFpui) return 1;
 	if (fun == &vFpuI) return 1;
 	if (fun == &vFpuu) return 1;
 	if (fun == &vFpup) return 1;
-	if (fun == &vFpdd) return 1;
+	if (fun == &vFpdd) return 3;
 	if (fun == &vFpll) return 1;
 	if (fun == &vFpLi) return 1;
 	if (fun == &vFpLL) return 1;
 	if (fun == &vFppi) return 1;
 	if (fun == &vFppu) return 1;
-	if (fun == &vFppd) return 1;
+	if (fun == &vFppd) return 2;
 	if (fun == &vFppL) return 1;
 	if (fun == &vFppp) return 1;
 	if (fun == &iFwww) return 1;
@@ -2870,9 +2870,9 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &iFipp) return 1;
 	if (fun == &iFuuu) return 1;
 	if (fun == &iFuup) return 1;
-	if (fun == &iFuff) return 1;
+	if (fun == &iFuff) return 3;
 	if (fun == &iFuLL) return 1;
-	if (fun == &iFfff) return 1;
+	if (fun == &iFfff) return 4;
 	if (fun == &iFLwp) return 1;
 	if (fun == &iFLip) return 1;
 	if (fun == &iFLLp) return 1;
@@ -2890,9 +2890,9 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &iFpup) return 1;
 	if (fun == &iFpUi) return 1;
 	if (fun == &iFpUU) return 1;
-	if (fun == &iFpfu) return 1;
-	if (fun == &iFpff) return 1;
-	if (fun == &iFpdd) return 1;
+	if (fun == &iFpfu) return 2;
+	if (fun == &iFpff) return 3;
+	if (fun == &iFpdd) return 3;
 	if (fun == &iFpli) return 1;
 	if (fun == &iFpll) return 1;
 	if (fun == &iFplp) return 1;
@@ -2904,7 +2904,7 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &iFppC) return 1;
 	if (fun == &iFppW) return 1;
 	if (fun == &iFppu) return 1;
-	if (fun == &iFppd) return 1;
+	if (fun == &iFppd) return 2;
 	if (fun == &iFppl) return 1;
 	if (fun == &iFppL) return 1;
 	if (fun == &iFppp) return 1;
@@ -2924,14 +2924,14 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &uFppu) return 1;
 	if (fun == &uFppp) return 1;
 	if (fun == &UFppi) return 1;
-	if (fun == &fFuii) return 1;
-	if (fun == &fFfff) return 1;
-	if (fun == &fFffp) return 1;
-	if (fun == &fFppL) return 1;
-	if (fun == &dFddd) return 1;
-	if (fun == &dFddp) return 1;
-	if (fun == &dFppi) return 1;
-	if (fun == &dFppp) return 1;
+	if (fun == &fFuii) return -1;
+	if (fun == &fFfff) return -4;
+	if (fun == &fFffp) return -3;
+	if (fun == &fFppL) return -1;
+	if (fun == &dFddd) return -4;
+	if (fun == &dFddp) return -3;
+	if (fun == &dFppi) return -1;
+	if (fun == &dFppp) return -1;
 	if (fun == &lFipi) return 1;
 	if (fun == &lFipL) return 1;
 	if (fun == &lFlll) return 1;
@@ -2960,7 +2960,7 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &pFupi) return 1;
 	if (fun == &pFupL) return 1;
 	if (fun == &pFUpi) return 1;
-	if (fun == &pFddd) return 1;
+	if (fun == &pFddd) return 4;
 	if (fun == &pFpii) return 1;
 	if (fun == &pFpiu) return 1;
 	if (fun == &pFpil) return 1;
@@ -2979,7 +2979,7 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &pFpLp) return 1;
 	if (fun == &pFppi) return 1;
 	if (fun == &pFppu) return 1;
-	if (fun == &pFppf) return 1;
+	if (fun == &pFppf) return 2;
 	if (fun == &pFppl) return 1;
 	if (fun == &pFppL) return 1;
 	if (fun == &pFppp) return 1;
@@ -2989,8 +2989,8 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &vFiuuu) return 1;
 	if (fun == &vFiulp) return 1;
 	if (fun == &vFiupu) return 1;
-	if (fun == &vFifff) return 1;
-	if (fun == &vFiddd) return 1;
+	if (fun == &vFifff) return 4;
+	if (fun == &vFiddd) return 4;
 	if (fun == &vFipii) return 1;
 	if (fun == &vFipup) return 1;
 	if (fun == &vFippi) return 1;
@@ -3000,9 +3000,9 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &vFuiui) return 1;
 	if (fun == &vFuiuu) return 1;
 	if (fun == &vFuiup) return 1;
-	if (fun == &vFuifi) return 1;
-	if (fun == &vFuiff) return 1;
-	if (fun == &vFuidd) return 1;
+	if (fun == &vFuifi) return 2;
+	if (fun == &vFuiff) return 3;
+	if (fun == &vFuidd) return 3;
 	if (fun == &vFuipi) return 1;
 	if (fun == &vFuipu) return 1;
 	if (fun == &vFuipp) return 1;
@@ -3011,18 +3011,18 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &vFuuip) return 1;
 	if (fun == &vFuuui) return 1;
 	if (fun == &vFuuuu) return 1;
-	if (fun == &vFuuuf) return 1;
-	if (fun == &vFuuud) return 1;
+	if (fun == &vFuuuf) return 2;
+	if (fun == &vFuuud) return 2;
 	if (fun == &vFuuup) return 1;
 	if (fun == &vFuupi) return 1;
 	if (fun == &vFuupp) return 1;
-	if (fun == &vFufff) return 1;
-	if (fun == &vFuddd) return 1;
+	if (fun == &vFufff) return 4;
+	if (fun == &vFuddd) return 4;
 	if (fun == &vFupii) return 1;
 	if (fun == &vFuppi) return 1;
 	if (fun == &vFUUpi) return 1;
-	if (fun == &vFffff) return 1;
-	if (fun == &vFdddd) return 1;
+	if (fun == &vFffff) return 5;
+	if (fun == &vFdddd) return 5;
 	if (fun == &vFpiii) return 1;
 	if (fun == &vFpiip) return 1;
 	if (fun == &vFpiuL) return 1;
@@ -3030,18 +3030,18 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &vFpipi) return 1;
 	if (fun == &vFpipp) return 1;
 	if (fun == &vFpuuu) return 1;
-	if (fun == &vFpudd) return 1;
+	if (fun == &vFpudd) return 3;
 	if (fun == &vFpupp) return 1;
-	if (fun == &vFpdii) return 1;
-	if (fun == &vFpddd) return 1;
+	if (fun == &vFpdii) return 2;
+	if (fun == &vFpddd) return 4;
 	if (fun == &vFpLLL) return 1;
 	if (fun == &vFppii) return 1;
-	if (fun == &vFppid) return 1;
+	if (fun == &vFppid) return 2;
 	if (fun == &vFppip) return 1;
 	if (fun == &vFppui) return 1;
 	if (fun == &vFppuu) return 1;
 	if (fun == &vFppup) return 1;
-	if (fun == &vFppdd) return 1;
+	if (fun == &vFppdd) return 3;
 	if (fun == &vFpppi) return 1;
 	if (fun == &vFpppu) return 1;
 	if (fun == &vFpppL) return 1;
@@ -3068,12 +3068,12 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &iFippL) return 1;
 	if (fun == &iFippp) return 1;
 	if (fun == &iFuipp) return 1;
-	if (fun == &iFuuff) return 1;
+	if (fun == &iFuuff) return 3;
 	if (fun == &iFuppi) return 1;
 	if (fun == &iFuppp) return 1;
 	if (fun == &iFpiii) return 1;
 	if (fun == &iFpiiu) return 1;
-	if (fun == &iFpiid) return 1;
+	if (fun == &iFpiid) return 2;
 	if (fun == &iFpiiL) return 1;
 	if (fun == &iFpiip) return 1;
 	if (fun == &iFpiuL) return 1;
@@ -3115,7 +3115,7 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &iFpppL) return 1;
 	if (fun == &iFpppp) return 1;
 	if (fun == &IFppip) return 1;
-	if (fun == &uFifff) return 1;
+	if (fun == &uFifff) return 4;
 	if (fun == &uFuuuu) return 1;
 	if (fun == &uFpipu) return 1;
 	if (fun == &uFpipp) return 1;
@@ -3126,7 +3126,7 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &uFpppi) return 1;
 	if (fun == &uFpppp) return 1;
 	if (fun == &UFpipp) return 1;
-	if (fun == &dFppiL) return 1;
+	if (fun == &dFppiL) return -1;
 	if (fun == &lFiipL) return 1;
 	if (fun == &lFipiI) return 1;
 	if (fun == &lFipLi) return 1;
@@ -3151,8 +3151,8 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &pFippL) return 1;
 	if (fun == &pFuiii) return 1;
 	if (fun == &pFulli) return 1;
-	if (fun == &pFdddd) return 1;
-	if (fun == &pFlfff) return 1;
+	if (fun == &pFdddd) return 5;
+	if (fun == &pFlfff) return 4;
 	if (fun == &pFpiii) return 1;
 	if (fun == &pFpiip) return 1;
 	if (fun == &pFpiuu) return 1;
@@ -3188,8 +3188,8 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &vFiuipi) return 1;
 	if (fun == &vFiuuuu) return 1;
 	if (fun == &vFiulpp) return 1;
-	if (fun == &vFiffff) return 1;
-	if (fun == &vFidddd) return 1;
+	if (fun == &vFiffff) return 5;
+	if (fun == &vFidddd) return 5;
 	if (fun == &vFilill) return 1;
 	if (fun == &vFipipu) return 1;
 	if (fun == &vFipipp) return 1;
@@ -3198,7 +3198,7 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &vFuiiiu) return 1;
 	if (fun == &vFuiiip) return 1;
 	if (fun == &vFuiiup) return 1;
-	if (fun == &vFuiifi) return 1;
+	if (fun == &vFuiifi) return 2;
 	if (fun == &vFuiIII) return 1;
 	if (fun == &vFuiuii) return 1;
 	if (fun == &vFuiuiu) return 1;
@@ -3207,8 +3207,8 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &vFuiuup) return 1;
 	if (fun == &vFuiupi) return 1;
 	if (fun == &vFuiupu) return 1;
-	if (fun == &vFuifff) return 1;
-	if (fun == &vFuiddd) return 1;
+	if (fun == &vFuifff) return 4;
+	if (fun == &vFuiddd) return 4;
 	if (fun == &vFuipii) return 1;
 	if (fun == &vFuipip) return 1;
 	if (fun == &vFuipup) return 1;
@@ -3227,19 +3227,20 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &vFuuuuu) return 1;
 	if (fun == &vFuuuup) return 1;
 	if (fun == &vFuupii) return 1;
-	if (fun == &vFuffff) return 1;
-	if (fun == &vFudddd) return 1;
+	if (fun == &vFuffff) return 5;
+	if (fun == &vFudddd) return 5;
 	if (fun == &vFupupi) return 1;
 	if (fun == &vFuppip) return 1;
 	if (fun == &vFupppp) return 1;
-	if (fun == &vFddddp) return 1;
+	if (fun == &vFfffff) return 6;
+	if (fun == &vFddddp) return 5;
 	if (fun == &vFpiiii) return 1;
 	if (fun == &vFpiipp) return 1;
 	if (fun == &vFpipii) return 1;
 	if (fun == &vFpuipp) return 1;
-	if (fun == &vFpuddd) return 1;
-	if (fun == &vFpddii) return 1;
-	if (fun == &vFpdddd) return 1;
+	if (fun == &vFpuddd) return 4;
+	if (fun == &vFpddii) return 3;
+	if (fun == &vFpdddd) return 5;
 	if (fun == &vFpliil) return 1;
 	if (fun == &vFppiii) return 1;
 	if (fun == &vFppiip) return 1;
@@ -3337,7 +3338,7 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &pFpuuip) return 1;
 	if (fun == &pFpuuWW) return 1;
 	if (fun == &pFpuuup) return 1;
-	if (fun == &pFpdddd) return 1;
+	if (fun == &pFpdddd) return 5;
 	if (fun == &pFppiii) return 1;
 	if (fun == &pFppiip) return 1;
 	if (fun == &pFppipi) return 1;
@@ -3353,8 +3354,8 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &vFiiiiii) return 1;
 	if (fun == &vFiiiuil) return 1;
 	if (fun == &vFiuippp) return 1;
-	if (fun == &vFiffiff) return 1;
-	if (fun == &vFiddidd) return 1;
+	if (fun == &vFiffiff) return 5;
+	if (fun == &vFiddidd) return 5;
 	if (fun == &vFuiiiii) return 1;
 	if (fun == &vFuiiiip) return 1;
 	if (fun == &vFuiiuii) return 1;
@@ -3366,8 +3367,8 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &vFuiuuuu) return 1;
 	if (fun == &vFuiupii) return 1;
 	if (fun == &vFuiupiu) return 1;
-	if (fun == &vFuiffff) return 1;
-	if (fun == &vFuidddd) return 1;
+	if (fun == &vFuiffff) return 5;
+	if (fun == &vFuidddd) return 5;
 	if (fun == &vFuipiup) return 1;
 	if (fun == &vFuuiiii) return 1;
 	if (fun == &vFuuiuii) return 1;
@@ -3380,21 +3381,25 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &vFuuuuii) return 1;
 	if (fun == &vFuuuuip) return 1;
 	if (fun == &vFuuuuuu) return 1;
-	if (fun == &vFuuuuff) return 1;
+	if (fun == &vFuuuuff) return 3;
 	if (fun == &vFuuuppi) return 1;
 	if (fun == &vFuuuppp) return 1;
-	if (fun == &vFuuffff) return 1;
-	if (fun == &vFuudddd) return 1;
-	if (fun == &vFuffiip) return 1;
-	if (fun == &vFuddiip) return 1;
+	if (fun == &vFuuffff) return 5;
+	if (fun == &vFuudddd) return 5;
+	if (fun == &vFuffiip) return 3;
+	if (fun == &vFufffff) return 6;
+	if (fun == &vFuddiip) return 3;
 	if (fun == &vFupupip) return 1;
 	if (fun == &vFuppppp) return 1;
+	if (fun == &vFffffff) return 7;
+	if (fun == &vFdddddd) return 7;
 	if (fun == &vFpiiiii) return 1;
 	if (fun == &vFpiiuuu) return 1;
 	if (fun == &vFpiippp) return 1;
 	if (fun == &vFpipppi) return 1;
-	if (fun == &vFpudddd) return 1;
-	if (fun == &vFpdddii) return 1;
+	if (fun == &vFpudddd) return 5;
+	if (fun == &vFpdddii) return 4;
+	if (fun == &vFpddddd) return 6;
 	if (fun == &vFppiiii) return 1;
 	if (fun == &vFppiiip) return 1;
 	if (fun == &vFppiipi) return 1;
@@ -3461,6 +3466,7 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &LFpipipi) return 1;
 	if (fun == &pFiiiiii) return 1;
 	if (fun == &pFiCiiCi) return 1;
+	if (fun == &pFdddddd) return 7;
 	if (fun == &pFpiiiiu) return 1;
 	if (fun == &pFpiiCCC) return 1;
 	if (fun == &pFpippip) return 1;
@@ -3474,20 +3480,27 @@ int isSimpleWrapper(wrapper_t fun) {
 	if (fun == &pFppippp) return 1;
 	if (fun == &pFpppppu) return 1;
 	if (fun == &pFpppppp) return 1;
-	if (fun == &vFiiffffp) return 1;
-	if (fun == &vFuipffff) return 1;
-	if (fun == &vFuipdddd) return 1;
-	if (fun == &vFuuuufff) return 1;
-	if (fun == &vFuuuffff) return 1;
-	if (fun == &vFuuudddd) return 1;
-	if (fun == &vFuuffiip) return 1;
-	if (fun == &vFuuddiip) return 1;
-	if (fun == &vFpddiidd) return 1;
-	if (fun == &iFppppdpi) return 1;
-	if (fun == &pFifffppp) return 1;
-	if (fun == &vFuuuuufff) return 1;
-	if (fun == &iFdddpppppp) return 1;
-	if (fun == &vFuffiiffiip) return 1;
-	if (fun == &vFuddiiddiip) return 1;
+	if (fun == &vFiiffffp) return 5;
+	if (fun == &vFuipffff) return 5;
+	if (fun == &vFuipdddd) return 5;
+	if (fun == &vFuuuufff) return 4;
+	if (fun == &vFuuuffff) return 5;
+	if (fun == &vFuuudddd) return 5;
+	if (fun == &vFuuffiip) return 3;
+	if (fun == &vFuuddiip) return 3;
+	if (fun == &vFuffffff) return 7;
+	if (fun == &vFudddddd) return 7;
+	if (fun == &vFpddiidd) return 5;
+	if (fun == &vFpdddddd) return 7;
+	if (fun == &iFppppdpi) return 2;
+	if (fun == &pFifffppp) return 4;
+	if (fun == &vFuuuuufff) return 4;
+	if (fun == &vFffffffff) return 9;
+	if (fun == &vFuffffffff) return 9;
+	if (fun == &vFffuuuufff) return 6;
+	if (fun == &iFdddpppppp) return 4;
+	if (fun == &vFuffiiffiip) return 5;
+	if (fun == &vFuddiiddiip) return 5;
+	if (fun == &vFppdddddddd) return 9;
 	return 0;
 }