X86: Implement shift right/left double microops.
authorGabe Black <gblack@eecs.umich.edu>
Fri, 7 Aug 2009 17:13:20 +0000 (10:13 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Fri, 7 Aug 2009 17:13:20 +0000 (10:13 -0700)
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.

src/arch/x86/isa/microops/regop.isa
src/arch/x86/isa/operands.isa
src/arch/x86/x86_traits.hh

index dc6819886ef98ae18b803f5d1850d40b0eaee168..017ac49e4d61dd5a7827ab8d21e679b25a6de19a 100644 (file)
@@ -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;"
index 5ea803bfce4ceef6f7ffa877e6993bbe61f7d0ce..135fc10df5c4e32d6f119b4de058d19d6cb95f98 100644 (file)
@@ -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),
index 8b50bdf9b926c3865d6b4afca6ae8f9957984ffb..a73aaef19e8508b54f256731b6864b208c48f722 100644 (file)
@@ -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;