From: Gabe Black Date: Fri, 7 Aug 2009 17:13:20 +0000 (-0700) Subject: X86: Implement shift right/left double microops. X-Git-Tag: Calvin_Submission~152 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=3a55fc5cace5fdf744a891c6d32c4a9d4c10694a;p=gem5.git X86: Implement shift right/left double microops. This is my best guess as far as what these should do. Other existing microops use implicit registers, mul1s and mul1u for instance, so this should be ok. The microop that loads the implicit DoubleBits register would fall into one of the microop slots for moving to/from special registers. --- diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index dc6819886..017ac49e4 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -884,6 +884,107 @@ let {{ } ''' + class Sld(RegOp): + code = ''' + uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); + uint8_t dataBits = dataSize * 8; + uint8_t realShiftAmt = shiftAmt % (2 * dataBits); + uint64_t result; + if (realShiftAmt == 0) { + result = psrc1; + } else if (realShiftAmt < dataBits) { + result = (psrc1 << realShiftAmt) | + (DoubleBits >> (dataBits - realShiftAmt)); + } else { + result = (DoubleBits << (realShiftAmt - dataBits)) | + (psrc1 >> (2 * dataBits - realShiftAmt)); + } + DestReg = merge(DestReg, result, 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 ((realShiftAmt == 0 && + bits(DoubleBits, 0)) || + (realShiftAmt <= dataBits && + bits(SrcReg1, dataBits - realShiftAmt)) || + (realShiftAmt > dataBits && + bits(DoubleBits, 2 * dataBits - realShiftAmt))) { + 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) && (bits(SrcReg1, dataBits - 1) ^ + bits(result, dataBits - 1))) + ccFlagBits = ccFlagBits | OFBit; + //Use the regular mechanisms to calculate the other flags. + ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), + DestReg, psrc1, op2); + } + ''' + + class Srd(RegOp): + code = ''' + uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); + uint8_t dataBits = dataSize * 8; + uint8_t realShiftAmt = shiftAmt % (2 * dataBits); + uint64_t result; + if (realShiftAmt == 0) { + result = psrc1; + } else if (realShiftAmt < dataBits) { + // Because what happens to the bits shift -in- on a right + // shift is not defined in the C/C++ standard, we have to + // mask them out to be sure they're zero. + uint64_t logicalMask = mask(dataBits - realShiftAmt); + result = ((psrc1 >> realShiftAmt) & logicalMask) | + (DoubleBits << (dataBits - realShiftAmt)); + } else { + uint64_t logicalMask = mask(2 * dataBits - realShiftAmt); + result = ((DoubleBits >> (realShiftAmt - dataBits)) & + logicalMask) | + (psrc1 << (2 * dataBits - realShiftAmt)); + } + DestReg = merge(DestReg, result, 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; + //If some combination of the CF bits need to be set, set them. + if ((realShiftAmt == 0 && + bits(DoubleBits, dataBits - 1)) || + (realShiftAmt <= dataBits && + bits(SrcReg1, realShiftAmt - 1)) || + (realShiftAmt > dataBits && + bits(DoubleBits, realShiftAmt - dataBits - 1))) { + 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) && (bits(SrcReg1, dataBits - 1) ^ + bits(result, dataBits - 1))) + ccFlagBits = ccFlagBits | OFBit; + //Use the regular mechanisms to calculate the other flags. + ccFlagBits = genFlags(ccFlagBits, ext & ~(CFBit | ECFBit | OFBit), + DestReg, psrc1, op2); + } + ''' + + class Mdb(WrRegOp): + code = 'DoubleBits = psrc1 ^ op2;' + class Wrip(WrRegOp, CondRegOp): code = 'RIP = psrc1 + sop2 + CSBase' else_code="RIP = RIP;" diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa index 5ea803bfc..135fc10df 100644 --- a/src/arch/x86/isa/operands.isa +++ b/src/arch/x86/isa/operands.isa @@ -127,6 +127,7 @@ def operands {{ 'Quotient': impIntReg(2, 9), 'Remainder': impIntReg(3, 10), 'Divisor': impIntReg(4, 11), + 'DoubleBits': impIntReg(5, 11), 'Rax': intReg('(INTREG_RAX)', 12), 'Rbx': intReg('(INTREG_RBX)', 13), 'Rcx': intReg('(INTREG_RCX)', 14), diff --git a/src/arch/x86/x86_traits.hh b/src/arch/x86/x86_traits.hh index 8b50bdf9b..a73aaef19 100644 --- a/src/arch/x86/x86_traits.hh +++ b/src/arch/x86/x86_traits.hh @@ -68,12 +68,13 @@ namespace X86ISA const int NumPseudoIntRegs = 1; //1. The condition code bits of the rflags register. - const int NumImplicitIntRegs = 5; + const int NumImplicitIntRegs = 6; //1. The lower part of the result of multiplication. //2. The upper part of the result of multiplication. //3. The quotient from division //4. The remainder from division //5. The divisor for division + //6. The register to use for shift doubles const int NumMMXRegs = 8; const int NumXMMRegs = 16;