summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/x86/isa/microops/regop.isa101
-rw-r--r--src/arch/x86/isa/operands.isa1
-rw-r--r--src/arch/x86/x86_traits.hh3
3 files changed, 104 insertions, 1 deletions
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;