From a7806f66032d23d58b010e2e9fd605bf4168e4d8 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 31 Oct 2020 21:00:55 +0200 Subject: [PATCH] JIT shift instruction fix. --- jit/compemu_midfunc_x86.cpp | 37 +++++++++++++++++++++++++++++---- jit/gencomp.cpp | 41 +++++++++++++++++++++++-------------- 2 files changed, 59 insertions(+), 19 deletions(-) diff --git a/jit/compemu_midfunc_x86.cpp b/jit/compemu_midfunc_x86.cpp index b4295522..41303730 100644 --- a/jit/compemu_midfunc_x86.cpp +++ b/jit/compemu_midfunc_x86.cpp @@ -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); } diff --git a/jit/gencomp.cpp b/jit/gencomp.cpp index 7dfde616..55b10827 100644 --- a/jit/gencomp.cpp +++ b/jit/gencomp.cpp @@ -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"); -- 2.47.3