about summary refs log tree commit diff stats
path: root/src/dynarec/rv64/dynarec_rv64_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dynarec/rv64/dynarec_rv64_helper.c')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.c323
1 files changed, 323 insertions, 0 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c
new file mode 100644
index 00000000..3dee0d98
--- /dev/null
+++ b/src/dynarec/rv64/dynarec_rv64_helper.c
@@ -0,0 +1,323 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <pthread.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "debug.h"
+#include "box64context.h"
+#include "dynarec.h"
+#include "emu/x64emu_private.h"
+#include "emu/x64run_private.h"
+#include "x64run.h"
+#include "x64emu.h"
+#include "box64stack.h"
+#include "callback.h"
+#include "emu/x64run_private.h"
+#include "x64trace.h"
+#include "dynarec_native.h"
+#include "../dynablock_private.h"
+#include "../tools/bridge_private.h"
+#include "custommem.h"
+
+#include "rv64_printer.h"
+#include "dynarec_rv64_private.h"
+#include "dynarec_rv64_functions.h"
+#include "dynarec_rv64_helper.h"
+
+/* setup r2 to address pointed by ED, also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
+uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, uint8_t scratch, int64_t* fixaddress, rex_t rex, int *l, int i12, int delta)
+{
+    MAYUSE(dyn); MAYUSE(ninst); MAYUSE(delta);
+
+    int lock = l?((l==LOCK_LOCK)?1:2):0;
+    if(lock==2)
+        *l = 0;
+    uint8_t ret = x2;
+    *fixaddress = 0;
+    if(hint>0) ret = hint;
+    MAYUSE(scratch);
+    if(!(nextop&0xC0)) {
+        if((nextop&7)==4) {
+            uint8_t sib = F8;
+            int sib_reg = ((sib>>3)&7)+(rex.x<<3);
+            if((sib&0x7)==5) {
+                int64_t tmp = F32S;
+                if (sib_reg!=4) {
+                    if(tmp && ((tmp<-2048) || (tmp>2047) || !i12)) {
+                        MOV64x(scratch, tmp);
+                        SLLI(ret, xRAX+sib_reg, (sib>>6));
+                        ADD(ret, ret, scratch);
+                    } else {
+                        SLLI(ret, xRAX+sib_reg, (sib>>6));
+                        *fixaddress = tmp;
+                    }
+                } else {
+                    switch(lock) {
+                        case 1: addLockAddress(tmp); break;
+                        case 2: if(isLockAddress(tmp)) *l=1; break;
+                    }
+                    MOV64x(ret, tmp);
+                }
+            } else {
+                if (sib_reg!=4) {
+                    SLLI(scratch, xRAX+sib_reg, (sib>>6));
+                    ADD(ret, xRAX+(sib&0x7)+(rex.b<<3), scratch);
+                } else {
+                    ret = xRAX+(sib&0x7)+(rex.b<<3);
+                }
+            }
+        } else if((nextop&7)==5) {
+            int64_t tmp = F32S64;
+            if(i12 && (tmp>=-2048) && (tmp<=2047)) {
+                GETIP(addr+delta);
+                ret = xRIP;
+                *fixaddress = tmp;
+            } else if((tmp>=-2048) && (tmp<=2047)) {
+                GETIP(addr+delta);
+                ADDI(ret, xRIP, tmp);
+            } else if(tmp+addr+delta<0x100000000LL) {
+                MOV64x(ret, tmp+addr+delta);
+            } else {
+                MOV64x(ret, tmp);
+                GETIP(addr+delta);
+                ADD(ret, ret, xRIP);
+            }
+            switch(lock) {
+                case 1: addLockAddress(addr+delta+tmp); break;
+                case 2: if(isLockAddress(addr+delta+tmp)) *l=1; break;
+            }
+        } else {
+            ret = xRAX+(nextop&7)+(rex.b<<3);
+        }
+    } else {
+        int64_t i64;
+        uint8_t sib = 0;
+        int sib_reg = 0;
+        if((nextop&7)==4) {
+            sib = F8;
+            sib_reg = ((sib>>3)&7)+(rex.x<<3);
+        }
+        if(nextop&0x80)
+            i64 = F32S;
+        else 
+            i64 = F8S;
+        if(i64==0 || ((i64>=-2048) && (i64<=2047)  && i12)) {
+            *fixaddress = i64;
+            if((nextop&7)==4) {
+                if (sib_reg!=4) {
+                    SLLI(scratch, xRAX+sib_reg, (sib>>6));
+                    ADD(ret, xRAX+(sib&0x07)+(rex.b<<3), scratch);
+                } else {
+                    ret = xRAX+(sib&0x07)+(rex.b<<3);
+                }
+            } else
+                ret = xRAX+(nextop&0x07)+(rex.b<<3);
+        } else {
+            if(i64>=-2048 && i64<=2047) {
+                if((nextop&7)==4) {
+                    if (sib_reg!=4) {
+                        SLLI(scratch, xRAX+sib_reg, (sib>>6));
+                        ADD(scratch, xRAX+(sib&0x07)+(rex.b<<3), scratch);
+                    } else {
+                        scratch = xRAX+(sib&0x07)+(rex.b<<3);
+                    }
+                } else
+                    scratch = xRAX+(nextop&0x07)+(rex.b<<3);
+                ADDI(ret, scratch, i64);
+            } else {
+                MOV64x(scratch, i64);
+                if((nextop&7)==4) {
+                    if (sib_reg!=4) {
+                        ADD(scratch, scratch, xRAX+(sib&0x07)+(rex.b<<3));
+                        SLLI(ret, xRAX+sib_reg, (sib>>6));
+                        ADD(ret, scratch, ret);
+                    } else {
+                        PASS3(int tmp = xRAX+(sib&0x07)+(rex.b<<3));
+                        ADD(ret, tmp, scratch);
+                    }
+                } else {
+                    PASS3(int tmp = xRAX+(nextop&0x07)+(rex.b<<3));
+                    ADD(ret, tmp, scratch);
+                }
+            }
+        }
+    }
+    *ed = ret;
+    return addr;
+}
+
+void jump_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst)
+{
+    MAYUSE(dyn); MAYUSE(ip); MAYUSE(ninst);
+    MESSAGE(LOG_DUMP, "Jump to epilog\n");
+
+    if(reg) {
+        if(reg!=xRIP) {
+            MV(xRIP, reg);
+        }
+    } else {
+        GETIP_(ip);
+    }
+    TABLE64(x2, (uintptr_t)rv64_epilog);
+    SMEND();
+    BR(x2);
+}
+
+void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst)
+{
+    MAYUSE(dyn); MAYUSE(ninst);
+    MESSAGE(LOG_DUMP, "Jump to next\n");
+
+    if(reg) {
+        if(reg!=xRIP) {
+            MV(xRIP, reg);
+        }
+        uintptr_t tbl = getJumpTable64();
+        MAYUSE(tbl);
+        TABLE64(x3, tbl);
+        SRLI(x2, xRIP, JMPTABL_START3);
+        SLLI(x2, x2, 3);
+        LD(x3, x3, x2);
+        LUI(x4, JMPTABLE_MASK2);    // x4 = mask
+        SRLI(x2, xRIP, JMPTABL_START2);
+        AND(x2, x2, x4);
+        SLLI(x2, x2, 3);
+        LD(x3, x3, x2);
+        if(JMPTABLE_MASK2!=JMPTABLE_MASK1) {
+            LUI(x4, JMPTABLE_MASK1);    // x4 = mask
+        }
+        SRLI(x2, xRIP, JMPTABL_START1);
+        AND(x2, x2, x4);
+        SLLI(x2, x2, 3);
+        LD(x3, x3, x2);
+        if(JMPTABLE_MASK1!=JMPTABLE_MASK0) {
+            LUI(x4, JMPTABLE_MASK0);    // x4 = mask
+        }
+        AND(x2, x2, x4);
+        SLLI(x2, x2, 3);
+        LD(x2, x3, x2);
+    } else {
+        uintptr_t p = getJumpTableAddress64(ip);
+        MAYUSE(p);
+        TABLE64(x3, p);
+        GETIP_(ip);
+        LD(x2, x3, 0);
+    }
+    if(reg!=A1) {
+        MV(A1, xRIP);
+    }
+    CLEARIP();
+    #ifdef HAVE_TRACE
+    //MOVx(x3, 15);    no access to PC reg 
+    #endif
+    SMEND();
+    JALR(x2); // save LR...
+}
+
+void fpu_reset(dynarec_rv64_t* dyn)
+{
+    //TODO
+}
+
+void fpu_reset_cache(dynarec_rv64_t* dyn, int ninst, int reset_n)
+{
+    //TODO
+}
+
+void fpu_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1, int s2, int s3)
+{
+    //TODO
+}
+
+// propagate ST stack state, especial stack pop that are defered
+void fpu_propagate_stack(dynarec_rv64_t* dyn, int ninst)
+{
+    //TODO
+}
+
+void mmx_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1)
+{
+    // TODO
+}
+
+void x87_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1, int s2, int s3)
+{
+    //TODO
+}
+
+#ifdef HAVE_TRACE
+void fpu_reflectcache(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3)
+{
+    //TODO
+}
+#endif
+void fpu_pushcache(dynarec_rv64_t* dyn, int ninst, int s1, int not07)
+{
+    //TODO
+}
+void fpu_popcache(dynarec_rv64_t* dyn, int ninst, int s1, int not07)
+{
+    //TODO
+}
+
+void rv64_move32(dynarec_rv64_t* dyn, int ninst, int reg, int32_t val)
+{
+    int32_t up=(val>>12);
+    int32_t r = val-(up<<12);
+    // check if there is the dreaded sign bit on imm12
+    if(r&0b100000000000 && r!=0xffffffff) {
+        ++up;
+        r = val-(up<<12);
+    }
+    LUI(reg, up);
+    if(r) {
+        ADDI(reg, reg, r);
+    }
+}
+void rv64_move64(dynarec_rv64_t* dyn, int ninst, int reg, int64_t val)
+{
+    if(((val<<(64-12))>>(64-12))==val) {
+        // simple 12bit value
+        MOV_U12(reg, (val&0b111111111111));
+        return;
+    }
+    if(((val<<32)>>32)==val) {
+        // 32bits value
+        rv64_move32(dyn, ninst, reg, val);
+        return;
+    }
+    if((val&0xffffffffLL)==val && (val&0x80000000)) {
+        // 32bits value, but with a sign bit
+        rv64_move32(dyn, ninst, reg, val);
+        ZEROUP(reg);
+        return;
+    }
+    //TODO: optimize that later
+    // Start with the upper 32bits
+    rv64_move32(dyn, ninst, reg, val>>32);
+    // now the lower part
+    uint32_t r = val&0xffffffff;
+    int s = 11;
+    if((r>>21)&0b11111111111) {
+        SLLI(reg, reg, s);
+        ORI(reg, reg, (r>>21)&0b11111111111);
+        s = 0;
+    }
+    s+=11;
+    if((r>>10)&0b11111111111) {
+        SLLI(reg, reg, s);
+        ORI(reg, reg, (r>>10)&0b11111111111);
+        s = 0;
+    }
+    s+=10;
+    if(r&0b1111111111) {
+        SLLI(reg, reg, s);
+        ORI(reg, reg, r&0b1111111111);
+        s=0;
+    }
+    if(s) {
+        SLLI(reg, reg, s);
+    }
+}
\ No newline at end of file