about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2025-01-02 17:35:43 +0100
committerptitSeb <sebastien.chev@gmail.com>2025-01-02 17:35:43 +0100
commit6a35cd2a56b289a69055906c6237fa6f80e3127a (patch)
tree05e6238c3cb8e60e642186d3dda4b2e74b6502b2 /src
parentebf03f88786fe43b23dd2cb9d5ba753d660b3ce2 (diff)
downloadbox64-6a35cd2a56b289a69055906c6237fa6f80e3127a.tar.gz
box64-6a35cd2a56b289a69055906c6237fa6f80e3127a.zip
[ARM64_DYNAREC] Change native flags handling in signal to make it more extensible
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_arch.c185
-rw-r--r--src/dynarec/arm64/dynarec_arm64_arch.h34
2 files changed, 186 insertions, 33 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_arch.c b/src/dynarec/arm64/dynarec_arm64_arch.c
index af84565c..6059ba63 100644
--- a/src/dynarec/arm64/dynarec_arm64_arch.c
+++ b/src/dynarec/arm64/dynarec_arm64_arch.c
@@ -1,6 +1,7 @@
 #include <stddef.h>
 #include <stdio.h>
 #include <ucontext.h>
+#include <string.h>
 
 #include "debug.h"
 #include "dynablock.h"
@@ -11,26 +12,126 @@
 #include "dynarec/dynablock_private.h"
 #include "dynarec_arm64_arch.h"
 
+typedef struct arch_build_s
+{
+    uint8_t flags:1;
+    uint8_t x87:1;
+    uint8_t mmx:1;
+    uint8_t sse:1;
+    uint8_t ymm:1;
+    arch_flags_t flags_;
+    arch_x87_t x87_;
+    arch_mmx_t mmx_;
+    arch_sse_t sse_;
+    arch_ymm_t ymm_;
+} arch_build_t;
+
+static int arch_build(dynarec_arm_t* dyn, int ninst, arch_build_t* arch)
+{
+    int ret = 0;
+    // flags
+    if((dyn->insts[ninst].f_entry.dfnone==0) || dyn->insts[ninst].need_nat_flags) {
+        ++ret;
+        arch->flags = 1;
+        arch->flags_.defered = dyn->insts[ninst].f_entry.dfnone==0;
+        arch->flags_.vf = dyn->insts[ninst].need_nat_flags&NF_VF;
+        arch->flags_.nf = dyn->insts[ninst].need_nat_flags&NF_SF;
+        arch->flags_.eq = dyn->insts[ninst].need_nat_flags&NF_EQ;
+        arch->flags_.cf = dyn->insts[ninst].need_nat_flags&NF_CF;
+        arch->flags_.inv_cf = !dyn->insts[ninst].normal_carry;
+    } else {
+        arch->flags = 0;
+        memset(&arch->flags_, 0, sizeof(arch_flags_t));
+    }
+    return ret;
+}
+
 size_t get_size_arch(dynarec_arm_t* dyn)
 {
-    if(!box64_dynarec_nativeflags)
-        return 0;
-    return dyn->isize*sizeof(arch_flags_t);
+    arch_build_t build = {0};
+    arch_build_t previous = {0};
+    size_t sz = 0;
+    int seq = 0;
+    int nseq = 0;
+    int last = 0;
+    if(!dyn->size) return 0;
+    for(int i=0; i<dyn->size; ++i) {
+        last = arch_build(dyn, i, &build);
+        if(!memcmp(&build, &previous, sizeof(arch_build_t)) && seq<((1<<12)-1) && i) {
+            // same sequence, increment
+            seq++;
+        } else {
+            seq = 0;
+            ++nseq;
+            memcpy(&previous, &build, sizeof(arch_build_t));
+            sz+=sizeof(arch_arch_t);
+            if(build.flags) sz+=sizeof(arch_flags_t);
+            if(build.x87) sz+=sizeof(arch_x87_t);
+            if(build.mmx) sz+=sizeof(arch_mmx_t);
+            if(build.sse) sz+=sizeof(arch_sse_t);
+            if(build.ymm) sz+=sizeof(arch_ymm_t);
+        }
+    }
+    if(nseq==1 && !last)
+        return 0;   //empty, no flags, no nothing
+    return sz;
 }
 
-void populate_arch(dynarec_arm_t* dyn, void* p)
+static void build_next(arch_arch_t* arch, arch_build_t* build)
 {
-    if(!box64_dynarec_nativeflags)
-        return;
+    arch->flags = build->flags;
+    arch->x87 = build->x87;
+    arch->mmx = build->mmx;
+    arch->sse = build->sse;
+    arch->ymm = build->ymm;
+    void* p = ((void*)arch)+sizeof(arch_arch_t);
+    #define GO(A)                                           \
+    if(arch->A) {                                           \
+        arch_##A##_t* A##_ = p;                             \
+        memcpy(p, &build->A##_, sizeof(arch_ ##A##_t));     \
+        p+=sizeof(arch_##A##_t);                            \
+    }
+    GO(flags)
+    GO(x87)
+    GO(mmx)
+    GO(sse)
+    GO(ymm)
+    #undef GO
+}
 
-    arch_flags_t* flags = p;
+static int sizeof_arch(arch_arch_t* arch)
+{
+    int sz = sizeof(arch_arch_t);
+    #define GO(A)   if(arch->A) sz+sizeof(arch_##A##_t)
+    GO(flags);
+    GO(x87);
+    GO(mmx);
+    GO(sse);
+    GO(ymm);
+    #undef GO
+}
+
+void populate_arch(dynarec_arm_t* dyn, void* p)
+{
+    arch_build_t build = {0};
+    arch_build_t previous = {0};
+    arch_arch_t* arch = p;
+    arch_arch_t* next = p;
+    int seq = 0;
     for(int i=0; i<dyn->size; ++i) {
-        flags[i].defered = dyn->insts[i].f_entry.dfnone==0;
-        flags[i].vf = dyn->insts[i].need_nat_flags&NF_VF;
-        flags[i].nf = dyn->insts[i].need_nat_flags&NF_SF;
-        flags[i].eq = dyn->insts[i].need_nat_flags&NF_EQ;
-        flags[i].cf = dyn->insts[i].need_nat_flags&NF_CF;
-        flags[i].inv_cf = !dyn->insts[i].normal_carry;
+        arch_build(dyn, i, &build);
+        if(!memcmp(&build, &previous, sizeof(arch_build_t)) && seq<((1<<12)-1) && i) {
+            // same sequence, increment
+            seq++;
+            arch->seq = seq;
+        } else {
+            arch = next;
+            build_next(arch, &build);
+            seq = 0;
+            memcpy(&previous, &build, sizeof(arch_build_t));
+            int sz = sizeof_arch(arch);
+            next = (arch_arch_t*)((uintptr_t)next+sz);
+        }
     }
 }
 
@@ -49,33 +150,51 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc)
 {
     if(!db->arch_size || !db->arch)
         return;
-    arch_flags_t* flags = db->arch;
     int ninst = getX64AddressInst(db, x64pc);
-printf_log(LOG_INFO, "adjust_arch(...), db=%p, x64pc=%p, nints=%d, flags:%s %c%c%c%c%s\n", db, (void*)x64pc, ninst, flags[ninst-1].defered?"defered":"", flags[ninst-1].vf?'V':' ', flags[ninst-1].nf?'S':' ', flags[ninst-1].eq?'Z':' ', flags[ninst-1].cf?'C':' ', (flags[ninst-1].cf && flags[ninst-1].inv_cf)?"inverted":"");
-    if(ninst<0)
+printf_log(LOG_INFO, "adjust_arch(...), db=%p, x64pc=%p, nints=%d", db, (void*)x64pc, ninst);
+    if(ninst<0) {
+printf_log(LOG_INFO, "\n");
         return;
+    }
     if(ninst==0) {
+printf_log(LOG_INFO, "\n");
         CHECK_FLAGS(emu);
         return;
     }
-    if(flags[ninst-1].defered) {
-        CHECK_FLAGS(emu);
-        //return;
-    }
-    if(flags[ninst-1].nf) {
-        CONDITIONAL_SET_FLAG(p->uc_mcontext.pstate&(1<<NZCV_N), F_SF);
+    // look for state at ninst-1
+    arch_arch_t* arch = db->arch;
+    arch_arch_t* next = arch;
+    int i = -1;
+    while(i<ninst-1) {
+        arch = next;
+        i += 1+arch->seq;
+        next = (arch_arch_t*)((uintptr_t)next + sizeof_arch(arch));
     }
-    if(flags[ninst-1].vf) {
-        CONDITIONAL_SET_FLAG(p->uc_mcontext.pstate&(1<<NZCV_V), F_OF);
-    }
-    if(flags[ninst-1].eq) {
-        CONDITIONAL_SET_FLAG(p->uc_mcontext.pstate&(1<<NZCV_Z), F_ZF);
-    }
-    if(flags[ninst-1].cf) {
-        if(flags[ninst-1].inv_cf) {
-            CONDITIONAL_SET_FLAG((p->uc_mcontext.pstate&(1<<NZCV_C))==0, F_CF);
-        } else {
-            CONDITIONAL_SET_FLAG(p->uc_mcontext.pstate&(1<<NZCV_C), F_CF);
+    int sz = sizeof(arch_arch_t);
+    if(arch->flags) {
+printf_log(LOG_INFO, " flags ");
+        arch_flags_t* flags = (arch_flags_t*)((uintptr_t)arch + sz);
+        sz += sizeof(arch_flags_t);
+        if(flags->defered) {
+            CHECK_FLAGS(emu);
+            //return;
+        }
+        if(flags->nf) {
+            CONDITIONAL_SET_FLAG(p->uc_mcontext.pstate&(1<<NZCV_N), F_SF);
+        }
+        if(flags->vf) {
+            CONDITIONAL_SET_FLAG(p->uc_mcontext.pstate&(1<<NZCV_V), F_OF);
+        }
+        if(flags->eq) {
+            CONDITIONAL_SET_FLAG(p->uc_mcontext.pstate&(1<<NZCV_Z), F_ZF);
+        }
+        if(flags->cf) {
+            if(flags->inv_cf) {
+                CONDITIONAL_SET_FLAG((p->uc_mcontext.pstate&(1<<NZCV_C))==0, F_CF);
+            } else {
+                CONDITIONAL_SET_FLAG(p->uc_mcontext.pstate&(1<<NZCV_C), F_CF);
+            }
         }
     }
+printf_log(LOG_INFO, "\n");
 }
\ No newline at end of file
diff --git a/src/dynarec/arm64/dynarec_arm64_arch.h b/src/dynarec/arm64/dynarec_arm64_arch.h
index a430cf74..68f65d8a 100644
--- a/src/dynarec/arm64/dynarec_arm64_arch.h
+++ b/src/dynarec/arm64/dynarec_arm64_arch.h
@@ -19,6 +19,40 @@ typedef struct arch_flags_s
     uint8_t inv_cf:1;
 } arch_flags_t;
 
+typedef struct arch_x87_s
+{
+    int8_t dela;        //up to +/-7
+    uint8_t x87;        // 1bit is STx present
+    uint32_t x87_pos;   //4bits per STx position
+} arch_x87_t;
+
+typedef struct arch_mmx_s
+{
+    uint8_t mmx;    //1bit for each mmx reg present
+} arch_mmx_t;
+
+typedef struct arch_sse_s
+{
+    uint16_t sse;   //1bit for each sse reg present
+} arch_sse_t;
+
+typedef struct arch_ymm_s
+{
+    uint16_t ymm0;      // 1bit for ymm0
+    uint16_t ymm;       // 1bit for each ymm present
+    uint64_t ymm_pos;   // 4bits for position of each ymm present
+} arch_ymm_t;
+
+typedef struct arch_arch_s
+{
+    uint16_t flags:1;
+    uint16_t x87:1;
+    uint16_t mmx:1;
+    uint16_t sse:1;
+    uint16_t ymm:1;
+    uint16_t seq:11;    // how many instruction on the same values
+} arch_arch_t;
+
 // get size of arch specific info (can be 0)
 size_t get_size_arch(dynarec_arm_t* dyn);
 //populate the array