summaryrefslogtreecommitdiff
path: root/src/arch/x86/isa
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86/isa')
-rw-r--r--src/arch/x86/isa/decoder/one_byte_opcodes.isa4
-rw-r--r--src/arch/x86/isa/formats/formats.isa4
-rw-r--r--src/arch/x86/isa/formats/string.isa88
-rw-r--r--src/arch/x86/isa/insts/string/scan_string.py65
-rw-r--r--src/arch/x86/isa/microasm.isa6
-rw-r--r--src/arch/x86/isa/microops/regop.isa96
-rw-r--r--src/arch/x86/isa/operands.isa4
7 files changed, 219 insertions, 48 deletions
diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa
index cce07d6fe..ee7fbc683 100644
--- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa
+++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa
@@ -342,8 +342,8 @@
0x3: stos_Yv_rAX();
0x4: lods_Al_Xb();
0x5: lods_rAX_Xv();
- 0x6: scas_Yb_Al();
- 0x7: scas_Yv_rAX();
+ 0x6: StringInst::SCAS(Yb);
+ 0x7: StringInst::SCAS(Yv);
}
format Inst {
0x16: MOV(Bb,Ib);
diff --git a/src/arch/x86/isa/formats/formats.isa b/src/arch/x86/isa/formats/formats.isa
index 1e7bb4a74..6906413c0 100644
--- a/src/arch/x86/isa/formats/formats.isa
+++ b/src/arch/x86/isa/formats/formats.isa
@@ -99,6 +99,10 @@
//thing on a variety of inputs
##include "multi.isa"
+//Include a format which implements an extra layer of decoding to handle the
+//repe and repne prefixes
+##include "string.isa"
+
//Include a format which makes instructions who's sole purpose is to generate
//a syscall.
##include "syscall.isa"
diff --git a/src/arch/x86/isa/formats/string.isa b/src/arch/x86/isa/formats/string.isa
new file mode 100644
index 000000000..cd182ff62
--- /dev/null
+++ b/src/arch/x86/isa/formats/string.isa
@@ -0,0 +1,88 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007 The Hewlett-Packard Development Company
+// All rights reserved.
+//
+// Redistribution and use of this software in source and binary forms,
+// with or without modification, are permitted provided that the
+// following conditions are met:
+//
+// The software must be used only for Non-Commercial Use which means any
+// use which is NOT directed to receiving any direct monetary
+// compensation for, or commercial advantage from such use. Illustrative
+// examples of non-commercial use are academic research, personal study,
+// teaching, education and corporate research & development.
+// Illustrative examples of commercial use are distributing products for
+// commercial advantage and providing services using the software for
+// commercial advantage.
+//
+// If you wish to use this software or functionality therein that may be
+// covered by patents for commercial use, please contact:
+// Director of Intellectual Property Licensing
+// Office of Strategy and Technology
+// Hewlett-Packard Company
+// 1501 Page Mill Road
+// Palo Alto, California 94304
+//
+// Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer. Redistributions
+// in binary form must reproduce the above copyright notice, this list of
+// conditions and the following disclaimer in the documentation and/or
+// other materials provided with the distribution. Neither the name of
+// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission. No right of
+// sublicense is granted herewith. Derivatives of the software and
+// output created using the software may be prepared, but only for
+// Non-Commercial Uses. Derivatives of the software may be shared with
+// others provided: (i) the others agree to abide by the list of
+// conditions herein which includes the Non-Commercial Use restrictions;
+// and (ii) such Derivatives of the software include the above copyright
+// notice to acknowledge the contribution from this software where
+// applicable, this list of conditions and the disclaimer below.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: Gabe Black
+
+//////////////////////////////////////////////////////////////////////////
+//
+// String Instructions
+//
+//////////////////////////////////////////////////////////////////////////
+
+def format StringInst(*opTypeSet) {{
+ allBlocks = OutputBlocks()
+
+ regBlocks = specializeInst(Name, list(opTypeSet), EmulEnv())
+ eBlocks = specializeInst(Name + "_E", list(opTypeSet), EmulEnv())
+ nBlocks = specializeInst(Name + "_N", list(opTypeSet), EmulEnv())
+
+ for blocks in (regBlocks, eBlocks, nBlocks):
+ allBlocks.header_output += blocks.header_output
+ allBlocks.decoder_output += blocks.decoder_output
+ allBlocks.exec_output += blocks.exec_output
+
+ allBlocks.decode_block = '''
+ if (LEGACY_REP) {
+ %s
+ } else if (LEGACY_REPNE) {
+ %s
+ } else {
+ %s
+ }
+ ''' % (eBlocks.decode_block, nBlocks.decode_block, regBlocks.decode_block)
+
+ (header_output, decoder_output,
+ decode_block, exec_output) = allBlocks.makeList()
+}};
diff --git a/src/arch/x86/isa/insts/string/scan_string.py b/src/arch/x86/isa/insts/string/scan_string.py
index cd3d5b549..b038cc00a 100644
--- a/src/arch/x86/isa/insts/string/scan_string.py
+++ b/src/arch/x86/isa/insts/string/scan_string.py
@@ -53,16 +53,55 @@
#
# Authors: Gabe Black
-microcode = ""
-#let {{
-# class SCAS(Inst):
-# "GenFault ${new UnimpInstFault}"
-# class SCASB(Inst):
-# "GenFault ${new UnimpInstFault}"
-# class SCASW(Inst):
-# "GenFault ${new UnimpInstFault}"
-# class SCASD(Inst):
-# "GenFault ${new UnimpInstFault}"
-# class SCASQ(Inst):
-# "GenFault ${new UnimpInstFault}"
-#}};
+microcode = '''
+def macroop SCAS_M {
+ # Find the constant we need to either add or subtract from rdi
+ ruflag t0, 10
+ movi t2, t2, dsz, flags=(CEZF,), dataSize=asz
+ subi t3, t0, dsz, dataSize=asz
+ mov t2, t2, t3, flags=(nCEZF,), dataSize=asz
+
+ ld t1, es, [1, t0, rdi]
+ sub t0, t1, rax, flags=(OF, SF, ZF, AF, PF, CF)
+
+ add rdi, rdi, t2, dataSize=asz
+};
+
+#
+# Versions which have the rep prefix. These could benefit from some loop
+# unrolling.
+#
+
+def macroop SCAS_E_M {
+ # Find the constant we need to either add or subtract from rdi
+ ruflag t0, 10
+ movi t2, t2, dsz, flags=(CEZF,), dataSize=asz
+ subi t3, t0, dsz, dataSize=asz
+ mov t2, t2, t3, flags=(nCEZF,), dataSize=asz
+
+ ld t1, es, [1, t0, rdi]
+ sub t0, t1, rax, flags=(OF, SF, ZF, AF, PF, CF)
+
+ subi rcx, rcx, 1, flags=(EZF,), dataSize=asz
+ add rdi, rdi, t2, dataSize=asz
+ bri t0, 4, flags=(CSTRZnEZF,)
+ fault "NoFault"
+};
+
+def macroop SCAS_N_M {
+ # Find the constant we need to either add or subtract from rdi
+ ruflag t0, 10
+ movi t2, t2, dsz, flags=(CEZF,), dataSize=asz
+ subi t3, t0, dsz, dataSize=asz
+ mov t2, t2, t3, flags=(nCEZF,), dataSize=asz
+
+ ld t1, es, [1, t0, rdi]
+ sub t0, t1, rax, flags=(OF, SF, ZF, AF, PF, CF)
+
+ subi rcx, rcx, 1, flags=(EZF,), dataSize=asz
+ add rdi, rdi, t2, dataSize=asz
+ bri t0, 4, flags=(CSTRnZnEZF,)
+ fault "NoFault"
+};
+
+'''
diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa
index 5c567a30c..af3148631 100644
--- a/src/arch/x86/isa/microasm.isa
+++ b/src/arch/x86/isa/microasm.isa
@@ -89,7 +89,7 @@ let {{
"index" : "env.index",
"base" : "env.base",
"dsz" : "env.dataSize",
- "osz" : "env.operandSize",
+ "asz" : "env.addressSize",
"ssz" : "env.stackSize"
}
assembler.symbols.update(symbols)
@@ -107,11 +107,13 @@ let {{
assembler.symbols[flag] = flag + "Bit"
for cond in ('True', 'False', 'ECF', 'EZF', 'SZnZF',
- 'MSTRZ', 'STRZ', 'MSTRC', 'STRZnZF',
+ 'MSTRZ', 'STRZ', 'MSTRC',
'OF', 'CF', 'ZF', 'CvZF',
'SF', 'PF', 'SxOF', 'SxOvZF'):
assembler.symbols["C%s" % cond] = "ConditionTests::%s" % cond
assembler.symbols["nC%s" % cond] = "ConditionTests::Not%s" % cond
+ assembler.symbols["CSTRZnEZF"] = "ConditionTests::STRZnEZF"
+ assembler.symbols["CSTRnZnEZF"] = "ConditionTests::STRnZnEZF"
assembler.symbols["CTrue"] = "ConditionTests::True"
assembler.symbols["CFalse"] = "ConditionTests::False"
diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa
index ac88be657..608b86a70 100644
--- a/src/arch/x86/isa/microops/regop.isa
+++ b/src/arch/x86/isa/microops/regop.isa
@@ -89,7 +89,7 @@ def template MicroRegOpExecute {{
}};
def template MicroRegOpImmExecute {{
- Fault %(class_name)sImm::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
@@ -140,21 +140,21 @@ def template MicroRegOpDeclare {{
def template MicroRegOpImmDeclare {{
- class %(class_name)sImm : public %(base_class)s
+ class %(class_name)s : public %(base_class)s
{
protected:
void buildMe();
public:
- %(class_name)sImm(ExtMachInst _machInst,
+ %(class_name)s(ExtMachInst _machInst,
const char * instMnem,
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
- RegIndex _src1, uint8_t _imm8, RegIndex _dest,
+ RegIndex _src1, uint16_t _imm8, RegIndex _dest,
uint8_t _dataSize, uint16_t _ext);
- %(class_name)sImm(ExtMachInst _machInst,
+ %(class_name)s(ExtMachInst _machInst,
const char * instMnem,
- RegIndex _src1, uint8_t _imm8, RegIndex _dest,
+ RegIndex _src1, uint16_t _imm8, RegIndex _dest,
uint8_t _dataSize, uint16_t _ext);
%(BasicExecDeclare)s
@@ -196,14 +196,14 @@ def template MicroRegOpConstructor {{
def template MicroRegOpImmConstructor {{
- inline void %(class_name)sImm::buildMe()
+ inline void %(class_name)s::buildMe()
{
%(constructor)s;
}
- inline %(class_name)sImm::%(class_name)sImm(
+ inline %(class_name)s::%(class_name)s(
ExtMachInst machInst, const char * instMnem,
- RegIndex _src1, uint8_t _imm8, RegIndex _dest,
+ RegIndex _src1, uint16_t _imm8, RegIndex _dest,
uint8_t _dataSize, uint16_t _ext) :
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
false, false, false, false,
@@ -213,10 +213,10 @@ def template MicroRegOpImmConstructor {{
buildMe();
}
- inline %(class_name)sImm::%(class_name)sImm(
+ inline %(class_name)s::%(class_name)s(
ExtMachInst machInst, const char * instMnem,
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
- RegIndex _src1, uint8_t _imm8, RegIndex _dest,
+ RegIndex _src1, uint16_t _imm8, RegIndex _dest,
uint8_t _dataSize, uint16_t _ext) :
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
isMicro, isDelayed, isFirst, isLast,
@@ -310,7 +310,7 @@ let {{
exec_output = ""
# A function which builds the C++ classes that implement the microops
- def setUpMicroRegOp(name, Name, base, code, flagCode = "", condCheck = "true", elseCode = ";"):
+ def setUpMicroRegOp(name, Name, base, code, flagCode = "", condCheck = "true", elseCode = ";", imm=False):
global header_output
global decoder_output
global exec_output
@@ -321,9 +321,14 @@ let {{
"flag_code" : flagCode,
"cond_check" : condCheck,
"else_code" : elseCode})
- header_output += MicroRegOpDeclare.subst(iop)
- decoder_output += MicroRegOpConstructor.subst(iop)
- exec_output += MicroRegOpExecute.subst(iop)
+ if imm:
+ header_output += MicroRegOpImmDeclare.subst(iop)
+ decoder_output += MicroRegOpImmConstructor.subst(iop)
+ exec_output += MicroRegOpImmExecute.subst(iop)
+ else:
+ header_output += MicroRegOpDeclare.subst(iop)
+ decoder_output += MicroRegOpConstructor.subst(iop)
+ exec_output += MicroRegOpExecute.subst(iop)
checkCCFlagBits = "checkCondition(ccFlagBits)"
@@ -397,10 +402,11 @@ let {{
microopClasses[name + 'i'] = RegOpChildImm
- setUpMicroRegOp(name + "i", Name + "Imm", "X86ISA::RegOpImm", immCode);
+ setUpMicroRegOp(name + "i", Name + "Imm", "X86ISA::RegOpImm", \
+ immCode, imm=True);
setUpMicroRegOp(name + "i", Name + "ImmFlags", "X86ISA::RegOpImm",
immCode, flagCode=immFlagCode,
- condCheck=condCode, elseCode=elseCode);
+ condCheck=condCode, elseCode=elseCode, imm=True);
# This has it's own function because Wr ops have implicit destinations
def defineMicroRegOpWr(mnemonic, code, elseCode=";"):
@@ -434,9 +440,11 @@ let {{
microopClasses[name + 'i'] = RegOpChildImm
- setUpMicroRegOp(name + 'i', Name + "Imm", "X86ISA::RegOpImm", immCode);
- setUpMicroRegOp(name + 'i', Name + "ImmFlags", "X86ISA::RegOpImm", immCode,
- condCheck = checkCCFlagBits, elseCode = elseCode);
+ setUpMicroRegOp(name + 'i', Name + "Imm", "X86ISA::RegOpImm", \
+ immCode, imm=True);
+ setUpMicroRegOp(name + 'i', Name + "ImmFlags", "X86ISA::RegOpImm", \
+ immCode, condCheck = checkCCFlagBits, elseCode = elseCode, \
+ imm=True);
# This has it's own function because Rd ops don't always have two parameters
def defineMicroRegOpRd(mnemonic, code):
@@ -444,29 +452,52 @@ let {{
name = mnemonic.lower()
class RegOpChild(RegOp):
+ className = Name
+ mnemonic = name
def __init__(self, dest, src1 = "NUM_INTREGS", dataSize="env.dataSize"):
super(RegOpChild, self).__init__(dest, src1, "NUM_INTREGS", None, dataSize)
- self.className = Name
- self.mnemonic = name
microopClasses[name] = RegOpChild
setUpMicroRegOp(name, Name, "X86ISA::RegOp", code);
- def defineMicroRegOpImm(mnemonic, code):
+ def defineMicroRegOpImm(mnemonic, code, flagCode=""):
Name = mnemonic
name = mnemonic.lower()
code = immPick + code
class RegOpChild(RegOpImm):
- def __init__(self, dest, src1, src2, dataSize="env.dataSize"):
- super(RegOpChild, self).__init__(dest, src1, src2, None, dataSize)
- self.className = Name
- self.mnemonic = name
+ className = Name
+ mnemonic = name
+ def __init__(self, dest, src1, src2, \
+ flags=None, dataSize="env.dataSize"):
+ super(RegOpChild, self).__init__(dest, \
+ src1, src2, flags, dataSize)
microopClasses[name] = RegOpChild
- setUpMicroRegOp(name, Name, "X86ISA::RegOpImm", code);
+ setUpMicroRegOp(name, Name, "X86ISA::RegOpImm", code, imm=True);
+ setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOpImm", \
+ code, flagCode=flagCode, imm=True);
+
+ def defineMicroRegOpRdImm(mnemonic, code, flagCode=""):
+ Name = mnemonic
+ name = mnemonic.lower()
+ code = immPick + code
+
+ class RegOpChildRdImm(RegOpImm):
+ className = Name
+ mnemonic = name
+ def __init__(self, dest, imm, flags=None, \
+ dataSize="env.dataSize"):
+ super(RegOpChildRdImm, self).__init__(dest, \
+ "NUM_INTREGS", imm, flags, dataSize)
+
+ microopClasses[name] = RegOpChildRdImm
+
+ setUpMicroRegOp(name, Name, "X86ISA::RegOpImm", code, imm=True);
+ setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOpImm", \
+ code, flagCode=flagCode, imm=True);
defineMicroRegOp('Add', 'DestReg = merge(DestReg, psrc1 + op2, dataSize)')
defineMicroRegOp('Or', 'DestReg = merge(DestReg, psrc1 | op2, dataSize);',
@@ -615,12 +646,17 @@ let {{
''')
defineMicroRegOpWr('Wrip', 'RIP = psrc1 + op2', elseCode="RIP = RIP;")
+ defineMicroRegOpWr('Br', 'nuIP = psrc1 + op2;', elseCode='nuIP = nuIP;')
defineMicroRegOpWr('Wruflags', 'ccFlagBits = psrc1 ^ op2')
defineMicroRegOpRd('Rdip', 'DestReg = RIP')
defineMicroRegOpRd('Ruflags', 'DestReg = ccFlagBits')
- defineMicroRegOpImm('Ruflag', 'DestReg = bits(ccFlagBits, imm8);', \
- flagCode = genCCFlagBitsLogic)
+ defineMicroRegOpRdImm('Ruflag', '''
+ int flag = bits(ccFlagBits, (1 << imm8) + 0*psrc1);
+ DestReg = merge(DestReg, flag, dataSize);
+ ccFlagBits = ccFlagBits & ~EZFBit;
+ ccFlagBits = ccFlagBits | ((flag == 0) ? EZFBit : 0);
+ ''')
defineMicroRegOpImm('Sext', '''
IntReg val = psrc1;
diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa
index 64179ca98..098a75370 100644
--- a/src/arch/x86/isa/operands.isa
+++ b/src/arch/x86/isa/operands.isa
@@ -104,7 +104,9 @@ def operands {{
'Data': ('IntReg', 'uqw', '(((data & 0x1C) == 4 ? foldOBit : 0) | data)', 'IsInteger', 6),
'rax': ('IntReg', 'uqw', '(INTREG_RAX)', 'IsInteger', 7),
'RIP': ('NPC', 'uqw', None, (None, None, 'IsControl'), 10),
- 'ccFlagBits': ('IntReg', 'uqw', 'NUM_INTREGS + NumMicroIntRegs', None, 20),
+ 'uIP': ('UPC', 'uqw', None, (None, None, 'IsControl'), 11),
+ 'nuIP': ('NUPC', 'uqw', None, (None, None, 'IsControl'), 12),
+ 'ccFlagBits': ('IntReg', 'uqw', 'NUM_INTREGS + NumMicroIntRegs', None, 20),
'SegBase': ('ControlReg', 'uqw', 'MISCREG_SEG_BASE_BASE + segment', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 50),
'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 100)
}};