diff --git a/bdshemu/bdshemu.c b/bdshemu/bdshemu.c index d186c93..4b76f65 100644 --- a/bdshemu/bdshemu.c +++ b/bdshemu/bdshemu.c @@ -2145,93 +2145,107 @@ ShemuEmulate( case ND_INS_ROL: case ND_INS_ROR: { - ND_UINT32 cnt, tempcnt, cntmask; + ND_UINT32 cnt, tempcnt, cntmask, bitwidth; ND_UINT8 tempCF = 0; GET_OP(Context, 0, &dst); GET_OP(Context, 1, &src); cnt = (ND_UINT32)src.Value.Qwords[0]; - tempcnt = 0; cntmask = ((dst.Size == 8) ? 0x3F : 0x1F); + tempcnt = (cnt & cntmask); + bitwidth = (ND_UINT32)dst.Size * 8; if (ND_INS_RCL == Context->Instruction.Instruction || ND_INS_RCR == Context->Instruction.Instruction) { - switch (dst.Size) + if (dst.Size == 1) { - case 1: tempcnt = (cnt & 0x1F) % 9; break; - case 2: tempcnt = (cnt & 0x1F) % 17; break; - case 4: tempcnt = (cnt & 0x1F); break; - case 8: tempcnt = (cnt & 0x3F); break; - default: break; + tempcnt %= 9; + } + else if (dst.Size == 2) + { + tempcnt %= 17; } } else { - tempcnt = (cnt & cntmask) % (dst.Size * 8); + tempcnt %= (dst.Size * 8); } if (ND_INS_RCL == Context->Instruction.Instruction) { - while (tempcnt != 0) + tempCF = GET_FLAG(Context, NDR_RFLAG_CF); + + if (tempcnt != 0) { - tempCF = ND_MSB(dst.Size, dst.Value.Qwords[0]); - dst.Value.Qwords[0] = (dst.Value.Qwords[0] << 1) + GET_FLAG(Context, NDR_RFLAG_CF); - SET_FLAG(Context, NDR_RFLAG_CF, tempCF); - tempcnt--; + // tempcnt is in range [1, dst bit width]. + ND_UINT64 left = (tempcnt == bitwidth) ? 0 : (dst.Value.Qwords[0] << tempcnt); + ND_UINT64 right = (tempcnt == 1) ? 0 : (dst.Value.Qwords[0] >> (bitwidth - tempcnt + 1)); + + SET_FLAG(Context, NDR_RFLAG_CF, ND_GET_BIT(bitwidth - tempcnt, dst.Value.Qwords[0])); + + dst.Value.Qwords[0] = left | ((ND_UINT64)tempCF << (tempcnt - 1)) | right; } if ((cnt & cntmask) == 1) { SET_FLAG(Context, NDR_RFLAG_OF, ND_MSB(dst.Size, dst.Value.Qwords[0]) ^ - GET_FLAG(Context, NDR_RFLAG_CF)); + GET_FLAG(Context, NDR_RFLAG_CF)); } } else if (ND_INS_RCR == Context->Instruction.Instruction) { + tempCF = GET_FLAG(Context, NDR_RFLAG_CF); + if ((cnt & cntmask) == 1) { SET_FLAG(Context, NDR_RFLAG_OF, ND_MSB(dst.Size, dst.Value.Qwords[0]) ^ - GET_FLAG(Context, NDR_RFLAG_CF)); + GET_FLAG(Context, NDR_RFLAG_CF)); } - while (tempcnt != 0) + if (tempcnt != 0) { - tempCF = ND_LSB(dst.Size, dst.Value.Qwords[0]); - dst.Value.Qwords[0] = (dst.Value.Qwords[0] >> 1) + - ((ND_UINT64)GET_FLAG(Context, NDR_RFLAG_CF) << (dst.Size * 8 - 1)); - SET_FLAG(Context, NDR_RFLAG_CF, tempCF); - tempcnt--; + // tempcnt is in range [1, dst bit width]. + ND_UINT64 left = (tempcnt == bitwidth) ? 0 : (dst.Value.Qwords[0] >> tempcnt); + ND_UINT64 right = (tempcnt == 1) ? 0 : (dst.Value.Qwords[0] << (bitwidth - tempcnt + 1)); + + SET_FLAG(Context, NDR_RFLAG_CF, ND_GET_BIT(tempcnt - 1, dst.Value.Qwords[0])); + + dst.Value.Qwords[0] = left | ((ND_UINT64)tempCF << (bitwidth - tempcnt)) | right; } } else if (ND_INS_ROL == Context->Instruction.Instruction) { - while (tempcnt != 0) + if (tempcnt != 0) { - tempCF = ND_MSB(dst.Size, dst.Value.Qwords[0]); - dst.Value.Qwords[0] = (dst.Value.Qwords[0] << 1) + tempCF; - tempcnt--; + // tempcnt is in range [1, dst bit width - 1]. + ND_UINT64 left = dst.Value.Qwords[0] << tempcnt; + ND_UINT64 right = dst.Value.Qwords[0] >> (bitwidth - tempcnt); + + dst.Value.Qwords[0] = left | right; } if ((cnt & cntmask) != 0) { - SET_FLAG(Context, NDR_RFLAG_CF, dst.Value.Qwords[0] & 1); + SET_FLAG(Context, NDR_RFLAG_CF, ND_LSB(dst.Size, dst.Value.Qwords[0])); } if ((cnt & cntmask) == 1) { SET_FLAG(Context, NDR_RFLAG_OF, ND_MSB(dst.Size, dst.Value.Qwords[0]) ^ - GET_FLAG(Context, NDR_RFLAG_CF)); + GET_FLAG(Context, NDR_RFLAG_CF)); } } else // ND_INS_ROR { - while (tempcnt != 0) + if (tempcnt != 0) { - tempCF = ND_LSB(dst.Size, dst.Value.Qwords[0]); - dst.Value.Qwords[0] = (dst.Value.Qwords[0] >> 1) + ((ND_UINT64)tempCF << (dst.Size * 8 - 1)); - tempcnt--; + // tempcnt is in range [1, dst bit width - 1]. + ND_UINT64 left = (dst.Value.Qwords[0] >> tempcnt); + ND_UINT64 right = (dst.Value.Qwords[0] << (bitwidth - tempcnt)); + + dst.Value.Qwords[0] = left | right; } if ((cnt & cntmask) != 0) @@ -2241,7 +2255,8 @@ ShemuEmulate( if ((cnt & cntmask) == 1) { - SET_FLAG(Context, NDR_RFLAG_OF, ND_MSB(dst.Size, dst.Value.Qwords[0]) ^ ND_GET_BIT(dst.Size * 8ULL - 2, dst.Value.Qwords[0])); + SET_FLAG(Context, NDR_RFLAG_OF, ND_MSB(dst.Size, dst.Value.Qwords[0]) ^ + ND_GET_BIT(dst.Size * 8ULL - 2, dst.Value.Qwords[0])); } }