]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
JIT shift instruction fix.
authorToni Wilen <twilen@winuae.net>
Sat, 31 Oct 2020 19:00:55 +0000 (21:00 +0200)
committerToni Wilen <twilen@winuae.net>
Sat, 31 Oct 2020 19:00:55 +0000 (21:00 +0200)
jit/compemu_midfunc_x86.cpp
jit/gencomp.cpp

index b42955221b05746426aa9628f7973296765b3b6a..413037309f442252f410bda4981c75153079b2da 100644 (file)
@@ -136,8 +136,9 @@ MIDFUNC(0,clear_overflow,(void))
 
 MIDFUNC(3,setcc_for_cntzero,(RR4 /* cnt */, RR4 data, int size, int ov))
 {
-       uae_u8 *branchadd;
-       uae_u8 *branchadd2;
+       uae_u8 *branchadd1a, *branchadd1b;
+       uae_u8* branchadd2;
+       uae_u8* branchadd3;
 
        evict(FLAGX);
        make_flags_live_internal();
@@ -162,7 +163,13 @@ MIDFUNC(3,setcc_for_cntzero,(RR4 /* cnt */, RR4 data, int size, int ov))
        raw_test_b_rr(X86_CL, X86_CL);
        /* if zero, leave X unaffected; carry flag will already be cleared */
        raw_jz_b_oponly();
-       branchadd = get_target();
+       branchadd1a = get_target();
+       skip_byte();
+
+       /* if >= 32, recalculate all flags */
+       raw_cmp_b_ri(X86_CL, 31);
+       raw_jcc_b_oponly(NATIVE_CC_HI);
+       branchadd1b = get_target();
        skip_byte();
 
        /* shift count was non-zero; update also x-flag */
@@ -172,7 +179,8 @@ MIDFUNC(3,setcc_for_cntzero,(RR4 /* cnt */, RR4 data, int size, int ov))
        raw_jmp_b_oponly();
        branchadd2 = get_target();
        skip_byte();
-       *branchadd = (uintptr)get_target() - ((uintptr)branchadd + 1);
+
+       *branchadd1a = (uintptr)get_target() - ((uintptr)branchadd1a + 1);
 
        /* shift count was zero; need to set Z & N flags since the native flags were unaffected */
        raw_popfl();
@@ -183,7 +191,28 @@ MIDFUNC(3,setcc_for_cntzero,(RR4 /* cnt */, RR4 data, int size, int ov))
                case 2: raw_test_w_rr(data, data); break;
                case 4: raw_test_l_rr(data, data); break;
        }
+
+       raw_jmp_b_oponly();
+       branchadd3 = get_target();
+       skip_byte();
+       *branchadd1b = (uintptr)get_target() - ((uintptr)branchadd1b + 1);
+
+       /* shift count was >=32, set all flags */
+       raw_popfl();
+       /* Set Z and N */
+       switch (size)
+       {
+       case 1: raw_test_b_rr(data, data); break;
+       case 2: raw_test_w_rr(data, data); break;
+       case 4: raw_test_l_rr(data, data); break;
+       }
+       /* Set C */
+       raw_bt_l_ri(data, 0);
+
+       *branchadd3 = (uintptr)get_target() - ((uintptr)branchadd3 + 1);
+
        unlock2(data);
+
        *branchadd2 = (uintptr)get_target() - ((uintptr)branchadd2 + 1);
 }
 
index 7dfde616bb8d8d582ad3a80c58bbbf8df4e7e447..55b108270c4ff0c30269c789ad5c7cc267a725ef 100644 (file)
@@ -2485,17 +2485,12 @@ gen_opcode(unsigned int opcode)
                if (curi->smode != immi) {
                        uses_cmov;
                        start_brace();
-                       comprintf("\tint cdata2 = scratchie++;\n");
-                       comprintf("\tint cdata = scratchie++;\n");
+                       comprintf("\tint cdata=scratchie++;\n");
                        comprintf("\tint tmpcnt=scratchie++;\n");
                        comprintf("\tmov_l_rr(tmpcnt,cnt);\n");
                        comprintf("\tand_l_ri(tmpcnt,63);\n");
                        comprintf("\tmov_l_ri(cdata, 0);\n");
 
-                       comprintf("\tmov_l_ri(cdata2, 32);\n");
-                       comprintf("\tcmp_l(tmpcnt, cdata2);\n");
-                       comprintf("\tcmov_l_rr(tmpcnt, cdata, NATIVE_CC_EQ);\n");
-
                        switch (curi->size) {
                        case sz_byte:
                                comprintf("\ttest_l_ri(tmpcnt, 0x38);\n");
@@ -2564,17 +2559,12 @@ gen_opcode(unsigned int opcode)
                if (curi->smode != immi) {
                        uses_cmov;
                        start_brace();
-                       comprintf("\tint cdata2 = scratchie++;\n");
                        comprintf("\tint cdata = scratchie++;\n");
                        comprintf("\tint tmpcnt = scratchie++;\n");
                        comprintf("\tmov_l_rr(tmpcnt,cnt);\n");
                        comprintf("\tand_l_ri(tmpcnt,63);\n");
                        comprintf("\tmov_l_ri(cdata, 0);\n");
 
-                       comprintf("\tmov_l_ri(cdata2, 32);\n");
-                       comprintf("\tcmp_l(tmpcnt, cdata2);\n");
-                       comprintf("\tcmov_l_rr(tmpcnt, cdata, NATIVE_CC_EQ);\n");
-
                        switch (curi->size) {
                        case sz_byte:
                                comprintf("\ttest_l_ri(tmpcnt, 0x38);\n");
@@ -2646,6 +2636,17 @@ gen_opcode(unsigned int opcode)
 
                if (!noflags) {
                        comprintf("\tstart_needflags();\n");
+
+                       comprintf("\tint cdata = scratchie++;\n");
+                       comprintf("\tint zero = scratchie++;\n");
+                       comprintf("\tint tmpcnt = scratchie++;\n");
+                       comprintf("\tmov_l_rr(cdata,data);\n");
+                       comprintf("\tmov_l_rr(tmpcnt,cnt);\n");
+                       comprintf("\tmov_l_ri(zero,0);\n");
+                       // if shift count is zero: C is always cleared
+                       comprintf("\tand_l_ri(tmpcnt,63);\n");
+                       comprintf("\tcmov_l_rr(cdata,zero,NATIVE_CC_EQ);\n");
+
                        /*
                         * x86 ROL instruction does not set ZF/SF, so we need extra checks here
                         */
@@ -2656,7 +2657,7 @@ gen_opcode(unsigned int opcode)
                        case sz_long: comprintf("\ttest_l_rr(data,data);\n"); break;
                        }
                        comprintf("}\n");
-                       comprintf("\tbt_l_ri(data,0x00);\n"); /* Set C */
+                       comprintf("\tbt_l_ri(cdata,0x00);\n"); /* Set C */
                        comprintf("\tlive_flags();\n");
                        comprintf("\tend_needflags();\n");
                }
@@ -2689,6 +2690,16 @@ gen_opcode(unsigned int opcode)
 
                if (!noflags) {
                        comprintf("\tstart_needflags();\n");
+
+                       comprintf("\tint cdata = scratchie++;\n");
+                       comprintf("\tint zero = scratchie++;\n");
+                       comprintf("\tint tmpcnt = scratchie++;\n");
+                       comprintf("\tmov_l_rr(cdata,data);\n");
+                       comprintf("\tmov_l_rr(tmpcnt,cnt);\n");
+                       comprintf("\tmov_l_ri(zero,0);\n");
+                       // if shift count is zero: C is always cleared
+                       comprintf("\tand_l_ri(tmpcnt,63);\n");
+                       comprintf("\tcmov_l_rr(cdata,zero,NATIVE_CC_EQ);\n");
                        /*
                         * x86 ROR instruction does not set ZF/SF, so we need extra checks here
                         */
@@ -2700,9 +2711,9 @@ gen_opcode(unsigned int opcode)
                        }
                        comprintf("}\n");
                        switch (curi->size) {
-                       case sz_byte: comprintf("\tbt_l_ri(data,0x07);\n"); break;
-                       case sz_word: comprintf("\tbt_l_ri(data,0x0f);\n"); break;
-                       case sz_long: comprintf("\tbt_l_ri(data,0x1f);\n"); break;
+                       case sz_byte: comprintf("\tbt_l_ri(cdata,0x07);\n"); break;
+                       case sz_word: comprintf("\tbt_l_ri(cdata,0x0f);\n"); break;
+                       case sz_long: comprintf("\tbt_l_ri(cdata,0x1f);\n"); break;
                        }
                        comprintf("\tlive_flags();\n");
                        comprintf("\tend_needflags();\n");