about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-15 17:35:52 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-15 17:35:52 +0100
commit34c1fec8f7f0d8d5f6655ad2ccedb3a62467628b (patch)
treee97851cb574b51192652dec907b818eb580cfdcd /src
parent14ec226747d0e62d8be0684550859c2583eef99e (diff)
downloadbox64-34c1fec8f7f0d8d5f6655ad2ccedb3a62467628b.tar.gz
box64-34c1fec8f7f0d8d5f6655ad2ccedb3a62467628b.zip
[DYNAREC] Added 2D and 83 /5 opcodes
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/arm64_emitter.h3
-rwxr-xr-xsrc/dynarec/dynarec_arm64_00.c35
-rwxr-xr-xsrc/dynarec/dynarec_arm64_emit_math.c159
-rwxr-xr-xsrc/dynarec/dynarec_arm64_helper.h2
4 files changed, 115 insertions, 84 deletions
diff --git a/src/dynarec/arm64_emitter.h b/src/dynarec/arm64_emitter.h
index 46b14eb3..84d9cdaf 100755
--- a/src/dynarec/arm64_emitter.h
+++ b/src/dynarec/arm64_emitter.h
@@ -144,6 +144,7 @@
 #define SUBw_U12(Rd, Rn, imm12)     EMIT(ADDSUB_IMM_gen(0, 1, 0, 0, (imm12)&0xfff, Rn, Rd))
 #define SUBSw_U12(Rd, Rn, imm12)    EMIT(ADDSUB_IMM_gen(0, 1, 0, 0, (imm12)&0xfff, Rn, Rd))
 #define SUBxw_U12(Rd, Rn, imm12)    EMIT(ADDSUB_IMM_gen(rex.w, 1, 0, 0, (imm12)&0xfff, Rn, Rd))
+#define SUBSxw_U12(Rd, Rn, imm12)   EMIT(ADDSUB_IMM_gen(rex.w, 1, 0, 0, (imm12)&0xfff, Rn, Rd))
 
 // LDR
 #define LDR_gen(size, op1, imm9, op2, Rn, Rt)    ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b01<<22 | (imm9)<<12 | (op2)<<10 | 0b01<<10 | (Rn)<<5 | (Rt))
@@ -217,10 +218,12 @@
 #define LOGIC_gen(sf, opc, N, immr, imms, Rn, Rd)  ((sf)<<31 | (opc)<<29 | 0b100100<<23 | (N)<<22 | (immr)<<16 | (imms)<<10 | (Rn) | Rd)
 #define ANDx_U13(Rd, Rn, imm13)         EMIT(LOGIC_gen(1, 0b00, ((imm13)>>12)&1, (imm13)&0b111111, ((imm13)>>6)&0b111111, Rn, Rd))
 #define ANDw_U12(Rd, Rn, imm12)         EMIT(LOGIC_gen(0, 0b00, 0, (imm12)&0b111111, ((imm12)>>6)&0b111111, Rn, Rd))
+#define ANDxw_U12(Rd, Rn, imm12)        EMIT(LOGIC_gen(rex.w, 0b00, 0, (imm12)&0b111111, ((imm12)>>6)&0b111111, Rn, Rd))
 #define ANDSx_U13(Rd, Rn, imm13)        EMIT(LOGIC_gen(1, 0b11, ((imm13)>>12)&1, (imm13)&0b111111, ((imm13)>>6)&0b111111, Rn, Rd))
 #define ANDSw_U12(Rd, Rn, imm12)        EMIT(LOGIC_gen(0, 0b11, 0, (imm12)&0b111111, ((imm12)>>6)&0b111111, Rn, Rd))
 #define ORRx_U13(Rd, Rn, imm13)         EMIT(LOGIC_gen(1, 0b01, ((imm13)>>12)&1, (imm13)&0b111111, ((imm13)>>6)&0b111111, Rn, Rd))
 #define ORRw_U12(Rd, Rn, imm12)         EMIT(LOGIC_gen(0, 0b01, 0, (imm12)&0b111111, ((imm12)>>6)&0b111111, Rn, Rd))
+#define ORRxw_U12(Rd, Rn, imm12)        EMIT(LOGIC_gen(rex.w, 0b01, 0, (imm12)&0b111111, ((imm12)>>6)&0b111111, Rn, Rd))
 
 #define LOGIC_REG_gen(sf, opc, shift, N, Rm, imm6, Rn, Rd)    ((sf)<<31 | (opc)<<29 | 0b01010<<24 | (shift)<<22 | (N)<<21 | (Rm)<<16 | (imm6)<<10 | (Rn)<<5 | (Rd))
 #define ANDx_REG(Rd, Rn, Rm)            EMIT(LOGIC_REG_gen(1, 0b00, 0b00, 0, Rm, 0, Rn, Rd))
diff --git a/src/dynarec/dynarec_arm64_00.c b/src/dynarec/dynarec_arm64_00.c
index 53b8f43e..17d0a8a9 100755
--- a/src/dynarec/dynarec_arm64_00.c
+++ b/src/dynarec/dynarec_arm64_00.c
@@ -67,6 +67,22 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             WBACK;
             break;
 
+        case 0x2B:
+            INST_NAME("SUB Gd, Ed");
+            SETFLAGS(X_ALL, SF_SET);
+            nextop = F8;
+            GETGD;
+            GETED(0);
+            emit_sub32(dyn, ninst, rex, gd, ed, x3, x4, x5);
+            break;
+
+        case 0x2D:
+            INST_NAME("SUB EAX, Id");
+            SETFLAGS(X_ALL, SF_SET);
+            i32 = F32S;
+            emit_sub32c(dyn, ninst, rex, xRAX, i32, x3, x4, x5);
+            break;
+
         case 0x50:
         case 0x51:
         case 0x52:
@@ -92,6 +108,25 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             POP1(gd);
             break;
 
+        case 0x81:
+        case 0x83:
+            nextop = F8;
+            switch((nextop>>3)&7) {
+
+                case 5: //SUB
+                    if(opcode==0x81) {INST_NAME("SUB Ed, Id");} else {INST_NAME("SUB Ed, Ib");}
+                    SETFLAGS(X_ALL, SF_SET);
+                    GETED((opcode==0x81)?4:1);
+                    if(opcode==0x81) i32 = F32S; else i32 = F8S;
+                    emit_sub32c(dyn, ninst, rex, ed, i32, x3, x4, x5);
+                    WBACK;
+                    break;
+
+                default:
+                    DEFAULT;
+            }
+            break;
+
         case 0x89:
             INST_NAME("MOV Ed, Gd");
             nextop=F8;
diff --git a/src/dynarec/dynarec_arm64_emit_math.c b/src/dynarec/dynarec_arm64_emit_math.c
index bc06904f..64a9a00d 100755
--- a/src/dynarec/dynarec_arm64_emit_math.c
+++ b/src/dynarec/dynarec_arm64_emit_math.c
@@ -211,89 +211,82 @@ void emit_sub32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
 }
 
 // emit SUB32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
-//void emit_sub32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
-//{
-//    if(s1==xESP && (!dyn->insts || dyn->insts[ninst].x64.need_flags==X_PEND))
-//    {
-//        // special case when doing math on ESP and only PEND is needed: ignoring it!
-//        if(c>=0 && c<256) {
-//            SUB_IMM8(s1, s1, c);
-//        } else {
-//            MOV32(s3, c);
-//            SUB_REG_LSL_IMM5(s1, s1, s3, 0);
-//        }
-//        return;
-//    }
-//    IFX(X_PEND) {
-//        MOV32(s3, c);
-//        STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1));
-//        STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
-//        SET_DF(s4, d_sub32);
-//    } else IFX(X_ALL) {
-//        SET_DFNONE(s4);
-//    }
-//    IFX(X_AF) {
-//        if(c>=0 && c<256) {
-//            MVN_REG_LSL_IMM5(s3, s1, 0);
-//            AND_IMM8(s4, s3, c);                // s4 = ~op1 & op2
-//            ORR_IMM8(s3, s3, c, 0);             // s3 = ~op1 | op2
-//        } else {
-//            IFX(X_PEND) {} else {MOV32(s3, c);}
-//            MVN_REG_LSL_IMM5(s4, s1, 0);
-//            ORR_REG_LSL_IMM5(s3, s4, s3, 0);
-//            MOV32(s4, c);
-//            BIC_REG_LSL_IMM5(s4, s4, s1, 0);
-//            PUSH(xSP, 1<<s3);
-//        }
-//    }
-//    if(c>=0 && c<256) {
-//        IFX(X_ALL) {
-//            SUBS_IMM8(s1, s1, c);
-//        } else {
-//            SUB_IMM8(s1, s1, c);
-//        }
-//    } else {
-//        IFXN(X_PEND, X_AF) {} else {MOV32(s3, c);}
-//        IFX(X_ALL) {
-//            SUBS_REG_LSL_IMM5(s1, s1, s3, 0);
-//        } else {
-//            SUB_REG_LSL_IMM5(s1, s1, s3, 0);
-//        }
-//    }
-//    IFX(X_PEND) {
-//        STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
-//    }
-//    IFX(X_AF) {
-//        if(c<0 || c>=256) {
-//            POP(xSP, 1<<s3);
-//        }
-//        AND_REG_LSL_IMM5(s3, s3, s1, 0);   // s3 = (~op1 | op2) & res
-//        ORR_REG_LSL_IMM5(s3, s3, s4, 0);   // s4 = (~op1 & op2) | ((~op1 | op2) & ~ res)
-//        MOV_REG_LSR_IMM5(s4, s3, 3);
-//        BFI(xFlags, s4, F_AF, 1);    // AF: bc & 0x08
-//    }
-//    IFX(X_ZF|X_CF) {
-//        BIC_IMM8(xFlags, xFlags, (1<<F_ZF)|(1<<F_CF), 0);
-//    }
-//    IFX(X_ZF) {
-//        ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
-//    }
-//    IFX(X_CF) {
-//        // Inverted carry
-//        ORR_IMM8_COND(cCC, xFlags, xFlags, 1<<F_CF, 0);
-//    }
-//    IFX(X_OF) {
-//        ORR_IMM8_COND(cVS, xFlags, xFlags, 0b10, 0x0b);
-//        BIC_IMM8_COND(cVC, xFlags, xFlags, 0b10, 0x0b);
-//    }
-//    IFX(X_SF) {
-//        MOV_REG_LSR_IMM5(s3, s1, 31);
-//        BFI(xFlags, s3, F_SF, 1);
-//    }
-//    IFX(X_PF) {
-//        emit_pf(dyn, ninst, s1, s3, s4);
-//    }
-//}
+void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5)
+{
+    if(s1==xRSP && (!dyn->insts || dyn->insts[ninst].x64.need_flags==X_PEND))
+    {
+        // special case when doing math on RSP and only PEND is needed: ignoring it!
+        SUBxw_U12(s1, s1, c);
+        return;
+    }
+    IFX(X_PEND) {
+        MOV64x(s3, c);
+        STRx_U12(s1, xEmu, offsetof(x64emu_t, op1));
+        STRx_U12(s3, xEmu, offsetof(x64emu_t, op2));
+        SET_DF(s4, d_sub32);
+    } else IFX(X_ALL) {
+        SET_DFNONE(s4);
+    }
+    IFX(X_AF) {
+        if(c>=0 && c<0x1000) {
+            MVNxw(s3, s1);
+            ANDxw_U12(s4, s3, c);                // s4 = ~op1 & op2
+            ORRxw_U12(s3, s3, c);             // s3 = ~op1 | op2
+        } else {
+            MOV64x(s5, c);
+            MVNxw(s4, s1);
+            ORRxw_REG(s3, s4, s5);
+            BICxw_REG(s4, s5, s1);
+        }
+    }
+    if(c>=0 && c<0x1000) {
+        IFX(X_ALL) {
+            SUBSxw_U12(s1, s1, c);
+        } else {
+            SUBxw_U12(s1, s1, c);
+        }
+    } else {
+        IFXN(X_PEND, X_AF) {} else {MOV64x(s5, c);}
+        IFX(X_ALL) {
+            SUBSxw_REG(s1, s1, s5);
+        } else {
+            SUBxw_REG(s1, s1, s5);
+        }
+    }
+    IFX(X_PEND) {
+        STRx_U12(s1, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX(X_AF) {
+        ANDxw_REG(s3, s3, s1);   // s3 = (~op1 | op2) & res
+        ORRxw_REG(s3, s3, s4);   // s4 = (~op1 & op2) | ((~op1 | op2) & ~ res)
+        LSRxw(s4, s3, 3);
+        BFIw(xFlags, s4, F_AF, 1);    // AF: bc & 0x08
+    }
+    IFX(X_ZF|X_CF|X_OF) {
+        MOVw(s5, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF));
+        BICx(xFlags, xFlags, s5);
+    }
+    IFX(X_ZF) {
+        Bcond(cNE, +4);
+        ORRw_U12(xFlags, xFlags, 1<<F_ZF);
+    }
+    IFX(X_CF) {
+        // inverted carry
+        Bcond(cCS, +4);
+        ORRw_U12(xFlags, xFlags, 1<<F_CF);
+    }
+    IFX(X_OF) {
+        Bcond(cVC, +4);
+        ORRw_U12(xFlags, xFlags, 1<<F_OF);
+    }
+    IFX(X_SF) {
+        LSRxw(s3, s1, (rex.w)?63:31);
+        BFIx(xFlags, s3, F_SF, 1);
+    }
+    IFX(X_PF) {
+        emit_pf(dyn, ninst, s1, s3, s4);
+    }
+}
 
 // emit ADD8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
 //void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4)
diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h
index a9068b48..d4e5a543 100755
--- a/src/dynarec/dynarec_arm64_helper.h
+++ b/src/dynarec/dynarec_arm64_helper.h
@@ -546,7 +546,7 @@ void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int save
 //void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
 //void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
 void emit_sub32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5);
-//void emit_sub32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
+void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5);
 //void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
 //void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
 //void emit_or32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);