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();
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 */
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();
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);
}
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");
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");
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
*/
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");
}
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
*/
}
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");