Merge zizzer.eecs.umich.edu:/bk/newmem

into  ewok.(none):/home/gblack/m5/newmemo3

src/sim/byteswap.hh:
    Hand Merge

--HG--
extra : convert_revision : 640d33ad0c416934e8a5107768e7f1dce6709ca8
This commit is contained in:
Gabe Black 2007-01-22 22:31:48 -08:00
commit 1352e55ceb
41 changed files with 1075 additions and 337 deletions

View file

@ -1,4 +1,4 @@
# Copyright (c) 2006 The Regents of The University of Michigan # Copyright (c) 2006-2007 The Regents of The University of Michigan
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
@ -38,6 +38,14 @@ class CowIdeDisk(IdeDisk):
def childImage(self, ci): def childImage(self, ci):
self.image.child.image_file = ci self.image.child.image_file = ci
class CowMmDisk(MmDisk):
image = CowDiskImage(child=RawDiskImage(read_only=True),
read_only=False)
def childImage(self, ci):
self.image.child.image_file = ci
class BaseTsunami(Tsunami): class BaseTsunami(Tsunami):
ethernet = NSGigE(configdata=NSGigEPciData(), ethernet = NSGigE(configdata=NSGigEPciData(),
pci_bus=0, pci_dev=1, pci_func=0) pci_bus=0, pci_dev=1, pci_func=0)
@ -100,8 +108,9 @@ def makeSparcSystem(mem_mode, mdesc = None):
self.hypervisor_desc.port = self.membus.port self.hypervisor_desc.port = self.membus.port
self.partition_desc.port = self.membus.port self.partition_desc.port = self.membus.port
self.intrctrl = IntrControl() self.intrctrl = IntrControl()
self.mem_mode = mem_mode self.disk0 = CowMmDisk()
self.disk0.childImage(disk('disk.s10hw2'))
self.disk0.pio = self.iobus.port
self.reset_bin = binary('reset.bin') self.reset_bin = binary('reset.bin')
self.hypervisor_bin = binary('q.bin') self.hypervisor_bin = binary('q.bin')
self.openboot_bin = binary('openboot.bin') self.openboot_bin = binary('openboot.bin')

View file

@ -52,6 +52,11 @@ namespace AlphaISA
newInfoSet = false; newInfoSet = false;
} }
void post(int int_type)
{
// sparc only
}
void post(int int_num, int index) void post(int int_num, int index)
{ {
DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);

View file

@ -80,7 +80,7 @@ namespace AlphaISA {
bool _kre() const { return (entry >> 8) & 0x1; } bool _kre() const { return (entry >> 8) & 0x1; }
bool _nomb() const { return (entry >> 7) & 0x1; } bool _nomb() const { return (entry >> 7) & 0x1; }
int _gh() const { return (entry >> 5) & 0x3; } int _gh() const { return (entry >> 5) & 0x3; }
bool _asm() const { return (entry >> 4) & 0x1; } bool _asm_() const { return (entry >> 4) & 0x1; }
bool _foe() const { return (entry >> 3) & 0x1; } bool _foe() const { return (entry >> 3) & 0x1; }
bool _fow() const { return (entry >> 2) & 0x1; } bool _fow() const { return (entry >> 2) & 0x1; }
bool _for() const { return (entry >> 1) & 0x1; } bool _for() const { return (entry >> 1) & 0x1; }

View file

@ -179,26 +179,23 @@ namespace SparcISA
(asi == ASI_LDTX_PL) || (asi == ASI_LDTX_PL) ||
(asi == ASI_LDTX_SL) || (asi == ASI_LDTX_SL) ||
(asi == ASI_BLK_PL) || (asi == ASI_BLK_PL) ||
(asi == ASI_BLK_SL); (asi == ASI_BLK_SL) ||
(asi == ASI_LTX_L);
} }
bool AsiIsTwin(ASI asi) bool AsiIsTwin(ASI asi)
{ {
return return
(asi == ASI_QUAD_LDD) || (asi >= ASI_LDTX_AIUP &&
(asi == ASI_LDTX_AIUP) || asi <= ASI_LDTX_N &&
(asi == ASI_LDTX_AIUS) || asi != ASI_QUEUE) ||
(asi == ASI_LDTX_REAL) || (asi >= ASI_LDTX_AIUP_L &&
(asi == ASI_LDTX_N) || asi <= ASI_LDTX_NL &&
(asi == ASI_LDTX_AIUP_L) || asi != 0x2D) ||
(asi == ASI_LDTX_AIUS_L) || asi == ASI_LDTX_P ||
(asi == ASI_LDTX_REAL_L) || asi == ASI_LDTX_S ||
(asi == ASI_LDTX_NL) || asi == ASI_LDTX_PL ||
(asi == ASI_LDTX_P) || asi == ASI_LDTX_SL;
(asi == ASI_LDTX_S) ||
(asi == ASI_LDTX_PL) ||
(asi == ASI_LDTX_SL) ||
(asi == ASI_LTX_L);
} }
bool AsiIsPartialStore(ASI asi) bool AsiIsPartialStore(ASI asi)

View file

@ -197,7 +197,7 @@ template<> SparcFaultBase::FaultVals
template<> SparcFaultBase::FaultVals template<> SparcFaultBase::FaultVals
SparcFault<InterruptLevelN>::vals = SparcFault<InterruptLevelN>::vals =
{"interrupt_level_n", 0x041, 0, {P, P, SH}}; {"interrupt_level_n", 0x040, 0, {P, P, SH}};
template<> SparcFaultBase::FaultVals template<> SparcFaultBase::FaultVals
SparcFault<HstickMatch>::vals = SparcFault<HstickMatch>::vals =
@ -240,7 +240,7 @@ template<> SparcFaultBase::FaultVals
{"dev_mondo", 0x07D, 1611, {P, P, SH}}; {"dev_mondo", 0x07D, 1611, {P, P, SH}};
template<> SparcFaultBase::FaultVals template<> SparcFaultBase::FaultVals
SparcFault<ResumeableError>::vals = SparcFault<ResumableError>::vals =
{"resume_error", 0x07E, 3330, {P, P, SH}}; {"resume_error", 0x07E, 3330, {P, P, SH}};
template<> SparcFaultBase::FaultVals template<> SparcFaultBase::FaultVals
@ -342,22 +342,8 @@ void doREDFault(ThreadContext *tc, TrapType tt)
//Update GL //Update GL
tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL)); tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL));
//set PSTATE.mm to 00 PSTATE = mbits(PSTATE, 2, 2); // just save the priv bit
//set PSTATE.pef to 1 PSTATE |= (1 << 4); //set PSTATE.pef to 1
PSTATE |= (1 << 4);
//set PSTATE.am to 0
PSTATE &= ~(1 << 3);
/* //set PSTATE.priv to 0
PSTATE &= ~(1 << 2);*/
//set PSTATE.ie to 0
//PSTATE.priv is set to 1 here. The manual says it should be 0, but
//Legion sets it to 1.
PSTATE |= (1 << 2);
//set PSTATE.cle to 0
PSTATE &= ~(1 << 9);
//PSTATE.tle is unchanged
//XXX Where is the tct bit?
//set PSTATE.tct to 0
tc->setMiscReg(MISCREG_PSTATE, PSTATE); tc->setMiscReg(MISCREG_PSTATE, PSTATE);
//set HPSTATE.red to 1 //set HPSTATE.red to 1
@ -446,46 +432,27 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL)); tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL));
//PSTATE.mm is unchanged //PSTATE.mm is unchanged
//PSTATE.pef = whether or not an fpu is present PSTATE |= (1 << 4); //PSTATE.pef = whether or not an fpu is present
//XXX We'll say there's one present, even though there aren't PSTATE &= ~(1 << 3); //PSTATE.am = 0
//implementations for a decent number of the instructions PSTATE &= ~(1 << 1); //PSTATE.ie = 0
PSTATE |= (1 << 4);
//PSTATE.am = 0
PSTATE &= ~(1 << 3);
if(!gotoHpriv)
{
//PSTATE.priv = 1
PSTATE |= (1 << 2);
//PSTATE.cle = PSTATE.tle
replaceBits(PSTATE, 9, 9, PSTATE >> 8);
}
else
{
//PSTATE.priv = 0
//PSTATE.priv is set to 1 here. The manual says it should be 0, but
//Legion sets it to 1.
PSTATE |= (1 << 2);
//PSTATE.cle = 0
PSTATE &= ~(1 << 9);
}
//PSTATE.ie = 0
PSTATE &= ~(1 << 1);
//PSTATE.tle is unchanged //PSTATE.tle is unchanged
//PSTATE.tct = 0 //PSTATE.tct = 0
//XXX Where exactly is this field?
tc->setMiscReg(MISCREG_PSTATE, PSTATE);
if (gotoHpriv) if (gotoHpriv)
{ {
//HPSTATE.red = 0 PSTATE &= ~(1 << 9); // PSTATE.cle = 0
HPSTATE &= ~(1 << 5); //The manual says PSTATE.priv should be 0, but Legion leaves it alone
//HPSTATE.hpriv = 1 HPSTATE &= ~(1 << 5); //HPSTATE.red = 0
HPSTATE |= (1 << 2); HPSTATE |= (1 << 2); //HPSTATE.hpriv = 1
//HPSTATE.ibe = 0 HPSTATE &= ~(1 << 10); //HPSTATE.ibe = 0
HPSTATE &= ~(1 << 10);
//HPSTATE.tlz is unchanged //HPSTATE.tlz is unchanged
tc->setMiscReg(MISCREG_HPSTATE, HPSTATE); tc->setMiscReg(MISCREG_HPSTATE, HPSTATE);
} else { // we are going to priv
PSTATE |= (1 << 2); //PSTATE.priv = 1
replaceBits(PSTATE, 9, 9, PSTATE >> 8); //PSTATE.cle = PSTATE.tle
} }
tc->setMiscReg(MISCREG_PSTATE, PSTATE);
bool changedCWP = true; bool changedCWP = true;
if (tt == 0x24) if (tt == 0x24)
@ -538,35 +505,35 @@ void SparcFaultBase::invoke(ThreadContext * tc)
//We can refer to this to see what the trap level -was-, but something //We can refer to this to see what the trap level -was-, but something
//in the middle could change it in the regfile out from under us. //in the middle could change it in the regfile out from under us.
MiscReg TL = tc->readMiscReg(MISCREG_TL); MiscReg tl = tc->readMiscReg(MISCREG_TL);
MiscReg TT = tc->readMiscReg(MISCREG_TT); MiscReg tt = tc->readMiscReg(MISCREG_TT);
MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE); MiscReg pstate = tc->readMiscReg(MISCREG_PSTATE);
MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); MiscReg hpstate = tc->readMiscReg(MISCREG_HPSTATE);
Addr PC, NPC; Addr PC, NPC;
PrivilegeLevel current; PrivilegeLevel current;
if(HPSTATE & (1 << 2)) if (hpstate & HPSTATE::hpriv)
current = Hyperprivileged; current = Hyperprivileged;
else if(PSTATE & (1 << 2)) else if (pstate & PSTATE::priv)
current = Privileged; current = Privileged;
else else
current = User; current = User;
PrivilegeLevel level = getNextLevel(current); PrivilegeLevel level = getNextLevel(current);
if(HPSTATE & (1 << 5) || TL == MaxTL - 1) { if ((hpstate & HPSTATE::red) || (tl == MaxTL - 1)) {
getREDVector(5, PC, NPC); getREDVector(5, PC, NPC);
doREDFault(tc, TT); doREDFault(tc, tt);
//This changes the hpstate and pstate, so we need to make sure we //This changes the hpstate and pstate, so we need to make sure we
//save the old version on the trap stack in doREDFault. //save the old version on the trap stack in doREDFault.
enterREDState(tc); enterREDState(tc);
} else if(TL == MaxTL) { } else if (tl == MaxTL) {
panic("Should go to error state here.. crap\n"); panic("Should go to error state here.. crap\n");
//Do error_state somehow? //Do error_state somehow?
//Probably inject a WDR fault using the interrupt mechanism. //Probably inject a WDR fault using the interrupt mechanism.
//What should the PC and NPC be set to? //What should the PC and NPC be set to?
} else if(TL > MaxPTL && level == Privileged) { } else if (tl > MaxPTL && level == Privileged) {
//guest_watchdog fault //guest_watchdog fault
doNormalFault(tc, trapType(), true); doNormalFault(tc, trapType(), true);
getHyperVector(tc, PC, NPC, 2); getHyperVector(tc, PC, NPC, 2);
@ -576,7 +543,7 @@ void SparcFaultBase::invoke(ThreadContext * tc)
getHyperVector(tc, PC, NPC, trapType()); getHyperVector(tc, PC, NPC, trapType());
} else { } else {
doNormalFault(tc, trapType(), false); doNormalFault(tc, trapType(), false);
getPrivVector(tc, PC, NPC, trapType(), TL+1); getPrivVector(tc, PC, NPC, trapType(), tl+1);
} }
tc->setPC(PC); tc->setPC(PC);

View file

@ -29,8 +29,8 @@
* Kevin Lim * Kevin Lim
*/ */
#ifndef __ALPHA_FAULTS_HH__ #ifndef __SPARC_FAULTS_HH__
#define __ALPHA_FAULTS_HH__ #define __SPARC_FAULTS_HH__
#include "sim/faults.hh" #include "sim/faults.hh"
@ -210,7 +210,7 @@ class CpuMondo : public SparcFault<CpuMondo> {};
class DevMondo : public SparcFault<DevMondo> {}; class DevMondo : public SparcFault<DevMondo> {};
class ResumeableError : public SparcFault<ResumeableError> {}; class ResumableError : public SparcFault<ResumableError> {};
class SpillNNormal : public EnumeratedFault<SpillNNormal> class SpillNNormal : public EnumeratedFault<SpillNNormal>
{ {
@ -280,4 +280,4 @@ static inline Fault genAlignmentFault()
} // SparcISA namespace } // SparcISA namespace
#endif // __FAULTS_HH__ #endif // __SPARC_FAULTS_HH__

View file

@ -24,8 +24,6 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Gabe Black
*/ */
#ifndef __ARCH_SPARC_INTERRUPT_HH__ #ifndef __ARCH_SPARC_INTERRUPT_HH__
@ -34,19 +32,45 @@
#include "arch/sparc/faults.hh" #include "arch/sparc/faults.hh"
#include "cpu/thread_context.hh" #include "cpu/thread_context.hh"
namespace SparcISA namespace SparcISA
{ {
enum interrupts_t {
trap_level_zero,
hstick_match,
interrupt_vector,
cpu_mondo,
dev_mondo,
resumable_error,
soft_interrupt,
num_interrupt_types
};
class Interrupts class Interrupts
{ {
protected:
private:
bool interrupts[num_interrupt_types];
int numPosted;
public: public:
Interrupts() Interrupts()
{ {
for (int i = 0; i < num_interrupt_types; ++i) {
interrupts[i] = false;
} }
numPosted = 0;
}
void post(int int_type)
{
if (int_type < 0 || int_type >= num_interrupt_types)
panic("posting unknown interrupt!\n");
interrupts[int_type] = true;
++numPosted;
}
void post(int int_num, int index) void post(int int_num, int index)
{ {
@ -64,9 +88,7 @@ namespace SparcISA
bool check_interrupts(ThreadContext * tc) const bool check_interrupts(ThreadContext * tc) const
{ {
// so far only handle softint interrupts if (numPosted)
int int_level = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT));
if (int_level)
return true; return true;
else else
return false; return false;
@ -74,20 +96,96 @@ namespace SparcISA
Fault getInterrupt(ThreadContext * tc) Fault getInterrupt(ThreadContext * tc)
{ {
// conditioning the softint interrups int hpstate = tc->readMiscReg(MISCREG_HPSTATE);
if (tc->readMiscReg(MISCREG_HPSTATE) & hpriv) { int pstate = tc->readMiscReg(MISCREG_PSTATE);
// if running in privileged mode, then pend the interrupt bool ie = pstate & PSTATE::ie;
return NoFault;
} else { // THESE ARE IN ORDER OF PRIORITY
int int_level = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT)); // since there are early returns, and the highest
if ((int_level <= tc->readMiscReg(MISCREG_PIL)) || // priority interrupts should get serviced,
!(tc->readMiscReg(MISCREG_PSTATE) & ie)) { // it is v. important that new interrupts are inserted
// if PIL or no interrupt enabled, then pend the interrupt // in the right order of processing
return NoFault; if (hpstate & HPSTATE::hpriv) {
} else { if (ie) {
return new InterruptLevelN(int_level); if (interrupts[hstick_match]) {
if (tc->readMiscReg(MISCREG_HINTP) & 1) {
interrupts[hstick_match] = false;
--numPosted;
return new HstickMatch;
} }
} }
if (interrupts[interrupt_vector]) {
interrupts[interrupt_vector] = false;
--numPosted;
//HAVEN'T IMPLed THIS YET
return NoFault;
}
} else {
if (interrupts[hstick_match]) {
return NoFault;
}
}
} else {
if (interrupts[trap_level_zero]) {
if ((pstate & HPSTATE::tlz) && (tc->readMiscReg(MISCREG_TL) == 0)) {
interrupts[trap_level_zero] = false;
--numPosted;
return new TrapLevelZero;
}
}
if (interrupts[hstick_match]) {
if (tc->readMiscReg(MISCREG_HINTP) & 1) {
interrupts[hstick_match] = false;
--numPosted;
return new HstickMatch;
}
}
if (ie) {
if (interrupts[cpu_mondo]) {
interrupts[cpu_mondo] = false;
--numPosted;
return new CpuMondo;
}
if (interrupts[dev_mondo]) {
interrupts[dev_mondo] = false;
--numPosted;
return new DevMondo;
}
if (interrupts[soft_interrupt]) {
int il = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT));
// it seems that interrupt vectors are right in
// the middle of interrupt levels with regard to
// priority, so have to check
if ((il < 6) &&
interrupts[interrupt_vector]) {
// may require more details here since there
// may be lots of interrupts embedded in an
// platform interrupt vector
interrupts[interrupt_vector] = false;
--numPosted;
//HAVEN'T IMPLed YET
return NoFault;
} else {
if (il > tc->readMiscReg(MISCREG_PIL)) {
uint64_t si = tc->readMiscReg(MISCREG_SOFTINT);
uint64_t more = si & ~(1 << (il + 1));
if (!InterruptLevel(more)) {
interrupts[soft_interrupt] = false;
--numPosted;
}
return new InterruptLevelN(il);
}
}
}
if (interrupts[resumable_error]) {
interrupts[resumable_error] = false;
--numPosted;
return new ResumableError;
}
}
}
return NoFault;
} }
void updateIntrInfo(ThreadContext * tc) void updateIntrInfo(ThreadContext * tc)

View file

@ -120,6 +120,8 @@ void IntRegFile::setReg(int intReg, const IntReg &val)
void IntRegFile::setCWP(int cwp) void IntRegFile::setCWP(int cwp)
{ {
int index = ((NWindows - cwp) % NWindows) * 2; int index = ((NWindows - cwp) % NWindows) * 2;
if (index < 0)
panic("Index less than 0. cwp=%d nwin=%d\n", cwp, NWindows);
offset[Outputs] = FrameOffset + (index * RegsPerFrame); offset[Outputs] = FrameOffset + (index * RegsPerFrame);
offset[Locals] = FrameOffset + ((index+1) * RegsPerFrame); offset[Locals] = FrameOffset + ((index+1) * RegsPerFrame);
offset[Inputs] = FrameOffset + offset[Inputs] = FrameOffset +
@ -137,6 +139,11 @@ void IntRegFile::setGlobals(int gl)
regView[Globals] = regGlobals[gl]; regView[Globals] = regGlobals[gl];
offset[Globals] = RegGlobalOffset + gl * RegsPerFrame; offset[Globals] = RegGlobalOffset + gl * RegsPerFrame;
if (regView[Globals] == regView[Inputs] ||
regView[Globals] == regView[Locals] ||
regView[Globals] == regView[Outputs] )
panic("Two register arrays set to the same thing!\n");
} }
void IntRegFile::serialize(std::ostream &os) void IntRegFile::serialize(std::ostream &os)

View file

@ -190,7 +190,7 @@ decode OP default Unknown::unknown()
}}); }});
0x0B: smul({{ 0x0B: smul({{
Rd.sdw = Rs1.sdw<31:0> * Rs2_or_imm13<31:0>; Rd.sdw = Rs1.sdw<31:0> * Rs2_or_imm13<31:0>;
Y = Rd.sdw; Y = Rd.sdw<63:32>;
}}); }});
0x0C: subc({{Rd.sdw = Rs1.sdw + (~Rs2_or_imm13) + 1 - Ccr<0:0>}}); 0x0C: subc({{Rd.sdw = Rs1.sdw + (~Rs2_or_imm13) + 1 - Ccr<0:0>}});
0x0D: udivx({{ 0x0D: udivx({{
@ -471,12 +471,12 @@ decode OP default Unknown::unknown()
//0x11-0x1F should cause an illegal instruction exception //0x11-0x1F should cause an illegal instruction exception
} }
0x2B: BasicOperate::flushw({{ 0x2B: BasicOperate::flushw({{
if(NWindows - 2 - Cansave == 0) if(NWindows - 2 - Cansave != 0)
{ {
if(Otherwin) if(Otherwin)
fault = new SpillNOther(Wstate<5:3>); fault = new SpillNOther(4*Wstate<5:3>);
else else
fault = new SpillNNormal(Wstate<2:0>); fault = new SpillNNormal(4*Wstate<2:0>);
} }
}}); }});
0x2C: decode MOVCC3 0x2C: decode MOVCC3
@ -891,9 +891,9 @@ decode OP default Unknown::unknown()
if(Canrestore == 0) if(Canrestore == 0)
{ {
if(Otherwin) if(Otherwin)
fault = new FillNOther(Wstate<5:3>); fault = new FillNOther(4*Wstate<5:3>);
else else
fault = new FillNNormal(Wstate<2:0>); fault = new FillNNormal(4*Wstate<2:0>);
} }
//Check for alignment faults //Check for alignment faults
else if(target & 0x3) else if(target & 0x3)
@ -941,9 +941,9 @@ decode OP default Unknown::unknown()
if(Cansave == 0) if(Cansave == 0)
{ {
if(Otherwin) if(Otherwin)
fault = new SpillNOther(Wstate<5:3>); fault = new SpillNOther(4*Wstate<5:3>);
else else
fault = new SpillNNormal(Wstate<2:0>); fault = new SpillNNormal(4*Wstate<2:0>);
} }
else if(Cleanwin - Canrestore == 0) else if(Cleanwin - Canrestore == 0)
{ {
@ -961,9 +961,9 @@ decode OP default Unknown::unknown()
if(Canrestore == 0) if(Canrestore == 0)
{ {
if(Otherwin) if(Otherwin)
fault = new FillNOther(Wstate<5:3>); fault = new FillNOther(4*Wstate<5:3>);
else else
fault = new FillNNormal(Wstate<2:0>); fault = new FillNNormal(4*Wstate<2:0>);
} }
else else
{ {
@ -1040,6 +1040,12 @@ decode OP default Unknown::unknown()
0x11: lduba({{Rd = Mem.ub;}}, {{EXT_ASI}}); 0x11: lduba({{Rd = Mem.ub;}}, {{EXT_ASI}});
0x12: lduha({{Rd = Mem.uhw;}}, {{EXT_ASI}}); 0x12: lduha({{Rd = Mem.uhw;}}, {{EXT_ASI}});
0x13: decode EXT_ASI { 0x13: decode EXT_ASI {
//ASI_LDTD_AIUP
0x22: TwinLoad::ldtx_aiup(
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
//ASI_LDTD_AIUS
0x23: TwinLoad::ldtx_aius(
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
//ASI_QUAD_LDD //ASI_QUAD_LDD
0x24: TwinLoad::ldtx_quad_ldd( 0x24: TwinLoad::ldtx_quad_ldd(
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}}); {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
@ -1058,6 +1064,12 @@ decode OP default Unknown::unknown()
//ASI_LDTX_N_L //ASI_LDTX_N_L
0x2F: TwinLoad::ldtx_n_l( 0x2F: TwinLoad::ldtx_n_l(
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}}); {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
//ASI_LDTX_P
0xE2: TwinLoad::ldtx_p(
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
//ASI_LDTX_S
0xE3: TwinLoad::ldtx_s(
{{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
default: ldtwa({{ default: ldtwa({{
uint64_t val = Mem.udw; uint64_t val = Mem.udw;
RdLow = val<31:0>; RdLow = val<31:0>;

View file

@ -451,6 +451,8 @@ let {{
flag_code = '' flag_code = ''
if (microPc == 7): if (microPc == 7):
flag_code = "flags[IsLastMicroOp] = true;" flag_code = "flags[IsLastMicroOp] = true;"
elif (microPc == 0):
flag_code = "flags[IsDelayedCommit] = true; flags[IsFirstMicroOp] = true;"
else: else:
flag_code = "flags[IsDelayedCommit] = true;" flag_code = "flags[IsDelayedCommit] = true;"
pcedCode = matcher.sub("Frd_%d" % microPc, code) pcedCode = matcher.sub("Frd_%d" % microPc, code)
@ -492,7 +494,7 @@ let {{
flag_code = "flags[IsLastMicroOp] = true;" flag_code = "flags[IsLastMicroOp] = true;"
pcedCode = matcher.sub("RdHigh", code) pcedCode = matcher.sub("RdHigh", code)
else: else:
flag_code = "flags[IsDelayedCommit] = true;" flag_code = "flags[IsDelayedCommit] = true; flags[IsFirstMicroOp] = true;"
pcedCode = matcher.sub("RdLow", code) pcedCode = matcher.sub("RdLow", code)
iop = InstObjParams(name, Name, 'TwinMem', iop = InstObjParams(name, Name, 'TwinMem',
{"code": pcedCode, "ea_code": addrCalcReg, {"code": pcedCode, "ea_code": addrCalcReg,

View file

@ -96,15 +96,6 @@ namespace SparcISA
StaticInstPtr decodeInst(ExtMachInst); StaticInstPtr decodeInst(ExtMachInst);
#if FULL_SYSTEM #if FULL_SYSTEM
////////// Interrupt Stuff ///////////
enum InterruptLevels
{
INTLEVEL_MIN = 1,
INTLEVEL_MAX = 15,
NumInterruptLevels = INTLEVEL_MAX - INTLEVEL_MIN
};
// I don't know what it's for, so I don't // I don't know what it's for, so I don't
// know what SPARC's value should be // know what SPARC's value should be
// For loading... XXX This maybe could be USegEnd?? --ali // For loading... XXX This maybe could be USegEnd?? --ali

View file

@ -215,7 +215,7 @@ MiscReg MiscRegFile::readReg(int miscReg)
case MISCREG_HTSTATE: case MISCREG_HTSTATE:
return htstate[tl-1]; return htstate[tl-1];
case MISCREG_HINTP: case MISCREG_HINTP:
panic("HINTP not implemented\n"); return hintp;
case MISCREG_HTBA: case MISCREG_HTBA:
return htba; return htba;
case MISCREG_HVER: case MISCREG_HVER:
@ -322,13 +322,13 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc)
// I'm not sure why legion ignores the lowest two bits, but we'll go // I'm not sure why legion ignores the lowest two bits, but we'll go
// with it // with it
// change from curCycle() to instCount() until we're done with legion // change from curCycle() to instCount() until we're done with legion
DPRINTFN("Instruction Count when TICK read: %#X stick=%#X\n", DPRINTF(Timer, "Instruction Count when TICK read: %#X stick=%#X\n",
tc->getCpuPtr()->instCount(), stick); tc->getCpuPtr()->instCount(), stick);
return mbits(tc->getCpuPtr()->instCount() + (int32_t)stick,62,2) | return mbits(tc->getCpuPtr()->instCount() + (int64_t)stick,62,2) |
mbits(tick,63,63); mbits(tick,63,63);
case MISCREG_FPRS: case MISCREG_FPRS:
warn("FPRS register read and FPU stuff not really implemented\n"); // in legion if fp is enabled du and dl are set
return fprs; return fprs | 0x3;
case MISCREG_PCR: case MISCREG_PCR:
case MISCREG_PIC: case MISCREG_PIC:
panic("Performance Instrumentation not impl\n"); panic("Performance Instrumentation not impl\n");
@ -386,7 +386,6 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val)
asi = val; asi = val;
break; break;
case MISCREG_FPRS: case MISCREG_FPRS:
warn("FPU not really implemented writing %#X to FPRS\n", val);
fprs = val; fprs = val;
break; break;
case MISCREG_TICK: case MISCREG_TICK:
@ -400,7 +399,7 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val)
gsr = val; gsr = val;
break; break;
case MISCREG_SOFTINT: case MISCREG_SOFTINT:
softint |= val; softint = val;
break; break;
case MISCREG_TICK_CMPR: case MISCREG_TICK_CMPR:
tick_cmpr = val; tick_cmpr = val;
@ -470,7 +469,7 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val)
htstate[tl-1] = val; htstate[tl-1] = val;
break; break;
case MISCREG_HINTP: case MISCREG_HINTP:
panic("HINTP not implemented\n"); hintp = val;
case MISCREG_HTBA: case MISCREG_HTBA:
htba = val; htba = val;
break; break;
@ -609,6 +608,8 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val)
void MiscRegFile::setRegWithEffect(int miscReg, void MiscRegFile::setRegWithEffect(int miscReg,
const MiscReg &val, ThreadContext * tc) const MiscReg &val, ThreadContext * tc)
{ {
MiscReg new_val = val;
switch (miscReg) { switch (miscReg) {
case MISCREG_STICK: case MISCREG_STICK:
case MISCREG_TICK: case MISCREG_TICK:
@ -616,7 +617,7 @@ void MiscRegFile::setRegWithEffect(int miscReg,
// use stick for offset and tick for holding intrrupt bit // use stick for offset and tick for holding intrrupt bit
stick = mbits(val,62,0) - tc->getCpuPtr()->instCount(); stick = mbits(val,62,0) - tc->getCpuPtr()->instCount();
tick = mbits(val,63,63); tick = mbits(val,63,63);
DPRINTFN("Writing TICK=%#X\n", val); DPRINTF(Timer, "Writing TICK=%#X\n", val);
break; break;
case MISCREG_FPRS: case MISCREG_FPRS:
//Configure the fpu based on the fprs //Configure the fpu based on the fprs
@ -631,13 +632,16 @@ void MiscRegFile::setRegWithEffect(int miscReg,
tl = val; tl = val;
return; return;
case MISCREG_CWP: case MISCREG_CWP:
tc->changeRegFileContext(CONTEXT_CWP, val); new_val = val > NWindows ? NWindows - 1 : val;
tc->changeRegFileContext(CONTEXT_CWP, new_val);
break; break;
case MISCREG_GL: case MISCREG_GL:
tc->changeRegFileContext(CONTEXT_GLOBALS, val); tc->changeRegFileContext(CONTEXT_GLOBALS, val);
break; break;
case MISCREG_PIL: case MISCREG_PIL:
case MISCREG_SOFTINT: case MISCREG_SOFTINT:
case MISCREG_SOFTINT_SET:
case MISCREG_SOFTINT_CLR:
case MISCREG_TICK_CMPR: case MISCREG_TICK_CMPR:
case MISCREG_STICK_CMPR: case MISCREG_STICK_CMPR:
case MISCREG_HINTP: case MISCREG_HINTP:
@ -666,7 +670,7 @@ void MiscRegFile::setRegWithEffect(int miscReg,
panic("Accessing Fullsystem register %s to %#x in SE mode\n", getMiscRegName(miscReg), val); panic("Accessing Fullsystem register %s to %#x in SE mode\n", getMiscRegName(miscReg), val);
#endif #endif
} }
setReg(miscReg, val); setReg(miscReg, new_val);
} }
void MiscRegFile::serialize(std::ostream & os) void MiscRegFile::serialize(std::ostream & os)

View file

@ -142,24 +142,26 @@ namespace SparcISA
MISCREG_NUMMISCREGS MISCREG_NUMMISCREGS
}; };
enum HPStateFields { struct HPSTATE {
id = 0x800, // this impl. dependent (id) field must always be '1' for T1000 const static uint64_t id = 0x800; // this impl. dependent (id) field m
ibe = 0x400, const static uint64_t ibe = 0x400;
red = 0x20, const static uint64_t red = 0x20;
hpriv = 0x4, const static uint64_t hpriv = 0x4;
tlz = 0x1 const static uint64_t tlz = 0x1;
}; };
enum PStateFields {
cle = 0x200, struct PSTATE {
tle = 0x100, const static int cle = 0x200;
mm = 0xC0, const static int tle = 0x100;
pef = 0x10, const static int mm = 0xC0;
am = 0x8, const static int pef = 0x10;
priv = 0x4, const static int am = 0x8;
ie = 0x2 const static int priv = 0x4;
const static int ie = 0x2;
}; };
const int NumMiscArchRegs = MISCREG_NUMMISCREGS; const int NumMiscArchRegs = MISCREG_NUMMISCREGS;
const int NumMiscRegs = MISCREG_NUMMISCREGS; const int NumMiscRegs = MISCREG_NUMMISCREGS;

View file

@ -255,10 +255,10 @@ int SparcISA::InterruptLevel(uint64_t softint)
if (softint & 0x10000 || softint & 0x1) if (softint & 0x10000 || softint & 0x1)
return 14; return 14;
int level = 14; int level = 15;
while (level >= 0 && !(1 << (level + 1) & softint)) while (level > 0 && !(1 << level & softint))
level--; level--;
if (1 << (level + 1) & softint) if (1 << level & softint)
return level; return level;
return 0; return 0;
} }

View file

@ -81,21 +81,45 @@ TLB::insert(Addr va, int partition_id, int context_id, bool real,
MapIter i; MapIter i;
TlbEntry *new_entry = NULL; TlbEntry *new_entry = NULL;
TlbRange tr; // TlbRange tr;
int x; int x;
cacheValid = false; cacheValid = false;
tr.va = va; va &= ~(PTE.size()-1);
/* tr.va = va;
tr.size = PTE.size() - 1; tr.size = PTE.size() - 1;
tr.contextId = context_id; tr.contextId = context_id;
tr.partitionId = partition_id; tr.partitionId = partition_id;
tr.real = real; tr.real = real;
*/
DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x pa=%#x pid=%d cid=%d r=%d entryid=%d\n", DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x pa=%#x pid=%d cid=%d r=%d entryid=%d\n",
va, PTE.paddr(), partition_id, context_id, (int)real, entry); va, PTE.paddr(), partition_id, context_id, (int)real, entry);
// Demap any entry that conflicts // Demap any entry that conflicts
for (x = 0; x < size; x++) {
if (tlb[x].range.real == real &&
tlb[x].range.partitionId == partition_id &&
tlb[x].range.va < va + PTE.size() - 1 &&
tlb[x].range.va + tlb[x].range.size >= va &&
(real || tlb[x].range.contextId == context_id ))
{
if (tlb[x].valid) {
freeList.push_front(&tlb[x]);
DPRINTF(TLB, "TLB: Conflicting entry %#X , deleting it\n", x);
tlb[x].valid = false;
if (tlb[x].used) {
tlb[x].used = false;
usedEntries--;
}
lookupTable.erase(tlb[x].range);
}
}
}
/*
i = lookupTable.find(tr); i = lookupTable.find(tr);
if (i != lookupTable.end()) { if (i != lookupTable.end()) {
i->second->valid = false; i->second->valid = false;
@ -108,7 +132,7 @@ TLB::insert(Addr va, int partition_id, int context_id, bool real,
i->second); i->second);
lookupTable.erase(i); lookupTable.erase(i);
} }
*/
if (entry != -1) { if (entry != -1) {
assert(entry < size && entry >= 0); assert(entry < size && entry >= 0);
@ -127,7 +151,6 @@ TLB::insert(Addr va, int partition_id, int context_id, bool real,
} while (tlb[x].pte.locked()); } while (tlb[x].pte.locked());
lastReplaced = x; lastReplaced = x;
new_entry = &tlb[x]; new_entry = &tlb[x];
lookupTable.erase(new_entry->range);
} }
/* /*
for (x = 0; x < size; x++) { for (x = 0; x < size; x++) {
@ -142,10 +165,15 @@ insertAllLocked:
// Update the last ently if their all locked // Update the last ently if their all locked
if (!new_entry) { if (!new_entry) {
new_entry = &tlb[size-1]; new_entry = &tlb[size-1];
lookupTable.erase(new_entry->range);
} }
freeList.remove(new_entry); freeList.remove(new_entry);
if (new_entry->valid && new_entry->used)
usedEntries--;
lookupTable.erase(new_entry->range);
DPRINTF(TLB, "Using entry: %#X\n", new_entry); DPRINTF(TLB, "Using entry: %#X\n", new_entry);
assert(PTE.valid()); assert(PTE.valid());
@ -315,10 +343,12 @@ TLB::invalidateAll()
cacheValid = false; cacheValid = false;
freeList.clear(); freeList.clear();
lookupTable.clear();
for (x = 0; x < size; x++) { for (x = 0; x < size; x++) {
if (tlb[x].valid == true) if (tlb[x].valid == true)
freeList.push_back(&tlb[x]); freeList.push_back(&tlb[x]);
tlb[x].valid = false; tlb[x].valid = false;
tlb[x].used = false;
} }
usedEntries = 0; usedEntries = 0;
} }
@ -385,6 +415,9 @@ TLB::writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct,
void void
TLB::writeTagAccess(ThreadContext *tc, int reg, Addr va, int context) TLB::writeTagAccess(ThreadContext *tc, int reg, Addr va, int context)
{ {
DPRINTF(TLB, "TLB: Writing Tag Access: va: %#X ctx: %#X value: %#X\n",
va, context, mbits(va, 63,13) | mbits(context,12,0));
tc->setMiscRegWithEffect(reg, mbits(va, 63,13) | mbits(context,12,0)); tc->setMiscRegWithEffect(reg, mbits(va, 63,13) | mbits(context,12,0));
} }
@ -507,8 +540,7 @@ ITB::translate(RequestPtr &req, ThreadContext *tc)
} }
if (e == NULL || !e->valid) { if (e == NULL || !e->valid) {
tc->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS, writeTagAccess(tc, vaddr, context);
vaddr & ~BytesInPageMask | context);
if (real) if (real)
return new InstructionRealTranslationMiss; return new InstructionRealTranslationMiss;
else else
@ -581,7 +613,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
int part_id = bits(tlbdata,15,8); int part_id = bits(tlbdata,15,8);
int tl = bits(tlbdata,18,16); int tl = bits(tlbdata,18,16);
int pri_context = bits(tlbdata,47,32); int pri_context = bits(tlbdata,47,32);
int sec_context = bits(tlbdata,47,32); int sec_context = bits(tlbdata,63,48);
bool real = false; bool real = false;
ContextType ct = Primary; ContextType ct = Primary;
@ -602,52 +634,42 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
ct = Primary; ct = Primary;
context = pri_context; context = pri_context;
} }
} else if (!hpriv && !red) {
if (tl > 0 || AsiIsNucleus(asi)) {
ct = Nucleus;
context = 0;
} else if (AsiIsSecondary(asi)) {
ct = Secondary;
context = sec_context;
} else { } else {
context = pri_context;
ct = Primary; //???
}
// We need to check for priv level/asi priv // We need to check for priv level/asi priv
if (!priv && !AsiIsUnPriv(asi)) { if (!priv && !hpriv && !AsiIsUnPriv(asi)) {
// It appears that context should be Nucleus in these cases? // It appears that context should be Nucleus in these cases?
writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi); writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi);
return new PrivilegedAction; return new PrivilegedAction;
} }
if (priv && AsiIsHPriv(asi)) {
if (!hpriv && AsiIsHPriv(asi)) {
writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi); writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi);
return new DataAccessException; return new DataAccessException;
} }
} else if (hpriv) { if (AsiIsPrimary(asi)) {
if (asi == ASI_P) { context = pri_context;
ct = Primary;
} else if (AsiIsSecondary(asi)) {
context = sec_context;
ct = Secondary;
} else if (AsiIsNucleus(asi)) {
ct = Nucleus;
context = 0;
} else { // ????
ct = Primary; ct = Primary;
context = pri_context; context = pri_context;
goto continueDtbFlow;
} }
} }
if (!implicit) { if (!implicit && asi != ASI_P && asi != ASI_S) {
if (AsiIsLittle(asi)) if (AsiIsLittle(asi))
panic("Little Endian ASIs not supported\n"); panic("Little Endian ASIs not supported\n");
if (AsiIsBlock(asi)) if (AsiIsBlock(asi))
panic("Block ASIs not supported\n"); panic("Block ASIs not supported\n");
if (AsiIsNoFault(asi)) if (AsiIsNoFault(asi))
panic("No Fault ASIs not supported\n"); panic("No Fault ASIs not supported\n");
if (write && asi == ASI_LDTX_P)
// block init store (like write hint64)
goto continueDtbFlow;
if (!write && asi == ASI_QUAD_LDD)
goto continueDtbFlow;
if (AsiIsTwin(asi))
panic("Twin ASIs not supported\n");
if (AsiIsPartialStore(asi)) if (AsiIsPartialStore(asi))
panic("Partial Store ASIs not supported\n"); panic("Partial Store ASIs not supported\n");
if (AsiIsInterrupt(asi)) if (AsiIsInterrupt(asi))
@ -662,11 +684,11 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
if (AsiIsSparcError(asi)) if (AsiIsSparcError(asi))
goto handleSparcErrorRegAccess; goto handleSparcErrorRegAccess;
if (!AsiIsReal(asi) && !AsiIsNucleus(asi)) if (!AsiIsReal(asi) && !AsiIsNucleus(asi) && !AsiIsAsIfUser(asi) &&
!AsiIsTwin(asi))
panic("Accessing ASI %#X. Should we?\n", asi); panic("Accessing ASI %#X. Should we?\n", asi);
} }
continueDtbFlow:
// If the asi is unaligned trap // If the asi is unaligned trap
if (vaddr & size-1) { if (vaddr & size-1) {
writeSfr(tc, vaddr, false, ct, false, OtherFault, asi); writeSfr(tc, vaddr, false, ct, false, OtherFault, asi);
@ -682,7 +704,7 @@ continueDtbFlow:
} }
if ((!lsu_dm && !hpriv) || AsiIsReal(asi)) { if ((!lsu_dm && !hpriv && !red) || AsiIsReal(asi)) {
real = true; real = true;
context = 0; context = 0;
}; };
@ -695,8 +717,7 @@ continueDtbFlow:
e = lookup(vaddr, part_id, real, context); e = lookup(vaddr, part_id, real, context);
if (e == NULL || !e->valid) { if (e == NULL || !e->valid) {
tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS, writeTagAccess(tc, vaddr, context);
vaddr & ~BytesInPageMask | context);
DPRINTF(TLB, "TLB: DTB Failed to find matching TLB entry\n"); DPRINTF(TLB, "TLB: DTB Failed to find matching TLB entry\n");
if (real) if (real)
return new DataRealTranslationMiss; return new DataRealTranslationMiss;
@ -868,7 +889,7 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
break; break;
case ASI_SPARC_ERROR_STATUS_REG: case ASI_SPARC_ERROR_STATUS_REG:
warn("returning 0 for SPARC ERROR regsiter read\n"); warn("returning 0 for SPARC ERROR regsiter read\n");
pkt->set(0); pkt->set((uint64_t)0);
break; break;
case ASI_HYP_SCRATCHPAD: case ASI_HYP_SCRATCHPAD:
case ASI_SCRATCHPAD: case ASI_SCRATCHPAD:
@ -880,6 +901,9 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS); temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS);
pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48); pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48);
break; break;
case 0x18:
pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_SFSR));
break;
case 0x30: case 0x30:
pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS)); pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS));
break; break;
@ -893,6 +917,12 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS);
pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48); pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48);
break; break;
case 0x18:
pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_SFSR));
break;
case 0x20:
pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_SFAR));
break;
case 0x30: case 0x30:
pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS)); pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS));
break; break;
@ -929,10 +959,40 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
data = mbits(tsbtemp,63,13); data = mbits(tsbtemp,63,13);
if (bits(tsbtemp,12,12)) if (bits(tsbtemp,12,12))
data |= ULL(1) << (13+bits(tsbtemp,3,0)); data |= ULL(1) << (13+bits(tsbtemp,3,0));
data |= temp >> (9 + bits(cnftemp,10,8) * 3) &
mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
pkt->set(data);
break;
case ASI_IMMU_TSB_PS0_PTR_REG:
temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS);
if (bits(temp,12,0) == 0) {
tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0);
cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG);
} else {
tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0);
cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG);
}
data = mbits(tsbtemp,63,13);
data |= temp >> (9 + bits(cnftemp,2,0) * 3) & data |= temp >> (9 + bits(cnftemp,2,0) * 3) &
mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4); mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
pkt->set(data); pkt->set(data);
break; break;
case ASI_IMMU_TSB_PS1_PTR_REG:
temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS);
if (bits(temp,12,0) == 0) {
tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1);
cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG);
} else {
tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1);
cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG);
}
data = mbits(tsbtemp,63,13);
if (bits(tsbtemp,12,12))
data |= ULL(1) << (13+bits(tsbtemp,3,0));
data |= temp >> (9 + bits(cnftemp,10,8) * 3) &
mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
pkt->set(data);
break;
default: default:
doMmuReadError: doMmuReadError:
@ -1044,7 +1104,11 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt)
break; break;
case ASI_IMMU: case ASI_IMMU:
switch (va) { switch (va) {
case 0x18:
tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_SFSR, data);
break;
case 0x30: case 0x30:
sext<59>(bits(data, 59,0));
tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS, data); tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS, data);
break; break;
default: default:
@ -1115,7 +1179,11 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt)
break; break;
case ASI_DMMU: case ASI_DMMU:
switch (va) { switch (va) {
case 0x18:
tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_SFSR, data);
break;
case 0x30: case 0x30:
sext<59>(bits(data, 59,0));
tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS, data); tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS, data);
break; break;
case 0x80: case 0x80:

View file

@ -24,8 +24,6 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
*/ */
#include "arch/sparc/miscregfile.hh" #include "arch/sparc/miscregfile.hh"
@ -44,16 +42,15 @@ MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
switch (miscReg) { switch (miscReg) {
/* Full system only ASRs */ /* Full system only ASRs */
case MISCREG_SOFTINT: case MISCREG_SOFTINT:
// Check if we are going to interrupt because of something setReg(miscReg, val);;
setReg(miscReg, val);
tc->getCpuPtr()->checkInterrupts = true;
warn("Writing to softint not really supported, writing: %#x\n", val);
break; break;
case MISCREG_SOFTINT_CLR: case MISCREG_SOFTINT_CLR:
return setRegWithEffect(miscReg, ~val & softint, tc); return setRegWithEffect(MISCREG_SOFTINT, ~val & softint, tc);
case MISCREG_SOFTINT_SET: case MISCREG_SOFTINT_SET:
return setRegWithEffect(miscReg, val | softint, tc); tc->getCpuPtr()->checkInterrupts = true;
tc->getCpuPtr()->post_interrupt(soft_interrupt);
return setRegWithEffect(MISCREG_SOFTINT, val | softint, tc);
case MISCREG_TICK_CMPR: case MISCREG_TICK_CMPR:
if (tickCompare == NULL) if (tickCompare == NULL)
@ -64,23 +61,24 @@ MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
time = (tick_cmpr & mask(63)) - (tick & mask(63)); time = (tick_cmpr & mask(63)) - (tick & mask(63));
if (!(tick_cmpr & ~mask(63)) && time > 0) if (!(tick_cmpr & ~mask(63)) && time > 0)
tickCompare->schedule(time * tc->getCpuPtr()->cycles(1)); tickCompare->schedule(time * tc->getCpuPtr()->cycles(1));
warn ("writing to TICK compare register %#X\n", val); panic("writing to TICK compare register %#X\n", val);
break; break;
case MISCREG_STICK_CMPR: case MISCREG_STICK_CMPR:
if (sTickCompare == NULL) if (sTickCompare == NULL)
sTickCompare = new STickCompareEvent(this, tc); sTickCompare = new STickCompareEvent(this, tc);
setReg(miscReg, val); setReg(miscReg, val);
if ((stick_cmpr & mask(63)) && sTickCompare->scheduled()) if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled())
sTickCompare->deschedule(); sTickCompare->deschedule();
time = (stick_cmpr & mask(63)) - (stick & mask(63)); time = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) -
tc->getCpuPtr()->instCount();
if (!(stick_cmpr & ~mask(63)) && time > 0) if (!(stick_cmpr & ~mask(63)) && time > 0)
sTickCompare->schedule(time * tc->getCpuPtr()->cycles(1)); sTickCompare->schedule(time * tc->getCpuPtr()->cycles(1) + curTick);
warn ("writing to sTICK compare register value %#X\n", val); DPRINTF(Timer, "writing to sTICK compare register value %#X\n", val);
break; break;
case MISCREG_PSTATE: case MISCREG_PSTATE:
if (val & ie && !(pstate & ie)) { if (val & PSTATE::ie && !(pstate & PSTATE::ie)) {
tc->getCpuPtr()->checkInterrupts = true; tc->getCpuPtr()->checkInterrupts = true;
} }
setReg(miscReg, val); setReg(miscReg, val);
@ -95,6 +93,9 @@ MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
case MISCREG_HVER: case MISCREG_HVER:
panic("Shouldn't be writing HVER\n"); panic("Shouldn't be writing HVER\n");
case MISCREG_HINTP:
setReg(miscReg, val);
case MISCREG_HTBA: case MISCREG_HTBA:
// clear lower 7 bits on writes. // clear lower 7 bits on writes.
setReg(miscReg, val & ULL(~0x7FFF)); setReg(miscReg, val & ULL(~0x7FFF));
@ -116,17 +117,18 @@ MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
if (hSTickCompare == NULL) if (hSTickCompare == NULL)
hSTickCompare = new HSTickCompareEvent(this, tc); hSTickCompare = new HSTickCompareEvent(this, tc);
setReg(miscReg, val); setReg(miscReg, val);
if ((hstick_cmpr & mask(63)) && hSTickCompare->scheduled()) if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled())
hSTickCompare->deschedule(); hSTickCompare->deschedule();
time = (hstick_cmpr & mask(63)) - (stick & mask(63)); time = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) -
tc->getCpuPtr()->instCount();
if (!(hstick_cmpr & ~mask(63)) && time > 0) if (!(hstick_cmpr & ~mask(63)) && time > 0)
hSTickCompare->schedule(time * tc->getCpuPtr()->cycles(1)); hSTickCompare->schedule(curTick + time * tc->getCpuPtr()->cycles(1));
warn ("writing to hsTICK compare register value %#X\n", val); DPRINTF(Timer, "writing to hsTICK compare register value %#X\n", val);
break; break;
case MISCREG_HPSTATE: case MISCREG_HPSTATE:
// T1000 spec says impl. dependent val must always be 1 // T1000 spec says impl. dependent val must always be 1
setReg(miscReg, val | id); setReg(miscReg, val | HPSTATE::id);
break; break;
case MISCREG_HTSTATE: case MISCREG_HTSTATE:
case MISCREG_STRAND_STS_REG: case MISCREG_STRAND_STS_REG:
@ -191,12 +193,47 @@ MiscRegFile::processTickCompare(ThreadContext *tc)
void void
MiscRegFile::processSTickCompare(ThreadContext *tc) MiscRegFile::processSTickCompare(ThreadContext *tc)
{ {
panic("tick compare not implemented\n"); // since our microcode instructions take two cycles we need to check if
// we're actually at the correct cycle or we need to wait a little while
// more
int ticks;
ticks = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) -
tc->getCpuPtr()->instCount();
assert(ticks >= 0 && "stick compare missed interrupt cycle");
if (ticks == 0) {
DPRINTF(Timer, "STick compare cycle reached at %#x\n",
(stick_cmpr & mask(63)));
if (!(tc->readMiscReg(MISCREG_STICK_CMPR) & (ULL(1) << 63))) {
tc->getCpuPtr()->post_interrupt(soft_interrupt);
tc->getCpuPtr()->checkInterrupts = true;
setRegWithEffect(MISCREG_SOFTINT, softint | (ULL(1) << 16), tc);
}
} else
sTickCompare->schedule(ticks * tc->getCpuPtr()->cycles(1) + curTick);
} }
void void
MiscRegFile::processHSTickCompare(ThreadContext *tc) MiscRegFile::processHSTickCompare(ThreadContext *tc)
{ {
panic("tick compare not implemented\n"); // since our microcode instructions take two cycles we need to check if
// we're actually at the correct cycle or we need to wait a little while
// more
int ticks;
ticks = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) -
tc->getCpuPtr()->instCount();
assert(ticks >= 0 && "hstick compare missed interrupt cycle");
if (ticks == 0) {
DPRINTF(Timer, "HSTick compare cycle reached at %#x\n",
(stick_cmpr & mask(63)));
if (!(tc->readMiscReg(MISCREG_HSTICK_CMPR) & (ULL(1) << 63))) {
setRegWithEffect(MISCREG_HINTP, 1, tc);
tc->getCpuPtr()->post_interrupt(hstick_match);
tc->getCpuPtr()->checkInterrupts = true;
}
// Need to do something to cause interrupt to happen here !!! @todo
} else
sTickCompare->schedule(ticks * tc->getCpuPtr()->cycles(1) + curTick);
} }

View file

@ -340,3 +340,41 @@ ElfObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask)
{ {
return loadSomeSymbols(symtab, STB_LOCAL); return loadSomeSymbols(symtab, STB_LOCAL);
} }
bool
ElfObject::isDynamic()
{
Elf *elf;
int sec_idx = 1; // there is a 0 but it is nothing, go figure
Elf_Scn *section;
GElf_Shdr shdr;
GElf_Ehdr ehdr;
// check that header matches library version
if (elf_version(EV_CURRENT) == EV_NONE)
panic("wrong elf version number!");
// get a pointer to elf structure
elf = elf_memory((char*)fileData,len);
assert(elf != NULL);
// Check that we actually have a elf file
if (gelf_getehdr(elf, &ehdr) ==0) {
panic("Not ELF, shouldn't be here");
}
// Get the first section
section = elf_getscn(elf, sec_idx);
// While there are no more sections
while (section != NULL) {
gelf_getshdr(section, &shdr);
if (!strcmp(".interp", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name)))
return true;
section = elf_getscn(elf, ++sec_idx);
} // while sections
return false;
}

View file

@ -58,6 +58,8 @@ class ElfObject : public ObjectFile
virtual bool loadLocalSymbols(SymbolTable *symtab, Addr addrMask = virtual bool loadLocalSymbols(SymbolTable *symtab, Addr addrMask =
std::numeric_limits<Addr>::max()); std::numeric_limits<Addr>::max());
virtual bool isDynamic();
static ObjectFile *tryFile(const std::string &fname, int fd, static ObjectFile *tryFile(const std::string &fname, int fd,
size_t len, uint8_t *data); size_t len, uint8_t *data);
Addr programHeaderTable() {return _programHeaderTable;} Addr programHeaderTable() {return _programHeaderTable;}

View file

@ -150,3 +150,9 @@ createObjectFile(const string &fname, bool raw)
munmap(fileData, len); munmap(fileData, len);
return NULL; return NULL;
} }
bool
ObjectFile::isDynamic()
{
return false;
}

View file

@ -83,6 +83,8 @@ class ObjectFile
virtual bool loadLocalSymbols(SymbolTable *symtab, Addr addrMask = virtual bool loadLocalSymbols(SymbolTable *symtab, Addr addrMask =
std::numeric_limits<Addr>::max()) = 0; std::numeric_limits<Addr>::max()) = 0;
virtual bool isDynamic();
Arch getArch() const { return arch; } Arch getArch() const { return arch; }
OpSys getOpSys() const { return opSys; } OpSys getOpSys() const { return opSys; }

View file

@ -63,19 +63,19 @@ RawObject::RawObject(const std::string &_filename, int _fd, size_t _len,
bool bool
RawObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask) RawObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask)
{ {
int fnameStart = filename.rfind('/',filename.size()) + 1; /* int fnameStart = filename.rfind('/',filename.size()) + 1;
int extStart = filename.rfind('.',filename.size()); int extStart = filename.rfind('.',filename.size());
symtab->insert(text.baseAddr & addrMask, filename.substr(fnameStart, symtab->insert(text.baseAddr & addrMask, filename.substr(fnameStart,
extStart-fnameStart) + "_start"); extStart-fnameStart) + "_start");*/
return true; return true;
} }
bool bool
RawObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask) RawObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask)
{ {
int fnameStart = filename.rfind('/',filename.size()) + 1; /* int fnameStart = filename.rfind('/',filename.size()) + 1;
int extStart = filename.rfind('.',filename.size()); int extStart = filename.rfind('.',filename.size());
symtab->insert(text.baseAddr & addrMask, filename.substr(fnameStart, symtab->insert(text.baseAddr & addrMask, filename.substr(fnameStart,
extStart-fnameStart) + "_start"); extStart-fnameStart) + "_start");*/
return true; return true;
} }

View file

@ -362,6 +362,12 @@ BaseCPU::ProfileEvent::process()
schedule(curTick + interval); schedule(curTick + interval);
} }
void
BaseCPU::post_interrupt(int int_type)
{
interrupts.post(int_type);
}
void void
BaseCPU::post_interrupt(int int_num, int index) BaseCPU::post_interrupt(int int_num, int index)
{ {

View file

@ -102,6 +102,7 @@ class BaseCPU : public MemObject
TheISA::Interrupts interrupts; TheISA::Interrupts interrupts;
public: public:
virtual void post_interrupt(int int_type);
virtual void post_interrupt(int int_num, int index); virtual void post_interrupt(int int_num, int index);
virtual void clear_interrupt(int int_num, int index); virtual void clear_interrupt(int int_num, int index);
virtual void clear_interrupts(); virtual void clear_interrupts();

View file

@ -36,12 +36,14 @@
class ThreadContext; class ThreadContext;
/** This class creates a global list of events that need a pointer to a /**
* thread context. When a switchover takes place the events can be migrated * This class creates a global list of events that need a pointer to a
* to the new thread context, otherwise you could have a wake timer interrupt * thread context. When a switchover takes place the events can be
* go off on a switched out cpu or other unfortunate events. This object MUST be * migrated to the new thread context, otherwise you could have a wake
* dynamically allocated to avoid it being deleted after a cpu switch happens. * timer interrupt go off on a switched out cpu or other unfortunate
* */ * events. This object MUST be dynamically allocated to avoid it being
* deleted after a cpu switch happens.
*/
class CpuEvent : public Event class CpuEvent : public Event
{ {
protected: protected:
@ -78,8 +80,8 @@ class CpuEventWrapper : public CpuEvent
T *object; T *object;
public: public:
CpuEventWrapper(T *obj, ThreadContext *_tc, EventQueue *q = &mainEventQueue, CpuEventWrapper(T *obj, ThreadContext *_tc,
Priority p = Default_Pri) EventQueue *q = &mainEventQueue, Priority p = Default_Pri)
: CpuEvent(q, _tc, p), object(obj) : CpuEvent(q, _tc, p), object(obj)
{ } { }
void process() { (object->*F)(tc); } void process() { (object->*F)(tc); }

View file

@ -59,6 +59,7 @@ using namespace TheISA;
#if THE_ISA == SPARC_ISA && FULL_SYSTEM #if THE_ISA == SPARC_ISA && FULL_SYSTEM
static int diffcount = 0; static int diffcount = 0;
static bool wasMicro = false;
#endif #endif
namespace Trace { namespace Trace {
@ -124,6 +125,7 @@ inline void printLevelHeader(ostream & os, int level)
void void
Trace::InstRecord::dump(ostream &outs) Trace::InstRecord::dump(ostream &outs)
{ {
DPRINTF(Sparc, "Instruction: %#X\n", staticInst->machInst);
if (flags[PRINT_REG_DELTA]) if (flags[PRINT_REG_DELTA])
{ {
#if THE_ISA == SPARC_ISA #if THE_ISA == SPARC_ISA
@ -317,6 +319,24 @@ Trace::InstRecord::dump(ostream &outs)
bool diffTlb = false; bool diffTlb = false;
Addr m5Pc, lgnPc; Addr m5Pc, lgnPc;
// We took a trap on a micro-op...
if (wasMicro && !staticInst->isMicroOp())
{
// let's skip comparing this cycle
while (!compared)
if (shared_data->flags == OWN_M5) {
shared_data->flags = OWN_LEGION;
compared = true;
}
compared = false;
wasMicro = false;
}
if (staticInst->isLastMicroOp())
wasMicro = false;
else if (staticInst->isMicroOp())
wasMicro = true;
if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) { if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) {
while (!compared) { while (!compared) {
@ -607,29 +627,34 @@ Trace::InstRecord::dump(ostream &outs)
<< endl;*/ << endl;*/
} }
} }
if (diffTlb) {
printColumnLabels(outs); printColumnLabels(outs);
char label[8]; char label[8];
for (int x = 0; x < 64; x++) { for (int x = 0; x < 64; x++) {
if (shared_data->itb[x] != ULL(0xFFFFFFFFFFFFFFFF) || if (shared_data->itb[x] != ULL(0xFFFFFFFFFFFFFFFF) ||
thread->getITBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF)) { thread->getITBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF)) {
sprintf(label, "I-TLB:%02d", x); sprintf(label, "I-TLB:%02d", x);
printRegPair(outs, label, thread->getITBPtr()->TteRead(x), shared_data->itb[x]); printRegPair(outs, label, thread->getITBPtr()->TteRead(x),
shared_data->itb[x]);
} }
} }
for (int x = 0; x < 64; x++) { for (int x = 0; x < 64; x++) {
if (shared_data->dtb[x] != ULL(0xFFFFFFFFFFFFFFFF) || if (shared_data->dtb[x] != ULL(0xFFFFFFFFFFFFFFFF) ||
thread->getDTBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF)) { thread->getDTBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF)) {
sprintf(label, "D-TLB:%02d", x); sprintf(label, "D-TLB:%02d", x);
printRegPair(outs, label, thread->getDTBPtr()->TteRead(x), shared_data->dtb[x]); printRegPair(outs, label, thread->getDTBPtr()->TteRead(x),
shared_data->dtb[x]);
} }
} }
thread->getITBPtr()->dumpAll(); thread->getITBPtr()->dumpAll();
thread->getDTBPtr()->dumpAll(); thread->getDTBPtr()->dumpAll();
}
diffcount++; diffcount++;
if (diffcount > 2) if (diffcount > 2)
fatal("Differences found between Legion and M5\n"); fatal("Differences found between Legion and M5\n");
} } else
diffcount = 0;
compared = true; compared = true;
shared_data->flags = OWN_LEGION; shared_data->flags = OWN_LEGION;

View file

@ -497,7 +497,7 @@ AtomicSimpleCPU::tick()
// @todo remove me after debugging with legion done // @todo remove me after debugging with legion done
if (curStaticInst && (!curStaticInst->isMicroOp() || if (curStaticInst && (!curStaticInst->isMicroOp() ||
curStaticInst->isLastMicroOp())) curStaticInst->isFirstMicroOp()))
instCnt++; instCnt++;
if (simulate_stalls) { if (simulate_stalls) {

View file

@ -437,6 +437,7 @@ void
BaseSimpleCPU::advancePC(Fault fault) BaseSimpleCPU::advancePC(Fault fault)
{ {
if (fault != NoFault) { if (fault != NoFault) {
curMacroStaticInst = StaticInst::nullStaticInstPtr;
fault->invoke(tc); fault->invoke(tc);
} else { } else {
//If we're at the last micro op for this instruction //If we're at the last micro op for this instruction

View file

@ -146,6 +146,7 @@ class StaticInstBase : public RefCounted
IsMicroOp, ///< Is a microop IsMicroOp, ///< Is a microop
IsDelayedCommit, ///< This microop doesn't commit right away IsDelayedCommit, ///< This microop doesn't commit right away
IsLastMicroOp, ///< This microop ends a microop sequence IsLastMicroOp, ///< This microop ends a microop sequence
IsFirstMicroOp, ///< This microop begins a microop sequence
//This flag doesn't do anything yet //This flag doesn't do anything yet
IsMicroBranch, ///< This microop branches within the microcode for a macroop IsMicroBranch, ///< This microop branches within the microcode for a macroop
@ -244,6 +245,7 @@ class StaticInstBase : public RefCounted
bool isMicroOp() const { return flags[IsMicroOp]; } bool isMicroOp() const { return flags[IsMicroOp]; }
bool isDelayedCommit() const { return flags[IsDelayedCommit]; } bool isDelayedCommit() const { return flags[IsDelayedCommit]; }
bool isLastMicroOp() const { return flags[IsLastMicroOp]; } bool isLastMicroOp() const { return flags[IsLastMicroOp]; }
bool isFirstMicroOp() const { return flags[IsFirstMicroOp]; }
//This flag doesn't do anything yet //This flag doesn't do anything yet
bool isMicroBranch() const { return flags[IsMicroBranch]; } bool isMicroBranch() const { return flags[IsMicroBranch]; }
//@} //@}

View file

@ -57,17 +57,13 @@ using namespace std;
//Should this be AlphaISA? //Should this be AlphaISA?
using namespace TheISA; using namespace TheISA;
TsunamiIO::RTC::RTC(const string &name, Tsunami* t, Tick i) TsunamiIO::RTC::RTC(const string &n, Tsunami* tsunami, time_t t, Tick i)
: _name(name), event(t, i), addr(0) : _name(n), event(tsunami, i), addr(0)
{ {
memset(clock_data, 0, sizeof(clock_data)); memset(clock_data, 0, sizeof(clock_data));
stat_regA = RTCA_32768HZ | RTCA_1024HZ; stat_regA = RTCA_32768HZ | RTCA_1024HZ;
stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR; stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR;
}
void
TsunamiIO::RTC::set_time(time_t t)
{
struct tm tm; struct tm tm;
gmtime_r(&t, &tm); gmtime_r(&t, &tm);
@ -428,7 +424,7 @@ TsunamiIO::PITimer::Counter::CounterEvent::description()
TsunamiIO::TsunamiIO(Params *p) TsunamiIO::TsunamiIO(Params *p)
: BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"), : BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"),
rtc(p->name + ".rtc", p->tsunami, p->frequency) rtc(p->name + ".rtc", p->tsunami, p->init_time, p->frequency)
{ {
pioSize = 0x100; pioSize = 0x100;
@ -436,7 +432,6 @@ TsunamiIO::TsunamiIO(Params *p)
tsunami->io = this; tsunami->io = this;
timerData = 0; timerData = 0;
rtc.set_time(p->init_time == 0 ? time(NULL) : p->init_time);
picr = 0; picr = 0;
picInterrupting = false; picInterrupting = false;
} }

View file

@ -110,10 +110,7 @@ class TsunamiIO : public BasicPioDevice
uint8_t stat_regB; uint8_t stat_regB;
public: public:
RTC(const std::string &name, Tsunami* t, Tick i); RTC(const std::string &name, Tsunami* tsunami, time_t t, Tick i);
/** Set the initial RTC time/date */
void set_time(time_t t);
/** RTC address port: write address of RTC RAM data to access */ /** RTC address port: write address of RTC RAM data to access */
void writeAddr(const uint8_t data); void writeAddr(const uint8_t data);

View file

@ -37,7 +37,9 @@ Import('env')
sources = [] sources = []
sources += Split(''' sources += Split('''
dtod.cc
t1000.cc t1000.cc
mm_disk.cc
''') ''')
# Convert file names to SCons File objects. This takes care of the # Convert file names to SCons File objects. This takes care of the

115
src/dev/sparc/dtod.cc Normal file
View file

@ -0,0 +1,115 @@
/*
* Copyright (c) 2004-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: Ali Saidi
*/
/** @file
* Time of date device implementation
*/
#include <sys/time.h>
#include <deque>
#include <string>
#include <vector>
#include "base/trace.hh"
#include "dev/sparc/dtod.hh"
#include "dev/platform.hh"
#include "mem/packet_access.hh"
#include "mem/port.hh"
#include "sim/builder.hh"
#include "sim/system.hh"
using namespace std;
using namespace TheISA;
DumbTOD::DumbTOD(Params *p)
: BasicPioDevice(p), todTime(p->init_time)
{
pioSize = 0x08;
struct tm tm;
gmtime_r((time_t*)&todTime, &tm);
DPRINTFN("Real-time clock set to %s\n", asctime(&tm));
DPRINTFN("Real-time clock set to %d\n", todTime);
}
Tick
DumbTOD::read(PacketPtr pkt)
{
assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
assert(pkt->getSize() == 8);
pkt->allocate();
pkt->set(todTime);
todTime += 1000;
pkt->result = Packet::Success;
return pioDelay;
}
Tick
DumbTOD::write(PacketPtr pkt)
{
panic("Dumb tod device doesn't support writes\n");
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(DumbTOD)
Param<Addr> pio_addr;
Param<Tick> pio_latency;
SimObjectParam<Platform *> platform;
SimObjectParam<System *> system;
Param<time_t> time;
END_DECLARE_SIM_OBJECT_PARAMS(DumbTOD)
BEGIN_INIT_SIM_OBJECT_PARAMS(DumbTOD)
INIT_PARAM(pio_addr, "Device Address"),
INIT_PARAM(pio_latency, "Programmed IO latency"),
INIT_PARAM(platform, "platform"),
INIT_PARAM(system, "system object"),
INIT_PARAM(time, "System time to use (0 for actual time")
END_INIT_SIM_OBJECT_PARAMS(DumbTOD)
CREATE_SIM_OBJECT(DumbTOD)
{
DumbTOD::Params *p = new DumbTOD::Params;
p->name =getInstanceName();
p->pio_addr = pio_addr;
p->pio_delay = pio_latency;
p->platform = platform;
p->system = system;
p->init_time = time;
return new DumbTOD(p);
}
REGISTER_SIM_OBJECT("DumbTOD", DumbTOD)

67
src/dev/sparc/dtod.hh Normal file
View file

@ -0,0 +1,67 @@
/*
* Copyright (c) 206, 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: Ali Saidi
*/
/** @file
* This device acts as a simple time of date device. It's implemented as a
* simple device register read.
*/
#ifndef __DEV_SPARC_DTOD_HH__
#define __DEV_SPARC_DTOD_HH__
#include "base/range.hh"
#include "dev/io_device.hh"
/**
* DumbTOD simply returns some idea of time when read. Until we finish with
* legion it starts with the start time and increments itself by 1000 each time.
*/
class DumbTOD : public BasicPioDevice
{
private:
uint64_t todTime;
public:
struct Params : public BasicPioDevice::Params
{
time_t init_time;
};
protected:
const Params *params() const { return (const Params *)_params; }
public:
DumbTOD(Params *p);
virtual Tick read(PacketPtr pkt);
virtual Tick write(PacketPtr pkt);
};
#endif // __DEV_BADDEV_HH__

137
src/dev/sparc/mm_disk.cc Normal file
View file

@ -0,0 +1,137 @@
/*
* 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: Ali Saidi
*/
/** @file
* This device acts as a disk similar to the memory mapped disk device
* in legion. Any access is translated to an offset in the disk image.
*/
#include "base/trace.hh"
#include "dev/sparc/mm_disk.hh"
#include "dev/platform.hh"
#include "mem/port.hh"
#include "mem/packet_access.hh"
#include "sim/builder.hh"
#include "sim/byteswap.hh"
#include "sim/system.hh"
MmDisk::MmDisk(Params *p)
: BasicPioDevice(p), image(p->image), curSector((uint64_t)-1), dirty(false)
{
memset(&bytes, 0, SectorSize);
pioSize = image->size() * SectorSize;
}
Tick
MmDisk::read(PacketPtr pkt)
{
Addr accessAddr;
off_t sector;
off_t bytes_read;
uint16_t *d16;
uint32_t *d32;
uint64_t *d64;
assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
accessAddr = pkt->getAddr() - pioAddr;
sector = accessAddr / SectorSize;
if (sector != curSector) {
if (dirty)
bytes_read = image->write(bytes, curSector);
bytes_read = image->read(bytes, sector);
curSector = sector;
}
switch (pkt->getSize()) {
case sizeof(uint8_t):
pkt->set(bytes[accessAddr % SectorSize]);
break;
case sizeof(uint16_t):
d16 = (uint16_t*)bytes + (accessAddr % SectorSize)/2;
pkt->set(htobe(*d16));
break;
case sizeof(uint32_t):
d32 = (uint32_t*)bytes + (accessAddr % SectorSize)/4;
pkt->set(htobe(*d32));
break;
case sizeof(uint64_t):
d64 = (uint64_t*)bytes + (accessAddr % SectorSize)/8;
pkt->set(htobe(*d64));
break;
default:
panic("Invalid access size\n");
}
pkt->result = Packet::Success;
return pioDelay;
}
Tick
MmDisk::write(PacketPtr pkt)
{
panic("need to implement\n");
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(MmDisk)
Param<Addr> pio_addr;
Param<Tick> pio_latency;
Param<Addr> pio_size;
SimObjectParam<Platform *> platform;
SimObjectParam<System *> system;
SimObjectParam<DiskImage *> image;
END_DECLARE_SIM_OBJECT_PARAMS(MmDisk)
BEGIN_INIT_SIM_OBJECT_PARAMS(MmDisk)
INIT_PARAM(pio_addr, "Device Address"),
INIT_PARAM(pio_latency, "Programmed IO latency"),
INIT_PARAM(pio_size, "Size of address range"),
INIT_PARAM(platform, "platform"),
INIT_PARAM(system, "system object"),
INIT_PARAM(image, "disk image")
END_INIT_SIM_OBJECT_PARAMS(MmDisk)
CREATE_SIM_OBJECT(MmDisk)
{
MmDisk::Params *p = new MmDisk::Params;
p->name = getInstanceName();
p->pio_addr = pio_addr;
p->pio_delay = pio_latency;
p->platform = platform;
p->system = system;
p->image = image;
return new MmDisk(p);
}
REGISTER_SIM_OBJECT("MmDisk", MmDisk)

70
src/dev/sparc/mm_disk.hh Normal file
View file

@ -0,0 +1,70 @@
/*
* 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: Ali Saidi
*/
/** @file
* This device acts as a disk similar to the memory mapped disk device
* in legion. Any access is translated to an offset in the disk image.
*/
#ifndef __DEV_SPARC_MM_DISK_HH__
#define __DEV_SPARC_MM_DISK_HH__
#include "base/range.hh"
#include "dev/io_device.hh"
#include "dev/disk_image.hh"
class MmDisk : public BasicPioDevice
{
private:
DiskImage *image;
off_t curSector;
bool dirty;
union {
uint8_t bytes[SectorSize];
uint32_t words[SectorSize/4];
};
public:
struct Params : public BasicPioDevice::Params
{
DiskImage *image;
};
protected:
const Params *params() const { return (const Params*)_params; }
public:
MmDisk(Params *p);
virtual Tick read(PacketPtr pkt);
virtual Tick write(PacketPtr pkt);
};
#endif //__DEV_SPARC_MM_DISK_HH__

View file

@ -304,7 +304,8 @@ def main():
sys.argv = arguments sys.argv = arguments
sys.path = [ os.path.dirname(sys.argv[0]) ] + sys.path sys.path = [ os.path.dirname(sys.argv[0]) ] + sys.path
scope = { '__file__' : sys.argv[0] } scope = { '__file__' : sys.argv[0],
'__name__' : '__m5_main__' }
# we want readline if we're doing anything interactive # we want readline if we're doing anything interactive
if options.interactive or options.pdb: if options.interactive or options.pdb:

View file

@ -5,6 +5,18 @@ from Uart import Uart8250
from Platform import Platform from Platform import Platform
from SimConsole import SimConsole, ConsoleListener from SimConsole import SimConsole, ConsoleListener
class MmDisk(BasicPioDevice):
type = 'MmDisk'
image = Param.DiskImage("Disk Image")
pio_addr = 0x1F40000000
class DumbTOD(BasicPioDevice):
type = 'DumbTOD'
time = Param.Time('01/01/2009', "System time to use ('Now' for real time)")
pio_addr = 0xfff0c1fff8
class T1000(Platform): class T1000(Platform):
type = 'T1000' type = 'T1000'
system = Param.System(Parent.any, "system") system = Param.System(Parent.any, "system")
@ -58,6 +70,8 @@ class T1000(Platform):
warn_access="Accessing SSI -- Unimplemented!") warn_access="Accessing SSI -- Unimplemented!")
hvuart = Uart8250(pio_addr=0xfff0c2c000) hvuart = Uart8250(pio_addr=0xfff0c2c000)
htod = DumbTOD()
puart0 = Uart8250(pio_addr=0x1f10000000) puart0 = Uart8250(pio_addr=0x1f10000000)
console = SimConsole(listener = ConsoleListener()) console = SimConsole(listener = ConsoleListener())
@ -80,3 +94,4 @@ class T1000(Platform):
self.fake_ssi.pio = bus.port self.fake_ssi.pio = bus.port
self.puart0.pio = bus.port self.puart0.pio = bus.port
self.hvuart.pio = bus.port self.hvuart.pio = bus.port
self.htod.pio = bus.port

View file

@ -13,8 +13,8 @@ class TsunamiCChip(BasicPioDevice):
class TsunamiIO(BasicPioDevice): class TsunamiIO(BasicPioDevice):
type = 'TsunamiIO' type = 'TsunamiIO'
time = Param.UInt64(1136073600, time = Param.Time('01/01/2009',
"System time to use (0 for actual time, default is 1/1/06)") "System time to use ('Now' for actual time)")
tsunami = Param.Tsunami(Parent.any, "Tsunami") tsunami = Param.Tsunami(Parent.any, "Tsunami")
frequency = Param.Frequency('1024Hz', "frequency of interrupts") frequency = Param.Frequency('1024Hz', "frequency of interrupts")

View file

@ -44,7 +44,12 @@
# #
##################################################################### #####################################################################
import sys, inspect, copy import copy
import datetime
import inspect
import sys
import time
import convert import convert
from util import * from util import *
@ -513,6 +518,50 @@ class EthernetAddr(ParamValue):
else: else:
return self.value return self.value
def parse_time(value):
strings = [ "%a %b %d %H:%M:%S %Z %Y",
"%a %b %d %H:%M:%S %Z %Y",
"%Y/%m/%d %H:%M:%S",
"%Y/%m/%d %H:%M",
"%Y/%m/%d",
"%m/%d/%Y %H:%M:%S",
"%m/%d/%Y %H:%M",
"%m/%d/%Y",
"%m/%d/%y %H:%M:%S",
"%m/%d/%y %H:%M",
"%m/%d/%y"]
for string in strings:
try:
return time.strptime(value, string)
except ValueError:
pass
raise ValueError, "Could not parse '%s' as a time" % value
class Time(ParamValue):
cxx_type = 'time_t'
def __init__(self, value):
if isinstance(value, time.struct_time):
self.value = time.mktime(value)
elif isinstance(value, int):
self.value = value
elif isinstance(value, str):
if value in ('Now', 'Today'):
self.value = time.time()
else:
self.value = time.mktime(parse_time(value))
elif isinstance(value, (datetime.datetime, datetime.date)):
self.value = time.mktime(value.timetuple())
else:
raise ValueError, "Could not parse '%s' as a time" % value
def __str__(self):
return str(int(self.value))
def ini_str(self):
return str(int(self.value))
# Enumerated types are a little more complex. The user specifies the # Enumerated types are a little more complex. The user specifies the
# type as Enum(foo) where foo is either a list or dictionary of # type as Enum(foo) where foo is either a list or dictionary of
# alternatives (typically strings, but not necessarily so). (In the # alternatives (typically strings, but not necessarily so). (In the
@ -973,6 +1022,7 @@ __all__ = ['Param', 'VectorParam',
'NetworkBandwidth', 'MemoryBandwidth', 'NetworkBandwidth', 'MemoryBandwidth',
'Range', 'AddrRange', 'TickRange', 'Range', 'AddrRange', 'TickRange',
'MaxAddr', 'MaxTick', 'AllMemory', 'MaxAddr', 'MaxTick', 'AllMemory',
'Time',
'NextEthernetAddr', 'NULL', 'NextEthernetAddr', 'NULL',
'Port', 'VectorPort'] 'Port', 'VectorPort']

View file

@ -132,7 +132,7 @@ template <typename T> static inline T letobe(T value) {return swap_byte(value);}
//For conversions not involving the guest system, we can define the functions //For conversions not involving the guest system, we can define the functions
//conditionally based on the BYTE_ORDER macro and outside of the namespaces //conditionally based on the BYTE_ORDER macro and outside of the namespaces
#if defined(_BIG_ENDIAN) || BYTE_ORDER == BIG_ENDIAN #if defined(_BIG_ENDIAN) || !defined(_LITTLE_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
const ByteOrder HostByteOrder = BigEndianByteOrder; const ByteOrder HostByteOrder = BigEndianByteOrder;
template <typename T> static inline T htole(T value) {return swap_byte(value);} template <typename T> static inline T htole(T value) {return swap_byte(value);}
template <typename T> static inline T letoh(T value) {return swap_byte(value);} template <typename T> static inline T letoh(T value) {return swap_byte(value);}

View file

@ -448,6 +448,11 @@ LiveProcess::create(const std::string &nm, System *system, int stdin_fd,
fatal("Can't load object file %s", executable); fatal("Can't load object file %s", executable);
} }
if (objFile->isDynamic())
fatal("Object file is a dynamic executable however only static "
"executables are supported!\n Please recompile your "
"executable as a static binary and try again.\n");
#if THE_ISA == ALPHA_ISA #if THE_ISA == ALPHA_ISA
if (objFile->getArch() != ObjectFile::Alpha) if (objFile->getArch() != ObjectFile::Alpha)
fatal("Object file architecture does not match compiled ISA (Alpha)."); fatal("Object file architecture does not match compiled ISA (Alpha).");