From 534c6a800ade5499bf37a896993ab86488b6654c Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 13 Sep 2007 16:35:20 -0700 Subject: X86: Make the shift and rotate instructions set the carry flag(s) and overflow flags like they're supposed to. --HG-- extra : convert_revision : c0523a5bbf53375ce979ca7d98a95e465be66fbe --- src/arch/x86/isa/microops/regop.isa | 143 ++++++++++++++++++++++++++++++++++-- 1 file changed, 136 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 371ff63da..98743e603 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -612,13 +612,34 @@ let {{ # Shift instructions - class Sll(FlagRegOp): + class Sll(RegOp): code = ''' uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize); ''' + flag_code = ''' + // If the shift amount is zero, no flags should be modified. + if (shiftAmt) { + //Zero out any flags we might modify. This way we only have to + //worry about setting them. + ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); + int CFBits = 0; + //Figure out if we -would- set the CF bits if requested. + if (bits(SrcReg1, dataSize * 8 - shiftAmt)) + CFBits = 1; + //If some combination of the CF bits need to be set, set them. + if ((ext & (CFBit | ECFBit)) && CFBits) + ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); + //Figure out what the OF bit should be. + if ((ext & OFBit) && (CFBits ^ bits(DestReg, dataSize * 8 - 1))) + ccFlagBits = ccFlagBits | OFBit; + //Use the regular mechanisms to calculate the other flags. + ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), + DestReg, psrc1, op2); + } + ''' - class Srl(FlagRegOp): + class Srl(RegOp): code = ''' uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); // Because what happens to the bits shift -in- on a right shift @@ -627,8 +648,25 @@ let {{ uint64_t logicalMask = mask(dataSize * 8 - shiftAmt); DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize); ''' + flag_code = ''' + // If the shift amount is zero, no flags should be modified. + if (shiftAmt) { + //Zero out any flags we might modify. This way we only have to + //worry about setting them. + ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); + //If some combination of the CF bits need to be set, set them. + if ((ext & (CFBit | ECFBit)) && bits(SrcReg1, shiftAmt - 1)) + ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); + //Figure out what the OF bit should be. + if ((ext & OFBit) && bits(SrcReg1, dataSize * 8 - 1)) + ccFlagBits = ccFlagBits | OFBit; + //Use the regular mechanisms to calculate the other flags. + ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), + DestReg, psrc1, op2); + } + ''' - class Sra(FlagRegOp): + class Sra(RegOp): code = ''' uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); // Because what happens to the bits shift -in- on a right shift @@ -638,8 +676,22 @@ let {{ -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt); DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize); ''' + flag_code = ''' + // If the shift amount is zero, no flags should be modified. + if (shiftAmt) { + //Zero out any flags we might modify. This way we only have to + //worry about setting them. + ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); + //If some combination of the CF bits need to be set, set them. + if ((ext & (CFBit | ECFBit)) && bits(SrcReg1, shiftAmt - 1)) + ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); + //Use the regular mechanisms to calculate the other flags. + ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), + DestReg, psrc1, op2); + } + ''' - class Ror(FlagRegOp): + class Ror(RegOp): code = ''' uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); @@ -652,8 +704,28 @@ let {{ else DestReg = DestReg; ''' + flag_code = ''' + // If the shift amount is zero, no flags should be modified. + if (shiftAmt) { + //Zero out any flags we might modify. This way we only have to + //worry about setting them. + ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); + //Find the most and second most significant bits of the result. + int msb = bits(DestReg, dataSize * 8 - 1); + int smsb = bits(DestReg, dataSize * 8 - 2); + //If some combination of the CF bits need to be set, set them. + if ((ext & (CFBit | ECFBit)) && msb) + ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); + //Figure out what the OF bit should be. + if ((ext & OFBit) && (msb ^ smsb)) + ccFlagBits = ccFlagBits | OFBit; + //Use the regular mechanisms to calculate the other flags. + ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), + DestReg, psrc1, op2); + } + ''' - class Rcr(FlagRegOp): + class Rcr(RegOp): code = ''' uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); @@ -669,8 +741,26 @@ let {{ else DestReg = DestReg; ''' + flag_code = ''' + // If the shift amount is zero, no flags should be modified. + if (shiftAmt) { + //Zero out any flags we might modify. This way we only have to + //worry about setting them. + ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); + //Figure out what the OF bit should be. + if ((ext & OFBit) && ((ccFlagBits & CFBit) ^ + bits(SrcReg1, dataSize * 8 - 1))) + ccFlagBits = ccFlagBits | OFBit; + //If some combination of the CF bits need to be set, set them. + if ((ext & (CFBit | ECFBit)) && bits(SrcReg1, shiftAmt - 1)) + ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); + //Use the regular mechanisms to calculate the other flags. + ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), + DestReg, psrc1, op2); + } + ''' - class Rol(FlagRegOp): + class Rol(RegOp): code = ''' uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); @@ -684,8 +774,28 @@ let {{ else DestReg = DestReg; ''' + flag_code = ''' + // If the shift amount is zero, no flags should be modified. + if (shiftAmt) { + //Zero out any flags we might modify. This way we only have to + //worry about setting them. + ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); + //The CF bits, if set, would be set to the lsb of the result. + int lsb = DestReg & 0x1; + int msb = bits(DestReg, dataSize * 8 - 1); + //If some combination of the CF bits need to be set, set them. + if ((ext & (CFBit | ECFBit)) && lsb) + ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); + //Figure out what the OF bit should be. + if ((ext & OFBit) && (msb ^ lsb)) + ccFlagBits = ccFlagBits | OFBit; + //Use the regular mechanisms to calculate the other flags. + ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), + DestReg, psrc1, op2); + } + ''' - class Rcl(FlagRegOp): + class Rcl(RegOp): code = ''' uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); @@ -703,6 +813,25 @@ let {{ else DestReg = DestReg; ''' + flag_code = ''' + // If the shift amount is zero, no flags should be modified. + if (shiftAmt) { + //Zero out any flags we might modify. This way we only have to + //worry about setting them. + ccFlagBits = ccFlagBits & ~(ext & (CFBit | ECFBit | OFBit)); + int msb = bits(DestReg, dataSize * 8 - 1); + int CFBits = bits(SrcReg1, dataSize * 8 - shiftAmt); + //If some combination of the CF bits need to be set, set them. + if ((ext & (CFBit | ECFBit)) && CFBits) + ccFlagBits = ccFlagBits | (ext & (CFBit | ECFBit)); + //Figure out what the OF bit should be. + if ((ext & OFBit) && (msb ^ CFBits)) + ccFlagBits = ccFlagBits | OFBit; + //Use the regular mechanisms to calculate the other flags. + ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), + DestReg, psrc1, op2); + } + ''' class Wrip(WrRegOp, CondRegOp): code = 'RIP = psrc1 + op2' -- cgit v1.2.3