summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2009-08-07 10:13:20 -0700
committerGabe Black <gblack@eecs.umich.edu>2009-08-07 10:13:20 -0700
commit3a55fc5cace5fdf744a891c6d32c4a9d4c10694a (patch)
tree36695ff44c29ff0b249d66e4fc05957e903c45ed
parent62a2e85c9a0af39970568b35afa4d050ef571b23 (diff)
downloadgem5-3a55fc5cace5fdf744a891c6d32c4a9d4c10694a.tar.xz
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.
-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;