X86: Make instructions use pick, and implement/adjust some multiplication microops and instructions.

--HG--
extra : convert_revision : 5c56f6819ee07d936b388b3d1810a3b73db84f9c
This commit is contained in:
Gabe Black 2007-07-30 13:28:05 -07:00
parent fad96cd0fc
commit bae96272a1
2 changed files with 184 additions and 43 deletions

View file

@ -55,6 +55,100 @@
microcode = ''' microcode = '''
#
# Byte version of one operand unsigned multiply.
#
def macroop MUL_B_R
{
mul1u rax, rax, reg, dataSize="2"
};
def macroop MUL_B_M
{
ld t1, ds, [scale, index, base], disp
mul1u rax, rax, t1, dataSize="2"
};
def macroop MUL_B_P
{
rdip t7
ld t1, ds, [scale, index, base], disp
mul1u rax, rax, t1, dataSize="2"
};
#
# One operand unsigned multiply.
#
def macroop MUL_R
{
muleh rdx, rax, reg
mulel rax, rax, reg
};
def macroop MUL_M
{
ld t1, ds, [scale, index, base], disp
muleh rdx, rax, t1
mulel rax, rax, t1
};
def macroop MUL_P
{
rdip t7
ld t1, ds, [scale, index, base], disp
muleh rdx, rax, t1
mulel rax, rax, t1
};
#
# Byte version of one operand signed multiply.
#
def macroop IMUL_B_R
{
mul1s rax, rax, reg, dataSize="2"
};
def macroop IMUL_B_M
{
ld t1, ds, [scale, index, base], disp
mul1s rax, rax, t1, dataSize="2"
};
def macroop IMUL_B_P
{
rdip t7
ld t1, ds, [scale, index, base], disp
mul1s rax, rax, t1, dataSize="2"
};
#
# One operand signed multiply.
#
def macroop IMUL_R
{
muleh rdx, rax, reg
mulel rax, rax, reg
};
def macroop IMUL_M
{
ld t1, ds, [scale, index, base], disp
muleh rdx, rax, t1
mulel rax, rax, t1
};
def macroop IMUL_P
{
rdip t7
ld t1, ds, [scale, index, base], disp
muleh rdx, rax, t1
mulel rax, rax, t1
};
# #
# Two operand signed multiply. These should set the CF and OF flags if the # Two operand signed multiply. These should set the CF and OF flags if the
# result is too large for the destination register # result is too large for the destination register
@ -62,33 +156,37 @@ microcode = '''
def macroop IMUL_R_R def macroop IMUL_R_R
{ {
mul1s reg, reg, regm mulel reg, reg, regm
}; };
def macroop IMUL_R_M def macroop IMUL_R_M
{ {
ld t1, ds, [scale, index, base], disp ld t1, ds, [scale, index, base], disp
mul1s reg, reg, t1 mulel reg, reg, t1
}; };
def macroop IMUL_R_P def macroop IMUL_R_P
{ {
rdip t7 rdip t7
ld t1, ds, [scale, index, base], disp ld t1, ds, [scale, index, base], disp
mul1s reg, reg, t1 mulel reg, reg, t1
}; };
#
# Three operand signed multiply.
#
def macroop IMUL_R_R_I def macroop IMUL_R_R_I
{ {
limm t1, imm limm t1, imm
mul1s reg, regm, t1 mulel reg, regm, t1
}; };
def macroop IMUL_R_M_I def macroop IMUL_R_M_I
{ {
limm t1, imm limm t1, imm
ld t2, ds, [scale, index, base], disp ld t2, ds, [scale, index, base], disp
mul1s reg, t2, t1 mulel reg, t2, t1
}; };
def macroop IMUL_R_P_I def macroop IMUL_R_P_I
@ -96,7 +194,7 @@ def macroop IMUL_R_P_I
rdip t7 rdip t7
limm t1, imm limm t1, imm
ld t2, ds, [0, t0, t7] ld t2, ds, [0, t0, t7]
mul1s reg, t2, t1 mulel reg, t2, t1
}; };
''' '''
#let {{ #let {{

View file

@ -65,6 +65,7 @@ def template MicroRegOpExecute {{
{ {
Fault fault = NoFault; Fault fault = NoFault;
DPRINTF(X86, "The data size is %d\n", dataSize);
%(op_decl)s; %(op_decl)s;
%(op_rd)s; %(op_rd)s;
@ -327,18 +328,26 @@ let {{
checkCCFlagBits = "checkCondition(ccFlagBits)" checkCCFlagBits = "checkCondition(ccFlagBits)"
genCCFlagBits = \ genCCFlagBits = \
"ccFlagBits = genFlags(ccFlagBits, ext, DestReg, SrcReg1, op2);" "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, src1, op2);"
genCCFlagBitsSub = \ genCCFlagBitsSub = \
"ccFlagBits = genFlags(ccFlagBits, ext, DestReg, SrcReg1, ~op2, true);" "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, src1, ~op2, true);"
genCCFlagBitsLogic = ''' genCCFlagBitsLogic = '''
//Don't have genFlags handle the OF or CF bits //Don't have genFlags handle the OF or CF bits
uint64_t mask = CFBit | OFBit; uint64_t mask = CFBit | OFBit;
ccFlagBits = genFlags(ccFlagBits, ext & ~mask, DestReg, SrcReg1, op2); ccFlagBits = genFlags(ccFlagBits, ext & ~mask, DestReg, src1, op2);
//If a logic microop wants to set these, it wants to set them to 0. //If a logic microop wants to set these, it wants to set them to 0.
ccFlagBits &= ~(CFBit & ext); ccFlagBits &= ~(CFBit & ext);
ccFlagBits &= ~(OFBit & ext); ccFlagBits &= ~(OFBit & ext);
''' '''
regPick = '''
IntReg src1 = pick(SrcReg1, 0, dataSize);
IntReg src2 = pick(SrcReg2, 1, dataSize);
'''
immPick = '''
IntReg src1 = pick(SrcReg1, 0, dataSize);
'''
# This creates a python representations of a microop which are a cross # This creates a python representations of a microop which are a cross
# product of reg/immediate and flag/no flag versions. # product of reg/immediate and flag/no flag versions.
@ -351,8 +360,8 @@ let {{
# of the code, one with an integer operand, and one with an immediate # of the code, one with an integer operand, and one with an immediate
# operand. # operand.
matcher = re.compile("op2(?P<typeQual>\\.\\w+)?") matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
regCode = matcher.sub("SrcReg2", code) regCode = regPick + matcher.sub("src2", code)
immCode = matcher.sub("imm8", code) immCode = immPick + matcher.sub("imm8", code)
if not cc: if not cc:
condCode = "true" condCode = "true"
@ -360,7 +369,7 @@ let {{
flagCode = "" flagCode = ""
condCode = checkCCFlagBits condCode = checkCCFlagBits
regFlagCode = matcher.sub("SrcReg2", flagCode) regFlagCode = matcher.sub("src2", flagCode)
immFlagCode = matcher.sub("imm8", flagCode) immFlagCode = matcher.sub("imm8", flagCode)
class RegOpChild(RegOp): class RegOpChild(RegOp):
@ -374,8 +383,9 @@ let {{
microopClasses[name] = RegOpChild microopClasses[name] = RegOpChild
setUpMicroRegOp(name, Name, "X86ISA::RegOp", regCode); setUpMicroRegOp(name, Name, "X86ISA::RegOp", regCode);
setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOp", regCode, setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOp",
flagCode=regFlagCode, condCheck=condCode, elseCode=elseCode); regCode, flagCode=regFlagCode,
condCheck=condCode, elseCode=elseCode);
class RegOpChildImm(RegOpImm): class RegOpChildImm(RegOpImm):
mnemonic = name + 'i' mnemonic = name + 'i'
@ -388,8 +398,9 @@ let {{
microopClasses[name + 'i'] = RegOpChildImm microopClasses[name + 'i'] = RegOpChildImm
setUpMicroRegOp(name + "i", Name + "Imm", "X86ISA::RegOpImm", immCode); setUpMicroRegOp(name + "i", Name + "Imm", "X86ISA::RegOpImm", immCode);
setUpMicroRegOp(name + "i", Name + "ImmFlags", "X86ISA::RegOpImm", immCode, setUpMicroRegOp(name + "i", Name + "ImmFlags", "X86ISA::RegOpImm",
flagCode=immFlagCode, condCheck=condCode, elseCode=elseCode); immCode, flagCode=immFlagCode,
condCheck=condCode, elseCode=elseCode);
# This has it's own function because Wr ops have implicit destinations # This has it's own function because Wr ops have implicit destinations
def defineMicroRegOpWr(mnemonic, code, elseCode=";"): def defineMicroRegOpWr(mnemonic, code, elseCode=";"):
@ -400,8 +411,8 @@ let {{
# of the code, one with an integer operand, and one with an immediate # of the code, one with an integer operand, and one with an immediate
# operand. # operand.
matcher = re.compile("op2(?P<typeQual>\\.\\w+)?") matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
regCode = matcher.sub("SrcReg2", code) regCode = regPick + matcher.sub("src2", code)
immCode = matcher.sub("imm8", code) immCode = immPick + matcher.sub("imm8", code)
class RegOpChild(RegOp): class RegOpChild(RegOp):
mnemonic = name mnemonic = name
@ -445,6 +456,7 @@ let {{
def defineMicroRegOpImm(mnemonic, code): def defineMicroRegOpImm(mnemonic, code):
Name = mnemonic Name = mnemonic
name = mnemonic.lower() name = mnemonic.lower()
code = immPick + code
class RegOpChild(RegOpImm): class RegOpChild(RegOpImm):
def __init__(self, dest, src1, src2, dataSize="env.dataSize"): def __init__(self, dest, src1, src2, dataSize="env.dataSize"):
@ -456,35 +468,66 @@ let {{
setUpMicroRegOp(name, Name, "X86ISA::RegOpImm", code); setUpMicroRegOp(name, Name, "X86ISA::RegOpImm", code);
defineMicroRegOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)') defineMicroRegOp('Add', 'DestReg = merge(DestReg, src1 + op2, dataSize)')
defineMicroRegOp('Or', 'DestReg = merge(DestReg, SrcReg1 | op2, dataSize)', defineMicroRegOp('Or', '''
DPRINTF(X86, "src1 = %#x\\n", src1);
DPRINTF(X86, "op2 = %#x\\n", op2);
DestReg = merge(DestReg, src1 | op2, dataSize);
''',
flagCode = genCCFlagBitsLogic) flagCode = genCCFlagBitsLogic)
defineMicroRegOp('Adc', ''' defineMicroRegOp('Adc', '''
CCFlagBits flags = ccFlagBits; CCFlagBits flags = ccFlagBits;
DestReg = merge(DestReg, SrcReg1 + op2 + flags.CF, dataSize); DestReg = merge(DestReg, src1 + op2 + flags.CF, dataSize);
''') ''')
defineMicroRegOp('Sbb', ''' defineMicroRegOp('Sbb', '''
CCFlagBits flags = ccFlagBits; CCFlagBits flags = ccFlagBits;
DestReg = merge(DestReg, SrcReg1 - op2 - flags.CF, dataSize); DestReg = merge(DestReg, src1 - op2 - flags.CF, dataSize);
''', flagCode = genCCFlagBitsSub) ''', flagCode = genCCFlagBitsSub)
defineMicroRegOp('And', \ defineMicroRegOp('And', \
'DestReg = merge(DestReg, SrcReg1 & op2, dataSize)', \ 'DestReg = merge(DestReg, src1 & op2, dataSize)', \
flagCode = genCCFlagBitsLogic) flagCode = genCCFlagBitsLogic)
defineMicroRegOp('Sub', \ defineMicroRegOp('Sub', \
'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', \ 'DestReg = merge(DestReg, src1 - op2, dataSize)', \
flagCode = genCCFlagBitsSub) flagCode = genCCFlagBitsSub)
defineMicroRegOp('Xor', \ defineMicroRegOp('Xor', \
'DestReg = merge(DestReg, SrcReg1 ^ op2, dataSize)', \ 'DestReg = merge(DestReg, src1 ^ op2, dataSize)', \
flagCode = genCCFlagBitsLogic) flagCode = genCCFlagBitsLogic)
defineMicroRegOp('Mul1s', \ defineMicroRegOp('Mul1s', '''
'DestReg = merge(DestReg, DestReg * op2, dataSize)') int signPos = (dataSize * 8) / 2 - 1;
defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)', IntReg srcVal1 = src1 | (-bits(src1, signPos) << signPos);
IntReg srcVal2 = op2 | (-bits(src1, signPos) << signPos);
DestReg = merge(DestReg, srcVal1 * srcVal2, dataSize)
''')
defineMicroRegOp('Mul1u', '''
int halfSize = (dataSize * 8) / 2;
IntReg srcVal1 = src1 & mask(halfSize);
IntReg srcVal2 = op2 & mask(halfSize);
DestReg = merge(DestReg, srcVal1 * srcVal2, dataSize)
''')
defineMicroRegOp('Mulel', \
'DestReg = merge(DestReg, src1 * op2, dataSize)')
defineMicroRegOp('Muleh', '''
int halfSize = (dataSize * 8) / 2;
uint64_t src1_h = src1 >> halfSize;
uint64_t src1_l = src1 & mask(halfSize);
uint64_t src2_h = op2 >> halfSize;
uint64_t src2_l = op2 & mask(halfSize);
uint64_t result =
((src1_l * src2_h) >> halfSize) +
((src1_h * src2_l) >> halfSize) +
src1_h * src2_h;
DestReg = merge(DestReg, result, dataSize);
''')
#
# HACK HACK HACK HACK - Put src1 in here but make it inert to shut up gcc.
#
defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, src1 * 0 + op2, dataSize)',
elseCode='DestReg=DestReg;', cc=True) elseCode='DestReg=DestReg;', cc=True)
# Shift instructions # Shift instructions
defineMicroRegOp('Sll', ''' defineMicroRegOp('Sll', '''
uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
DestReg = merge(DestReg, SrcReg1 << shiftAmt, dataSize); DestReg = merge(DestReg, src1 << shiftAmt, dataSize);
''') ''')
defineMicroRegOp('Srl', ''' defineMicroRegOp('Srl', '''
uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
@ -492,7 +535,7 @@ let {{
// is not defined in the C/C++ standard, we have to mask them out // is not defined in the C/C++ standard, we have to mask them out
// to be sure they're zero. // to be sure they're zero.
uint64_t logicalMask = mask(dataSize * 8 - shiftAmt); uint64_t logicalMask = mask(dataSize * 8 - shiftAmt);
DestReg = merge(DestReg, (SrcReg1 >> shiftAmt) & logicalMask, dataSize); DestReg = merge(DestReg, (src1 >> shiftAmt) & logicalMask, dataSize);
''') ''')
defineMicroRegOp('Sra', ''' defineMicroRegOp('Sra', '''
uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5))); uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
@ -501,15 +544,15 @@ let {{
// them manually to be sure. // them manually to be sure.
uint64_t arithMask = uint64_t arithMask =
-bits(op2, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt); -bits(op2, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt);
DestReg = merge(DestReg, (SrcReg1 >> shiftAmt) | arithMask, dataSize); DestReg = merge(DestReg, (src1 >> shiftAmt) | arithMask, dataSize);
''') ''')
defineMicroRegOp('Ror', ''' defineMicroRegOp('Ror', '''
uint8_t shiftAmt = uint8_t shiftAmt =
(op2 & ((dataSize == 8) ? mask(6) : mask(5))); (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
if(shiftAmt) if(shiftAmt)
{ {
uint64_t top = SrcReg1 << (dataSize * 8 - shiftAmt); uint64_t top = src1 << (dataSize * 8 - shiftAmt);
uint64_t bottom = bits(SrcReg1, dataSize * 8, shiftAmt); uint64_t bottom = bits(src1, dataSize * 8, shiftAmt);
DestReg = merge(DestReg, top | bottom, dataSize); DestReg = merge(DestReg, top | bottom, dataSize);
} }
else else
@ -523,8 +566,8 @@ let {{
CCFlagBits flags = ccFlagBits; CCFlagBits flags = ccFlagBits;
uint64_t top = flags.CF << (dataSize * 8 - shiftAmt); uint64_t top = flags.CF << (dataSize * 8 - shiftAmt);
if(shiftAmt > 1) if(shiftAmt > 1)
top |= SrcReg1 << (dataSize * 8 - shiftAmt - 1); top |= src1 << (dataSize * 8 - shiftAmt - 1);
uint64_t bottom = bits(SrcReg1, dataSize * 8, shiftAmt); uint64_t bottom = bits(src1, dataSize * 8, shiftAmt);
DestReg = merge(DestReg, top | bottom, dataSize); DestReg = merge(DestReg, top | bottom, dataSize);
} }
else else
@ -535,9 +578,9 @@ let {{
(op2 & ((dataSize == 8) ? mask(6) : mask(5))); (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
if(shiftAmt) if(shiftAmt)
{ {
uint64_t top = SrcReg1 << shiftAmt; uint64_t top = src1 << shiftAmt;
uint64_t bottom = uint64_t bottom =
bits(SrcReg1, dataSize * 8 - 1, dataSize * 8 - shiftAmt); bits(src1, dataSize * 8 - 1, dataSize * 8 - shiftAmt);
DestReg = merge(DestReg, top | bottom, dataSize); DestReg = merge(DestReg, top | bottom, dataSize);
} }
else else
@ -549,27 +592,27 @@ let {{
if(shiftAmt) if(shiftAmt)
{ {
CCFlagBits flags = ccFlagBits; CCFlagBits flags = ccFlagBits;
uint64_t top = SrcReg1 << shiftAmt; uint64_t top = src1 << shiftAmt;
uint64_t bottom = flags.CF << (shiftAmt - 1); uint64_t bottom = flags.CF << (shiftAmt - 1);
if(shiftAmt > 1) if(shiftAmt > 1)
bottom |= bottom |=
bits(SrcReg1, dataSize * 8 - 1, bits(src1, dataSize * 8 - 1,
dataSize * 8 - shiftAmt + 1); dataSize * 8 - shiftAmt + 1);
DestReg = merge(DestReg, top | bottom, dataSize); DestReg = merge(DestReg, top | bottom, dataSize);
} }
else else
DestReg = DestReg; DestReg = DestReg;
''') ''')
defineMicroRegOpWr('Wrip', 'RIP = SrcReg1 + op2', elseCode="RIP = RIP;") defineMicroRegOpWr('Wrip', 'RIP = src1 + op2', elseCode="RIP = RIP;")
defineMicroRegOpRd('Rdip', 'DestReg = RIP') defineMicroRegOpRd('Rdip', 'DestReg = RIP')
defineMicroRegOpImm('Sext', ''' defineMicroRegOpImm('Sext', '''
IntReg val = SrcReg1; IntReg val = src1;
int sign_bit = bits(val, imm8-1, imm8-1); int sign_bit = bits(val, imm8-1, imm8-1);
val = sign_bit ? (val | ~mask(imm8)) : val; val = sign_bit ? (val | ~mask(imm8)) : val;
DestReg = merge(DestReg, val, dataSize);''') DestReg = merge(DestReg, val, dataSize);''')
defineMicroRegOpImm('Zext', 'DestReg = bits(SrcReg1, imm8-1, 0);') defineMicroRegOpImm('Zext', 'DestReg = bits(src1, imm8-1, 0);')
}}; }};