diff options
Diffstat (limited to 'src/arch/sparc')
33 files changed, 1674 insertions, 450 deletions
diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript index e317502e0..281c166c0 100644 --- a/src/arch/sparc/SConscript +++ b/src/arch/sparc/SConscript @@ -54,7 +54,11 @@ base_sources = Split(''' # Full-system sources full_system_sources = Split(''' - ua2005.cc + arguments.cc + remote_gdb.cc + stacktrace.cc + system.cc + tlb.cc vtophys.cc ''') diff --git a/src/arch/sparc/arguments.cc b/src/arch/sparc/arguments.cc new file mode 100644 index 000000000..44adf4a15 --- /dev/null +++ b/src/arch/sparc/arguments.cc @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2003-2005 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: Nathan Binkert + */ + +#include "arch/sparc/arguments.hh" +#include "arch/sparc/vtophys.hh" +#include "cpu/thread_context.hh" +#include "mem/vport.hh" + +using namespace SparcISA; + +Arguments::Data::~Data() +{ + while (!data.empty()) { + delete [] data.front(); + data.pop_front(); + } +} + +char * +Arguments::Data::alloc(size_t size) +{ + char *buf = new char[size]; + data.push_back(buf); + return buf; +} + +uint64_t +Arguments::getArg(bool fp) +{ + //The caller uses %o0-%05 for the first 6 arguments even if their floating + //point. Double precision floating point values take two registers/args. + //Quads, structs, and unions are passed as pointers. All arguments beyond + //the sixth are passed on the stack past the 16 word window save area, + //space for the struct/union return pointer, and space reserved for the + //first 6 arguments which the caller may use but doesn't have to. + if (number < 6) { + return tc->readIntReg(8 + number); + } else { + Addr sp = tc->readIntReg(14); + VirtualPort *vp = tc->getVirtPort(tc); + uint64_t arg = vp->read<uint64_t>(sp + 92 + (number-6) * sizeof(uint64_t)); + tc->delVirtPort(vp); + return arg; + } +} + diff --git a/src/arch/sparc/arguments.hh b/src/arch/sparc/arguments.hh new file mode 100644 index 000000000..8f925dd25 --- /dev/null +++ b/src/arch/sparc/arguments.hh @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2003-2005 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: Nathan Binkert + */ + +#ifndef __ARCH_SPARC_ARGUMENTS_HH__ +#define __ARCH_SPARC_ARGUMENTS_HH__ + +#include <assert.h> + +#include "arch/sparc/vtophys.hh" +#include "base/refcnt.hh" +#include "sim/host.hh" + +class ThreadContext; + +namespace SparcISA { + +class Arguments +{ + protected: + ThreadContext *tc; + int number; + uint64_t getArg(bool fp = false); + + protected: + class Data : public RefCounted + { + public: + Data(){} + ~Data(); + + private: + std::list<char *> data; + + public: + char *alloc(size_t size); + }; + + RefCountingPtr<Data> data; + + public: + Arguments(ThreadContext *ctx, int n = 0) + : tc(ctx), number(n), data(NULL) + { assert(number >= 0); data = new Data;} + Arguments(const Arguments &args) + : tc(args.tc), number(args.number), data(args.data) {} + ~Arguments() {} + + ThreadContext *getThreadContext() const { return tc; } + + const Arguments &operator=(const Arguments &args) { + tc = args.tc; + number = args.number; + data = args.data; + return *this; + } + + Arguments &operator++() { + ++number; + assert(number >= 0); + return *this; + } + + Arguments operator++(int) { + Arguments args = *this; + ++number; + assert(number >= 0); + return args; + } + + Arguments &operator--() { + --number; + assert(number >= 0); + return *this; + } + + Arguments operator--(int) { + Arguments args = *this; + --number; + assert(number >= 0); + return args; + } + + const Arguments &operator+=(int index) { + number += index; + assert(number >= 0); + return *this; + } + + const Arguments &operator-=(int index) { + number -= index; + assert(number >= 0); + return *this; + } + + Arguments operator[](int index) { + return Arguments(tc, index); + } + + template <class T> + operator T() { + assert(sizeof(T) <= sizeof(uint64_t)); + T data = static_cast<T>(getArg()); + return data; + } + + template <class T> + operator T *() { + T *buf = (T *)data->alloc(sizeof(T)); + CopyData(tc, buf, getArg(), sizeof(T)); + return buf; + } + + operator char *() { + char *buf = data->alloc(2048); + CopyStringOut(tc, buf, getArg(), 2048); + return buf; + } +}; + +}; // namespace SparcISA + +#endif // __ARCH_SPARC_ARGUMENTS_HH__ diff --git a/src/arch/sparc/asi.hh b/src/arch/sparc/asi.hh index 876567225..6677b23df 100644 --- a/src/arch/sparc/asi.hh +++ b/src/arch/sparc/asi.hh @@ -219,4 +219,4 @@ namespace SparcISA }; -#endif // __ARCH_SPARC_TLB_HH__ +#endif // __ARCH_SPARC_ASI_HH__ diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc index 169ad7986..6a905a76c 100644 --- a/src/arch/sparc/faults.cc +++ b/src/arch/sparc/faults.cc @@ -33,12 +33,13 @@ #include "arch/sparc/faults.hh" #include "arch/sparc/isa_traits.hh" -#include "arch/sparc/process.hh" #include "base/bitfield.hh" #include "base/trace.hh" +#include "config/full_system.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" #if !FULL_SYSTEM +#include "arch/sparc/process.hh" #include "mem/page_table.hh" #include "sim/process.hh" #endif @@ -217,9 +218,9 @@ void doNormalFault(ThreadContext *tc, TrapType tt) //Update the global register level if(1/*We're delivering the trap in priveleged mode*/) - tc->setMiscReg(MISCREG_GL, max<int>(GL+1, MaxGL)); + tc->setMiscReg(MISCREG_GL, min<int>(GL+1, MaxGL)); else - tc->setMiscReg(MISCREG_GL, max<int>(GL+1, MaxPGL)); + tc->setMiscReg(MISCREG_GL, min<int>(GL+1, MaxPGL)); //PSTATE.mm is unchanged //PSTATE.pef = whether or not an fpu is present @@ -286,32 +287,45 @@ void SparcFaultBase::invoke(ThreadContext * tc) countStat()++; //Use the SPARC trap state machine - /*// exception restart address - if (setRestartAddress() || !tc->inPalMode()) - tc->setMiscReg(AlphaISA::IPR_EXC_ADDR, tc->regs.pc); - - if (skipFaultingInstruction()) { - // traps... skip faulting instruction. - tc->setMiscReg(AlphaISA::IPR_EXC_ADDR, - tc->readMiscReg(AlphaISA::IPR_EXC_ADDR) + 4); - } - - if (!tc->inPalMode()) - AlphaISA::swap_palshadow(&(tc->regs), true); +} - tc->regs.pc = tc->readMiscReg(AlphaISA::IPR_PAL_BASE) + vect(); - tc->regs.npc = tc->regs.pc + sizeof(MachInst);*/ +void PowerOnReset::invoke(ThreadContext * tc) +{ + //For SPARC, when a system is first started, there is a power + //on reset Trap which sets the processor into the following state. + //Bits that aren't set aren't defined on startup. + /* + tl = MaxTL; + gl = MaxGL; + + tickFields.counter = 0; //The TICK register is unreadable bya + tickFields.npt = 1; //The TICK register is unreadable by by !priv + + softint = 0; // Clear all the soft interrupt bits + tick_cmprFields.int_dis = 1; // disable timer compare interrupts + tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing + stickFields.npt = 1; //The TICK register is unreadable by by !priv + stick_cmprFields.int_dis = 1; // disable timer compare interrupts + stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing + + tt[tl] = _trapType; + pstate = 0; // fields 0 but pef + pstateFields.pef = 1; + + hpstate = 0; + hpstateFields.red = 1; + hpstateFields.hpriv = 1; + hpstateFields.tlz = 0; // this is a guess + hintp = 0; // no interrupts pending + hstick_cmprFields.int_dis = 1; // disable timer compare interrupts + hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing + */ } #endif #if !FULL_SYSTEM -void TrapInstruction::invoke(ThreadContext * tc) -{ - // Should be handled in ISA. -} - void SpillNNormal::invoke(ThreadContext *tc) { doNormalFault(tc, trapType()); diff --git a/src/arch/sparc/faults.hh b/src/arch/sparc/faults.hh index 22f83c1e5..677f8e77e 100644 --- a/src/arch/sparc/faults.hh +++ b/src/arch/sparc/faults.hh @@ -113,7 +113,10 @@ static inline Fault genAlignmentFault() return new MemAddressNotAligned; } -class PowerOnReset : public SparcFault<PowerOnReset> {}; +class PowerOnReset : public SparcFault<PowerOnReset> +{ + void invoke(ThreadContext * tc); +}; class WatchDogReset : public SparcFault<WatchDogReset> {}; @@ -192,7 +195,10 @@ class SpillNNormal : public EnumeratedFault<SpillNNormal> public: SpillNNormal(uint32_t n) : EnumeratedFault<SpillNNormal>(n) {;} + //These need to be handled specially to enable spill traps in SE +#if !FULL_SYSTEM void invoke(ThreadContext * tc); +#endif }; class SpillNOther : public EnumeratedFault<SpillNOther> @@ -207,7 +213,10 @@ class FillNNormal : public EnumeratedFault<FillNNormal> public: FillNNormal(uint32_t n) : EnumeratedFault<FillNNormal>(n) {;} + //These need to be handled specially to enable fill traps in SE +#if !FULL_SYSTEM void invoke(ThreadContext * tc); +#endif }; class FillNOther : public EnumeratedFault<FillNOther> @@ -219,14 +228,9 @@ class FillNOther : public EnumeratedFault<FillNOther> class TrapInstruction : public EnumeratedFault<TrapInstruction> { - private: - uint64_t syscall_num; public: TrapInstruction(uint32_t n, uint64_t syscall) : EnumeratedFault<TrapInstruction>(n), syscall_num(syscall) {;} -#if !FULL_SYSTEM - void invoke(ThreadContext * tc); -#endif }; diff --git a/src/arch/sparc/floatregfile.cc b/src/arch/sparc/floatregfile.cc index 3afe6ef54..7f3d5a758 100644 --- a/src/arch/sparc/floatregfile.cc +++ b/src/arch/sparc/floatregfile.cc @@ -34,6 +34,8 @@ #include "sim/byteswap.hh" #include "sim/serialize.hh" +#include <string.h> + using namespace SparcISA; using namespace std; @@ -55,7 +57,7 @@ string SparcISA::getFloatRegName(RegIndex index) void FloatRegFile::clear() { - bzero(regSpace, sizeof(regSpace)); + memset(regSpace, 0, sizeof(regSpace)); } FloatReg FloatRegFile::readReg(int floatReg, int width) diff --git a/src/arch/sparc/interrupts.hh b/src/arch/sparc/interrupts.hh new file mode 100644 index 000000000..0072f4184 --- /dev/null +++ b/src/arch/sparc/interrupts.hh @@ -0,0 +1,92 @@ +/* + * 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_INTERRUPT_HH__ +#define __ARCH_SPARC_INTERRUPT_HH__ + +#include "arch/sparc/faults.hh" + +namespace SparcISA +{ + class Interrupts + { + protected: + Fault interrupts[NumInterruptLevels]; + bool requested[NumInterruptLevels]; + + public: + Interrupts() + { + for(int x = 0; x < NumInterruptLevels; x++) + { + interrupts[x] = new InterruptLevelN(x); + requested[x] = false; + } + } + void post(int int_num, int index) + { + if(int_num < 0 || int_num >= NumInterruptLevels) + panic("int_num out of bounds\n"); + + requested[int_num] = true; + } + + void clear(int int_num, int index) + { + requested[int_num] = false; + } + + void clear_all() + { + for(int x = 0; x < NumInterruptLevels; x++) + requested[x] = false; + } + + bool check_interrupts(ThreadContext * tc) const + { + return true; + } + + Fault getInterrupt(ThreadContext * tc) + { + return NoFault; + } + + void serialize(std::ostream &os) + { + } + + void unserialize(Checkpoint *cp, const std::string §ion) + { + } + }; +} + +#endif // __ARCH_SPARC_INTERRUPT_HH__ diff --git a/src/arch/sparc/intregfile.cc b/src/arch/sparc/intregfile.cc index bef62f6ae..0e313dc94 100644 --- a/src/arch/sparc/intregfile.cc +++ b/src/arch/sparc/intregfile.cc @@ -33,6 +33,8 @@ #include "base/trace.hh" #include "sim/serialize.hh" +#include <string.h> + using namespace SparcISA; using namespace std; @@ -62,7 +64,7 @@ void IntRegFile::clear() for (x = 0; x < MaxGL; x++) memset(regGlobals[x], 0, sizeof(IntReg) * RegsPerFrame); for(int x = 0; x < 2 * NWindows; x++) - bzero(regSegments[x], sizeof(IntReg) * RegsPerFrame); + memset(regSegments[x], 0, sizeof(IntReg) * RegsPerFrame); } IntRegFile::IntRegFile() @@ -75,8 +77,14 @@ IntRegFile::IntRegFile() IntReg IntRegFile::readReg(int intReg) { - IntReg val = - regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask]; + IntReg val; + if(intReg < NumRegularIntRegs) + val = regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask]; + else if((intReg -= NumRegularIntRegs) < NumMicroIntRegs) + val = microRegs[intReg]; + else + panic("Tried to read non-existant integer register\n"); + DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, val); return val; } @@ -86,7 +94,12 @@ Fault IntRegFile::setReg(int intReg, const IntReg &val) if(intReg) { DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val); - regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val; + if(intReg < NumRegularIntRegs) + regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val; + else if((intReg -= NumRegularIntRegs) < NumMicroIntRegs) + microRegs[intReg] = val; + else + panic("Tried to set non-existant integer register\n"); } return NoFault; } @@ -123,6 +136,7 @@ void IntRegFile::serialize(std::ostream &os) SERIALIZE_ARRAY(regGlobals[x], RegsPerFrame); for(x = 0; x < 2 * NWindows; x++) SERIALIZE_ARRAY(regSegments[x], RegsPerFrame); + SERIALIZE_ARRAY(microRegs, NumMicroIntRegs); } void IntRegFile::unserialize(Checkpoint *cp, const std::string §ion) @@ -132,4 +146,5 @@ void IntRegFile::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_ARRAY(regGlobals[x], RegsPerFrame); for(unsigned int x = 0; x < 2 * NWindows; x++) UNSERIALIZE_ARRAY(regSegments[x], RegsPerFrame); + UNSERIALIZE_ARRAY(microRegs, NumMicroIntRegs); } diff --git a/src/arch/sparc/intregfile.hh b/src/arch/sparc/intregfile.hh index d305c753b..223e3b34c 100644 --- a/src/arch/sparc/intregfile.hh +++ b/src/arch/sparc/intregfile.hh @@ -65,6 +65,7 @@ namespace SparcISA IntReg regGlobals[MaxGL][RegsPerFrame]; IntReg regSegments[2 * NWindows][RegsPerFrame]; + IntReg microRegs[NumMicroIntRegs]; enum regFrame {Globals, Outputs, Locals, Inputs, NumFrames}; diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index dc7597e5e..a5f43367d 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -353,14 +353,14 @@ decode OP default Unknown::unknown() 0x1: Nop::membar({{/*stuff*/}}); } default: rdasr({{ - Rd = xc->readMiscRegWithEffect(RS1 + AsrStart, fault); + Rd = xc->readMiscRegWithEffect(RS1 + AsrStart); }}); } 0x29: HPriv::rdhpr({{ - Rd = xc->readMiscRegWithEffect(RS1 + HprStart, fault); + Rd = xc->readMiscRegWithEffect(RS1 + HprStart); }}); 0x2A: Priv::rdpr({{ - Rd = xc->readMiscRegWithEffect(RS1 + PrStart, fault); + Rd = xc->readMiscRegWithEffect(RS1 + PrStart); }}); 0x2B: BasicOperate::flushw({{ if(NWindows - 2 - Cansave == 0) @@ -851,16 +851,15 @@ decode OP default Unknown::unknown() 0x09: ldsb({{Rd = (int8_t)Mem.sb;}}); 0x0A: ldsh({{Rd = (int16_t)Mem.shw;}}); 0x0B: ldx({{Rd = (int64_t)Mem.sdw;}}); - 0x0D: ldstub({{ - Rd = Mem.ub; - Mem.ub = 0xFF; - }}); } + 0x0D: LoadStore::ldstub( + {{Rd = Mem.ub;}}, + {{Mem.ub = 0xFF;}}); 0x0E: Store::stx({{Mem.udw = Rd}}); 0x0F: LoadStore::swap( - {{*temp = Rd.uw; + {{uReg0 = Rd.uw; Rd.uw = Mem.uw;}}, - {{Mem.uw = *temp;}}); + {{Mem.uw = uReg0;}}); format Load { 0x10: lduwa({{Rd = Mem.uw;}}); 0x11: lduba({{Rd = Mem.ub;}}); @@ -888,9 +887,9 @@ decode OP default Unknown::unknown() {{Mem.ub = 0xFF}}); 0x1E: Store::stxa({{Mem.udw = Rd}}); 0x1F: LoadStore::swapa( - {{*temp = Rd.uw; + {{uReg0 = Rd.uw; Rd.uw = Mem.uw;}}, - {{Mem.uw = *temp;}}); + {{Mem.uw = uReg0;}}); format Trap { 0x20: Load::ldf({{Frd.uw = Mem.uw;}}); 0x21: decode X { @@ -1073,19 +1072,21 @@ decode OP default Unknown::unknown() {{fault = new DataAccessException;}}); } } - 0x3C: Cas::casa({{ - uint64_t val = Mem.uw; - if(Rs2.uw == val) + 0x3C: Cas::casa( + {{uReg0 = Mem.uw;}}, + {{if(Rs2.uw == uReg0) Mem.uw = Rd.uw; - Rd.uw = val; - }}); + else + storeCond = false; + Rd.uw = uReg0;}}); 0x3D: Nop::prefetcha({{ }}); - 0x3E: Cas::casxa({{ - uint64_t val = Mem.udw; - if(Rs2 == val) + 0x3E: Cas::casxa( + {{uReg0 = Mem.udw;}}, + {{if(Rs2 == uReg0) Mem.udw = Rd; - Rd = val; - }}); + else + storeCond = false; + Rd = uReg0;}}); } } } diff --git a/src/arch/sparc/isa/formats/formats.isa b/src/arch/sparc/isa/formats/formats.isa index 5b81a1ab1..8125e6349 100644 --- a/src/arch/sparc/isa/formats/formats.isa +++ b/src/arch/sparc/isa/formats/formats.isa @@ -42,9 +42,6 @@ //Include the memory formats ##include "mem/mem.isa" -//Include the compare and swap format -##include "cas.isa" - //Include the trap format ##include "trap.isa" diff --git a/src/arch/sparc/isa/formats/mem/basicmem.isa b/src/arch/sparc/isa/formats/mem/basicmem.isa index c13194d0f..cb6c2f161 100644 --- a/src/arch/sparc/isa/formats/mem/basicmem.isa +++ b/src/arch/sparc/isa/formats/mem/basicmem.isa @@ -32,100 +32,6 @@ // Mem instructions // -output header {{ - /** - * Base class for memory operations. - */ - class Mem : public SparcStaticInst - { - protected: - - // Constructor - Mem(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : - SparcStaticInst(mnem, _machInst, __opClass) - { - } - - std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) const; - }; - - /** - * Class for memory operations which use an immediate offset. - */ - class MemImm : public Mem - { - protected: - - // Constructor - MemImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : - Mem(mnem, _machInst, __opClass), imm(sext<13>(SIMM13)) - {} - - std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) const; - - const int32_t imm; - }; -}}; - -output decoder {{ - std::string Mem::generateDisassembly(Addr pc, - const SymbolTable *symtab) const - { - std::stringstream response; - bool load = flags[IsLoad]; - bool save = flags[IsStore]; - - printMnemonic(response, mnemonic); - if(save) - { - printReg(response, _srcRegIdx[0]); - ccprintf(response, ", "); - } - ccprintf(response, "[ "); - printReg(response, _srcRegIdx[!save ? 0 : 1]); - ccprintf(response, " + "); - printReg(response, _srcRegIdx[!save ? 1 : 2]); - ccprintf(response, " ]"); - if(load) - { - ccprintf(response, ", "); - printReg(response, _destRegIdx[0]); - } - - return response.str(); - } - - std::string MemImm::generateDisassembly(Addr pc, - const SymbolTable *symtab) const - { - std::stringstream response; - bool load = flags[IsLoad]; - bool save = flags[IsStore]; - - printMnemonic(response, mnemonic); - if(save) - { - printReg(response, _srcRegIdx[0]); - ccprintf(response, ", "); - } - ccprintf(response, "[ "); - printReg(response, _srcRegIdx[!save ? 0 : 1]); - if(imm >= 0) - ccprintf(response, " + 0x%x ]", imm); - else - ccprintf(response, " + -0x%x ]", -imm); - if(load) - { - ccprintf(response, ", "); - printReg(response, _destRegIdx[0]); - } - - return response.str(); - } -}}; - def template MemDeclare {{ /** * Static instruction class for "%(mnemonic)s". @@ -156,7 +62,7 @@ let {{ header_output = MemDeclare.subst(iop) + MemDeclare.subst(iop_imm) decoder_output = BasicConstructor.subst(iop) + BasicConstructor.subst(iop_imm) decode_block = ROrImmDecode.subst(iop) - exec_output = doSplitExecute(code, addrCalcReg, addrCalcImm, execute, + exec_output = doDualSplitExecute(code, addrCalcReg, addrCalcImm, execute, faultCode, name, name + "Imm", Name, Name + "Imm", opt_flags) return (header_output, decoder_output, exec_output, decode_block) }}; diff --git a/src/arch/sparc/isa/formats/mem/blockmem.isa b/src/arch/sparc/isa/formats/mem/blockmem.isa index 93ad1b2b8..8b4aca473 100644 --- a/src/arch/sparc/isa/formats/mem/blockmem.isa +++ b/src/arch/sparc/isa/formats/mem/blockmem.isa @@ -56,14 +56,14 @@ output header {{ {} }; - class BlockMemMicro : public SparcDelayedMicroInst + class BlockMemMicro : public SparcMicroInst { protected: // Constructor BlockMemMicro(const char *mnem, ExtMachInst _machInst, OpClass __opClass, int8_t _offset) : - SparcDelayedMicroInst(mnem, _machInst, __opClass), + SparcMicroInst(mnem, _machInst, __opClass), offset(_offset) {} @@ -290,6 +290,8 @@ let {{ flag_code = '' if (microPc == 7): flag_code = "flags[IsLastMicroOp] = true;" + else: + flag_code = "flags[IsDelayedCommit] = true;" pcedCode = matcher.sub("Frd_%d" % microPc, code) iop = InstObjParams(name, Name, 'BlockMem', pcedCode, opt_flags, {"ea_code": addrCalcReg, @@ -301,7 +303,7 @@ let {{ "set_flags": flag_code}) decoder_output += BlockMemMicroConstructor.subst(iop) decoder_output += BlockMemMicroConstructor.subst(iop_imm) - exec_output += doSplitExecute( + exec_output += doDualSplitExecute( pcedCode, addrCalcReg, addrCalcImm, execute, faultCode, makeMicroName(name, microPc), makeMicroName(name + "Imm", microPc), diff --git a/src/arch/sparc/isa/formats/mem/mem.isa b/src/arch/sparc/isa/formats/mem/mem.isa index 20a22c45d..fedece2b8 100644 --- a/src/arch/sparc/isa/formats/mem/mem.isa +++ b/src/arch/sparc/isa/formats/mem/mem.isa @@ -41,5 +41,5 @@ //Include the block memory format ##include "blockmem.isa" -//Include the load/store memory format +//Include the load/store and cas memory format ##include "loadstore.isa" diff --git a/src/arch/sparc/isa/formats/mem/util.isa b/src/arch/sparc/isa/formats/mem/util.isa index 241a25d17..b9f7fde2d 100644 --- a/src/arch/sparc/isa/formats/mem/util.isa +++ b/src/arch/sparc/isa/formats/mem/util.isa @@ -33,6 +33,100 @@ // Mem utility templates and functions // +output header {{ + /** + * Base class for memory operations. + */ + class Mem : public SparcStaticInst + { + protected: + + // Constructor + Mem(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : + SparcStaticInst(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + }; + + /** + * Class for memory operations which use an immediate offset. + */ + class MemImm : public Mem + { + protected: + + // Constructor + MemImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : + Mem(mnem, _machInst, __opClass), imm(sext<13>(SIMM13)) + {} + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + + const int32_t imm; + }; +}}; + +output decoder {{ + std::string Mem::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + bool load = flags[IsLoad]; + bool save = flags[IsStore]; + + printMnemonic(response, mnemonic); + if(save) + { + printReg(response, _srcRegIdx[0]); + ccprintf(response, ", "); + } + ccprintf(response, "[ "); + printReg(response, _srcRegIdx[!save ? 0 : 1]); + ccprintf(response, " + "); + printReg(response, _srcRegIdx[!save ? 1 : 2]); + ccprintf(response, " ]"); + if(load) + { + ccprintf(response, ", "); + printReg(response, _destRegIdx[0]); + } + + return response.str(); + } + + std::string MemImm::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + bool load = flags[IsLoad]; + bool save = flags[IsStore]; + + printMnemonic(response, mnemonic); + if(save) + { + printReg(response, _srcRegIdx[0]); + ccprintf(response, ", "); + } + ccprintf(response, "[ "); + printReg(response, _srcRegIdx[!save ? 0 : 1]); + if(imm >= 0) + ccprintf(response, " + 0x%x ]", imm); + else + ccprintf(response, " + -0x%x ]", -imm); + if(load) + { + ccprintf(response, ", "); + printReg(response, _destRegIdx[0]); + } + + return response.str(); + } +}}; + //This template provides the execute functions for a load def template LoadExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, @@ -102,6 +196,9 @@ def template StoreExecute {{ { Fault fault = NoFault; uint64_t write_result = 0; + //This is to support the conditional store in cas instructions. + //It should be optomized out in all the others + bool storeCond = true; Addr EA; %(op_decl)s; %(op_rd)s; @@ -112,7 +209,7 @@ def template StoreExecute {{ { %(code)s; } - if(fault == NoFault) + if(storeCond && fault == NoFault) { fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result); } @@ -130,6 +227,7 @@ def template StoreExecute {{ { Fault fault = NoFault; uint64_t write_result = 0; + bool storeCond = true; Addr EA; %(op_decl)s; %(op_rd)s; @@ -140,7 +238,7 @@ def template StoreExecute {{ { %(code)s; } - if(fault == NoFault) + if(storeCond && fault == NoFault) { fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result); } @@ -204,23 +302,29 @@ let {{ //and in the other they're distributed across two. Also note that for //execute functions, the name of the base class doesn't matter. let {{ - def doSplitExecute(code, eaRegCode, eaImmCode, execute, + def doSplitExecute(code, eaCode, execute, + faultCode, name, Name, opt_flags): + codeIop = InstObjParams(name, Name, '', code, opt_flags) + eaIop = InstObjParams(name, Name, '', eaCode, + opt_flags, {"fault_check": faultCode}) + iop = InstObjParams(name, Name, '', code, opt_flags, + {"fault_check": faultCode, "ea_code" : eaCode}) + (iop.ea_decl, + iop.ea_rd, + iop.ea_wb) = (eaIop.op_decl, eaIop.op_rd, eaIop.op_wb) + (iop.code_decl, + iop.code_rd, + iop.code_wb) = (codeIop.op_decl, codeIop.op_rd, codeIop.op_wb) + return execute.subst(iop) + + + def doDualSplitExecute(code, eaRegCode, eaImmCode, execute, faultCode, nameReg, nameImm, NameReg, NameImm, opt_flags): - codeIop = InstObjParams(nameReg, NameReg, '', code, opt_flags) executeCode = '' for (eaCode, name, Name) in ( (eaRegCode, nameReg, NameReg), (eaImmCode, nameImm, NameImm)): - eaIop = InstObjParams(name, Name, '', eaCode, - opt_flags, {"fault_check": faultCode}) - iop = InstObjParams(name, Name, '', code, opt_flags, - {"fault_check": faultCode, "ea_code" : eaCode}) - (iop.ea_decl, - iop.ea_rd, - iop.ea_wb) = (eaIop.op_decl, eaIop.op_rd, eaIop.op_wb) - (iop.code_decl, - iop.code_rd, - iop.code_wb) = (codeIop.op_decl, codeIop.op_rd, codeIop.op_wb) - executeCode += execute.subst(iop) + executeCode += doSplitExecute(code, eaCode, + execute, faultCode, name, Name, opt_flags) return executeCode }}; diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa index ba2c38e91..80b499b91 100644 --- a/src/arch/sparc/isa/operands.isa +++ b/src/arch/sparc/isa/operands.isa @@ -61,6 +61,7 @@ def operands {{ 'RdHigh': ('IntReg', 'udw', 'RD | 1', 'IsInteger', 3), 'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 4), 'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 5), + 'uReg0': ('IntReg', 'udw', 'NumRegularIntRegs+0', 'IsInteger', 6), 'Frds': ('FloatReg', 'sf', 'RD', 'IsFloating', 10), 'Frd': ('FloatReg', 'df', 'dfpr(RD)', 'IsFloating', 10), # Each Frd_N refers to the Nth double precision register from Frd. diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh index fb09121a3..46a0ebbfb 100644 --- a/src/arch/sparc/isa_traits.hh +++ b/src/arch/sparc/isa_traits.hh @@ -57,13 +57,17 @@ namespace SparcISA //This makes sure the big endian versions of certain functions are used. using namespace BigEndianGuest; - // SPARC have a delay slot + // SPARC has a delay slot #define ISA_HAS_DELAY_SLOT 1 // SPARC NOP (sethi %(hi(0), g0) const MachInst NoopMachInst = 0x01000000; - const int NumIntRegs = 32; + const int NumRegularIntRegs = 32; + const int NumMicroIntRegs = 1; + const int NumIntRegs = + NumRegularIntRegs + + NumMicroIntRegs; const int NumFloatRegs = 64; const int NumMiscRegs = 40; diff --git a/src/arch/sparc/kernel_stats.hh b/src/arch/sparc/kernel_stats.hh new file mode 100644 index 000000000..c007c54c2 --- /dev/null +++ b/src/arch/sparc/kernel_stats.hh @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2004-2005 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_KERNEL_STATS_HH__ +#define __ARCH_SPARC_KERNEL_STATS_HH__ + +#include <map> +#include <stack> +#include <string> +#include <vector> + +#include "kern/kernel_stats.hh" + +namespace SparcISA { +namespace Kernel { + +enum cpu_mode { hypervisor, kernel, user, idle, cpu_mode_num }; +extern const char *modestr[]; + +class Statistics : public ::Kernel::Statistics +{ + public: + Statistics(System *system) : ::Kernel::Statistics(system) + {} +}; + +} /* end namespace AlphaISA::Kernel */ +} /* end namespace AlphaISA */ + +#endif // __ARCH_SPARC_KERNEL_STATS_HH__ diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc index bf4572878..217fba0bd 100644 --- a/src/arch/sparc/miscregfile.cc +++ b/src/arch/sparc/miscregfile.cc @@ -31,9 +31,14 @@ #include "arch/sparc/miscregfile.hh" #include "base/trace.hh" +#include "config/full_system.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" +#if FULL_SYSTEM +#include "arch/sparc/system.hh" +#endif + using namespace SparcISA; using namespace std; @@ -55,66 +60,8 @@ string SparcISA::getMiscRegName(RegIndex index) return miscRegName[index]; } -#if FULL_SYSTEM - -//XXX These need an implementation someplace -/** Fullsystem only register version of ReadRegWithEffect() */ -MiscReg MiscRegFile::readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc); -/** Fullsystem only register version of SetRegWithEffect() */ -Fault MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, - ThreadContext * tc); -#endif - void MiscRegFile::reset() { - pstateFields.pef = 0; //No FPU - //pstateFields.pef = 1; //FPU -#if FULL_SYSTEM - //For SPARC, when a system is first started, there is a power - //on reset Trap which sets the processor into the following state. - //Bits that aren't set aren't defined on startup. - tl = MaxTL; - gl = MaxGL; - - tickFields.counter = 0; //The TICK register is unreadable bya - tickFields.npt = 1; //The TICK register is unreadable by by !priv - - softint = 0; // Clear all the soft interrupt bits - tick_cmprFields.int_dis = 1; // disable timer compare interrupts - tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing - stickFields.npt = 1; //The TICK register is unreadable by by !priv - stick_cmprFields.int_dis = 1; // disable timer compare interrupts - stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing - - - tt[tl] = power_on_reset; - pstate = 0; // fields 0 but pef - pstateFields.pef = 1; - - hpstate = 0; - hpstateFields.red = 1; - hpstateFields.hpriv = 1; - hpstateFields.tlz = 0; // this is a guess - hintp = 0; // no interrupts pending - hstick_cmprFields.int_dis = 1; // disable timer compare interrupts - hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing -#else -/* //This sets up the initial state of the processor for usermode processes - pstateFields.priv = 0; //Process runs in user mode - pstateFields.ie = 1; //Interrupts are enabled - fsrFields.rd = 0; //Round to nearest - fsrFields.tem = 0; //Floating point traps not enabled - fsrFields.ns = 0; //Non standard mode off - fsrFields.qne = 0; //Floating point queue is empty - fsrFields.aexc = 0; //No accrued exceptions - fsrFields.cexc = 0; //No current exceptions - - //Register window management registers - otherwin = 0; //No windows contain info from other programs - canrestore = 0; //There are no windows to pop - cansave = MaxTL - 2; //All windows are available to save into - cleanwin = MaxTL;*/ -#endif } MiscReg MiscRegFile::readReg(int miscReg) @@ -214,10 +161,20 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc) case MISCREG_PCR: case MISCREG_PIC: panic("Performance Instrumentation not impl\n"); - /** Floating Point Status Register */ case MISCREG_FSR: panic("Floating Point not implemented\n"); +//We'll include this only in FS so we don't need the SparcSystem type around +//in SE. +#if FULL_SYSTEM + case MISCREG_STICK: + SparcSystem *sys; + sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr()); + assert(sys != NULL); + return curTick/Clock::Int::ns - sys->sysTick | stickFields.npt << 63; +#endif + case MISCREG_HVER: + return NWindows | MaxTL << 8 | MaxGL << 16; } return readReg(miscReg); } @@ -337,10 +294,38 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val) } } +inline void MiscRegFile::setImplicitAsis() +{ + //The spec seems to use trap level to indicate the privilege level of the + //processor. It's unclear whether the implicit ASIs should directly depend + //on the trap level, or if they should really be based on the privelege + //bits + if(tl == 0) + { + implicitInstAsi = implicitDataAsi = + pstateFields.cle ? ASI_PRIMARY_LITTLE : ASI_PRIMARY; + } + else if(tl <= MaxPTL) + { + implicitInstAsi = ASI_NUCLEUS; + implicitDataAsi = pstateFields.cle ? ASI_NUCLEUS_LITTLE : ASI_NUCLEUS; + } + else + { + //This is supposed to force physical addresses to match the spec. + //It might not because of context values and partition values. + implicitInstAsi = implicitDataAsi = ASI_REAL; + } +} + void MiscRegFile::setRegWithEffect(int miscReg, const MiscReg &val, ThreadContext * tc) { const uint64_t Bit64 = (1ULL << 63); +#if FULL_SYSTEM + uint64_t time; + SparcSystem *sys; +#endif switch (miscReg) { case MISCREG_TICK: tickFields.counter = tc->getCpuPtr()->curCycle() - val & ~Bit64; @@ -352,12 +337,84 @@ void MiscRegFile::setRegWithEffect(int miscReg, case MISCREG_PCR: //Set up performance counting based on pcr value break; + case MISCREG_PSTATE: + pstate = val; + setImplicitAsis(); + return; + case MISCREG_TL: + tl = val; + setImplicitAsis(); + return; case MISCREG_CWP: tc->changeRegFileContext(CONTEXT_CWP, val); break; case MISCREG_GL: tc->changeRegFileContext(CONTEXT_GLOBALS, val); break; + case MISCREG_SOFTINT: + //We need to inject interrupts, and or notify the interrupt + //object that it needs to use a different interrupt level. + //Any newly appropriate interrupts will happen when the cpu gets + //around to checking for them. This might not be quite what we + //want. + break; + case MISCREG_SOFTINT_CLR: + //Do whatever this is supposed to do... + break; + case MISCREG_SOFTINT_SET: + //Do whatever this is supposed to do... + break; +#if FULL_SYSTEM + case MISCREG_TICK_CMPR: + if (tickCompare == NULL) + tickCompare = new TickCompareEvent(this, tc); + setReg(miscReg, val); + if (tick_cmprFields.int_dis && tickCompare->scheduled()) + tickCompare->deschedule(); + time = tick_cmprFields.tick_cmpr - tickFields.counter; + if (!tick_cmprFields.int_dis && time > 0) + tickCompare->schedule(time * tc->getCpuPtr()->cycles(1)); + break; +#endif + case MISCREG_PIL: + //We need to inject interrupts, and or notify the interrupt + //object that it needs to use a different interrupt level. + //Any newly appropriate interrupts will happen when the cpu gets + //around to checking for them. This might not be quite what we + //want. + break; +//We'll include this only in FS so we don't need the SparcSystem type around +//in SE. +#if FULL_SYSTEM + case MISCREG_STICK: + sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr()); + assert(sys != NULL); + sys->sysTick = curTick/Clock::Int::ns - val & ~Bit64; + stickFields.npt = val & Bit64 ? 1 : 0; + break; + case MISCREG_STICK_CMPR: + if (sTickCompare == NULL) + sTickCompare = new STickCompareEvent(this, tc); + sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr()); + assert(sys != NULL); + if (stick_cmprFields.int_dis && sTickCompare->scheduled()) + sTickCompare->deschedule(); + time = stick_cmprFields.tick_cmpr - sys->sysTick; + if (!stick_cmprFields.int_dis && time > 0) + sTickCompare->schedule(time * Clock::Int::ns); + break; + case MISCREG_HSTICK_CMPR: + if (hSTickCompare == NULL) + hSTickCompare = new HSTickCompareEvent(this, tc); + sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr()); + assert(sys != NULL); + if (hstick_cmprFields.int_dis && hSTickCompare->scheduled()) + hSTickCompare->deschedule(); + int64_t time = hstick_cmprFields.tick_cmpr - sys->sysTick; + if (!hstick_cmprFields.int_dis && time > 0) + hSTickCompare->schedule(time * Clock::Int::ns); + break; +#endif } setReg(miscReg, val); } @@ -389,6 +446,8 @@ void MiscRegFile::serialize(std::ostream & os) SERIALIZE_ARRAY(htstate, MaxTL); SERIALIZE_SCALAR(htba); SERIALIZE_SCALAR(hstick_cmpr); + SERIALIZE_SCALAR((int)implicitInstAsi); + SERIALIZE_SCALAR((int)implicitDataAsi); } void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section) @@ -418,5 +477,29 @@ void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section) UNSERIALIZE_ARRAY(htstate, MaxTL); UNSERIALIZE_SCALAR(htba); UNSERIALIZE_SCALAR(hstick_cmpr); + int temp; + UNSERIALIZE_SCALAR(temp); + implicitInstAsi = (ASI)temp; + UNSERIALIZE_SCALAR(temp); + implicitDataAsi = (ASI)temp; } +#if FULL_SYSTEM +void +MiscRegFile::processTickCompare(ThreadContext *tc) +{ + panic("tick compare not implemented\n"); +} + +void +MiscRegFile::processSTickCompare(ThreadContext *tc) +{ + panic("tick compare not implemented\n"); +} + +void +MiscRegFile::processHSTickCompare(ThreadContext *tc) +{ + panic("tick compare not implemented\n"); +} +#endif diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh index 771cb1ed6..0e424dbd2 100644 --- a/src/arch/sparc/miscregfile.hh +++ b/src/arch/sparc/miscregfile.hh @@ -32,9 +32,11 @@ #ifndef __ARCH_SPARC_MISCREGFILE_HH__ #define __ARCH_SPARC_MISCREGFILE_HH__ +#include "arch/sparc/asi.hh" #include "arch/sparc/faults.hh" #include "arch/sparc/isa_traits.hh" #include "arch/sparc/types.hh" +#include "cpu/cpuevent.hh" #include <string> @@ -329,6 +331,9 @@ namespace SparcISA } fsrFields; }; + ASI implicitInstAsi; + ASI implicitDataAsi; + // These need to check the int_dis field and if 0 then // set appropriate bit in softint and checkinterrutps on the cpu #if FULL_SYSTEM @@ -349,12 +354,6 @@ namespace SparcISA typedef CpuEventWrapper<MiscRegFile, &MiscRegFile::processHSTickCompare> HSTickCompareEvent; HSTickCompareEvent *hSTickCompare; - - /** Fullsystem only register version of ReadRegWithEffect() */ - MiscReg readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc); - /** Fullsystem only register version of SetRegWithEffect() */ - Fault setFSRegWithEffect(int miscReg, const MiscReg &val, - ThreadContext * tc); #endif public: @@ -374,6 +373,16 @@ namespace SparcISA void setRegWithEffect(int miscReg, const MiscReg &val, ThreadContext * tc); + ASI getInstAsid() + { + return implicitInstAsi; + } + + ASI getDataAsid() + { + return implicitDataAsi; + } + void serialize(std::ostream & os); void unserialize(Checkpoint * cp, const std::string & section); @@ -385,6 +394,7 @@ namespace SparcISA bool isHyperPriv() { return hpstateFields.hpriv; } bool isPriv() { return hpstateFields.hpriv || pstateFields.priv; } bool isNonPriv() { return !isPriv(); } + inline void setImplicitAsis(); }; } diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc index 5eb874d39..65e6017da 100644 --- a/src/arch/sparc/regfile.cc +++ b/src/arch/sparc/regfile.cc @@ -79,24 +79,20 @@ MiscReg RegFile::readMiscReg(int miscReg) return miscRegFile.readReg(miscReg); } -MiscReg RegFile::readMiscRegWithEffect(int miscReg, - Fault &fault, ThreadContext *tc) +MiscReg RegFile::readMiscRegWithEffect(int miscReg, ThreadContext *tc) { - fault = NoFault; return miscRegFile.readRegWithEffect(miscReg, tc); } -Fault RegFile::setMiscReg(int miscReg, const MiscReg &val) +void RegFile::setMiscReg(int miscReg, const MiscReg &val) { miscRegFile.setReg(miscReg, val); - return NoFault; } -Fault RegFile::setMiscRegWithEffect(int miscReg, const MiscReg &val, +void RegFile::setMiscRegWithEffect(int miscReg, const MiscReg &val, ThreadContext * tc) { miscRegFile.setRegWithEffect(miscReg, val, tc); - return NoFault; } FloatReg RegFile::readFloatReg(int floatReg, int width) @@ -122,27 +118,26 @@ FloatRegBits RegFile::readFloatRegBits(int floatReg) FloatRegFile::SingleWidth); } -Fault RegFile::setFloatReg(int floatReg, const FloatReg &val, int width) +void RegFile::setFloatReg(int floatReg, const FloatReg &val, int width) { - return floatRegFile.setReg(floatReg, val, width); + floatRegFile.setReg(floatReg, val, width); } -Fault RegFile::setFloatReg(int floatReg, const FloatReg &val) +void RegFile::setFloatReg(int floatReg, const FloatReg &val) { //Use the "natural" width of a single float - return setFloatReg(floatReg, val, FloatRegFile::SingleWidth); + setFloatReg(floatReg, val, FloatRegFile::SingleWidth); } -Fault RegFile::setFloatRegBits(int floatReg, const FloatRegBits &val, int width) +void RegFile::setFloatRegBits(int floatReg, const FloatRegBits &val, int width) { - return floatRegFile.setRegBits(floatReg, val, width); + floatRegFile.setRegBits(floatReg, val, width); } -Fault RegFile::setFloatRegBits(int floatReg, const FloatRegBits &val) +void RegFile::setFloatRegBits(int floatReg, const FloatRegBits &val) { //Use the "natural" width of a single float - return floatRegFile.setRegBits(floatReg, val, - FloatRegFile::SingleWidth); + floatRegFile.setRegBits(floatReg, val, FloatRegFile::SingleWidth); } IntReg RegFile::readIntReg(int intReg) @@ -150,9 +145,9 @@ IntReg RegFile::readIntReg(int intReg) return intRegFile.readReg(intReg); } -Fault RegFile::setIntReg(int intReg, const IntReg &val) +void RegFile::setIntReg(int intReg, const IntReg &val) { - return intRegFile.setReg(intReg, val); + intRegFile.setReg(intReg, val); } void RegFile::serialize(std::ostream &os) diff --git a/src/arch/sparc/regfile.hh b/src/arch/sparc/regfile.hh index 500fbbba4..9f33435f6 100644 --- a/src/arch/sparc/regfile.hh +++ b/src/arch/sparc/regfile.hh @@ -32,7 +32,6 @@ #ifndef __ARCH_SPARC_REGFILE_HH__ #define __ARCH_SPARC_REGFILE_HH__ -#include "arch/sparc/faults.hh" #include "arch/sparc/floatregfile.hh" #include "arch/sparc/intregfile.hh" #include "arch/sparc/isa_traits.hh" @@ -76,14 +75,23 @@ namespace SparcISA MiscReg readMiscReg(int miscReg); - MiscReg readMiscRegWithEffect(int miscReg, - Fault &fault, ThreadContext *tc); + MiscReg readMiscRegWithEffect(int miscReg, ThreadContext *tc); - Fault setMiscReg(int miscReg, const MiscReg &val); + void setMiscReg(int miscReg, const MiscReg &val); - Fault setMiscRegWithEffect(int miscReg, const MiscReg &val, + void setMiscRegWithEffect(int miscReg, const MiscReg &val, ThreadContext * tc); + ASI instAsid() + { + return miscRegFile.getInstAsid(); + } + + ASI dataAsid() + { + return miscRegFile.getDataAsid(); + } + FloatReg readFloatReg(int floatReg, int width); FloatReg readFloatReg(int floatReg); @@ -92,17 +100,17 @@ namespace SparcISA FloatRegBits readFloatRegBits(int floatReg); - Fault setFloatReg(int floatReg, const FloatReg &val, int width); + void setFloatReg(int floatReg, const FloatReg &val, int width); - Fault setFloatReg(int floatReg, const FloatReg &val); + void setFloatReg(int floatReg, const FloatReg &val); - Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width); + void setFloatRegBits(int floatReg, const FloatRegBits &val, int width); - Fault setFloatRegBits(int floatReg, const FloatRegBits &val); + void setFloatRegBits(int floatReg, const FloatRegBits &val); IntReg readIntReg(int intReg); - Fault setIntReg(int intReg, const IntReg &val); + void setIntReg(int intReg, const IntReg &val); void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); diff --git a/src/arch/sparc/remote_gdb.cc b/src/arch/sparc/remote_gdb.cc new file mode 100644 index 000000000..c76f8b820 --- /dev/null +++ b/src/arch/sparc/remote_gdb.cc @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2002-2005 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: Nathan Binkert + */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 + */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/* + * $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $ + * + * Taken from NetBSD + * + * "Stub" to allow remote cpu to debug over a serial line using gdb. + */ + +#include <sys/signal.h> + +#include <string> +#include <unistd.h> + +#include "arch/vtophys.hh" +#include "arch/sparc/remote_gdb.hh" +#include "base/intmath.hh" +#include "base/remote_gdb.hh" +#include "base/socket.hh" +#include "base/trace.hh" +#include "config/full_system.hh" +#include "cpu/thread_context.hh" +#include "cpu/static_inst.hh" +#include "mem/physical.hh" +#include "mem/port.hh" +#include "sim/system.hh" + +using namespace std; +using namespace TheISA; + +RemoteGDB::RemoteGDB(System *_system, ThreadContext *c) + : BaseRemoteGDB(_system, c, NumGDBRegs) +{} + +/////////////////////////////////////////////////////////// +// RemoteGDB::acc +// +// Determine if the mapping at va..(va+len) is valid. +// +bool +RemoteGDB::acc(Addr va, size_t len) +{ + //@Todo In NetBSD, this function checks if all addresses + //from va to va + len have valid page mape entries. Not + //sure how this will work for other OSes or in general. + return true; +} + +/////////////////////////////////////////////////////////// +// RemoteGDB::getregs +// +// Translate the kernel debugger register format into +// the GDB register format. +void +RemoteGDB::getregs() +{ + memset(gdbregs.regs, 0, gdbregs.size); + + gdbregs.regs[RegPc] = context->readPC(); + gdbregs.regs[RegNpc] = context->readNextPC(); + for(int x = RegG0; x <= RegI0 + 7; x++) + gdbregs.regs[x] = context->readIntReg(x - RegG0); + //Floating point registers are left at 0 in netbsd + //All registers other than the pc, npc and int regs + //are ignored as well. +} + +/////////////////////////////////////////////////////////// +// RemoteGDB::setregs +// +// Translate the GDB register format into the kernel +// debugger register format. +// +void +RemoteGDB::setregs() +{ + context->setPC(gdbregs.regs[RegPc]); + context->setNextPC(gdbregs.regs[RegNpc]); + for(int x = RegG0; x <= RegI0 + 7; x++) + context->setIntReg(x - RegG0, gdbregs.regs[x]); + //Only the integer registers, pc and npc are set in netbsd +} + +void +RemoteGDB::clearSingleStep() +{ + panic("SPARC does not support hardware single stepping\n"); +} + +void +RemoteGDB::setSingleStep() +{ + panic("SPARC does not support hardware single stepping\n"); +} diff --git a/src/arch/sparc/remote_gdb.hh b/src/arch/sparc/remote_gdb.hh new file mode 100644 index 000000000..e4b66b783 --- /dev/null +++ b/src/arch/sparc/remote_gdb.hh @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2002-2005 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: Nathan Binkert + */ + +#ifndef __ARCH_ALPHA_REMOTE_GDB_HH__ +#define __ARCH_ALPHA_REMOTE_GDB_HH__ + +#include <map> + +#include "arch/types.hh" +#include "base/remote_gdb.hh" +#include "cpu/pc_event.hh" +#include "base/pollevent.hh" + +class System; +class ThreadContext; +class PhysicalMemory; + +namespace SparcISA +{ + class RemoteGDB : public BaseRemoteGDB + { + protected: + enum RegisterConstants + { + RegG0 = 0, RegO0 = 8, RegL0 = 16, RegI0 = 24, + RegF0 = 32, RegF32 = 64, + RegPc = 80, RegNpc, RegCcr, RegFsr, RegFprs, RegY, RegAsi, + RegVer, RegTick, RegPil, RegPstate, + RegTstate, RegTba, RegTl, RegTt, RegTpc, RegTnpc, RegWstate, + RegCwp, RegCansave, RegCanrestore, RegCleanwin, RegOtherwin, + RegAsr16 = 103, + RegIcc = 119, RegXcc, + RegFcc0 = 121, + NumGDBRegs + }; + + public: + RemoteGDB(System *system, ThreadContext *context); + + bool acc(Addr addr, size_t len); + + protected: + void getregs(); + void setregs(); + + void clearSingleStep(); + void setSingleStep(); + }; +} + +#endif /* __ARCH_ALPHA_REMOTE_GDB_H__ */ diff --git a/src/arch/sparc/stacktrace.cc b/src/arch/sparc/stacktrace.cc new file mode 100644 index 000000000..2eb697bf2 --- /dev/null +++ b/src/arch/sparc/stacktrace.cc @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2005 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: Nathan Binkert + */ + +#include <string> + +#include "arch/sparc/isa_traits.hh" +#include "arch/sparc/stacktrace.hh" +#include "arch/sparc/vtophys.hh" +#include "base/bitfield.hh" +#include "base/trace.hh" +#include "cpu/base.hh" +#include "cpu/thread_context.hh" +#include "sim/system.hh" + +using namespace std; +namespace SparcISA +{ + ProcessInfo::ProcessInfo(ThreadContext *_tc) + : tc(_tc) + { + Addr addr = 0; + + VirtualPort *vp; + + vp = tc->getVirtPort(); + + if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr)) + panic("thread info not compiled into kernel\n"); + thread_info_size = vp->readGtoH<int32_t>(addr); + + if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr)) + panic("thread info not compiled into kernel\n"); + task_struct_size = vp->readGtoH<int32_t>(addr); + + if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr)) + panic("thread info not compiled into kernel\n"); + task_off = vp->readGtoH<int32_t>(addr); + + if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr)) + panic("thread info not compiled into kernel\n"); + pid_off = vp->readGtoH<int32_t>(addr); + + if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr)) + panic("thread info not compiled into kernel\n"); + name_off = vp->readGtoH<int32_t>(addr); + + tc->delVirtPort(vp); + } + + Addr + ProcessInfo::task(Addr ksp) const + { + Addr base = ksp & ~0x3fff; + if (base == ULL(0xfffffc0000000000)) + return 0; + + Addr tsk; + + VirtualPort *vp; + + vp = tc->getVirtPort(); + tsk = vp->readGtoH<Addr>(base + task_off); + tc->delVirtPort(vp); + + return tsk; + } + + int + ProcessInfo::pid(Addr ksp) const + { + Addr task = this->task(ksp); + if (!task) + return -1; + + uint16_t pd; + + VirtualPort *vp; + + vp = tc->getVirtPort(); + pd = vp->readGtoH<uint16_t>(task + pid_off); + tc->delVirtPort(vp); + + return pd; + } + + string + ProcessInfo::name(Addr ksp) const + { + Addr task = this->task(ksp); + if (!task) + return "console"; + + char comm[256]; + CopyStringOut(tc, comm, task + name_off, sizeof(comm)); + if (!comm[0]) + return "startup"; + + return comm; + } + + StackTrace::StackTrace() + : tc(0), stack(64) + { + } + + StackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst) + : tc(0), stack(64) + { + trace(_tc, inst); + } + + StackTrace::~StackTrace() + { + } + + void + StackTrace::trace(ThreadContext *_tc, bool is_call) + { +#if 0 + tc = _tc; + + bool usermode = (tc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; + + Addr pc = tc->readNextPC(); + bool kernel = tc->getSystemPtr()->kernelStart <= pc && + pc <= tc->getSystemPtr()->kernelEnd; + + if (usermode) { + stack.push_back(user); + return; + } + + if (!kernel) { + stack.push_back(console); + return; + } + + SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; + Addr ksp = tc->readIntReg(TheISA::StackPointerReg); + Addr bottom = ksp & ~0x3fff; + Addr addr; + + if (is_call) { + if (!symtab->findNearestAddr(pc, addr)) + panic("could not find address %#x", pc); + + stack.push_back(addr); + pc = tc->readPC(); + } + + Addr ra; + int size; + + while (ksp > bottom) { + if (!symtab->findNearestAddr(pc, addr)) + panic("could not find symbol for pc=%#x", pc); + assert(pc >= addr && "symbol botch: callpc < func"); + + stack.push_back(addr); + + if (isEntry(addr)) + return; + + if (decodePrologue(ksp, pc, addr, size, ra)) { + if (!ra) + return; + + if (size <= 0) { + stack.push_back(unknown); + return; + } + + pc = ra; + ksp += size; + } else { + stack.push_back(unknown); + return; + } + + bool kernel = tc->getSystemPtr()->kernelStart <= pc && + pc <= tc->getSystemPtr()->kernelEnd; + if (!kernel) + return; + + if (stack.size() >= 1000) + panic("unwinding too far"); + } + + panic("unwinding too far"); +#endif + } + + bool + StackTrace::isEntry(Addr addr) + { +#if 0 + if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp12)) + return true; + + if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp7)) + return true; + + if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp11)) + return true; + + if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp21)) + return true; + + if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp9)) + return true; + + if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp2)) + return true; +#endif + return false; + } + + bool + StackTrace::decodeStack(MachInst inst, int &disp) + { + // lda $sp, -disp($sp) + // + // Opcode<31:26> == 0x08 + // RA<25:21> == 30 + // RB<20:16> == 30 + // Disp<15:0> + const MachInst mem_mask = 0xffff0000; + const MachInst lda_pattern = 0x23de0000; + const MachInst lda_disp_mask = 0x0000ffff; + + // subq $sp, disp, $sp + // addq $sp, disp, $sp + // + // Opcode<31:26> == 0x10 + // RA<25:21> == 30 + // Lit<20:13> + // One<12> = 1 + // Func<11:5> == 0x20 (addq) + // Func<11:5> == 0x29 (subq) + // RC<4:0> == 30 + const MachInst intop_mask = 0xffe01fff; + const MachInst addq_pattern = 0x43c0141e; + const MachInst subq_pattern = 0x43c0153e; + const MachInst intop_disp_mask = 0x001fe000; + const int intop_disp_shift = 13; + + if ((inst & mem_mask) == lda_pattern) + disp = -sext<16>(inst & lda_disp_mask); + else if ((inst & intop_mask) == addq_pattern) + disp = -int((inst & intop_disp_mask) >> intop_disp_shift); + else if ((inst & intop_mask) == subq_pattern) + disp = int((inst & intop_disp_mask) >> intop_disp_shift); + else + return false; + + return true; + } + + bool + StackTrace::decodeSave(MachInst inst, int ®, int &disp) + { + // lda $stq, disp($sp) + // + // Opcode<31:26> == 0x08 + // RA<25:21> == ? + // RB<20:16> == 30 + // Disp<15:0> + const MachInst stq_mask = 0xfc1f0000; + const MachInst stq_pattern = 0xb41e0000; + const MachInst stq_disp_mask = 0x0000ffff; + const MachInst reg_mask = 0x03e00000; + const int reg_shift = 21; + + if ((inst & stq_mask) == stq_pattern) { + reg = (inst & reg_mask) >> reg_shift; + disp = sext<16>(inst & stq_disp_mask); + } else { + return false; + } + + return true; + } + + /* + * Decode the function prologue for the function we're in, and note + * which registers are stored where, and how large the stack frame is. + */ + bool + StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, + int &size, Addr &ra) + { + size = 0; + ra = 0; + + for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) { + MachInst inst; + CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst)); + + int reg, disp; + if (decodeStack(inst, disp)) { + if (size) { + // panic("decoding frame size again"); + return true; + } + size += disp; + } else if (decodeSave(inst, reg, disp)) { + if (!ra && reg == ReturnAddressReg) { + CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr)); + if (!ra) { + // panic("no return address value pc=%#x\n", pc); + return false; + } + } + } + } + + return true; + } + +#if TRACING_ON + void + StackTrace::dump() + { + StringWrap name(tc->getCpuPtr()->name()); + SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; + + DPRINTFN("------ Stack ------\n"); + + string symbol; + for (int i = 0, size = stack.size(); i < size; ++i) { + Addr addr = stack[size - i - 1]; + if (addr == user) + symbol = "user"; + else if (addr == console) + symbol = "console"; + else if (addr == unknown) + symbol = "unknown"; + else + symtab->findSymbol(addr, symbol); + + DPRINTFN("%#x: %s\n", addr, symbol); + } + } +#endif +} diff --git a/src/arch/sparc/stacktrace.hh b/src/arch/sparc/stacktrace.hh index 54d3d17be..4bc5d779b 100644 --- a/src/arch/sparc/stacktrace.hh +++ b/src/arch/sparc/stacktrace.hh @@ -35,87 +35,90 @@ #include "cpu/static_inst.hh" class ThreadContext; -class StackTrace; - -class ProcessInfo +namespace SparcISA { - private: - ThreadContext *tc; + class StackTrace; - int thread_info_size; - int task_struct_size; - int task_off; - int pid_off; - int name_off; + class ProcessInfo + { + private: + ThreadContext *tc; - public: - ProcessInfo(ThreadContext *_tc); + int thread_info_size; + int task_struct_size; + int task_off; + int pid_off; + int name_off; - Addr task(Addr ksp) const; - int pid(Addr ksp) const; - std::string name(Addr ksp) const; -}; + public: + ProcessInfo(ThreadContext *_tc); -class StackTrace -{ - protected: - typedef TheISA::MachInst MachInst; - private: - ThreadContext *tc; - std::vector<Addr> stack; - - private: - bool isEntry(Addr addr); - bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra); - bool decodeSave(MachInst inst, int ®, int &disp); - bool decodeStack(MachInst inst, int &disp); - - void trace(ThreadContext *tc, bool is_call); - - public: - StackTrace(); - StackTrace(ThreadContext *tc, StaticInstPtr inst); - ~StackTrace(); - - void clear() + Addr task(Addr ksp) const; + int pid(Addr ksp) const; + std::string name(Addr ksp) const; + }; + + class StackTrace { - tc = 0; - stack.clear(); - } + protected: + typedef TheISA::MachInst MachInst; + private: + ThreadContext *tc; + std::vector<Addr> stack; + + private: + bool isEntry(Addr addr); + bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra); + bool decodeSave(MachInst inst, int ®, int &disp); + bool decodeStack(MachInst inst, int &disp); - bool valid() const { return tc != NULL; } - bool trace(ThreadContext *tc, StaticInstPtr inst); + void trace(ThreadContext *tc, bool is_call); - public: - const std::vector<Addr> &getstack() const { return stack; } + public: + StackTrace(); + StackTrace(ThreadContext *tc, StaticInstPtr inst); + ~StackTrace(); - static const int user = 1; - static const int console = 2; - static const int unknown = 3; + void clear() + { + tc = 0; + stack.clear(); + } + + bool valid() const { return tc != NULL; } + bool trace(ThreadContext *tc, StaticInstPtr inst); + + public: + const std::vector<Addr> &getstack() const { return stack; } + + static const int user = 1; + static const int console = 2; + static const int unknown = 3; #if TRACING_ON - private: - void dump(); + private: + void dump(); - public: - void dprintf() { if (DTRACE(Stack)) dump(); } + public: + void dprintf() { if (DTRACE(Stack)) dump(); } #else - public: - void dprintf() {} + public: + void dprintf() {} #endif -}; + }; -inline bool -StackTrace::trace(ThreadContext *tc, StaticInstPtr inst) -{ - if (!inst->isCall() && !inst->isReturn()) - return false; + inline bool + StackTrace::trace(ThreadContext *tc, StaticInstPtr inst) + { + if (!inst->isCall() && !inst->isReturn()) + return false; - if (valid()) - clear(); + if (valid()) + clear(); - trace(tc, !inst->isReturn()); - return true; + trace(tc, !inst->isReturn()); + return true; + } } #endif // __ARCH_SPARC_STACKTRACE_HH__ diff --git a/src/arch/sparc/system.cc b/src/arch/sparc/system.cc index ef6443d17..952ac2deb 100644 --- a/src/arch/sparc/system.cc +++ b/src/arch/sparc/system.cc @@ -77,7 +77,7 @@ SparcSystem::SparcSystem(Params *p) hypervisor->loadSections(&functionalPort, SparcISA::LoadAddrMask); // load symbols - if (!reset->loadGlobalSymbols(reset)) + if (!reset->loadGlobalSymbols(resetSymtab)) panic("could not load reset symbols\n"); if (!openboot->loadGlobalSymbols(openbootSymtab)) @@ -148,7 +148,10 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem) Param<std::string> hypervisor_bin; Param<std::string> openboot_bin; + Param<Tick> boot_cpu_frequency; Param<std::string> boot_osflags; + Param<uint64_t> system_type; + Param<uint64_t> system_rev; Param<std::string> readfile; Param<unsigned int> init_param; @@ -156,7 +159,6 @@ END_DECLARE_SIM_OBJECT_PARAMS(SparcSystem) BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem) - INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), INIT_PARAM(physmem, "phsyical memory"), INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)", System::MemoryModeStrings), @@ -164,12 +166,13 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem) INIT_PARAM(reset_bin, "file that contains the reset code"), INIT_PARAM(hypervisor_bin, "file that contains the hypervisor code"), INIT_PARAM(openboot_bin, "file that contains the openboot code"), + INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot", "a"), - INIT_PARAM_DFLT(readfile, "file to read startup script from", ""), - INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0), INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34), - INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10) + INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10), + INIT_PARAM_DFLT(readfile, "file to read startup script from", ""), + INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0) END_INIT_SIM_OBJECT_PARAMS(SparcSystem) diff --git a/src/arch/sparc/system.hh b/src/arch/sparc/system.hh index 614707f6c..0b79eda38 100644 --- a/src/arch/sparc/system.hh +++ b/src/arch/sparc/system.hh @@ -46,7 +46,7 @@ class SparcSystem : public System struct Params : public System::Params { std::string reset_bin; - std::string hypervison_bin; + std::string hypervisor_bin; std::string openboot_bin; std::string boot_osflags; uint64_t system_type; @@ -111,8 +111,11 @@ class SparcSystem : public System return addFuncEvent<T>(openbootSymtab, lbl); } - virtual Addr fixFuncEventAddr(Addr addr); - + virtual Addr fixFuncEventAddr(Addr addr) + { + //XXX This may eventually have to do something useful. + return addr; + } }; #endif diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc new file mode 100644 index 000000000..0b1a2ff5f --- /dev/null +++ b/src/arch/sparc/tlb.cc @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2001-2005 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: Nathan Binkert + * Steve Reinhardt + * Andrew Schultz + */ + +#include "arch/sparc/tlb.hh" +#include "sim/builder.hh" + +namespace SparcISA +{ + DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB) + + BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB) + + Param<int> size; + + END_DECLARE_SIM_OBJECT_PARAMS(ITB) + + BEGIN_INIT_SIM_OBJECT_PARAMS(ITB) + + INIT_PARAM_DFLT(size, "TLB size", 48) + + END_INIT_SIM_OBJECT_PARAMS(ITB) + + + CREATE_SIM_OBJECT(ITB) + { + return new ITB(getInstanceName(), size); + } + + REGISTER_SIM_OBJECT("SparcITB", ITB) + + BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB) + + Param<int> size; + + END_DECLARE_SIM_OBJECT_PARAMS(DTB) + + BEGIN_INIT_SIM_OBJECT_PARAMS(DTB) + + INIT_PARAM_DFLT(size, "TLB size", 64) + + END_INIT_SIM_OBJECT_PARAMS(DTB) + + + CREATE_SIM_OBJECT(DTB) + { + return new DTB(getInstanceName(), size); + } + + REGISTER_SIM_OBJECT("SparcDTB", DTB) +} diff --git a/src/arch/sparc/tlb.hh b/src/arch/sparc/tlb.hh index 35ff08b43..0fdba6baf 100644 --- a/src/arch/sparc/tlb.hh +++ b/src/arch/sparc/tlb.hh @@ -31,5 +31,47 @@ #ifndef __ARCH_SPARC_TLB_HH__ #define __ARCH_SPARC_TLB_HH__ +#include "mem/request.hh" +#include "sim/faults.hh" +#include "sim/sim_object.hh" + +class ThreadContext; + +namespace SparcISA +{ + class TLB : public SimObject + { + public: + TLB(const std::string &name, int size) : SimObject(name) + { + } + }; + + class ITB : public TLB + { + public: + ITB(const std::string &name, int size) : TLB(name, size) + { + } + + Fault translate(RequestPtr &req, ThreadContext *tc) const + { + return NoFault; + } + }; + + class DTB : public TLB + { + public: + DTB(const std::string &name, int size) : TLB(name, size) + { + } + + Fault translate(RequestPtr &req, ThreadContext *tc, bool write) const + { + return NoFault; + } + }; +} #endif // __ARCH_SPARC_TLB_HH__ diff --git a/src/arch/sparc/utility.hh b/src/arch/sparc/utility.hh index 23fddf0e9..e2b0b2307 100644 --- a/src/arch/sparc/utility.hh +++ b/src/arch/sparc/utility.hh @@ -31,6 +31,7 @@ #ifndef __ARCH_SPARC_UTILITY_HH__ #define __ARCH_SPARC_UTILITY_HH__ +#include "arch/sparc/faults.hh" #include "arch/sparc/isa_traits.hh" #include "base/misc.hh" #include "base/bitfield.hh" @@ -99,6 +100,12 @@ namespace SparcISA template <class TC> void zeroRegisters(TC *tc); + inline void initCPU(ThreadContext *tc, int cpuId) + { + static Fault por = new PowerOnReset(); + por->invoke(tc); + } + } // namespace SparcISA #endif diff --git a/src/arch/sparc/vtophys.cc b/src/arch/sparc/vtophys.cc index f7fd92c15..429126b70 100644 --- a/src/arch/sparc/vtophys.cc +++ b/src/arch/sparc/vtophys.cc @@ -32,135 +32,47 @@ #include <string> -#include "arch/alpha/ev5.hh" -#include "arch/alpha/vtophys.hh" +#include "arch/sparc/vtophys.hh" #include "base/chunk_generator.hh" #include "base/trace.hh" #include "cpu/thread_context.hh" #include "mem/vport.hh" using namespace std; -using namespace AlphaISA; -AlphaISA::PageTableEntry -AlphaISA::kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr) +namespace SparcISA { - Addr level1_pte = ptbr + vaddr.level1(); - AlphaISA::PageTableEntry level1 = mem->read<uint64_t>(level1_pte); - if (!level1.valid()) { - DPRINTF(VtoPhys, "level 1 PTE not valid, va = %#\n", vaddr); - return 0; + PageTableEntry kernel_pte_lookup(FunctionalPort *mem, + Addr ptbr, VAddr vaddr) + { + PageTableEntry pte(4); + return pte; } - Addr level2_pte = level1.paddr() + vaddr.level2(); - AlphaISA::PageTableEntry level2 = mem->read<uint64_t>(level2_pte); - if (!level2.valid()) { - DPRINTF(VtoPhys, "level 2 PTE not valid, va = %#x\n", vaddr); - return 0; + Addr vtophys(Addr vaddr) + { + return vaddr; } - Addr level3_pte = level2.paddr() + vaddr.level3(); - AlphaISA::PageTableEntry level3 = mem->read<uint64_t>(level3_pte); - if (!level3.valid()) { - DPRINTF(VtoPhys, "level 3 PTE not valid, va = %#x\n", vaddr); - return 0; + Addr vtophys(ThreadContext *tc, Addr addr) + { + return addr; } - return level3; -} -Addr -AlphaISA::vtophys(Addr vaddr) -{ - Addr paddr = 0; - if (AlphaISA::IsUSeg(vaddr)) - DPRINTF(VtoPhys, "vtophys: invalid vaddr %#x", vaddr); - else if (AlphaISA::IsK0Seg(vaddr)) - paddr = AlphaISA::K0Seg2Phys(vaddr); - else - panic("vtophys: ptbr is not set on virtual lookup"); - DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr); - - return paddr; -} - -Addr -AlphaISA::vtophys(ThreadContext *tc, Addr addr) -{ - AlphaISA::VAddr vaddr = addr; - Addr ptbr = tc->readMiscReg(AlphaISA::IPR_PALtemp20); - Addr paddr = 0; - //@todo Andrew couldn't remember why he commented some of this code - //so I put it back in. Perhaps something to do with gdb debugging? - if (AlphaISA::PcPAL(vaddr) && (vaddr < EV5::PalMax)) { - paddr = vaddr & ~ULL(1); - } else { - if (AlphaISA::IsK0Seg(vaddr)) { - paddr = AlphaISA::K0Seg2Phys(vaddr); - } else if (!ptbr) { - paddr = vaddr; - } else { - AlphaISA::PageTableEntry pte = - kernel_pte_lookup(tc->getPhysPort(), ptbr, vaddr); - if (pte.valid()) - paddr = pte.paddr() | vaddr.offset(); - } + void CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen) + { } + void CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen) + { + } - DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr); - - return paddr; -} - - -void -AlphaISA::CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen) -{ - uint8_t *dst = (uint8_t *)dest; - VirtualPort *vp = tc->getVirtPort(tc); - - vp->readBlob(src, dst, cplen); - - tc->delVirtPort(vp); - -} - -void -AlphaISA::CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen) -{ - uint8_t *src = (uint8_t *)source; - VirtualPort *vp = tc->getVirtPort(tc); - - vp->writeBlob(dest, src, cplen); - - tc->delVirtPort(vp); -} - -void -AlphaISA::CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen) -{ - int len = 0; - VirtualPort *vp = tc->getVirtPort(tc); - - do { - vp->readBlob(vaddr++, (uint8_t*)dst++, 1); - len++; - } while (len < maxlen && dst[len] != 0 ); - - tc->delVirtPort(vp); - dst[len] = 0; -} + void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen) + { + } -void -AlphaISA::CopyStringIn(ThreadContext *tc, char *src, Addr vaddr) -{ - VirtualPort *vp = tc->getVirtPort(tc); - for (ChunkGenerator gen(vaddr, strlen(src), AlphaISA::PageBytes); !gen.done(); - gen.next()) + void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr) { - vp->writeBlob(gen.addr(), (uint8_t*)src, gen.size()); - src += gen.size(); } - tc->delVirtPort(vp); } |