about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_66.c211
-rw-r--r--src/dynarec/arm64/dynarec_arm64_emit_shift.c269
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.h12
3 files changed, 411 insertions, 81 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c
index 9e8fe773..258edfd5 100644
--- a/src/dynarec/arm64/dynarec_arm64_66.c
+++ b/src/dynarec/arm64/dynarec_arm64_66.c
@@ -972,42 +972,42 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 4:

                 case 6:

                     INST_NAME("SHL Ew, Ib");

-                    UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}

-                    SETFLAGS(X_ALL, SF_PENDING);

-                    GETEW(x1, 1);

-                    u8 = F8;

-                    UFLAG_IF {MOV32w(x2, (u8&0x1f));}

-                    UFLAG_OP12(ed, x2)

-                    LSLw_IMM(ed, ed, u8&0x1f);

-                    EWBACK;

-                    UFLAG_RES(ed);

-                    UFLAG_DF(x3, d_shl16);

+                    if(geted_ib(dyn, addr, ninst, nextop)&0x1f) {

+                        SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined

+                        GETEW(x1, 0);

+                        u8 = (F8)&0x1f;

+                        emit_shl16c(dyn, ninst, x1, u8, x5, x4);

+                        EWBACK;

+                    } else {

+                        FAKEED;

+                        F8;

+                    }

                     break;

                 case 5:

                     INST_NAME("SHR Ed, Ib");

-                    UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}

-                    SETFLAGS(X_ALL, SF_PENDING);

-                    GETEW(x1, 1);

-                    u8 = F8;

-                    UFLAG_IF {MOV32w(x2, (u8&0x1f));}

-                    UFLAG_OP12(ed, x2)

-                    LSRw_IMM(ed, ed, u8&0x1f);

-                    EWBACK;

-                    UFLAG_RES(ed);

-                    UFLAG_DF(x3, d_shr16);

+                    if(geted_ib(dyn, addr, ninst, nextop)&0x1f) {

+                        SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined

+                        GETEW(x1, 0);

+                        u8 = (F8)&0x1f;

+                        emit_shr16c(dyn, ninst, x1, u8, x5, x4);

+                        EWBACK;

+                    } else {

+                        FAKEED;

+                        F8;

+                    }

                     break;

                 case 7:

                     INST_NAME("SAR Ed, Ib");

-                    SETFLAGS(X_ALL, SF_PENDING);

-                    UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}

-                    GETSEW(x1, 1);

-                    u8 = F8;

-                    UFLAG_IF {MOV32w(x2, (u8&0x1f));}

-                    UFLAG_OP12(ed, x2)

-                    ASRw(ed, ed, (u8&0x1f));

-                    EWBACK;

-                    UFLAG_RES(ed);

-                    UFLAG_DF(x3, d_sar16);

+                    if(geted_ib(dyn, addr, ninst, nextop)&0x1f) {

+                        SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined

+                        GETSEW(x1, 0);

+                        u8 = (F8)&0x1f;

+                        emit_sar16c(dyn, ninst, x1, u8, x5, x4);

+                        EWBACK;

+                    } else {

+                        FAKEED;

+                        F8;

+                    }

                     break;

             }

             break;

@@ -1030,17 +1030,77 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             break;

 

         case 0xD1:

+            nextop = F8;

+            switch((nextop>>3)&7) {

+                case 0:

+                    INST_NAME("ROL Ew, 1");

+                    MOV32w(x2, 1);

+                    MESSAGE(LOG_DUMP, "Need Optimization\n");

+                    SETFLAGS(X_OF|X_CF, SF_SET);

+                    GETEW(x1, 0);

+                    CALL_(rol16, x1, x3);

+                    EWBACK;

+                    break;

+                case 1:

+                    INST_NAME("ROR Ew, 1");

+                    MOV32w(x2, 1);

+                    MESSAGE(LOG_DUMP, "Need Optimization\n");

+                    SETFLAGS(X_OF|X_CF, SF_SET);

+                    GETEW(x1, 0);

+                    CALL_(ror16, x1, x3);

+                    EWBACK;

+                    break;

+                case 2:

+                    INST_NAME("RCL Ew, 1");

+                    MESSAGE(LOG_DUMP, "Need Optimization\n");

+                    READFLAGS(X_CF);

+                    SETFLAGS(X_OF|X_CF, SF_SET);

+                    MOV32w(x2, 1);

+                    GETEW(x1, 0);

+                    CALL_(rcl16, x1, x3);

+                    EWBACK;

+                    break;

+                case 3:

+                    INST_NAME("RCR Ew, 1");

+                    MESSAGE(LOG_DUMP, "Need Optimization\n");

+                    READFLAGS(X_CF);

+                    SETFLAGS(X_OF|X_CF, SF_SET);

+                    MOV32w(x2, 1);

+                    GETEW(x1, 0);

+                    CALL_(rcr16, x1, x3);

+                    EWBACK;

+                    break;

+                case 4:

+                case 6:

+                    INST_NAME("SHL Ew, 1");

+                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined

+                    GETEW(x1, 0);

+                    emit_shl16c(dyn, ninst, x1, 1, x5, x4);

+                    EWBACK;

+                    break;

+                case 5:

+                    INST_NAME("SHR Ew, 1");

+                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined

+                    GETEW(x1, 0);

+                    emit_shr16c(dyn, ninst, x1, 1, x5, x4);

+                    EWBACK;

+                    break;

+                case 7:

+                    INST_NAME("SAR Ew, 1");

+                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined

+                    GETSEW(x1, 0);

+                    emit_sar16c(dyn, ninst, x1, 1, x5, x4);

+                    EWBACK;

+                    break;

+            }

+            break;

+

         case 0xD3:

             nextop = F8;

             switch((nextop>>3)&7) {

                 case 0:

-                    if(opcode==0xD1) {

-                        INST_NAME("ROL Ew, 1");

-                        MOV32w(x2, 1);

-                    } else {

-                        INST_NAME("ROL Ew, CL");

-                        ANDw_mask(x2, xRCX, 0, 0b00100);

-                    }

+                    INST_NAME("ROL Ew, CL");

+                    ANDw_mask(x2, xRCX, 0, 0b00100);

                     MESSAGE(LOG_DUMP, "Need Optimization\n");

                     SETFLAGS(X_OF|X_CF, SF_SET);

                     GETEW(x1, 0);

@@ -1048,13 +1108,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     EWBACK;

                     break;

                 case 1:

-                    if(opcode==0xD1) {

-                        INST_NAME("ROR Ew, 1");

-                        MOV32w(x2, 1);

-                    } else {

-                        INST_NAME("ROR Ew, CL");

-                        ANDw_mask(x2, xRCX, 0, 0b00100);

-                    }

+                    INST_NAME("ROR Ew, CL");

+                    ANDw_mask(x2, xRCX, 0, 0b00100);

                     MESSAGE(LOG_DUMP, "Need Optimization\n");

                     SETFLAGS(X_OF|X_CF, SF_SET);

                     GETEW(x1, 0);

@@ -1062,76 +1117,70 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     EWBACK;

                     break;

                 case 2:

-                    if(opcode==0xD1) {INST_NAME("RCL Ew, 1"); } else { INST_NAME("RCL Ew, CL");}

+                    INST_NAME("RCL Ew, CL");

                     MESSAGE(LOG_DUMP, "Need Optimization\n");

                     READFLAGS(X_CF);

                     SETFLAGS(X_OF|X_CF, SF_SET);

-                    if(opcode==0xD1) {MOV32w(x2, 1);} else {ANDw_mask(x2, xRCX, 0, 0b00100);}

+                    ANDw_mask(x2, xRCX, 0, 0b00100);

                     GETEW(x1, 0);

                     CALL_(rcl16, x1, x3);

                     EWBACK;

                     break;

                 case 3:

-                    if(opcode==0xD1) {INST_NAME("RCR Ew, 1");} else {INST_NAME("RCR Ew, CL");}

+                    INST_NAME("RCR Ew, CL");

                     MESSAGE(LOG_DUMP, "Need Optimization\n");

                     READFLAGS(X_CF);

                     SETFLAGS(X_OF|X_CF, SF_SET);

-                    if(opcode==0xD1) {MOV32w(x2, 1);} else {ANDw_mask(x2, xRCX, 0, 0b00100);}

+                    ANDw_mask(x2, xRCX, 0, 0b00100);

                     GETEW(x1, 0);

                     CALL_(rcr16, x1, x3);

                     EWBACK;

                     break;

                 case 4:

                 case 6:

-                    if(opcode==0xD1) {

-                        INST_NAME("SHL Ew, 1");

-                        MOV32w(x4, 1);

+                    INST_NAME("SHL Ew, CL");

+                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined

+                    if(box64_dynarec_safeflags>1)

+                        MAYSETFLAGS();

+                    UFLAG_IF {

+                        ANDSw_mask(x2, xRCX, 0, 0b00100);  //mask=0x00000001f

+                        B_NEXT(cEQ);

                     } else {

-                        INST_NAME("SHL Ew, CL");

-                        ANDw_mask(x4, xRCX, 0, 0b00100);

+                        ANDw_mask(x2, xRCX, 0, 0b00100);  //mask=0x00000001f

                     }

-                    UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}

-                    SETFLAGS(X_ALL, SF_PENDING);

                     GETEW(x1, 0);

-                    UFLAG_OP12(ed, x4)

-                    LSLw_REG(ed, ed, x4);

+                    emit_shl16(dyn, ninst, x1, x2, x5, x4);

                     EWBACK;

-                    UFLAG_RES(ed);

-                    UFLAG_DF(x3, d_shl16);

                     break;

                 case 5:

-                    if(opcode==0xD1) {

-                        INST_NAME("SHR Ew, 1");

-                        MOV32w(x4, 1);

+                    INST_NAME("SHR Ew, CL");

+                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined

+                    if(box64_dynarec_safeflags>1)

+                        MAYSETFLAGS();

+                    UFLAG_IF {

+                        ANDSw_mask(x2, xRCX, 0, 0b00100);  //mask=0x00000001f

+                        B_NEXT(cEQ);

                     } else {

-                        INST_NAME("SHR Ew, CL");

-                        ANDw_mask(x4, xRCX, 0, 0b00100);

+                        ANDw_mask(x2, xRCX, 0, 0b00100);  //mask=0x00000001f

                     }

-                    UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}

-                    SETFLAGS(X_ALL, SF_PENDING);

                     GETEW(x1, 0);

-                    UFLAG_OP12(ed, x4)

-                    LSRw_REG(ed, ed, x4);

+                    emit_shr16(dyn, ninst, x1, x2, x5, x4);

                     EWBACK;

-                    UFLAG_RES(ed);

-                    UFLAG_DF(x3, d_shr16);

                     break;

                 case 7:

-                    if(opcode==0xD1) {

-                        INST_NAME("SAR Ew, 1");

-                        MOV32w(x4, 1);

+                    INST_NAME("SAR Ew, CL");

+                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined

+                    if(box64_dynarec_safeflags>1)

+                        MAYSETFLAGS();

+                    UFLAG_IF {

+                        ANDSw_mask(x2, xRCX, 0, 0b00100);  //mask=0x00000001f

+                        B_NEXT(cEQ);

                     } else {

-                        INST_NAME("SAR Ew, CL");

-                        ANDw_mask(x4, xRCX, 0, 0b00100);

+                        ANDw_mask(x2, xRCX, 0, 0b00100);  //mask=0x00000001f

                     }

-                    UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}

-                    SETFLAGS(X_ALL, SF_PENDING);

                     GETSEW(x1, 0);

-                    UFLAG_OP12(ed, x4)

-                    ASRw_REG(ed, ed, x4);

+                    emit_sar16(dyn, ninst, x1, x2, x5, x4);

                     EWBACK;

-                    UFLAG_RES(ed);

-                    UFLAG_DF(x3, d_sar16);

                     break;

             }

             break;

diff --git a/src/dynarec/arm64/dynarec_arm64_emit_shift.c b/src/dynarec/arm64/dynarec_arm64_emit_shift.c
index 8f84ceb1..edb16a74 100644
--- a/src/dynarec/arm64/dynarec_arm64_emit_shift.c
+++ b/src/dynarec/arm64/dynarec_arm64_emit_shift.c
@@ -540,6 +540,275 @@ void emit_sar8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
     }
 }
 
+// emit SHL16 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch. s3 can be same as s2
+void emit_shl16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
+{
+    IFX(X_PEND) {
+        STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
+        STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
+        SET_DF(s4, d_shl16);
+    } else IFX(X_ALL) {
+        SET_DFNONE(s4);
+    }
+    IFX(X_CF | X_OF) {
+        MOV32w(s4, 16);
+        SUBw_REG(s4, s4, s2);
+        LSRw_REG(s4, s1, s4);
+        BFIw(xFlags, s4, F_CF, 1);
+    }
+    LSLw_REG(s1, s1, s2);
+    IFX(X_PEND) {
+        STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX(X_ZF) {
+        TSTw_mask(s1, 0, 15);
+        CSETw(s4, cEQ);
+        BFIw(xFlags, s4, F_ZF, 1);
+    }
+    IFX(X_SF) {
+        LSRw(s4, s1, 15);
+        BFIw(xFlags, s4, F_SF, 1);
+    }
+    IFX(X_OF) {
+        CMPSw_U12(s2, 1);   // if s2==1
+            IFX(X_SF) {} else {LSRw(s4, s1, 15);}
+            EORw_REG(s4, s4, xFlags);  // CF is set if OF is asked
+            CSELw(s4, s4, wZR, cEQ);
+            BFIw(xFlags, s4, F_OF, 1);
+    }
+    IFX(X_PF) {
+        emit_pf(dyn, ninst, s1, s3, s4);
+    }
+}
+
+// emit SHL16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
+void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4)
+{
+    if(!c)
+        return;
+    IFX(X_PEND) {
+        MOV32w(s3, c);
+        STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
+        STRH_U12(s3, xEmu, offsetof(x64emu_t, op2));
+        SET_DF(s4, d_shl16);
+    } else IFX(X_ALL) {
+        SET_DFNONE(s4);
+    }
+    if(c<16) {
+        IFX(X_CF|X_OF) {
+            LSRw(s3, s1, 16-c);
+            BFIw(xFlags, s3, F_CF, 1);
+        }
+        LSLw(s1, s1, c);
+
+        IFX(X_PEND) {
+            STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
+        }
+        IFX(X_ZF) {
+            TSTw_mask(s1, 0, 15);
+            CSETw(s4, cEQ);
+            BFIw(xFlags, s4, F_ZF, 1);
+        }
+        IFX(X_SF) {
+            LSRw(s4, s1, 15);
+            BFIw(xFlags, s4, F_SF, 1);
+        }
+        IFX(X_OF) {
+            if(c==1) {
+                IFX(X_SF) {} else {LSRw(s4, s1, 15);}
+                EORw_REG(s4, s4, xFlags);  // CF is set if OF is asked
+                BFIw(xFlags, s4, F_OF, 1);
+            } else {
+                BFCw(xFlags, F_OF, 1);
+            }
+        }
+        IFX(X_PF) {
+            emit_pf(dyn, ninst, s1, s3, s4);
+        }
+    } else {
+        IFX(X_CF) {
+            LSLw(s3, s1, c-1);
+            BFXILw(xFlags, s3, 15, 1);   // insert F_CF from s3[15:1]
+        }
+        MOVw_REG(s1, xZR);
+        IFX(X_OF) {
+            BFCw(xFlags, F_OF, 1);
+        }
+        IFX(X_SF) {
+            BFCw(xFlags, F_SF, 1);
+        }
+        IFX(X_PF | X_ZF) {
+            MOV32w(s3, 1);
+            IFX(X_ZF) {
+                BFIw(xFlags, s3, F_ZF, 1);
+            }
+            IFX(X_PF) {
+                BFIw(xFlags, s3, F_PF, 1);
+            }
+        }
+    }
+}
+
+// emit SHR16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s2 can be same as s3
+void emit_shr16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
+{
+    IFX(X_PEND) {
+        STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
+        STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
+        SET_DF(s4, d_shr16);
+    } else IFX(X_ALL) {
+        SET_DFNONE(s4);
+    }
+    IFX(X_CF) {
+        SUBw_U12(s3, s2, 1);
+        LSRw_REG(s3, s1, s3);
+        BFIw(xFlags, s3, 0, 1);
+    }
+    IFX(X_OF) {
+        CMPSw_U12(s2, 1);   // if s2==1
+            Bcond(cNE, 4+2*4);
+            LSRw(s4, s1, 7);
+            BFIw(xFlags, s4, F_OF, 1);
+    }
+    LSRw_REG(s1, s1, s2);
+    IFX(X_PEND) {
+        STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX(X_ZF) {
+        TSTw_mask(s1, 0, 15);
+        CSETw(s4, cEQ);
+        BFIw(xFlags, s4, F_ZF, 1);
+    }
+    IFX(X_SF) {
+        LSRw(s4, s1, 15);
+        BFIw(xFlags, s4, F_SF, 1);
+    }
+    IFX(X_PF) {
+        emit_pf(dyn, ninst, s1, s3, s4);
+    }
+}
+
+// emit SHR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
+void emit_shr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4)
+{
+    if(!c)
+        return;
+    IFX(X_PEND) {
+        MOV32w(s3, c);
+        STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
+        STRH_U12(s3, xEmu, offsetof(x64emu_t, op2));
+        SET_DF(s4, d_shr16);
+    } else IFX(X_ALL) {
+        SET_DFNONE(s4);
+    }
+    IFX(X_CF) {
+        if(c==1) {
+            BFIw(xFlags, s1, 0, 1);
+        } else {
+            LSRw(s3, s1, c-1);
+            BFIw(xFlags, s3, 0, 1);
+        }
+    }
+    IFX(X_OF) {
+        if(c==1) {
+            LSRw(s4, s1, 15);
+            BFIw(xFlags, s4, F_OF, 1);
+        }
+    }
+    LSRw(s1, s1, c);
+    IFX(X_PEND) {
+        STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX(X_ZF) {
+        TSTw_mask(s1, 0, 15);
+        CSETw(s4, cEQ);
+        BFIw(xFlags, s4, F_ZF, 1);
+    }
+    IFX(X_SF) {
+        LSRw(s4, s1, 15);
+        BFIx(xFlags, s4, F_SF, 1);
+    }
+    IFX(X_PF) {
+        emit_pf(dyn, ninst, s1, s3, s4);
+    }
+}
+
+// emit SAR16 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch
+void emit_sar16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
+{
+    IFX(X_PEND) {
+        STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
+        STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
+        SET_DF(s4, d_sar16);
+    } else IFX(X_ALL) {
+        SET_DFNONE(s4);
+    }
+    IFX(X_CF) {
+        SUBw_U12(s3, s2, 1);
+        ASRw_REG(s3, s1, s3);
+        BFIw(xFlags, s3, 0, 1);
+    }
+    ASRw_REG(s1, s1, s2);
+    IFX(X_PEND) {
+        STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX(X_ZF) {
+        TSTw_mask(s1, 0, 15);
+        CSETw(s4, cEQ);
+        BFIw(xFlags, s4, F_ZF, 1);
+    }
+    IFX(X_SF) {
+        LSRw(s4, s1, 15);
+        BFIw(xFlags, s4, F_SF, 1);
+    }
+    IFX(X_OF) {
+        CMPSw_U12(s2, 1);
+        Bcond(cNE, 4+4);
+            BFCw(xFlags, F_OF, 1);
+    }
+    IFX(X_PF) {
+        emit_pf(dyn, ninst, s1, s3, s4);
+    }
+}
+
+// emit SAR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
+void emit_sar16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4)
+{
+    if(!c)
+        return;
+    IFX(X_PEND) {
+        MOV32w(s3, c);
+        STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
+        STRH_U12(s3, xEmu, offsetof(x64emu_t, op2));
+        SET_DF(s4, d_sar16);
+    } else IFX(X_ALL) {
+        SET_DFNONE(s4);
+    }
+    IFX(X_CF) {
+        ASRw(s3, s1, c-1);
+        BFIw(xFlags, s3, 0, 1);
+    }
+    ASRw(s1, s1, c);
+    IFX(X_PEND) {
+        STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX(X_ZF) {
+        TSTw_mask(s1, 0, 15);
+        CSETw(s4, cEQ);
+        BFIw(xFlags, s4, F_ZF, 1);
+    }
+    IFX(X_SF) {
+        LSRw(s4, s1, 15);
+        BFIw(xFlags, s4, F_SF, 1);
+    }
+    IFX(X_OF)
+        if(c==1) {
+            BFCw(xFlags, F_OF, 1);
+    }
+    IFX(X_PF) {
+        emit_pf(dyn, ninst, s1, s3, s4);
+    }
+}
 // emit ROL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
 void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
 {
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h
index 2c0588fd..d24423c4 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.h
+++ b/src/dynarec/arm64/dynarec_arm64_helper.h
@@ -1029,6 +1029,12 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
 #define emit_shr8c      STEPNAME(emit_shr8c)
 #define emit_sar8       STEPNAME(emit_sar8)
 #define emit_sar8c      STEPNAME(emit_sar8c)
+#define emit_shl16      STEPNAME(emit_shl16)
+#define emit_shl16c     STEPNAME(emit_shl16c)
+#define emit_shr16      STEPNAME(emit_shr16)
+#define emit_shr16c     STEPNAME(emit_shr16c)
+#define emit_sar16      STEPNAME(emit_sar16)
+#define emit_sar16c     STEPNAME(emit_sar16c)
 #define emit_rol32c     STEPNAME(emit_rol32c)
 #define emit_ror32c     STEPNAME(emit_ror32c)
 #define emit_rol8c      STEPNAME(emit_rol8c)
@@ -1168,6 +1174,12 @@ void emit_shr8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
 void emit_shr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
 void emit_sar8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
 void emit_sar8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
+void emit_shl16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
+void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
+void emit_shr16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
+void emit_shr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
+void emit_sar16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
+void emit_sar16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
 void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
 void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
 void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);