diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2007-03-15 02:52:51 +0000 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2007-03-15 02:52:51 +0000 |
commit | 32368a2bd62409b303b0fcbe796fc94e4902657d (patch) | |
tree | af146159b4488dc9bf1c581162452a8de06a3d16 | |
parent | ff90b8c1aa99711eeb55c5eba29519f77cbc041c (diff) | |
parent | a2b56088fb4d12aee73ecfeaba88cfa46f98567e (diff) | |
download | gem5-32368a2bd62409b303b0fcbe796fc94e4902657d.tar.xz |
Merge zizzer.eecs.umich.edu:/bk/newmem
into ahchoo.blinky.homelinux.org:/home/gblack/m5/newmem-x86
src/arch/mips/utility.hh:
src/arch/x86/SConscript:
Hand merge
--HG--
extra : convert_revision : 0ba457aab52bf6ffc9191fd1fe1006ca7704b5b0
-rw-r--r-- | src/arch/SConscript | 1 | ||||
-rw-r--r-- | src/arch/alpha/predecoder.hh | 107 | ||||
-rw-r--r-- | src/arch/alpha/utility.hh | 13 | ||||
-rw-r--r-- | src/arch/mips/predecoder.hh | 100 | ||||
-rw-r--r-- | src/arch/mips/utility.hh | 13 | ||||
-rw-r--r-- | src/arch/sparc/predecoder.hh | 112 | ||||
-rw-r--r-- | src/arch/sparc/utility.hh | 16 | ||||
-rw-r--r-- | src/arch/x86/SConscript | 2 | ||||
-rw-r--r-- | src/arch/x86/isa/formats/unknown.isa | 3 | ||||
-rw-r--r-- | src/arch/x86/predecoder.hh | 412 | ||||
-rw-r--r-- | src/arch/x86/predecoder_tables.cc | 143 | ||||
-rw-r--r-- | src/arch/x86/types.hh | 71 | ||||
-rw-r--r-- | src/arch/x86/utility.hh | 16 | ||||
-rw-r--r-- | src/cpu/base.hh | 8 | ||||
-rw-r--r-- | src/cpu/o3/fetch.hh | 4 | ||||
-rw-r--r-- | src/cpu/o3/fetch_impl.hh | 12 | ||||
-rw-r--r-- | src/cpu/simple/atomic.cc | 32 | ||||
-rw-r--r-- | src/cpu/simple/base.cc | 55 | ||||
-rw-r--r-- | src/cpu/simple/base.hh | 11 | ||||
-rw-r--r-- | src/cpu/static_inst.hh | 6 |
20 files changed, 1034 insertions, 103 deletions
diff --git a/src/arch/SConscript b/src/arch/SConscript index c3ff69f46..0ac25b6c7 100644 --- a/src/arch/SConscript +++ b/src/arch/SConscript @@ -51,6 +51,7 @@ isa_switch_hdrs = Split(''' locked_mem.hh mmaped_ipr.hh process.hh + predecoder.hh regfile.hh remote_gdb.hh stacktrace.hh diff --git a/src/arch/alpha/predecoder.hh b/src/arch/alpha/predecoder.hh new file mode 100644 index 000000000..4e89f53a6 --- /dev/null +++ b/src/arch/alpha/predecoder.hh @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: 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 holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * 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 + */ + +#ifndef __ARCH_ALPHA_PREDECODER_HH__ +#define __ARCH_ALPHA_PREDECODER_HH__ + +#include "arch/alpha/types.hh" +#include "base/misc.hh" +#include "sim/host.hh" + +class ThreadContext; + +namespace AlphaISA +{ + class Predecoder + { + protected: + ThreadContext * tc; + //The pc of the current instruction + Addr fetchPC; + //The extended machine instruction being generated + ExtMachInst ext_inst; + + public: + Predecoder(ThreadContext * _tc) : tc(_tc) + {} + + ThreadContext * getTC() + { + return tc; + } + + void setTC(ThreadContext * _tc) + { + tc = _tc; + } + + void process() + { + } + + //Use this to give data to the predecoder. This should be used + //when there is control flow. + void moreBytes(Addr pc, Addr off, MachInst inst) + { + fetchPC = pc; + assert(off == 0); + ext_inst = inst; +#if FULL_SYSTEM + if (pc && 0x1) + ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32); +#endif + } + + //Use this to give data to the predecoder. This should be used + //when instructions are executed in order. + void moreBytes(MachInst machInst) + { + moreBytes(fetchPC + sizeof(machInst), 0, machInst); + } + + bool needMoreBytes() + { + return true; + } + + bool extMachInstReady() + { + return true; + } + + //This returns a constant reference to the ExtMachInst to avoid a copy + const ExtMachInst & getExtMachInst() + { + return ext_inst; + } + }; +}; + +#endif // __ARCH_ALPHA_PREDECODER_HH__ diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh index b7844c7eb..c20394a92 100644 --- a/src/arch/alpha/utility.hh +++ b/src/arch/alpha/utility.hh @@ -48,19 +48,6 @@ namespace AlphaISA return (tc->readMiscRegNoEffect(AlphaISA::IPR_DTB_CM) & 0x18) != 0; } - static inline ExtMachInst - makeExtMI(MachInst inst, Addr pc) { -#if FULL_SYSTEM - ExtMachInst ext_inst = inst; - if (pc && 0x1) - return ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32); - else - return ext_inst; -#else - return ExtMachInst(inst); -#endif - } - inline bool isCallerSaveIntegerRegister(unsigned int reg) { panic("register classification not implemented"); return (reg >= 1 && reg <= 8 || reg >= 22 && reg <= 25 || reg == 27); diff --git a/src/arch/mips/predecoder.hh b/src/arch/mips/predecoder.hh new file mode 100644 index 000000000..a25cce8a7 --- /dev/null +++ b/src/arch/mips/predecoder.hh @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: 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 holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * 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 + */ + +#ifndef __ARCH_MIPS_PREDECODER_HH__ +#define __ARCH_MIPS_PREDECODER_HH__ + +#include "arch/mips/types.hh" +#include "base/misc.hh" +#include "sim/host.hh" + +class ThreadContext; + +namespace MipsISA +{ + class Predecoder + { + protected: + ThreadContext * tc; + //The extended machine instruction being generated + ExtMachInst emi; + + public: + Predecoder(ThreadContext * _tc) : tc(_tc) + {} + + ThreadContext * getTC() + { + return tc; + } + + void setTC(ThreadContext * _tc) + { + tc = _tc; + } + + void process() + { + } + + //Use this to give data to the predecoder. This should be used + //when there is control flow. + void moreBytes(Addr currPC, Addr off, MachInst inst) + { + assert(off == 0); + emi = inst; + } + + //Use this to give data to the predecoder. This should be used + //when instructions are executed in order. + void moreBytes(MachInst machInst) + { + moreBytes(0, 0, machInst); + } + + bool needMoreBytes() + { + return true; + } + + bool extMachInstReady() + { + return true; + } + + //This returns a constant reference to the ExtMachInst to avoid a copy + const ExtMachInst & getExtMachInst() + { + return emi; + } + }; +}; + +#endif // __ARCH_MIPS_PREDECODER_HH__ diff --git a/src/arch/mips/utility.hh b/src/arch/mips/utility.hh index b5c1e31e1..12db1de57 100644 --- a/src/arch/mips/utility.hh +++ b/src/arch/mips/utility.hh @@ -88,19 +88,6 @@ namespace MipsISA { return 0; } - static inline ExtMachInst - makeExtMI(MachInst inst, ThreadContext * xc) { -#if FULL_SYSTEM - ExtMachInst ext_inst = inst; - if (xc->readPC() && 0x1) - return ext_inst|=(static_cast<ExtMachInst>(xc->readPC() & 0x1) << 32); - else - return ext_inst; -#else - return ExtMachInst(inst); -#endif - } - inline void startupCPU(ThreadContext *tc, int cpuId) { tc->activate(0); diff --git a/src/arch/sparc/predecoder.hh b/src/arch/sparc/predecoder.hh new file mode 100644 index 000000000..71b14b020 --- /dev/null +++ b/src/arch/sparc/predecoder.hh @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: 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 holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * 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 + */ + +#ifndef __ARCH_SPARC_PREDECODER_HH__ +#define __ARCH_SPARC_PREDECODER_HH__ + +#include "arch/sparc/types.hh" +#include "base/misc.hh" +#include "sim/host.hh" + +class ThreadContext; + +namespace SparcISA +{ + class Predecoder + { + protected: + ThreadContext * tc; + //The extended machine instruction being generated + ExtMachInst emi; + + public: + Predecoder(ThreadContext * _tc) : tc(_tc) + {} + + ThreadContext * getTC() + { + return tc; + } + + void setTC(ThreadContext * _tc) + { + tc = _tc; + } + + void process() + { + } + + //Use this to give data to the predecoder. This should be used + //when there is control flow. + void moreBytes(Addr currPC, Addr off, MachInst inst) + { + assert(off == 0); + + emi = inst; + //The I bit, bit 13, is used to figure out where the ASI + //should come from. Use that in the ExtMachInst. This is + //slightly redundant, but it removes the need to put a condition + //into all the execute functions + if(inst & (1 << 13)) + emi |= (static_cast<ExtMachInst>( + tc->readMiscRegNoEffect(MISCREG_ASI)) + << (sizeof(MachInst) * 8)); + else + emi |= (static_cast<ExtMachInst>(bits(inst, 12, 5)) + << (sizeof(MachInst) * 8)); + } + + //Use this to give data to the predecoder. This should be used + //when instructions are executed in order. + void moreBytes(MachInst machInst) + { + moreBytes(0, 0, machInst); + } + + bool needMoreBytes() + { + return true; + } + + bool extMachInstReady() + { + return true; + } + + //This returns a constant reference to the ExtMachInst to avoid a copy + const ExtMachInst & getExtMachInst() + { + return emi; + } + }; +}; + +#endif // __ARCH_SPARC_PREDECODER_HH__ diff --git a/src/arch/sparc/utility.hh b/src/arch/sparc/utility.hh index dc9201401..1458231f2 100644 --- a/src/arch/sparc/utility.hh +++ b/src/arch/sparc/utility.hh @@ -48,22 +48,6 @@ namespace SparcISA tc->readMiscRegNoEffect(MISCREG_HPSTATE & (1 << 2))); } - inline ExtMachInst - makeExtMI(MachInst inst, ThreadContext * xc) { - ExtMachInst emi = (MachInst) inst; - //The I bit, bit 13, is used to figure out where the ASI - //should come from. Use that in the ExtMachInst. This is - //slightly redundant, but it removes the need to put a condition - //into all the execute functions - if(inst & (1 << 13)) - emi |= (static_cast<ExtMachInst>(xc->readMiscRegNoEffect(MISCREG_ASI)) - << (sizeof(MachInst) * 8)); - else - emi |= (static_cast<ExtMachInst>(bits(inst, 12, 5)) - << (sizeof(MachInst) * 8)); - return emi; - } - inline bool isCallerSaveIntegerRegister(unsigned int reg) { panic("register classification not implemented"); return false; diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript index f49225758..f693caf6f 100644 --- a/src/arch/x86/SConscript +++ b/src/arch/x86/SConscript @@ -84,11 +84,11 @@ # Authors: Gabe Black Import('*') - if env['TARGET_ISA'] == 'x86': Source('floatregfile.cc') Source('intregfile.cc') Source('miscregfile.cc') + Source('predecoder_tables.cc') Source('regfile.cc') Source('remote_gdb.cc') diff --git a/src/arch/x86/isa/formats/unknown.isa b/src/arch/x86/isa/formats/unknown.isa index 605ddcb69..43ddc20c1 100644 --- a/src/arch/x86/isa/formats/unknown.isa +++ b/src/arch/x86/isa/formats/unknown.isa @@ -120,7 +120,8 @@ output exec {{ Fault Unknown::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { - panic("No instructions are implemented for X86!\n"); + warn("No instructions are implemented for X86!\n"); + return NoFault; } }}; diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh new file mode 100644 index 000000000..371ce9db9 --- /dev/null +++ b/src/arch/x86/predecoder.hh @@ -0,0 +1,412 @@ +/* + * 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 + */ + +#ifndef __ARCH_X86_PREDECODER_HH__ +#define __ARCH_X86_PREDECODER_HH__ + +#include "arch/x86/types.hh" +#include "base/bitfield.hh" +#include "base/misc.hh" +#include "sim/host.hh" + +class ThreadContext; + +namespace X86ISA +{ + class Predecoder + { + private: + static const uint8_t Prefixes[256]; + static const uint8_t UsesModRM[2][256]; + + protected: + ThreadContext * tc; + //The bytes to be predecoded + MachInst fetchChunk; + //The pc of the start of fetchChunk + Addr basePC; + //The offset into fetchChunk of current processing + int offset; + //The extended machine instruction being generated + ExtMachInst emi; + + //State machine state + protected: + //Whether or not we're out of bytes + bool outOfBytes; + //Whether we've completed generating an ExtMachInst + bool emiIsReady; + //The size of the displacement value + int displacementSize; + int displacementCollected; + //The size of the immediate value + int immediateSize; + int immediateCollected; + + //These are local to some of the states. I need to turn the states + //into inline functions to clean things up a bit. + int toGet; + int remaining; + MachInst partialDisp; + + enum State { + Prefix, + Opcode, + ModRM, + SIB, + Displacement, + Immediate + }; + + State state; + + public: + Predecoder(ThreadContext * _tc) : + tc(_tc), basePC(0), offset(0), + outOfBytes(true), emiIsReady(false), + state(Prefix) + {} + + ThreadContext * getTC() + { + return tc; + } + + void setTC(ThreadContext * _tc) + { + tc = _tc; + } + + void process() + { + warn("About to process some bytes\n"); + assert(!outOfBytes); + assert(!emiIsReady); + while(!emiIsReady && !outOfBytes) + { + uint8_t nextByte = (fetchChunk >> (offset * 8)) & 0xff; + switch(state) + { + case Prefix: + uint8_t prefix = Prefixes[nextByte]; + switch(prefix) + { + //Operand size override prefixes + case OperandSizeOverride: + warn("Found operand size override prefix!\n"); + offset++; + break; + case AddressSizeOverride: + warn("Found address size override prefix!\n"); + offset++; + break; + //Segment override prefixes + case CSOverride: + warn("Found cs segment override!\n"); + offset++; + break; + case DSOverride: + warn("Found ds segment override!\n"); + offset++; + break; + case ESOverride: + warn("Found es segment override!\n"); + offset++; + break; + case FSOverride: + warn("Found fs segment override!\n"); + offset++; + break; + case GSOverride: + warn("Found gs segment override!\n"); + offset++; + break; + case SSOverride: + warn("Found ss segment override!\n"); + offset++; + break; + case Lock: + warn("Found lock prefix!\n"); + offset++; + break; + case Rep: + warn("Found rep prefix!\n"); + offset++; + break; + case Repne: + warn("Found repne prefix!\n"); + offset++; + break; + case Rex: + warn("Found Rex prefix %#x!\n", nextByte); + offset++; + break; + case 0: + emi.twoByteOpcode = false; + state = Opcode; + break; + default: + panic("Unrecognized prefix %#x\n", nextByte); + } + break; + case Opcode: + if(nextByte == 0xf0) + { + warn("Found two byte opcode!\n"); + emi.twoByteOpcode = true; + } + else + { + warn("Found opcode %#x!\n", nextByte); + if (UsesModRM[emi.twoByteOpcode ? 1 : 0][nextByte]) { + state = ModRM; + } else if(0 /* uses immediate */) { + //Figure out how big the immediate should be + immediateCollected = 0; + emi.immediate = 0; + state = Immediate; + } else { + emiIsReady = true; + state = Prefix; + } + } + offset++; + break; + case ModRM: + warn("Found modrm byte %#x!\n", nextByte); + if (0) {//in 16 bit mode + //figure out 16 bit displacement size + if(nextByte & 0xC7 == 0x06 || + nextByte & 0xC0 == 0x40) + displacementSize = 1; + else if(nextByte & 0xC7 == 0x80) + displacementSize = 2; + else + displacementSize = 0; + } else { + //figure out 32/64 bit displacement size + if(nextByte & 0xC7 == 0x06 || + nextByte & 0xC0 == 0x40) + displacementSize = 4; + else if(nextByte & 0xC7 == 0x80) + displacementSize = 2; + else + displacementSize = 4; + } + //If there's an SIB, get that next. + //There is no SIB in 16 bit mode. + if(nextByte & 0x7 == 4 && + nextByte & 0xC0 != 0xC0) { + // && in 32/64 bit mode) + state = SIB; + } else if(displacementSize) { + displacementCollected = 0; + emi.displacement = 0; + state = Displacement; + } else if(immediateSize) { + immediateCollected = 0; + emi.immediate = 0; + state = Immediate; + } else { + emiIsReady = true; + state = Prefix; + } + //The ModRM byte is consumed no matter what + offset++; + break; + case SIB: + warn("Found SIB byte %#x!\n", nextByte); + offset++; + if(displacementSize) { + displacementCollected = 0; + emi.displacement = 0; + state = Displacement; + } else if(immediateSize) { + immediateCollected = 0; + emi.immediate = 0; + state = Immediate; + } else { + emiIsReady = true; + state = Prefix; + } + break; + case Displacement: + //Gather up the displacement, or at least as much of it + //as we can get. + + //Figure out how many bytes we still need to get for the + //displacement. + toGet = displacementSize - displacementCollected; + //Figure out how many bytes are left in our "buffer" + remaining = sizeof(MachInst) - offset; + //Get as much as we need, up to the amount available. + toGet = toGet > remaining ? remaining : toGet; + + //Shift the bytes we want to be all the way to the right + partialDisp = fetchChunk >> offset; + //Mask off what we don't want + partialDisp &= mask(toGet * 8); + //Shift it over to overlay with our displacement. + partialDisp <<= displacementCollected; + //Put it into our displacement + emi.displacement |= partialDisp; + //Update how many bytes we've collected. + displacementCollected += toGet; + + if(displacementSize == displacementCollected) { + //Sign extend the displacement + switch(displacementSize) + { + case 1: + emi.displacement = sext<8>(emi.displacement); + break; + case 2: + emi.displacement = sext<16>(emi.displacement); + break; + case 4: + emi.displacement = sext<32>(emi.displacement); + break; + default: + panic("Undefined displacement size!\n"); + } + if(immediateSize) { + immediateCollected = 0; + emi.immediate = 0; + state = Immediate; + } else { + emiIsReady = true; + state = Prefix; + } + } + break; + case Immediate: + //Gather up the displacement, or at least as much of it + //as we can get + + //Figure out how many bytes we still need to get for the + //immediate. + toGet = immediateSize - immediateCollected; + //Figure out how many bytes are left in our "buffer" + remaining = sizeof(MachInst) - offset; + //Get as much as we need, up to the amount available. + toGet = toGet > remaining ? remaining : toGet; + + //Shift the bytes we want to be all the way to the right + partialDisp = fetchChunk >> offset; + //Mask off what we don't want + partialDisp &= mask(toGet * 8); + //Shift it over to overlay with our immediate. + partialDisp <<= displacementCollected; + //Put it into our immediate + emi.displacement |= partialDisp; + //Update how many bytes we've collected. + displacementCollected += toGet; + if(immediateSize == immediateCollected) + { + emiIsReady = true; + state = Prefix; + } + break; + default: + panic("Unrecognized state! %d\n", state); + } + if(offset == sizeof(MachInst)) + outOfBytes = true; + } + } + + //Use this to give data to the predecoder. This should be used + //when there is control flow. + void moreBytes(Addr currPC, Addr off, MachInst data) + { + basePC = currPC; + offset = off; + fetchChunk = data; + assert(off < sizeof(MachInst)); + outOfBytes = false; + warn("About to call process.\n"); + process(); + } + + //Use this to give data to the predecoder. This should be used + //when instructions are executed in order. + void moreBytes(MachInst machInst) + { + moreBytes(basePC + sizeof(machInst), 0, machInst); + } + + bool needMoreBytes() + { + return outOfBytes; + } + + bool extMachInstReady() + { + return emiIsReady; + } + + //This returns a constant reference to the ExtMachInst to avoid a copy + const ExtMachInst & getExtMachInst() + { + assert(emiIsReady); + emiIsReady = false; + return emi; + } + }; +}; + +#endif // __ARCH_X86_PREDECODER_HH__ diff --git a/src/arch/x86/predecoder_tables.cc b/src/arch/x86/predecoder_tables.cc new file mode 100644 index 000000000..9304eee47 --- /dev/null +++ b/src/arch/x86/predecoder_tables.cc @@ -0,0 +1,143 @@ +/* + * 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 + */ + +#include "arch/x86/predecoder.hh" +#include "arch/x86/types.hh" + +namespace X86ISA +{ + const uint8_t CS = CSOverride; + const uint8_t DS = DSOverride; + const uint8_t ES = ESOverride; + const uint8_t FS = FSOverride; + const uint8_t GS = GSOverride; + const uint8_t SS = SSOverride; + + const uint8_t OO = OperandSizeOverride; + const uint8_t AO = AddressSizeOverride; + const uint8_t LO = Lock; + const uint8_t RE = Rep; + const uint8_t RN = Repne; + const uint8_t RX = Rex; + + //This table identifies whether a byte is a prefix, and if it is, + //which prefix it is. + const uint8_t Predecoder::Prefixes[256] = + { //LSB +// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F +/* 0*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 1*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 2*/ 0 , 0 , 0 , 0 , 0 , 0 , ES, 0 , 0 , 0 , 0 , 0 , 0 , 0 , CS, 0, +/* 3*/ 0 , 0 , 0 , 0 , 0 , 0 , SS, 0 , 0 , 0 , 0 , 0 , 0 , 0 , DS, 0, +/* 4*/ RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, +/* 5*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 6*/ 0 , 0 , 0 , 0 , FS, GS, OO, AO, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 7*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 8*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 9*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* A*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* B*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* C*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* D*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* E*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* F*/ LO, 0 , RN, RE, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 + }; + + //This table identifies whether a particular opcode uses the ModRM byte + const uint8_t Predecoder::UsesModRM[2][256] = + {//For one byte instructions + { //LSB +// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F +/* 0 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0, +/* 1 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0, +/* 2 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0, +/* 3 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0, +/* 4 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 5 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 6 */ 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1 , 0 , 0 , 0 , 0, +/* 7 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 8 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* A */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* B */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* C */ 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* D */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* E */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* F */ 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 + }, + //For two byte instructions + { //LSB +// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F +/* 0 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1, +/* 1 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 2 */ 1 , 1 , 1 , 1 , 1 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* 3 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 4 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* 5 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* 6 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* 7 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1, +/* 8 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 9 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* A */ 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1, +/* B */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1, +/* C */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* D */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* E */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* F */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 + } + }; +} diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh index 63f65eee5..68d95de94 100644 --- a/src/arch/x86/types.hh +++ b/src/arch/x86/types.hh @@ -59,13 +59,76 @@ #define __ARCH_X86_TYPES_HH__ #include <inttypes.h> +#include <iostream> namespace X86ISA { - //XXX This won't work - typedef uint32_t MachInst; - //XXX This won't work either - typedef uint64_t ExtMachInst; + //This really determines how many bytes are passed to the predecoder. + typedef uint64_t MachInst; + + enum Prefixes { + NoOverride = 0, + CSOverride = 1, + DSOverride = 2, + ESOverride = 3, + FSOverride = 4, + GSOverride = 5, + SSOverride = 6, + //The Rex prefix obviously doesn't fit in with the above, but putting + //it here lets us save double the space the enums take up. + Rex = 7, + //There can be only one segment override, so they share the + //first 3 bits in the legacyPrefixes bitfield. + SegmentOverride = 0x7, + OperandSizeOverride = 8, + AddressSizeOverride = 16, + Lock = 32, + Rep = 64, + Repne = 128 + }; + + //The intermediate structure the x86 predecoder returns. + struct ExtMachInst + { + public: //XXX These should be hidden in the future + + uint8_t legacyPrefixes; + uint8_t rexPrefix; + bool twoByteOpcode; + uint8_t opcode; + uint64_t immediate; + uint64_t displacement; + + public: + + //These are to pacify the decoder for now. This will go away once + //it can handle non integer inputs, and in the mean time allow me to + //excercise the predecoder a little. + operator unsigned int() + { + return 0; + } + + ExtMachInst(unsigned int) + {;} + + ExtMachInst() + {;} + }; + + inline static std::ostream & + operator << (std::ostream & os, const ExtMachInst & emi) + { + os << "{X86 ExtMachInst}"; + return os; + } + + inline static bool + operator == (const ExtMachInst &emi1, const ExtMachInst &emi2) + { + //Since this is empty, it's always equal + return true; + } typedef uint64_t IntReg; //XXX Should this be a 128 bit structure for XMM memory ops? diff --git a/src/arch/x86/utility.hh b/src/arch/x86/utility.hh index 1fbe1fffe..b616886a5 100644 --- a/src/arch/x86/utility.hh +++ b/src/arch/x86/utility.hh @@ -59,11 +59,22 @@ #define __ARCH_X86_UTILITY_HH__ #include "arch/x86/types.hh" +#include "base/hashmap.hh" #include "base/misc.hh" #include "sim/host.hh" class ThreadContext; +namespace __hash_namespace { + template<> + struct hash<X86ISA::ExtMachInst> { + size_t operator()(const X86ISA::ExtMachInst &emi) const { + //Because these are all the same, return 0 + return 0; + }; + }; +} + namespace X86ISA { static inline bool @@ -72,11 +83,6 @@ namespace X86ISA return false; } - inline ExtMachInst - makeExtMI(MachInst inst, ThreadContext * xc) { - return inst; - } - inline bool isCallerSaveIntegerRegister(unsigned int reg) { panic("register classification not implemented"); return false; diff --git a/src/cpu/base.hh b/src/cpu/base.hh index 7167bfde0..4d8300186 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -34,11 +34,11 @@ #include <vector> +#include "arch/isa_traits.hh" #include "base/statistics.hh" #include "config/full_system.hh" #include "sim/eventq.hh" #include "mem/mem_object.hh" -#include "arch/isa_traits.hh" #if FULL_SYSTEM #include "arch/interrupts.hh" @@ -50,6 +50,11 @@ class ThreadContext; class System; class Port; +namespace TheISA +{ + class Predecoder; +} + class CPUProgressEvent : public Event { protected: @@ -125,6 +130,7 @@ class BaseCPU : public MemObject protected: std::vector<ThreadContext *> threadContexts; + std::vector<TheISA::Predecoder *> predecoders; public: diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index 8347ed775..da7ce00f5 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -33,6 +33,7 @@ #define __CPU_O3_FETCH_HH__ #include "arch/utility.hh" +#include "arch/predecoder.hh" #include "base/statistics.hh" #include "base/timebuf.hh" #include "cpu/pc_event.hh" @@ -338,6 +339,9 @@ class DefaultFetch /** BPredUnit. */ BPredUnit branchPred; + /** Predecoder. */ + TheISA::Predecoder predecoder; + /** Per-thread fetch PC. */ Addr PC[Impl::MaxThreads]; diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index ac0149d18..1256dd233 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -103,6 +103,7 @@ DefaultFetch<Impl>::IcachePort::recvRetry() template<class Impl> DefaultFetch<Impl>::DefaultFetch(Params *params) : branchPred(params), + predecoder(NULL), decodeToFetchDelay(params->decodeToFetchDelay), renameToFetchDelay(params->renameToFetchDelay), iewToFetchDelay(params->iewToFetchDelay), @@ -1117,13 +1118,10 @@ DefaultFetch<Impl>::fetch(bool &status_change) inst = TheISA::gtoh(*reinterpret_cast<TheISA::MachInst *> (&cacheData[tid][offset])); -#if THE_ISA == ALPHA_ISA - ext_inst = TheISA::makeExtMI(inst, fetch_PC); -#elif THE_ISA == SPARC_ISA - ext_inst = TheISA::makeExtMI(inst, cpu->thread[tid]->getTC()); -#elif THE_ISA == MIPS_ISA - ext_inst = TheISA::makeExtMI(inst, cpu->thread[tid]->getTC()); -#endif + predecoder.setTC(cpu->thread[tid]->getTC()); + predecoder.moreBytes(fetch_PC, 0, inst); + + ext_inst = predecoder.getExtMachInst(); // Create a new DynInst from the instruction fetched. DynInstPtr instruction = new DynInst(ext_inst, diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 6a14a8aa5..6f69b5ac4 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -516,17 +516,28 @@ AtomicSimpleCPU::tick() Fault fault = setupFetchRequest(ifetch_req); if (fault == NoFault) { - ifetch_pkt->reinitFromRequest(); + Tick icache_latency = 0; + bool icache_access = false; + dcache_access = false; // assume no dcache access - Tick icache_latency = icachePort.sendAtomic(ifetch_pkt); - // ifetch_req is initialized to read the instruction directly - // into the CPU object's inst field. + //Fetch more instruction memory if necessary + if(predecoder.needMoreBytes()) + { + icache_access = true; + ifetch_pkt->reinitFromRequest(); + + icache_latency = icachePort.sendAtomic(ifetch_pkt); + // ifetch_req is initialized to read the instruction directly + // into the CPU object's inst field. + } - dcache_access = false; // assume no dcache access preExecute(); - fault = curStaticInst->execute(this, traceData); - postExecute(); + if(curStaticInst) + { + fault = curStaticInst->execute(this, traceData); + postExecute(); + } // @todo remove me after debugging with legion done if (curStaticInst && (!curStaticInst->isMicroOp() || @@ -534,7 +545,8 @@ AtomicSimpleCPU::tick() instCnt++; if (simulate_stalls) { - Tick icache_stall = icache_latency - cycles(1); + Tick icache_stall = + icache_access ? icache_latency - cycles(1) : 0; Tick dcache_stall = dcache_access ? dcache_latency - cycles(1) : 0; Tick stall_cycles = (icache_stall + dcache_stall) / cycles(1); @@ -545,8 +557,8 @@ AtomicSimpleCPU::tick() } } - - advancePC(fault); + if(predecoder.needMoreBytes()) + advancePC(fault); } if (_status != Idle) diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 9feb09851..cd139492a 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -70,7 +70,7 @@ using namespace std; using namespace TheISA; BaseSimpleCPU::BaseSimpleCPU(Params *p) - : BaseCPU(p), thread(NULL) + : BaseCPU(p), thread(NULL), predecoder(NULL) { #if FULL_SYSTEM thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb); @@ -367,18 +367,23 @@ BaseSimpleCPU::preExecute() inst = gtoh(inst); //If we're not in the middle of a macro instruction if (!curMacroStaticInst) { -#if THE_ISA == ALPHA_ISA - StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->readPC())); -#elif THE_ISA == SPARC_ISA - StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->getTC())); -#elif THE_ISA == X86_ISA - StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->getTC())); -#elif THE_ISA == MIPS_ISA - //Mips doesn't do anything in it's MakeExtMI function right now, - //so it won't be called. - StaticInstPtr instPtr = StaticInst::decode(inst); -#endif - if (instPtr->isMacroOp()) { + StaticInstPtr instPtr = NULL; + + //Predecode, ie bundle up an ExtMachInst + //This should go away once the constructor can be set up properly + predecoder.setTC(thread->getTC()); + //If more fetch data is needed, pass it in. + if(predecoder.needMoreBytes()) + predecoder.moreBytes(thread->readPC(), 0, inst); + else + predecoder.process(); + //If an instruction is ready, decode it + if (predecoder.extMachInstReady()) + instPtr = StaticInst::decode(predecoder.getExtMachInst()); + + //If we decoded an instruction and it's microcoded, start pulling + //out micro ops + if (instPtr && instPtr->isMacroOp()) { curMacroStaticInst = instPtr; curStaticInst = curMacroStaticInst-> fetchMicroOp(thread->readMicroPC()); @@ -391,17 +396,19 @@ BaseSimpleCPU::preExecute() fetchMicroOp(thread->readMicroPC()); } + //If we decoded an instruction this "tick", record information about it. + if(curStaticInst) + { + traceData = Trace::getInstRecord(curTick, tc, curStaticInst, + thread->readPC()); - traceData = Trace::getInstRecord(curTick, tc, curStaticInst, - thread->readPC()); - - DPRINTF(Decode,"Decode: Decoded %s instruction (opcode: 0x%x): 0x%x\n", - curStaticInst->getName(), curStaticInst->getOpcode(), - curStaticInst->machInst); + DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n", + curStaticInst->getName(), curStaticInst->machInst); #if FULL_SYSTEM - thread->setInst(inst); + thread->setInst(inst); #endif // FULL_SYSTEM + } } void @@ -444,9 +451,9 @@ BaseSimpleCPU::advancePC(Fault fault) fault->invoke(tc); thread->setMicroPC(0); thread->setNextMicroPC(1); - } else { + } else if (predecoder.needMoreBytes()) { //If we're at the last micro op for this instruction - if (curStaticInst->isLastMicroOp()) { + if (curStaticInst && curStaticInst->isLastMicroOp()) { //We should be working with a macro op assert(curMacroStaticInst); //Close out this macro op, and clean up the @@ -465,13 +472,9 @@ BaseSimpleCPU::advancePC(Fault fault) } else { // go to the next instruction thread->setPC(thread->readNextPC()); -#if ISA_HAS_DELAY_SLOT thread->setNextPC(thread->readNextNPC()); thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); assert(thread->readNextPC() != thread->readNextNPC()); -#else - thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); -#endif } } diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index eae24014b..787259c96 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -33,6 +33,7 @@ #ifndef __CPU_SIMPLE_BASE_HH__ #define __CPU_SIMPLE_BASE_HH__ +#include "arch/predecoder.hh" #include "base/statistics.hh" #include "config/full_system.hh" #include "cpu/base.hh" @@ -63,6 +64,10 @@ class Process; class RemoteGDB; class GDBListener; +namespace TheISA +{ + class Predecoder; +} class ThreadContext; class Checkpoint; @@ -74,7 +79,6 @@ namespace Trace { class BaseSimpleCPU : public BaseCPU { protected: - typedef TheISA::MachInst MachInst; typedef TheISA::MiscReg MiscReg; typedef TheISA::FloatReg FloatReg; typedef TheISA::FloatRegBits FloatRegBits; @@ -122,7 +126,10 @@ class BaseSimpleCPU : public BaseCPU #endif // current instruction - MachInst inst; + TheISA::MachInst inst; + + // The predecoder + TheISA::Predecoder predecoder; // Static data storage TheISA::LargestRead dataReg; diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index 416c8ab56..a58ac85d6 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -35,6 +35,7 @@ #include <string> #include "arch/isa_traits.hh" +#include "arch/utility.hh" #include "sim/faults.hh" #include "base/bitfield.hh" #include "base/hashmap.hh" @@ -439,9 +440,6 @@ class StaticInst : public StaticInstBase //This is defined as inline below. static StaticInstPtr decode(ExtMachInst mach_inst); - /// Return opcode of machine instruction - uint32_t getOpcode() { return bits(machInst, 31, 26);} - /// Return name of machine instruction std::string getName() { return mnemonic; } }; @@ -474,7 +472,7 @@ class StaticInstPtr : public RefCountingPtr<StaticInst> /// Construct directly from machine instruction. /// Calls StaticInst::decode(). - StaticInstPtr(TheISA::ExtMachInst mach_inst) + explicit StaticInstPtr(TheISA::ExtMachInst mach_inst) : RefCountingPtr<StaticInst>(StaticInst::decode(mach_inst)) { } |