about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorLeslie Zhai <zhaixiang@loongson.cn>2024-11-14 23:01:36 +0800
committerGitHub <noreply@github.com>2024-11-14 16:01:36 +0100
commit12f4afcba28931ea6f367e11abc2f27ba68ee7f9 (patch)
tree4dc742c23ba83f85b9614cc0c800d197f62b89f9 /src
parentcd2638d11a1ce7d1db868e47953740ac540c40ee (diff)
downloadbox64-12f4afcba28931ea6f367e11abc2f27ba68ee7f9.tar.gz
box64-12f4afcba28931ea6f367e11abc2f27ba68ee7f9.zip
[LA64] Implement convert x64_va_list_t to sysv_varargs for float (#2025) (#2031)
* [LA64] Implement convert x64_va_list_t to sysv_varargs for float (#2025)

* [LA64] Implement myStackAlignGVariantNew (#2025)

* [LA64] Limit the log to LOG_DEBUG (#2055)

* [LA64] Add missing file (#2025)
Diffstat (limited to 'src')
-rw-r--r--src/include/myalign.h3
-rw-r--r--src/libtools/myalign.c60
-rw-r--r--src/wrapped/wrappedglib2.c41
3 files changed, 101 insertions, 3 deletions
diff --git a/src/include/myalign.h b/src/include/myalign.h
index 8e33aef1..8c6bcc06 100644
--- a/src/include/myalign.h
+++ b/src/include/myalign.h
@@ -135,7 +135,7 @@ typdef struct {
 #define CREATE_SYSV_VALIST(A) \
   va_list sysv_varargs = (va_list)A
 // not creating CONVERT_VALIST(A) on purpose
-// this one will create a VA_LIST from x64_va_list using only GPRS and 100 stack element
+// this one will create a VA_LIST from x64_va_list using only GPRS (NOFLOAT) and 100 stack element
 #define CREATE_VALIST_FROM_VALIST(VA, SCRATCH)                          \
   va_list sysv_varargs;                                                 \
   {                                                                     \
@@ -179,6 +179,7 @@ void myStackAlignValist(x64emu_t* emu, const char* fmt, uint64_t* mystack, x64_v
 void myStackAlignWValist(x64emu_t* emu, const char* fmt, uint64_t* mystack, x64_va_list_t va);
 void myStackAlignScanfValist(x64emu_t* emu, const char* fmt, uint64_t* mystack, x64_va_list_t va);
 void myStackAlignScanfWValist(x64emu_t* emu, const char* fmt, uint64_t* mystack, x64_va_list_t va);
+void myStackAlignGVariantNew(x64emu_t* emu, const char* fmt, uint64_t* scratch, x64_va_list_t* b);
 #endif
 
 struct x64_stat64 {                   /* x86_64       arm64 */
diff --git a/src/libtools/myalign.c b/src/libtools/myalign.c
index d60070bd..796795c0 100644
--- a/src/libtools/myalign.c
+++ b/src/libtools/myalign.c
@@ -1139,6 +1139,66 @@ void myStackAlignScanfWValist(x64emu_t* emu, const char* fmt, uint64_t* mystack,
     }
 }
 
+void myStackAlignGVariantNew(x64emu_t* emu, const char* fmt, uint64_t* scratch, x64_va_list_t* b)
+{
+    uintptr_t* p = (uintptr_t*)(emu->scratch);
+    uintptr_t* p2 = (uintptr_t*)scratch;
+    int n = (X64_VA_MAX_REG - (*b)->gp_offset)/8;
+    int m = (X64_VA_MAX_XMM - (*b)->fp_offset)/8;
+    if(n) memcpy(&p[0], (*b)->reg_save_area+X64_VA_MAX_REG-n*8, n*8+m*16);
+    memcpy(&p[n+m], (*b)->overflow_arg_area, 20*8);
+    if (box64_log == LOG_DEBUG) {
+        printf_log(LOG_DEBUG, "%s\n", __FUNCTION__);
+        for (int i = 0; i < n+m+20; i++) {
+            printf_log(LOG_DEBUG, "p%d: 0x%lx\n", i, p[i]);
+        }
+    }
+    int idx = 0;
+    int gr_offs = 0;    // offset in the reg_save_area
+    int fr_offs = 0;
+    int oa_gr_offs = 0; // offset in the overflow_arg_area
+    int oa_fr_offs = 0;
+    const char* pfmt = fmt;
+    while (*pfmt) {
+        switch (*pfmt) {
+        case 'd':
+            // double
+            if (fr_offs > m-2) {
+                p2[idx] = p[n+m+oa_fr_offs];
+                oa_gr_offs++;
+                oa_fr_offs++;
+            } else {
+                p2[idx] = p[n+fr_offs];
+                fr_offs+=2;
+            }
+            idx++;
+            break;
+        case 'b':
+        case 'y':
+        case 'n':
+        case 'q':
+        case 'i':
+        case 'h':
+        case 'u':
+        case 'x':
+        case 't':
+            if (gr_offs > n-1) {
+                p2[idx] = p[n+m+oa_gr_offs];
+                oa_gr_offs++;
+                oa_fr_offs++;
+            } else {
+                p2[idx] = p[gr_offs];
+                gr_offs++;
+            }
+            idx++;
+            break;
+        default:
+            break;
+        }
+        pfmt++;
+    }
+}
+
 #endif
 
 #define MUTEX_SIZE_X64 40
diff --git a/src/wrapped/wrappedglib2.c b/src/wrapped/wrappedglib2.c
index 210729f0..3a481eff 100644
--- a/src/wrapped/wrappedglib2.c
+++ b/src/wrapped/wrappedglib2.c
@@ -3,6 +3,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <dlfcn.h>
+#include <stdarg.h>
 
 #include "wrappedlibs.h"
 
@@ -1077,9 +1078,45 @@ EXPORT void* my_g_variant_new_va(x64emu_t* emu, char* fmt, void* endptr, x64_va_
     #ifdef CONVERT_VALIST
     CONVERT_VALIST(*b);
     #else
-    CREATE_VALIST_FROM_VALIST(*b, emu->scratch);
+      #if defined(__loongarch64) || defined(__riscv)
+        va_list sysv_varargs;
+        uint64_t scratch[N_SCRATCH];
+        myStackAlignGVariantNew(emu, fmt, scratch, b);
+        sysv_varargs = (va_list)scratch;
+      #else
+        CREATE_VALIST_FROM_VALIST(*b, emu->scratch);
+      #endif
     #endif
-    va_list* aligned = &VARARGS;
+    if (box64_log == LOG_DEBUG) {
+        printf_log(LOG_DEBUG, "fmt: %s\n", fmt);
+        const char* pfmt = fmt;
+        int i = 0;
+        while (*pfmt) {
+            switch (*pfmt) {
+            case 'b':
+            case 'y':
+            case 'n':
+            case 'q':
+            case 'i':
+            case 'h':
+            case 'u':
+                printf_log(LOG_DEBUG, "%2d: %d\n", i, va_arg(sysv_varargs, int));
+                break;
+            case 'x':
+            case 't':
+                printf_log(LOG_DEBUG, "%2d: %ld\n", i, va_arg(sysv_varargs, long));
+                break;
+            case 'd':
+                printf_log(LOG_DEBUG, "%2d: %f\n", i, va_arg(sysv_varargs, double));
+                break;
+            default:
+              break;
+            }
+            pfmt++;
+            i++;
+        }
+    }
+    va_list* aligned = &sysv_varargs;
     return my->g_variant_new_va(fmt, endptr, &aligned);
 }