diff options
Diffstat (limited to 'src/arch/x86/isa')
-rw-r--r-- | src/arch/x86/isa/decoder/one_byte_opcodes.isa | 4 | ||||
-rw-r--r-- | src/arch/x86/isa/formats/formats.isa | 4 | ||||
-rw-r--r-- | src/arch/x86/isa/formats/string.isa | 88 | ||||
-rw-r--r-- | src/arch/x86/isa/insts/string/scan_string.py | 65 | ||||
-rw-r--r-- | src/arch/x86/isa/microasm.isa | 6 | ||||
-rw-r--r-- | src/arch/x86/isa/microops/regop.isa | 96 | ||||
-rw-r--r-- | src/arch/x86/isa/operands.isa | 4 |
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) }}; |