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
This commit is contained in:
commit
32368a2bd6
20 changed files with 1035 additions and 104 deletions
|
@ -51,6 +51,7 @@ isa_switch_hdrs = Split('''
|
||||||
locked_mem.hh
|
locked_mem.hh
|
||||||
mmaped_ipr.hh
|
mmaped_ipr.hh
|
||||||
process.hh
|
process.hh
|
||||||
|
predecoder.hh
|
||||||
regfile.hh
|
regfile.hh
|
||||||
remote_gdb.hh
|
remote_gdb.hh
|
||||||
stacktrace.hh
|
stacktrace.hh
|
||||||
|
|
107
src/arch/alpha/predecoder.hh
Normal file
107
src/arch/alpha/predecoder.hh
Normal file
|
@ -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__
|
|
@ -48,19 +48,6 @@ namespace AlphaISA
|
||||||
return (tc->readMiscRegNoEffect(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
|
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) {
|
inline bool isCallerSaveIntegerRegister(unsigned int reg) {
|
||||||
panic("register classification not implemented");
|
panic("register classification not implemented");
|
||||||
return (reg >= 1 && reg <= 8 || reg >= 22 && reg <= 25 || reg == 27);
|
return (reg >= 1 && reg <= 8 || reg >= 22 && reg <= 25 || reg == 27);
|
||||||
|
|
100
src/arch/mips/predecoder.hh
Normal file
100
src/arch/mips/predecoder.hh
Normal file
|
@ -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__
|
|
@ -88,19 +88,6 @@ namespace MipsISA {
|
||||||
return 0;
|
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)
|
inline void startupCPU(ThreadContext *tc, int cpuId)
|
||||||
{
|
{
|
||||||
tc->activate(0);
|
tc->activate(0);
|
||||||
|
|
112
src/arch/sparc/predecoder.hh
Normal file
112
src/arch/sparc/predecoder.hh
Normal file
|
@ -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__
|
|
@ -48,22 +48,6 @@ namespace SparcISA
|
||||||
tc->readMiscRegNoEffect(MISCREG_HPSTATE & (1 << 2)));
|
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) {
|
inline bool isCallerSaveIntegerRegister(unsigned int reg) {
|
||||||
panic("register classification not implemented");
|
panic("register classification not implemented");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -84,11 +84,11 @@
|
||||||
# Authors: Gabe Black
|
# Authors: Gabe Black
|
||||||
|
|
||||||
Import('*')
|
Import('*')
|
||||||
|
|
||||||
if env['TARGET_ISA'] == 'x86':
|
if env['TARGET_ISA'] == 'x86':
|
||||||
Source('floatregfile.cc')
|
Source('floatregfile.cc')
|
||||||
Source('intregfile.cc')
|
Source('intregfile.cc')
|
||||||
Source('miscregfile.cc')
|
Source('miscregfile.cc')
|
||||||
|
Source('predecoder_tables.cc')
|
||||||
Source('regfile.cc')
|
Source('regfile.cc')
|
||||||
Source('remote_gdb.cc')
|
Source('remote_gdb.cc')
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,8 @@ output exec {{
|
||||||
Fault Unknown::execute(%(CPU_exec_context)s *xc,
|
Fault Unknown::execute(%(CPU_exec_context)s *xc,
|
||||||
Trace::InstRecord *traceData) const
|
Trace::InstRecord *traceData) const
|
||||||
{
|
{
|
||||||
panic("No instructions are implemented for X86!\n");
|
warn("No instructions are implemented for X86!\n");
|
||||||
|
return NoFault;
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|
412
src/arch/x86/predecoder.hh
Normal file
412
src/arch/x86/predecoder.hh
Normal file
|
@ -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__
|
143
src/arch/x86/predecoder_tables.cc
Normal file
143
src/arch/x86/predecoder_tables.cc
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -59,13 +59,76 @@
|
||||||
#define __ARCH_X86_TYPES_HH__
|
#define __ARCH_X86_TYPES_HH__
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace X86ISA
|
namespace X86ISA
|
||||||
{
|
{
|
||||||
//XXX This won't work
|
//This really determines how many bytes are passed to the predecoder.
|
||||||
typedef uint32_t MachInst;
|
typedef uint64_t MachInst;
|
||||||
//XXX This won't work either
|
|
||||||
typedef uint64_t ExtMachInst;
|
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;
|
typedef uint64_t IntReg;
|
||||||
//XXX Should this be a 128 bit structure for XMM memory ops?
|
//XXX Should this be a 128 bit structure for XMM memory ops?
|
||||||
|
|
|
@ -59,11 +59,22 @@
|
||||||
#define __ARCH_X86_UTILITY_HH__
|
#define __ARCH_X86_UTILITY_HH__
|
||||||
|
|
||||||
#include "arch/x86/types.hh"
|
#include "arch/x86/types.hh"
|
||||||
|
#include "base/hashmap.hh"
|
||||||
#include "base/misc.hh"
|
#include "base/misc.hh"
|
||||||
#include "sim/host.hh"
|
#include "sim/host.hh"
|
||||||
|
|
||||||
class ThreadContext;
|
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
|
namespace X86ISA
|
||||||
{
|
{
|
||||||
static inline bool
|
static inline bool
|
||||||
|
@ -72,11 +83,6 @@ namespace X86ISA
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ExtMachInst
|
|
||||||
makeExtMI(MachInst inst, ThreadContext * xc) {
|
|
||||||
return inst;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool isCallerSaveIntegerRegister(unsigned int reg) {
|
inline bool isCallerSaveIntegerRegister(unsigned int reg) {
|
||||||
panic("register classification not implemented");
|
panic("register classification not implemented");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -34,11 +34,11 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "arch/isa_traits.hh"
|
||||||
#include "base/statistics.hh"
|
#include "base/statistics.hh"
|
||||||
#include "config/full_system.hh"
|
#include "config/full_system.hh"
|
||||||
#include "sim/eventq.hh"
|
#include "sim/eventq.hh"
|
||||||
#include "mem/mem_object.hh"
|
#include "mem/mem_object.hh"
|
||||||
#include "arch/isa_traits.hh"
|
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
#include "arch/interrupts.hh"
|
#include "arch/interrupts.hh"
|
||||||
|
@ -50,6 +50,11 @@ class ThreadContext;
|
||||||
class System;
|
class System;
|
||||||
class Port;
|
class Port;
|
||||||
|
|
||||||
|
namespace TheISA
|
||||||
|
{
|
||||||
|
class Predecoder;
|
||||||
|
}
|
||||||
|
|
||||||
class CPUProgressEvent : public Event
|
class CPUProgressEvent : public Event
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
@ -125,6 +130,7 @@ class BaseCPU : public MemObject
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<ThreadContext *> threadContexts;
|
std::vector<ThreadContext *> threadContexts;
|
||||||
|
std::vector<TheISA::Predecoder *> predecoders;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#define __CPU_O3_FETCH_HH__
|
#define __CPU_O3_FETCH_HH__
|
||||||
|
|
||||||
#include "arch/utility.hh"
|
#include "arch/utility.hh"
|
||||||
|
#include "arch/predecoder.hh"
|
||||||
#include "base/statistics.hh"
|
#include "base/statistics.hh"
|
||||||
#include "base/timebuf.hh"
|
#include "base/timebuf.hh"
|
||||||
#include "cpu/pc_event.hh"
|
#include "cpu/pc_event.hh"
|
||||||
|
@ -338,6 +339,9 @@ class DefaultFetch
|
||||||
/** BPredUnit. */
|
/** BPredUnit. */
|
||||||
BPredUnit branchPred;
|
BPredUnit branchPred;
|
||||||
|
|
||||||
|
/** Predecoder. */
|
||||||
|
TheISA::Predecoder predecoder;
|
||||||
|
|
||||||
/** Per-thread fetch PC. */
|
/** Per-thread fetch PC. */
|
||||||
Addr PC[Impl::MaxThreads];
|
Addr PC[Impl::MaxThreads];
|
||||||
|
|
||||||
|
|
|
@ -103,6 +103,7 @@ DefaultFetch<Impl>::IcachePort::recvRetry()
|
||||||
template<class Impl>
|
template<class Impl>
|
||||||
DefaultFetch<Impl>::DefaultFetch(Params *params)
|
DefaultFetch<Impl>::DefaultFetch(Params *params)
|
||||||
: branchPred(params),
|
: branchPred(params),
|
||||||
|
predecoder(NULL),
|
||||||
decodeToFetchDelay(params->decodeToFetchDelay),
|
decodeToFetchDelay(params->decodeToFetchDelay),
|
||||||
renameToFetchDelay(params->renameToFetchDelay),
|
renameToFetchDelay(params->renameToFetchDelay),
|
||||||
iewToFetchDelay(params->iewToFetchDelay),
|
iewToFetchDelay(params->iewToFetchDelay),
|
||||||
|
@ -1117,13 +1118,10 @@ DefaultFetch<Impl>::fetch(bool &status_change)
|
||||||
inst = TheISA::gtoh(*reinterpret_cast<TheISA::MachInst *>
|
inst = TheISA::gtoh(*reinterpret_cast<TheISA::MachInst *>
|
||||||
(&cacheData[tid][offset]));
|
(&cacheData[tid][offset]));
|
||||||
|
|
||||||
#if THE_ISA == ALPHA_ISA
|
predecoder.setTC(cpu->thread[tid]->getTC());
|
||||||
ext_inst = TheISA::makeExtMI(inst, fetch_PC);
|
predecoder.moreBytes(fetch_PC, 0, inst);
|
||||||
#elif THE_ISA == SPARC_ISA
|
|
||||||
ext_inst = TheISA::makeExtMI(inst, cpu->thread[tid]->getTC());
|
ext_inst = predecoder.getExtMachInst();
|
||||||
#elif THE_ISA == MIPS_ISA
|
|
||||||
ext_inst = TheISA::makeExtMI(inst, cpu->thread[tid]->getTC());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Create a new DynInst from the instruction fetched.
|
// Create a new DynInst from the instruction fetched.
|
||||||
DynInstPtr instruction = new DynInst(ext_inst,
|
DynInstPtr instruction = new DynInst(ext_inst,
|
||||||
|
|
|
@ -516,17 +516,28 @@ AtomicSimpleCPU::tick()
|
||||||
Fault fault = setupFetchRequest(ifetch_req);
|
Fault fault = setupFetchRequest(ifetch_req);
|
||||||
|
|
||||||
if (fault == NoFault) {
|
if (fault == NoFault) {
|
||||||
|
Tick icache_latency = 0;
|
||||||
|
bool icache_access = false;
|
||||||
|
dcache_access = false; // assume no dcache access
|
||||||
|
|
||||||
|
//Fetch more instruction memory if necessary
|
||||||
|
if(predecoder.needMoreBytes())
|
||||||
|
{
|
||||||
|
icache_access = true;
|
||||||
ifetch_pkt->reinitFromRequest();
|
ifetch_pkt->reinitFromRequest();
|
||||||
|
|
||||||
Tick icache_latency = icachePort.sendAtomic(ifetch_pkt);
|
icache_latency = icachePort.sendAtomic(ifetch_pkt);
|
||||||
// ifetch_req is initialized to read the instruction directly
|
// ifetch_req is initialized to read the instruction directly
|
||||||
// into the CPU object's inst field.
|
// into the CPU object's inst field.
|
||||||
|
}
|
||||||
|
|
||||||
dcache_access = false; // assume no dcache access
|
|
||||||
preExecute();
|
preExecute();
|
||||||
|
|
||||||
|
if(curStaticInst)
|
||||||
|
{
|
||||||
fault = curStaticInst->execute(this, traceData);
|
fault = curStaticInst->execute(this, traceData);
|
||||||
postExecute();
|
postExecute();
|
||||||
|
}
|
||||||
|
|
||||||
// @todo remove me after debugging with legion done
|
// @todo remove me after debugging with legion done
|
||||||
if (curStaticInst && (!curStaticInst->isMicroOp() ||
|
if (curStaticInst && (!curStaticInst->isMicroOp() ||
|
||||||
|
@ -534,7 +545,8 @@ AtomicSimpleCPU::tick()
|
||||||
instCnt++;
|
instCnt++;
|
||||||
|
|
||||||
if (simulate_stalls) {
|
if (simulate_stalls) {
|
||||||
Tick icache_stall = icache_latency - cycles(1);
|
Tick icache_stall =
|
||||||
|
icache_access ? icache_latency - cycles(1) : 0;
|
||||||
Tick dcache_stall =
|
Tick dcache_stall =
|
||||||
dcache_access ? dcache_latency - cycles(1) : 0;
|
dcache_access ? dcache_latency - cycles(1) : 0;
|
||||||
Tick stall_cycles = (icache_stall + dcache_stall) / cycles(1);
|
Tick stall_cycles = (icache_stall + dcache_stall) / cycles(1);
|
||||||
|
@ -545,7 +557,7 @@ AtomicSimpleCPU::tick()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if(predecoder.needMoreBytes())
|
||||||
advancePC(fault);
|
advancePC(fault);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ using namespace std;
|
||||||
using namespace TheISA;
|
using namespace TheISA;
|
||||||
|
|
||||||
BaseSimpleCPU::BaseSimpleCPU(Params *p)
|
BaseSimpleCPU::BaseSimpleCPU(Params *p)
|
||||||
: BaseCPU(p), thread(NULL)
|
: BaseCPU(p), thread(NULL), predecoder(NULL)
|
||||||
{
|
{
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb);
|
thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb);
|
||||||
|
@ -367,18 +367,23 @@ BaseSimpleCPU::preExecute()
|
||||||
inst = gtoh(inst);
|
inst = gtoh(inst);
|
||||||
//If we're not in the middle of a macro instruction
|
//If we're not in the middle of a macro instruction
|
||||||
if (!curMacroStaticInst) {
|
if (!curMacroStaticInst) {
|
||||||
#if THE_ISA == ALPHA_ISA
|
StaticInstPtr instPtr = NULL;
|
||||||
StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->readPC()));
|
|
||||||
#elif THE_ISA == SPARC_ISA
|
//Predecode, ie bundle up an ExtMachInst
|
||||||
StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->getTC()));
|
//This should go away once the constructor can be set up properly
|
||||||
#elif THE_ISA == X86_ISA
|
predecoder.setTC(thread->getTC());
|
||||||
StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->getTC()));
|
//If more fetch data is needed, pass it in.
|
||||||
#elif THE_ISA == MIPS_ISA
|
if(predecoder.needMoreBytes())
|
||||||
//Mips doesn't do anything in it's MakeExtMI function right now,
|
predecoder.moreBytes(thread->readPC(), 0, inst);
|
||||||
//so it won't be called.
|
else
|
||||||
StaticInstPtr instPtr = StaticInst::decode(inst);
|
predecoder.process();
|
||||||
#endif
|
//If an instruction is ready, decode it
|
||||||
if (instPtr->isMacroOp()) {
|
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;
|
curMacroStaticInst = instPtr;
|
||||||
curStaticInst = curMacroStaticInst->
|
curStaticInst = curMacroStaticInst->
|
||||||
fetchMicroOp(thread->readMicroPC());
|
fetchMicroOp(thread->readMicroPC());
|
||||||
|
@ -391,18 +396,20 @@ BaseSimpleCPU::preExecute()
|
||||||
fetchMicroOp(thread->readMicroPC());
|
fetchMicroOp(thread->readMicroPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//If we decoded an instruction this "tick", record information about it.
|
||||||
|
if(curStaticInst)
|
||||||
|
{
|
||||||
traceData = Trace::getInstRecord(curTick, tc, curStaticInst,
|
traceData = Trace::getInstRecord(curTick, tc, curStaticInst,
|
||||||
thread->readPC());
|
thread->readPC());
|
||||||
|
|
||||||
DPRINTF(Decode,"Decode: Decoded %s instruction (opcode: 0x%x): 0x%x\n",
|
DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n",
|
||||||
curStaticInst->getName(), curStaticInst->getOpcode(),
|
curStaticInst->getName(), curStaticInst->machInst);
|
||||||
curStaticInst->machInst);
|
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
thread->setInst(inst);
|
thread->setInst(inst);
|
||||||
#endif // FULL_SYSTEM
|
#endif // FULL_SYSTEM
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BaseSimpleCPU::postExecute()
|
BaseSimpleCPU::postExecute()
|
||||||
|
@ -444,9 +451,9 @@ BaseSimpleCPU::advancePC(Fault fault)
|
||||||
fault->invoke(tc);
|
fault->invoke(tc);
|
||||||
thread->setMicroPC(0);
|
thread->setMicroPC(0);
|
||||||
thread->setNextMicroPC(1);
|
thread->setNextMicroPC(1);
|
||||||
} else {
|
} else if (predecoder.needMoreBytes()) {
|
||||||
//If we're at the last micro op for this instruction
|
//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
|
//We should be working with a macro op
|
||||||
assert(curMacroStaticInst);
|
assert(curMacroStaticInst);
|
||||||
//Close out this macro op, and clean up the
|
//Close out this macro op, and clean up the
|
||||||
|
@ -465,13 +472,9 @@ BaseSimpleCPU::advancePC(Fault fault)
|
||||||
} else {
|
} else {
|
||||||
// go to the next instruction
|
// go to the next instruction
|
||||||
thread->setPC(thread->readNextPC());
|
thread->setPC(thread->readNextPC());
|
||||||
#if ISA_HAS_DELAY_SLOT
|
|
||||||
thread->setNextPC(thread->readNextNPC());
|
thread->setNextPC(thread->readNextNPC());
|
||||||
thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
|
thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
|
||||||
assert(thread->readNextPC() != thread->readNextNPC());
|
assert(thread->readNextPC() != thread->readNextNPC());
|
||||||
#else
|
|
||||||
thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#ifndef __CPU_SIMPLE_BASE_HH__
|
#ifndef __CPU_SIMPLE_BASE_HH__
|
||||||
#define __CPU_SIMPLE_BASE_HH__
|
#define __CPU_SIMPLE_BASE_HH__
|
||||||
|
|
||||||
|
#include "arch/predecoder.hh"
|
||||||
#include "base/statistics.hh"
|
#include "base/statistics.hh"
|
||||||
#include "config/full_system.hh"
|
#include "config/full_system.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
|
@ -63,6 +64,10 @@ class Process;
|
||||||
class RemoteGDB;
|
class RemoteGDB;
|
||||||
class GDBListener;
|
class GDBListener;
|
||||||
|
|
||||||
|
namespace TheISA
|
||||||
|
{
|
||||||
|
class Predecoder;
|
||||||
|
}
|
||||||
class ThreadContext;
|
class ThreadContext;
|
||||||
class Checkpoint;
|
class Checkpoint;
|
||||||
|
|
||||||
|
@ -74,7 +79,6 @@ namespace Trace {
|
||||||
class BaseSimpleCPU : public BaseCPU
|
class BaseSimpleCPU : public BaseCPU
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
typedef TheISA::MachInst MachInst;
|
|
||||||
typedef TheISA::MiscReg MiscReg;
|
typedef TheISA::MiscReg MiscReg;
|
||||||
typedef TheISA::FloatReg FloatReg;
|
typedef TheISA::FloatReg FloatReg;
|
||||||
typedef TheISA::FloatRegBits FloatRegBits;
|
typedef TheISA::FloatRegBits FloatRegBits;
|
||||||
|
@ -122,7 +126,10 @@ class BaseSimpleCPU : public BaseCPU
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// current instruction
|
// current instruction
|
||||||
MachInst inst;
|
TheISA::MachInst inst;
|
||||||
|
|
||||||
|
// The predecoder
|
||||||
|
TheISA::Predecoder predecoder;
|
||||||
|
|
||||||
// Static data storage
|
// Static data storage
|
||||||
TheISA::LargestRead dataReg;
|
TheISA::LargestRead dataReg;
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "arch/isa_traits.hh"
|
#include "arch/isa_traits.hh"
|
||||||
|
#include "arch/utility.hh"
|
||||||
#include "sim/faults.hh"
|
#include "sim/faults.hh"
|
||||||
#include "base/bitfield.hh"
|
#include "base/bitfield.hh"
|
||||||
#include "base/hashmap.hh"
|
#include "base/hashmap.hh"
|
||||||
|
@ -439,9 +440,6 @@ class StaticInst : public StaticInstBase
|
||||||
//This is defined as inline below.
|
//This is defined as inline below.
|
||||||
static StaticInstPtr decode(ExtMachInst mach_inst);
|
static StaticInstPtr decode(ExtMachInst mach_inst);
|
||||||
|
|
||||||
/// Return opcode of machine instruction
|
|
||||||
uint32_t getOpcode() { return bits(machInst, 31, 26);}
|
|
||||||
|
|
||||||
/// Return name of machine instruction
|
/// Return name of machine instruction
|
||||||
std::string getName() { return mnemonic; }
|
std::string getName() { return mnemonic; }
|
||||||
};
|
};
|
||||||
|
@ -474,7 +472,7 @@ class StaticInstPtr : public RefCountingPtr<StaticInst>
|
||||||
|
|
||||||
/// Construct directly from machine instruction.
|
/// Construct directly from machine instruction.
|
||||||
/// Calls StaticInst::decode().
|
/// Calls StaticInst::decode().
|
||||||
StaticInstPtr(TheISA::ExtMachInst mach_inst)
|
explicit StaticInstPtr(TheISA::ExtMachInst mach_inst)
|
||||||
: RefCountingPtr<StaticInst>(StaticInst::decode(mach_inst))
|
: RefCountingPtr<StaticInst>(StaticInst::decode(mach_inst))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue