summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/alpha/utility.cc11
-rw-r--r--src/arch/alpha/utility.hh3
-rw-r--r--src/arch/arm/system.hh5
-rw-r--r--src/arch/arm/utility.cc60
-rw-r--r--src/arch/arm/utility.hh4
-rw-r--r--src/arch/mips/utility.cc11
-rw-r--r--src/arch/mips/utility.hh4
-rw-r--r--src/arch/power/utility.cc7
-rw-r--r--src/arch/power/utility.hh2
-rw-r--r--src/arch/sparc/utility.cc12
-rw-r--r--src/arch/sparc/utility.hh4
-rw-r--r--src/arch/x86/utility.cc9
-rw-r--r--src/arch/x86/utility.hh4
-rw-r--r--src/kern/system_events.cc12
-rw-r--r--src/sim/arguments.cc4
-rw-r--r--src/sim/arguments.hh10
16 files changed, 128 insertions, 34 deletions
diff --git a/src/arch/alpha/utility.cc b/src/arch/alpha/utility.cc
index 0d865e520..80ec360b7 100644
--- a/src/arch/alpha/utility.cc
+++ b/src/arch/alpha/utility.cc
@@ -40,7 +40,7 @@
namespace AlphaISA {
uint64_t
-getArgument(ThreadContext *tc, int number, bool fp)
+getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp)
{
#if FULL_SYSTEM
const int NumArgumentRegs = 6;
@@ -96,5 +96,14 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest)
copyIprs(src, dest);
}
+void
+skipFunction(ThreadContext *tc)
+{
+ Addr newpc = tc->readIntReg(ReturnAddressReg);
+ tc->setPC(newpc);
+ tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst));
+}
+
+
} // namespace AlphaISA
diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh
index 281fc4492..360e155f8 100644
--- a/src/arch/alpha/utility.hh
+++ b/src/arch/alpha/utility.hh
@@ -41,7 +41,7 @@
namespace AlphaISA {
-uint64_t getArgument(ThreadContext *tc, int number, bool fp);
+uint64_t getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp);
inline bool
inUserMode(ThreadContext *tc)
@@ -94,6 +94,7 @@ void copyRegs(ThreadContext *src, ThreadContext *dest);
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
+void skipFunction(ThreadContext *tc);
} // namespace AlphaISA
#endif // __ARCH_ALPHA_UTILITY_HH__
diff --git a/src/arch/arm/system.hh b/src/arch/arm/system.hh
index adf6d4f7b..fe5ba6447 100644
--- a/src/arch/arm/system.hh
+++ b/src/arch/arm/system.hh
@@ -67,7 +67,10 @@ class ArmSystem : public System
virtual Addr fixFuncEventAddr(Addr addr)
{
- //XXX This may eventually have to do something useful.
+ // Remove the low bit that thumb symbols have set
+ // but that aren't actually odd aligned
+ if (addr & 0x1)
+ return (addr & ~1) | PcTBit;
return addr;
}
};
diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc
index 3e574ccaf..9672c5136 100644
--- a/src/arch/arm/utility.cc
+++ b/src/arch/arm/utility.cc
@@ -42,6 +42,10 @@
#include "arch/arm/utility.hh"
#include "cpu/thread_context.hh"
+#if FULL_SYSTEM
+#include "arch/arm/vtophys.hh"
+#include "mem/vport.hh"
+#endif
namespace ArmISA {
@@ -57,17 +61,43 @@ initCPU(ThreadContext *tc, int cpuId)
reset->invoke(tc);
}
-uint64_t getArgument(ThreadContext *tc, int number, bool fp) {
+uint64_t getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp) {
#if FULL_SYSTEM
+ if (fp)
+ panic("getArgument(): Floating point arguments not implemented\n");
+
if (number < NumArgumentRegs) {
- if (fp)
- panic("getArgument(): Floating point arguments not implemented\n");
- else
- return tc->readIntReg(number);
- }
- else {
- panic("getArgument(): Argument index %d beyond max supported (%d).\n",
- number, NumArgumentRegs - 1);
+ // If the argument is 64 bits, it must be in an even regiser number
+ // Increment the number here if it isn't even
+ if (size == sizeof(uint64_t)) {
+ if ((number % 2) != 0)
+ number++;
+ // Read the two halves of the data
+ // number is inc here to get the second half of the 64 bit reg
+ uint64_t tmp;
+ tmp = tc->readIntReg(number++);
+ tmp |= tc->readIntReg(number) << 32;
+ return tmp;
+ } else {
+ return tc->readIntReg(number);
+ }
+ } else {
+ Addr sp = tc->readIntReg(StackPointerReg);
+ VirtualPort *vp = tc->getVirtPort();
+ uint64_t arg;
+ if (size == sizeof(uint64_t)) {
+ // If the argument is even it must be aligned
+ if ((number % 2) != 0)
+ number++;
+ arg = vp->read<uint64_t>(sp +
+ (number-NumArgumentRegs) * sizeof(uint32_t));
+ // since two 32 bit args == 1 64 bit arg, increment number
+ number++;
+ } else {
+ arg = vp->read<uint32_t>(sp +
+ (number-NumArgumentRegs) * sizeof(uint32_t));
+ }
+ return arg;
}
#else
panic("getArgument() only implemented for FULL_SYSTEM\n");
@@ -90,5 +120,17 @@ readCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2)
}
+void
+skipFunction(ThreadContext *tc)
+{
+ Addr newpc = tc->readIntReg(ReturnAddressReg);
+ newpc &= ~ULL(1);
+ if (isThumb(tc->readPC()))
+ tc->setPC(newpc | PcTBit);
+ else
+ tc->setPC(newpc);
+ tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst));
+}
+
}
diff --git a/src/arch/arm/utility.hh b/src/arch/arm/utility.hh
index 8c2ccd4f6..21c0a9c04 100644
--- a/src/arch/arm/utility.hh
+++ b/src/arch/arm/utility.hh
@@ -156,11 +156,13 @@ namespace ArmISA {
return !cpacr.asedis && vfpEnabled(cpacr, cpsr, fpexc);
}
-uint64_t getArgument(ThreadContext *tc, int number, bool fp);
+uint64_t getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp);
Fault setCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2);
Fault readCp15Register(uint32_t &Rd, int CRn, int opc1, int CRm, int opc2);
+void skipFunction(ThreadContext *tc);
+
};
diff --git a/src/arch/mips/utility.cc b/src/arch/mips/utility.cc
index ab6a00af3..7dd74551e 100644
--- a/src/arch/mips/utility.cc
+++ b/src/arch/mips/utility.cc
@@ -52,7 +52,7 @@ using namespace std;
namespace MipsISA {
uint64_t
-getArgument(ThreadContext *tc, int number, bool fp)
+getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp)
{
#if FULL_SYSTEM
if (number < 4) {
@@ -264,5 +264,14 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest)
{
panic("Copy Misc. Regs Not Implemented Yet\n");
}
+void
+skipFunction(ThreadContext *tc)
+{
+ Addr newpc = tc->readIntReg(ReturnAddressReg);
+ tc->setPC(newpc);
+ tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst));
+ tc->setNextPC(tc->readNextPC() + sizeof(TheISA::MachInst));
+}
+
} // namespace MipsISA
diff --git a/src/arch/mips/utility.hh b/src/arch/mips/utility.hh
index f827e9b33..d073f3116 100644
--- a/src/arch/mips/utility.hh
+++ b/src/arch/mips/utility.hh
@@ -45,7 +45,7 @@ class ThreadContext;
namespace MipsISA {
-uint64_t getArgument(ThreadContext *tc, int number, bool fp);
+uint64_t getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp);
////////////////////////////////////////////////////////////////////////
//
@@ -103,6 +103,8 @@ void startupCPU(ThreadContext *tc, int cpuId);
void copyRegs(ThreadContext *src, ThreadContext *dest);
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
+void skipFunction(ThreadContext *tc);
+
};
diff --git a/src/arch/power/utility.cc b/src/arch/power/utility.cc
index c3d49ed16..ece17f4d1 100644
--- a/src/arch/power/utility.cc
+++ b/src/arch/power/utility.cc
@@ -55,4 +55,11 @@ copyRegs(ThreadContext *src, ThreadContext *dest)
dest->setNextPC(src->readNextPC());
}
+void
+skipFunction(ThreadContext *tc)
+{
+ panic("Not Implemented for POWER");
+}
+
+
} // PowerISA namespace
diff --git a/src/arch/power/utility.hh b/src/arch/power/utility.hh
index b3eed9de3..c8cd441ba 100644
--- a/src/arch/power/utility.hh
+++ b/src/arch/power/utility.hh
@@ -61,6 +61,8 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest)
{
}
+void skipFunction(ThreadContext *tc);
+
} // PowerISA namespace
#endif // __ARCH_POWER_UTILITY_HH__
diff --git a/src/arch/sparc/utility.cc b/src/arch/sparc/utility.cc
index 9a062e841..e14be48e2 100644
--- a/src/arch/sparc/utility.cc
+++ b/src/arch/sparc/utility.cc
@@ -45,7 +45,7 @@ namespace SparcISA {
//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.
-uint64_t getArgument(ThreadContext *tc, int number, bool fp) {
+uint64_t getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp) {
#if FULL_SYSTEM
const int NumArgumentRegs = 6;
if (number < NumArgumentRegs) {
@@ -219,6 +219,16 @@ copyRegs(ThreadContext *src, ThreadContext *dest)
}
void
+skipFunction(ThreadContext *tc)
+{
+ Addr newpc = tc->readIntReg(ReturnAddressReg);
+ tc->setPC(newpc);
+ tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst));
+ tc->setNextPC(tc->readNextPC() + sizeof(TheISA::MachInst));
+}
+
+
+void
initCPU(ThreadContext *tc, int cpuId)
{
static Fault por = new PowerOnReset();
diff --git a/src/arch/sparc/utility.hh b/src/arch/sparc/utility.hh
index 70044a6c2..39e23aa26 100644
--- a/src/arch/sparc/utility.hh
+++ b/src/arch/sparc/utility.hh
@@ -41,7 +41,7 @@
namespace SparcISA
{
- uint64_t getArgument(ThreadContext *tc, int number, bool fp);
+ uint64_t getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp);
static inline bool
inUserMode(ThreadContext *tc)
@@ -75,6 +75,8 @@ namespace SparcISA
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
+ void skipFunction(ThreadContext *tc);
+
} // namespace SparcISA
#endif
diff --git a/src/arch/x86/utility.cc b/src/arch/x86/utility.cc
index 50574bcde..d74bb74b6 100644
--- a/src/arch/x86/utility.cc
+++ b/src/arch/x86/utility.cc
@@ -52,7 +52,7 @@
namespace X86ISA {
-uint64_t getArgument(ThreadContext *tc, int number, bool fp) {
+uint64_t getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp) {
#if FULL_SYSTEM
panic("getArgument() not implemented for x86!\n");
#else
@@ -233,4 +233,11 @@ copyRegs(ThreadContext *src, ThreadContext *dest)
dest->setNextPC(src->readNextPC());
}
+void
+skipFunction(ThreadContext *tc)
+{
+ panic("Not implemented for x86\n");
+}
+
+
} //namespace X86_ISA
diff --git a/src/arch/x86/utility.hh b/src/arch/x86/utility.hh
index bfa102529..fd9ac59fd 100644
--- a/src/arch/x86/utility.hh
+++ b/src/arch/x86/utility.hh
@@ -52,7 +52,7 @@ class ThreadContext;
namespace X86ISA
{
- uint64_t getArgument(ThreadContext *tc, int number, bool fp);
+ uint64_t getArgument(ThreadContext *tc, int &number, uint8_t size, bool fp);
static inline bool
inUserMode(ThreadContext *tc)
@@ -83,6 +83,8 @@ namespace X86ISA
void copyRegs(ThreadContext *src, ThreadContext *dest);
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
+
+ void skipFunction(ThreadContext *tc);
};
#endif // __ARCH_X86_UTILITY_HH__
diff --git a/src/kern/system_events.cc b/src/kern/system_events.cc
index bd01ed9ed..25856e466 100644
--- a/src/kern/system_events.cc
+++ b/src/kern/system_events.cc
@@ -30,6 +30,7 @@
*/
#include "arch/isa_traits.hh"
+#include "arch/utility.hh"
#include "base/trace.hh"
#include "config/the_isa.hh"
#include "cpu/thread_context.hh"
@@ -40,14 +41,9 @@ using namespace TheISA;
void
SkipFuncEvent::process(ThreadContext *tc)
{
- Addr newpc = tc->readIntReg(ReturnAddressReg);
-
DPRINTF(PCEvent, "skipping %s: pc=%x, newpc=%x\n", description,
- tc->readPC(), newpc);
+ tc->readPC(), tc->readIntReg(ReturnAddressReg));
- tc->setPC(newpc);
- tc->setNextPC(tc->readPC() + sizeof(TheISA::MachInst));
-#if ISA_HAS_DELAY_SLOT
- tc->setNextPC(tc->readNextPC() + sizeof(TheISA::MachInst));
-#endif
+ // Call ISA specific code to do the skipping
+ TheISA::skipFunction(tc);
}
diff --git a/src/sim/arguments.cc b/src/sim/arguments.cc
index 339a57f90..511fc630d 100644
--- a/src/sim/arguments.cc
+++ b/src/sim/arguments.cc
@@ -50,8 +50,8 @@ Arguments::Data::alloc(size_t size)
}
uint64_t
-Arguments::getArg(bool fp)
+Arguments::getArg(uint8_t size, bool fp)
{
- return TheISA::getArgument(tc, number, fp);
+ return TheISA::getArgument(tc, number, size, fp);
}
diff --git a/src/sim/arguments.hh b/src/sim/arguments.hh
index abc3da812..97b848e03 100644
--- a/src/sim/arguments.hh
+++ b/src/sim/arguments.hh
@@ -45,7 +45,7 @@ class Arguments
protected:
ThreadContext *tc;
int number;
- uint64_t getArg(bool fp = false);
+ uint64_t getArg(uint8_t size, bool fp = false);
protected:
class Data : public RefCounted
@@ -82,7 +82,7 @@ class Arguments
// for checking if an argument is NULL
bool operator!() {
- return getArg() == 0;
+ return getArg(TheISA::MachineBytes) == 0;
}
Arguments &operator++() {
@@ -130,20 +130,20 @@ class Arguments
template <class T>
operator T() {
assert(sizeof(T) <= sizeof(uint64_t));
- T data = static_cast<T>(getArg());
+ T data = static_cast<T>(getArg(sizeof(T)));
return data;
}
template <class T>
operator T *() {
T *buf = (T *)data->alloc(sizeof(T));
- CopyData(tc, buf, getArg(), sizeof(T));
+ CopyData(tc, buf, getArg(sizeof(T)), sizeof(T));
return buf;
}
operator char *() {
char *buf = data->alloc(2048);
- CopyStringOut(tc, buf, getArg(), 2048);
+ CopyStringOut(tc, buf, getArg(TheISA::MachineBytes), 2048);
return buf;
}
};